Merge "aaudio: call stop() from the callback"
diff --git a/apex/Android.bp b/apex/Android.bp
index 05cc2c5..51e4c23 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -27,12 +27,31 @@
"libmpeg2extractor",
"liboggextractor",
"libwavextractor",
+ // MediaPlayer2
+ "libmediaplayer2_jni",
],
key: "com.android.media.key",
}
+apex {
+ name: "com.android.media.swcodec",
+ compile_multilib: "32",
+ manifest: "manifest_codec.json",
+ native_shared_libs: [
+ "libmedia_codecserviceregistrant",
+ ],
+ use_vendor: true,
+ key: "com.android.media.swcodec.key",
+}
+
apex_key {
name: "com.android.media.key",
public_key: "com.android.media.avbpubkey",
private_key: "com.android.media.pem",
}
+
+apex_key {
+ name: "com.android.media.swcodec.key",
+ public_key: "com.android.media.swcodec.avbpubkey",
+ private_key: "com.android.media.swcodec.pem",
+}
diff --git a/apex/com.android.media.swcodec.avbpubkey b/apex/com.android.media.swcodec.avbpubkey
new file mode 100644
index 0000000..0459723
--- /dev/null
+++ b/apex/com.android.media.swcodec.avbpubkey
Binary files differ
diff --git a/apex/com.android.media.swcodec.pem b/apex/com.android.media.swcodec.pem
new file mode 100644
index 0000000..e379cd3
--- /dev/null
+++ b/apex/com.android.media.swcodec.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKgIBAAKCAgEAvB6lOEEOR58KMcFlayEZjsXuPgcfHi/OPxcvfpiGLCpOcK3l
+OPChWUvDRcIHMB7BO+Csfxs0HgsHvvZfNyoNIm99WcjFbboiO7WrBBArIszPr14X
+cfY2NxzT9LBj+EqAnbdL+4OQW1/npLHNE0qtDcxL71ipbjSuKNb58E9qGL0KwvkS
+fwwueWj++bg/iz7dq0mz7iKpnxYscNm4RhJjqcG2Usmg4Ejhr8h5UmOUmTJbObC/
+vzClXQqeeuzS8NTtGVgQ/CI9gC2WN9upq2p/2T7P4U3o3CWvBytUoLKR0UyC83ey
+S8XJgOa42uWR3T/eJOI1ZS4H6Srg1o2XC8Yb8EprFI/NM6/+/5DX/FgDimsslAP6
+Qq4+pSte9v/FjWGqy7QBQaefFRGRuS63xHcSZhXC9J2CFdnxo8+65QT8r4yfQEei
+Ax/0Q94yB7VIL1pIJxHEonKjtd3iKdFEKQzADJ3edsmtHybERdJKCxcm9QIrDCsC
+4YVT9nX0OoC9RD5d5EVD7W5I6eEnRu6igrKIKgUVppeYFQNZD+o+eiNJa4yoggRl
+h8sT0/xLKjMRxAQ7fafi1j+LB2O7UgJmIDDAnidq8Aoz7h3pNi139rNWrjNfwhus
+nMcZvL9dTVv26JWeESHP/zAfAX7j1rfkDwR02ocRLquwEUs1+UHA27Wi1bMCAwEA
+AQKCAgAO3PT83tb7/arWh4s1zaWxTB4otHNW9Tv8bB6KiA6Bys3rxTGJMCnvXjcN
+eekLekKWMoguer3BaemwwtJ/D0l+YQSsZVqD8uLliNL8PTLLSxdVqb98d5GNBTAR
+8yXS5kAHNgZA1wI+1fL9ZjbnwUyu/Gc7f+vTE0J3Y5TX0c52KemBwiAd/Z5mZU9P
+96i9nbfx4p7ev8pbEWttdyZCEw3gybdYDyowzlFWjCZZxhhlij7+7eIYfwVxtncT
+C0cXVBtvly+wXBwz1mY5/5cGPiHfzkCqcndlfWy4ykmjcLhoqvzls51Ys0Xac2BD
+m0PNEVDB5UWGuv5RA9xD12gJvBtU3D7ggMw6C5RcXJT+jSYmSFtD2klWi+It8A/N
+Hv42soKskt6JqYAWE1cvJ3PEqH9ASEJNq2R0Z/PmuM000UJyzU9KId3SNwjXA1Xc
+Kn9hRga4uf9elHTjkTDt79/8+Xv7hjer9sF/S/np7g04rUjIWkuFkC/7NK2tQSh1
+mljV1sD9SF4DPfVK75LwJJaQUlI7TtGd5KJ7FzZwvb+w8ODrpW3hkt6FcI6KwE/a
+QT1T2Z9DknXJSYNdWGrj6vMHsYMiyz8IdAHSCrOB6eXCQxpitbn6W71Raw7f9UaZ
+VDK5AhTU493hkGj1no4cJwecXInMigg/c4ywk2Ibh6IV8O0nkQKCAQEA2+dQQ0IF
+vvVgmQ2WxHBD7M2mbOyf43YBY6Ka6oPBNGPVpZE8X8LoTavQLV+SgCkH8T6gY7XS
+5L4Ze0JFxfua0o1rm6+L2XrOx5F/A2Y40YcPclEik5h1woSwH/J1iHGiEhY8Nqeu
+9GCvjQojkgXx/Rn3Nz+lpvZ329O3H85RWWGF0l60RwLOkig0ZwUb619t8affmGIl
+sxdDv2nfy7OtJX8iGDua7Kf64dvVWQKKtACWkARrlkcWX3uoESxkpSDxue+z7ndH
+o7uHLfM8Tx+Rn+QvYWuRW5TPLbEDMbIYrX65ISt2r/T7v/04XdAC8YpCQRytlqPI
+fpDm15htyHBizQKCAQEA2v+5otRoY56JduISaVGlsJ/IbvKzDAIyWmM14EpRCR5E
+lu+MpTcRAiFQAbHGXr1tMlTFdVFD090WAzIKaKtADFVLXobIHeGspnRCq5OpVp9W
+RvLtVwLxflHAc2yN9/LNtnBqHUgt+S01LBPElybdGHQRTtqAKXhkp31sM21O34Go
+Pri/IxgupWxykMaW44Kig1Cr5DKvc8cwUsGuyDdJm8oBQeNPTMWqSnXtqoTWSaYg
+2kxiMTFokrkSXgufb8wng6OXt/QelywrhG3hAsldPO3GdKidDSxhWZSgpUXXFdAX
+y4GO0IcRJBF/WJtYTYtR+l84nQA2/1Ye4ujFlT0afwKCAQEAmXrXpSm2cvI2CnzW
+hqJIdkWOa6W3bn1VOOIrt5Rfy54GZnl4pumVU2igcpqq2HJKzdDFBvLHj8kyZbn6
+ktUp2NzFhzK9q/uvyNA+0vOMoojeeg4w0MzvG+WaO6Hw8FtHH9KPEiJ01LGKtSin
+bOpjXCC8T75HcsHBJBefTz6jvnt3eD2LG6jU3mPbNy/0rZG8XZaqU2PlJhsNuNI/
+VaBBL9OMy1cGqTgQvYS+YlKI1ls2uqurH4bcEaZvxhSy5iGZNQodDkoIITnofmSu
+6haBgBQ2EYuPN1kkRKKwNQY1fRneQk1gmCynbPdiWO+urkCuP12xtlr3u4aM51rG
+/Meb3QKCAQEA12SxZm9XhLOHLIBJ74A4YLGm50iZxXPbpn7xnHo7naZBe9p8EHtK
+pTeygxggrUnOPrSVyT92YMiQP/BVwIC+a+LwUDZsWMd/ke/DKxH+eY4Zw4pm2S+x
+6bXqfRwFvhr3LTr/g3FcljlalNGUh73Xs5dk9pN9fkxFY16+rw4Rh0709Uur4o6E
+QnuZar+H5Ji10kXj6nvXiR4ebybEC3QlV66k8fLqKe44AShf61jfkmxs34hFA3E/
+EyAn6ouv8rtvGdArBuh5teHho0yXBLCcnbKXgGHepfhCf2LpZeR9GZ0j6iqxFnPh
+7gGvqKyReyNOK9y/x9tQPG6tzit3OcNxbQKCAQEAuDheDOSkXPopXMvLAKOHBIdZ
+rbQ7oFTDHt59gbucM7U8/l2YtaxuKOQFBLnzQa/amIkkrtklYwOsz8E24d7Nm39w
+ykLHwX0XrmjAm6M4XKmDv66a+kSnSV6LEbKZdjvXP02DV+tGeZ5VsnNvJDquxMsD
+fvRTspB8j8CpU96szekxl/tCRhqbdw/4kVTSj5BF++OaRRcJrAyj1B2qf1ynAZE1
+gUvVPkEYa914zcrxg9XIXT4M7yqB7i8KJegOtOtcWjJ7uTiP+638AvygJLMJnSrV
++HjFZWG6P9btZmLHSEBRvwGOAilp0qejXo866l0fmnlGy7ehKz8u3PzvnlPYjQ==
+-----END RSA PRIVATE KEY-----
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
new file mode 100644
index 0000000..e2bceec
--- /dev/null
+++ b/apex/manifest_codec.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.media.swcodec",
+ "version": 1
+}
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 60c9f85..d96f403 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -137,6 +137,7 @@
shared_libs: [
"libhwbinder",
"libcamera2ndk_vendor",
+ "libcamera_metadata",
"libmediandk",
"libnativewindow",
"libutils",
@@ -144,6 +145,9 @@
"libcutils",
"liblog",
],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
cflags: [
"-D__ANDROID_VNDK__",
],
diff --git a/camera/ndk/NdkCameraCaptureSession.cpp b/camera/ndk/NdkCameraCaptureSession.cpp
index 540d84e..ab796fb 100644
--- a/camera/ndk/NdkCameraCaptureSession.cpp
+++ b/camera/ndk/NdkCameraCaptureSession.cpp
@@ -80,7 +80,9 @@
if (session->isClosed()) {
ALOGE("%s: session %p is already closed", __FUNCTION__, session);
- *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ if (captureSequenceId != nullptr) {
+ *captureSequenceId = CAPTURE_SEQUENCE_ID_NONE;
+ }
return ACAMERA_ERROR_SESSION_CLOSED;
}
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index f395b44..575ee9d 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -34,7 +34,10 @@
namespace android {
namespace acam {
-using CameraStatusAndId = frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using frameworks::cameraservice::service::V2_0::CameraStatusAndId;
+using frameworks::cameraservice::common::V2_0::ProviderIdAndVendorTagSections;
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
// Static member definitions
const char* CameraManagerGlobal::kCameraIdKey = "CameraId";
@@ -43,6 +46,104 @@
Mutex CameraManagerGlobal::sLock;
CameraManagerGlobal* CameraManagerGlobal::sInstance = nullptr;
+/**
+ * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * input. Not part of vendor available VendorTagDescriptor class because that class is used by
+ * default HAL implementation code as well.
+ */
+class HidlVendorTagDescriptor : public VendorTagDescriptor {
+public:
+ /**
+ * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+ * vector.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ static status_t createDescriptorFromHidl(const hidl_vec<VendorTagSection>& vts,
+ /*out*/ sp<VendorTagDescriptor> *descriptor);
+};
+
+status_t HidlVendorTagDescriptor::createDescriptorFromHidl(const hidl_vec<VendorTagSection> &vts,
+ sp<VendorTagDescriptor> *descriptor) {
+ int tagCount = 0;
+
+ for (size_t s = 0; s < vts.size(); s++) {
+ tagCount += vts[s].tags.size();
+ }
+
+ if (tagCount < 0 || tagCount > INT32_MAX) {
+ ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
+ return BAD_VALUE;
+ }
+
+ Vector<uint32_t> tagArray;
+ LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+ "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+ sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+ desc->mTagCount = tagCount;
+
+ KeyedVector<uint32_t, String8> tagToSectionMap;
+
+ int idx = 0;
+ for (size_t s = 0; s < vts.size(); s++) {
+ const VendorTagSection& section = vts[s];
+ const char *sectionName = section.sectionName.c_str();
+ if (sectionName == NULL) {
+ ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
+ return BAD_VALUE;
+ }
+ String8 sectionString(sectionName);
+ desc->mSections.add(sectionString);
+
+ for (size_t j = 0; j < section.tags.size(); j++) {
+ uint32_t tag = section.tags[j].tagId;
+ if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+ ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+ return BAD_VALUE;
+ }
+
+ tagArray.editItemAt(idx++) = section.tags[j].tagId;
+
+ const char *tagName = section.tags[j].tagName.c_str();
+ if (tagName == NULL) {
+ ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
+ return BAD_VALUE;
+ }
+ desc->mTagToNameMap.add(tag, String8(tagName));
+ tagToSectionMap.add(tag, sectionString);
+
+ int tagType = (int) section.tags[j].tagType;
+ if (tagType < 0 || tagType >= NUM_TYPES) {
+ ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+ return BAD_VALUE;
+ }
+ desc->mTagToTypeMap.emplace(tag, tagType);
+ }
+ }
+
+ for (size_t i = 0; i < tagArray.size(); ++i) {
+ uint32_t tag = tagArray[i];
+ String8 sectionString = tagToSectionMap.valueFor(tag);
+
+ // Set up tag to section index map
+ ssize_t index = desc->mSections.indexOf(sectionString);
+ LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+ desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+ // Set up reverse mapping
+ ssize_t reverseIndex = -1;
+ if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+ KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+ reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+ }
+ desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+ }
+
+ *descriptor = std::move(desc);
+ return OK;
+}
+
CameraManagerGlobal&
CameraManagerGlobal::getInstance() {
Mutex::Autolock _l(sLock);
@@ -80,8 +181,34 @@
return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
}
-// TODO: Add back when vendor tags are supported for libcamera2ndk_vendor when
-// the HIDL interface supports querying by vendor id.
+bool CameraManagerGlobal::setupVendorTags() {
+ sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
+ Status status = Status::NO_ERROR;
+ std::vector<ProviderIdAndVendorTagSections> providerIdsAndVts;
+ auto remoteRet = mCameraService->getCameraVendorTagSections([&status, &providerIdsAndVts]
+ (Status s,
+ auto &IdsAndVts) {
+ status = s;
+ providerIdsAndVts = IdsAndVts; });
+
+ if (!remoteRet.isOk() || status != Status::NO_ERROR) {
+ ALOGE("Failed to retrieve VendorTagSections %s", remoteRet.description().c_str());
+ return false;
+ }
+ // Convert each providers VendorTagSections into a VendorTagDescriptor and
+ // add it to the cache
+ for (auto &providerIdAndVts : providerIdsAndVts) {
+ sp<VendorTagDescriptor> vendorTagDescriptor;
+ if (HidlVendorTagDescriptor::createDescriptorFromHidl(providerIdAndVts.vendorTagSections,
+ &vendorTagDescriptor) != OK) {
+ ALOGE("Failed to convert from Hidl: VendorTagDescriptor");
+ return false;
+ }
+ tagCache->addVendorDescriptor(providerIdAndVts.providerId, vendorTagDescriptor);
+ }
+ VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
+ return true;
+}
sp<ICameraService> CameraManagerGlobal::getCameraService() {
Mutex::Autolock _l(mLock);
@@ -140,6 +267,13 @@
if (!remoteRet.isOk() || status != Status::NO_ERROR) {
ALOGE("Failed to add listener to camera service %s", remoteRet.description().c_str());
}
+
+ // Setup vendor tags
+ if (!setupVendorTags()) {
+ ALOGE("Unable to set up vendor tags");
+ return nullptr;
+ }
+
for (auto& c : cameraStatuses) {
onStatusChangedLocked(c);
}
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.h b/camera/ndk/ndk_vendor/impl/ACameraManager.h
index c8d640f..6b1365a 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.h
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.h
@@ -142,6 +142,8 @@
void onStatusChanged(const CameraStatusAndId &statusAndId);
void onStatusChangedLocked(const CameraStatusAndId &statusAndId);
+ bool setupVendorTags();
+
// Utils for status
static bool validStatus(CameraDeviceStatus status);
static bool isStatusAvailable(CameraDeviceStatus status);
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 579412e..93108b0 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -37,12 +37,7 @@
#include <media/NdkImage.h>
#include <media/NdkImageReader.h>
#include <cutils/native_handle.h>
-
-//#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
-//#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
-#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
-#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#include <VendorTagDescriptor.h>
namespace {
@@ -53,40 +48,31 @@
static constexpr int kTestImageHeight = 480;
static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
+using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+
class CameraHelper {
public:
- CameraHelper(native_handle_t* imgReaderAnw) : mImgReaderAnw(imgReaderAnw) {}
+ CameraHelper(const char* id, ACameraManager *manager) :
+ mImgReaderAnw(nullptr), mCameraId(id), mCameraManager(manager) {}
~CameraHelper() { closeCamera(); }
- int initCamera() {
- if (mImgReaderAnw == nullptr) {
+ struct PhysicalImgReaderInfo {
+ const char* physicalCameraId;
+ native_handle_t* anw;
+ };
+ int initCamera(native_handle_t* imgReaderAnw,
+ const std::vector<PhysicalImgReaderInfo>& physicalImgReaders) {
+ if (imgReaderAnw == nullptr) {
ALOGE("Cannot initialize camera before image reader get initialized.");
return -1;
}
+ if (mIsCameraReady) {
+ ALOGE("initCamera should only be called once.");
+ return -1;
+ }
+
int ret;
-
- mCameraManager = ACameraManager_create();
- if (mCameraManager == nullptr) {
- ALOGE("Failed to create ACameraManager.");
- return -1;
- }
-
- ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
- if (ret != AMEDIA_OK) {
- ALOGE("Failed to get cameraIdList: ret=%d", ret);
- return ret;
- }
- if (mCameraIdList->numCameras < 1) {
- ALOGW("Device has no camera on board.");
- return 0;
- }
-
- // We always use the first camera.
- mCameraId = mCameraIdList->cameraIds[0];
- if (mCameraId == nullptr) {
- ALOGE("Failed to get cameraId.");
- return -1;
- }
+ mImgReaderAnw = imgReaderAnw;
ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
if (ret != AMEDIA_OK || mDevice == nullptr) {
@@ -94,18 +80,6 @@
return -1;
}
- ret = ACameraManager_getCameraCharacteristics(mCameraManager, mCameraId, &mCameraMetadata);
- if (ret != ACAMERA_OK || mCameraMetadata == nullptr) {
- ALOGE("Get camera %s characteristics failure. ret %d, metadata %p", mCameraId, ret,
- mCameraMetadata);
- return -1;
- }
-
- if (!isCapabilitySupported(ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)) {
- ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
- return 0;
- }
-
// Create capture session
ret = ACaptureSessionOutputContainer_create(&mOutputs);
if (ret != AMEDIA_OK) {
@@ -122,6 +96,25 @@
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret;
}
+
+ for (auto& physicalStream : physicalImgReaders) {
+ ACaptureSessionOutput* sessionOutput = nullptr;
+ ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
+ physicalStream.physicalCameraId, &sessionOutput);
+ if (ret != ACAMERA_OK) {
+ ALOGE("ACaptureSessionPhysicalOutput_create failed, ret=%d", ret);
+ return ret;
+ }
+ ret = ACaptureSessionOutputContainer_add(mOutputs, sessionOutput);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
+ return ret;
+ }
+ mExtraOutputs.push_back(sessionOutput);
+ // Assume that at most one physical stream per physical camera.
+ mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
+ }
+
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -145,21 +138,25 @@
return ret;
}
+ for (auto& physicalStream : physicalImgReaders) {
+ ACameraOutputTarget* outputTarget = nullptr;
+ ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACameraOutputTarget_create failed, ret=%d", ret);
+ return ret;
+ }
+ ret = ACaptureRequest_addTarget(mStillRequest, outputTarget);
+ if (ret != AMEDIA_OK) {
+ ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
+ return ret;
+ }
+ mReqExtraOutputs.push_back(outputTarget);
+ }
+
mIsCameraReady = true;
return 0;
}
- bool isCapabilitySupported(acamera_metadata_enum_android_request_available_capabilities_t cap) {
- ACameraMetadata_const_entry entry;
- ACameraMetadata_getConstEntry(
- mCameraMetadata, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
- for (uint32_t i = 0; i < entry.count; i++) {
- if (entry.data.u8[i] == cap) {
- return true;
- }
- }
- return false;
- }
bool isCameraReady() { return mIsCameraReady; }
@@ -169,6 +166,10 @@
ACameraOutputTarget_free(mReqImgReaderOutput);
mReqImgReaderOutput = nullptr;
}
+ for (auto& outputTarget : mReqExtraOutputs) {
+ ACameraOutputTarget_free(outputTarget);
+ }
+ mReqExtraOutputs.clear();
if (mStillRequest) {
ACaptureRequest_free(mStillRequest);
mStillRequest = nullptr;
@@ -182,6 +183,10 @@
ACaptureSessionOutput_free(mImgReaderOutput);
mImgReaderOutput = nullptr;
}
+ for (auto& extraOutput : mExtraOutputs) {
+ ACaptureSessionOutput_free(extraOutput);
+ }
+ mExtraOutputs.clear();
if (mOutputs) {
ACaptureSessionOutputContainer_free(mOutputs);
mOutputs = nullptr;
@@ -191,19 +196,6 @@
ACameraDevice_close(mDevice);
mDevice = nullptr;
}
- if (mCameraMetadata) {
- ACameraMetadata_free(mCameraMetadata);
- mCameraMetadata = nullptr;
- }
- // Destroy camera manager
- if (mCameraIdList) {
- ACameraManager_deleteCameraIdList(mCameraIdList);
- mCameraIdList = nullptr;
- }
- if (mCameraManager) {
- ACameraManager_delete(mCameraManager);
- mCameraManager = nullptr;
- }
mIsCameraReady = false;
}
@@ -213,6 +205,12 @@
&seqId);
}
+ int takeLogicalCameraPicture() {
+ int seqId;
+ return ACameraCaptureSession_logicalCamera_capture(mSession, &mLogicalCaptureCallbacks,
+ 1, &mStillRequest, &seqId);
+ }
+
bool checkCallbacks(int pictureCount) {
std::lock_guard<std::mutex> lock(mMutex);
if (mCompletedCaptureCallbackCount != pictureCount) {
@@ -241,22 +239,22 @@
native_handle_t* mImgReaderAnw = nullptr; // not owned by us.
- // Camera manager
- ACameraManager* mCameraManager = nullptr;
- ACameraIdList* mCameraIdList = nullptr;
// Camera device
- ACameraMetadata* mCameraMetadata = nullptr;
ACameraDevice* mDevice = nullptr;
// Capture session
ACaptureSessionOutputContainer* mOutputs = nullptr;
ACaptureSessionOutput* mImgReaderOutput = nullptr;
+ std::vector<ACaptureSessionOutput*> mExtraOutputs;
+
ACameraCaptureSession* mSession = nullptr;
// Capture request
ACaptureRequest* mStillRequest = nullptr;
ACameraOutputTarget* mReqImgReaderOutput = nullptr;
+ std::vector<ACameraOutputTarget*> mReqExtraOutputs;
bool mIsCameraReady = false;
const char* mCameraId;
+ ACameraManager* mCameraManager;
int mCompletedCaptureCallbackCount = 0;
std::mutex mMutex;
ACameraCaptureSession_captureCallbacks mCaptureCallbacks = {
@@ -264,7 +262,6 @@
this, // context
nullptr, // onCaptureStarted
nullptr, // onCaptureProgressed
- // onCaptureCompleted, called serially, so no lock needed.
[](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
const ACameraMetadata *) {
CameraHelper *ch = static_cast<CameraHelper *>(ctx);
@@ -275,8 +272,44 @@
nullptr, // onCaptureSequenceCompleted
nullptr, // onCaptureSequenceAborted
nullptr, // onCaptureBufferLost
- };
+ };
+ std::vector<std::string> mPhysicalCameraIds;
+ ACameraCaptureSession_logicalCamera_captureCallbacks mLogicalCaptureCallbacks = {
+ // TODO: Add tests for other callbacks
+ this, // context
+ nullptr, // onCaptureStarted
+ nullptr, // onCaptureProgressed
+ [](void* ctx , ACameraCaptureSession *, ACaptureRequest *,
+ const ACameraMetadata *, size_t physicalResultCount,
+ const char** physicalCameraIds, const ACameraMetadata** physicalResults) {
+ CameraHelper *ch = static_cast<CameraHelper *>(ctx);
+ std::lock_guard<std::mutex> lock(ch->mMutex);
+ ASSERT_EQ(physicalResultCount, ch->mPhysicalCameraIds.size());
+ for (size_t i = 0; i < physicalResultCount; i++) {
+ ASSERT_TRUE(physicalCameraIds[i] != nullptr);
+ ASSERT_TRUE(physicalResults[i] != nullptr);
+ ASSERT_NE(std::find(ch->mPhysicalCameraIds.begin(),
+ ch->mPhysicalCameraIds.end(), physicalCameraIds[i]),
+ ch->mPhysicalCameraIds.end());
+
+ // Verify frameNumber and sensorTimestamp exist in physical
+ // result metadata
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(
+ physicalResults[i], ACAMERA_SYNC_FRAME_NUMBER, &entry);
+ ASSERT_EQ(entry.count, 1);
+ ACameraMetadata_getConstEntry(
+ physicalResults[i], ACAMERA_SENSOR_TIMESTAMP, &entry);
+ ASSERT_EQ(entry.count, 1);
+ }
+ ch->mCompletedCaptureCallbackCount++;
+ },
+ nullptr, // onCaptureFailed
+ nullptr, // onCaptureSequenceCompleted
+ nullptr, // onCaptureSequenceAborted
+ nullptr, // onCaptureBufferLost
+ };
};
class ImageReaderTestCase {
@@ -476,84 +509,278 @@
AImageReader_BufferRemovedListener mReaderDetachedCb{this, onBufferRemoved};
};
-bool takePictures(uint64_t readerUsage, int readerMaxImages, bool readerAsync, int pictureCount) {
- int ret = 0;
- ImageReaderTestCase testCase(
- kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
- readerAsync);
- ret = testCase.initImageReader();
- if (ret < 0) {
- ALOGE("Unable to initialize ImageReader");
+
+class AImageReaderVendorTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ mCameraManager = ACameraManager_create();
+ if (mCameraManager == nullptr) {
+ ALOGE("Failed to create ACameraManager.");
+ return;
+ }
+
+ camera_status_t ret = ACameraManager_getCameraIdList(mCameraManager, &mCameraIdList);
+ if (ret != ACAMERA_OK) {
+ ALOGE("Failed to get cameraIdList: ret=%d", ret);
+ return;
+ }
+ // TODO: Add more rigorous tests for vendor tags
+ ASSERT_NE(VendorTagDescriptorCache::getGlobalVendorTagCache(), nullptr);
+ if (mCameraIdList->numCameras < 1) {
+ ALOGW("Device has no camera on board.");
+ return;
+ }
+ }
+ void TearDown() override {
+ // Destroy camera manager
+ if (mCameraIdList) {
+ ACameraManager_deleteCameraIdList(mCameraIdList);
+ mCameraIdList = nullptr;
+ }
+ if (mCameraManager) {
+ ACameraManager_delete(mCameraManager);
+ mCameraManager = nullptr;
+ }
+ }
+
+ bool takePictures(const char* id, uint64_t readerUsage, int readerMaxImages,
+ bool readerAsync, int pictureCount) {
+ int ret = 0;
+
+ ImageReaderTestCase testCase(
+ kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+ readerAsync);
+ ret = testCase.initImageReader();
+ if (ret < 0) {
+ ALOGE("Unable to initialize ImageReader");
+ return false;
+ }
+
+ CameraHelper cameraHelper(id, mCameraManager);
+ ret = cameraHelper.initCamera(testCase.getNativeWindow(), {});
+ if (ret < 0) {
+ ALOGE("Unable to initialize camera helper");
+ return false;
+ }
+
+ if (!cameraHelper.isCameraReady()) {
+ ALOGW("Camera is not ready after successful initialization. It's either due to camera "
+ "on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
+ "camera on board.");
+ return true;
+ }
+
+ for (int i = 0; i < pictureCount; i++) {
+ ret = cameraHelper.takePicture();
+ if (ret < 0) {
+ ALOGE("Unable to take picture");
+ return false;
+ }
+ }
+
+ // Sleep until all capture finished
+ for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
+ usleep(kCaptureWaitUs);
+ if (testCase.getAcquiredImageCount() == pictureCount) {
+ ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
+ pictureCount);
+ break;
+ }
+ }
+ return testCase.getAcquiredImageCount() == pictureCount &&
+ cameraHelper.checkCallbacks(pictureCount);
+ }
+
+ bool testTakePicturesNative(const char* id) {
+ for (auto& readerUsage :
+ {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
+ for (auto& readerMaxImages : {1, 4, 8}) {
+ for (auto& readerAsync : {true, false}) {
+ for (auto& pictureCount : {1, 4, 8}) {
+ if (!takePictures(id, readerUsage, readerMaxImages,
+ readerAsync, pictureCount)) {
+ ALOGE("Test takePictures failed for test case usage=%" PRIu64
+ ", maxImages=%d, async=%d, pictureCount=%d",
+ readerUsage, readerMaxImages, readerAsync, pictureCount);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ // Camera manager
+ ACameraManager* mCameraManager = nullptr;
+ ACameraIdList* mCameraIdList = nullptr;
+
+ bool isCapabilitySupported(ACameraMetadata* staticInfo,
+ acamera_metadata_enum_android_request_available_capabilities_t cap) {
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(
+ staticInfo, ACAMERA_REQUEST_AVAILABLE_CAPABILITIES, &entry);
+ for (uint32_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == cap) {
+ return true;
+ }
+ }
return false;
}
- CameraHelper cameraHelper(testCase.getNativeWindow());
- ret = cameraHelper.initCamera();
- if (ret < 0) {
- ALOGE("Unable to initialize camera helper");
+ bool isSizeSupportedForFormat(ACameraMetadata* staticInfo,
+ int32_t format, int32_t width, int32_t height) {
+ ACameraMetadata_const_entry entry;
+ ACameraMetadata_getConstEntry(staticInfo,
+ ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+ for (uint32_t i = 0; i < entry.count; i += 4) {
+ if (entry.data.i32[i] == format &&
+ entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ entry.data.i32[i+1] == width &&
+ entry.data.i32[i+2] == height) {
+ return true;
+ }
+ }
return false;
}
+ void findCandidateLogicalCamera(const char **cameraId,
+ ACameraMetadata** staticMetadata,
+ std::vector<const char*>* candidatePhysicalIds) {
+ // Find first available logical camera
+ for (int i = 0; i < mCameraIdList->numCameras; i++) {
+ camera_status_t ret;
+ ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, mCameraIdList->cameraIds[i], staticMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(*staticMetadata, nullptr);
+
+ if (!isCapabilitySupported(*staticMetadata,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA)) {
+ ACameraMetadata_free(*staticMetadata);
+ *staticMetadata = nullptr;
+ continue;
+ }
+
+ // Check returned physical camera Ids are valid
+ size_t physicalCameraIdCnt = 0;
+ const char*const* physicalCameraIds = nullptr;
+ bool isLogicalCamera = ACameraMetadata_isLogicalMultiCamera(*staticMetadata,
+ &physicalCameraIdCnt, &physicalCameraIds);
+ ASSERT_TRUE(isLogicalCamera);
+ ASSERT_GE(physicalCameraIdCnt, 2);
+ ACameraMetadata* physicalCameraMetadata = nullptr;
+ candidatePhysicalIds->clear();
+ for (size_t j = 0; j < physicalCameraIdCnt && candidatePhysicalIds->size() < 2; j++) {
+ ASSERT_GT(strlen(physicalCameraIds[j]), 0);
+ ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, physicalCameraIds[j], &physicalCameraMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(physicalCameraMetadata, nullptr);
+
+ if (isSizeSupportedForFormat(physicalCameraMetadata, kTestImageFormat,
+ kTestImageWidth, kTestImageHeight)) {
+ candidatePhysicalIds->push_back(physicalCameraIds[j]);
+ }
+ ACameraMetadata_free(physicalCameraMetadata);
+ }
+ if (candidatePhysicalIds->size() == 2) {
+ *cameraId = mCameraIdList->cameraIds[i];
+ return;
+ } else {
+ ACameraMetadata_free(*staticMetadata);
+ *staticMetadata = nullptr;
+ }
+ }
+ *cameraId = nullptr;
+ return;
+ }
+};
+
+TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
+ // We always use the first camera.
+ const char* cameraId = mCameraIdList->cameraIds[0];
+ ASSERT_TRUE(cameraId != nullptr);
+
+ ACameraMetadata* staticMetadata = nullptr;
+ camera_status_t ret = ACameraManager_getCameraCharacteristics(
+ mCameraManager, cameraId, &staticMetadata);
+ ASSERT_EQ(ret, ACAMERA_OK);
+ ASSERT_NE(staticMetadata, nullptr);
+
+ bool isBC = isCapabilitySupported(staticMetadata,
+ ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
+
+ ACameraMetadata_free(staticMetadata);
+
+ if (!isBC) {
+ ALOGW("Camera does not support BACKWARD_COMPATIBLE.");
+ return;
+ }
+
+ EXPECT_TRUE(testTakePicturesNative(cameraId));
+}
+
+TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
+ const char* cameraId = nullptr;
+ ACameraMetadata* staticMetadata = nullptr;
+ std::vector<const char*> physicalCameraIds;
+
+ findCandidateLogicalCamera(&cameraId, &staticMetadata, &physicalCameraIds);
+ if (cameraId == nullptr) {
+ // Couldn't find logical camera to test
+ return;
+ }
+
+ // Test streaming the logical multi-camera
+ uint64_t readerUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
+ int32_t readerMaxImages = 8;
+ bool readerAsync = false;
+ const int pictureCount = 6;
+ std::vector<ImageReaderTestCase*> testCases;
+ for (size_t i = 0; i < 3; i++) {
+ ImageReaderTestCase* testCase = new ImageReaderTestCase(
+ kTestImageWidth, kTestImageHeight, kTestImageFormat, readerUsage, readerMaxImages,
+ readerAsync);
+ ASSERT_EQ(testCase->initImageReader(), 0);
+ testCases.push_back(testCase);
+ }
+
+ CameraHelper cameraHelper(cameraId, mCameraManager);
+ std::vector<CameraHelper::PhysicalImgReaderInfo> physicalImgReaderInfo;
+ physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
+ physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
+
+ int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo);
+ ASSERT_EQ(ret, 0);
+
if (!cameraHelper.isCameraReady()) {
ALOGW("Camera is not ready after successful initialization. It's either due to camera on "
"board lacks BACKWARDS_COMPATIBLE capability or the device does not have camera on "
"board.");
- return true;
+ return;
}
for (int i = 0; i < pictureCount; i++) {
- ret = cameraHelper.takePicture();
- if (ret < 0) {
- ALOGE("Unable to take picture");
- return false;
- }
+ ret = cameraHelper.takeLogicalCameraPicture();
+ ASSERT_EQ(ret, 0);
}
// Sleep until all capture finished
for (int i = 0; i < kCaptureWaitRetry * pictureCount; i++) {
usleep(kCaptureWaitUs);
- if (testCase.getAcquiredImageCount() == pictureCount) {
+ if (testCases[0]->getAcquiredImageCount() == pictureCount) {
ALOGI("Session take ~%d ms to capture %d images", i * kCaptureWaitUs / 1000,
pictureCount);
break;
}
}
- return testCase.getAcquiredImageCount() == pictureCount &&
- cameraHelper.checkCallbacks(pictureCount);
-}
+ ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
+ ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+ ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
-class AImageReaderWindowHandleTest : public ::testing::Test {
- public:
- void SetUp() override {
- }
- void TearDown() override {
-
- }
-
-};
-
-bool testTakePicturesNative() {
- for (auto& readerUsage :
- {AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
- for (auto& readerMaxImages : {1, 4, 8}) {
- for (auto& readerAsync : {true, false}) {
- for (auto& pictureCount : {1, 4, 8}) {
- if (!takePictures(readerUsage, readerMaxImages, readerAsync, pictureCount)) {
- ALOGE("Test takePictures failed for test case usage=%" PRIu64 ", maxImages=%d, "
- "async=%d, pictureCount=%d",
- readerUsage, readerMaxImages, readerAsync, pictureCount);
- return false;
- }
- }
- }
- }
- }
- return true;
-}
-
-
-TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) {
- EXPECT_TRUE(testTakePicturesNative());
+ ACameraMetadata_free(staticMetadata);
}
} // namespace
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 7a10302..6eb2e9f 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -8,7 +8,7 @@
SineSource.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia libmedia_omx libmediaextractor libutils libbinder \
+ libstagefright libmedia libmedia_omx libutils libbinder \
libstagefright_foundation libjpeg libui libgui libcutils liblog \
libhidlbase \
android.hardware.media.omx@1.0 \
@@ -36,7 +36,7 @@
record.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia libmediaextractor liblog libutils libbinder \
+ libstagefright libmedia liblog libutils libbinder \
libstagefright_foundation
LOCAL_C_INCLUDES:= \
@@ -61,7 +61,7 @@
recordvideo.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia libmediaextractor liblog libutils libbinder \
+ libstagefright libmedia liblog libutils libbinder \
libstagefright_foundation
LOCAL_C_INCLUDES:= \
@@ -87,7 +87,7 @@
audioloop.cpp
LOCAL_SHARED_LIBRARIES := \
- libstagefright libmedia libmediaextractor liblog libutils libbinder \
+ libstagefright libmedia liblog libutils libbinder \
libstagefright_foundation
LOCAL_C_INCLUDES:= \
@@ -111,7 +111,7 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libui libgui \
- libstagefright_foundation libmedia libcutils libmediaextractor
+ libstagefright_foundation libmedia libcutils
LOCAL_C_INCLUDES:= \
frameworks/av/media/libstagefright \
@@ -203,7 +203,7 @@
LOCAL_SHARED_LIBRARIES := \
libstagefright liblog libutils libbinder libstagefright_foundation \
- libcutils libc libmediaextractor
+ libcutils libc
LOCAL_C_INCLUDES:= \
frameworks/av/media/libstagefright \
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 86e9040..34a9a40 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -224,11 +224,15 @@
player->setSource(rawSource);
rawSource.clear();
- player->start(true /* sourceAlreadyStarted */);
+ err = player->start(true /* sourceAlreadyStarted */);
- status_t finalStatus;
- while (!player->reachedEOS(&finalStatus)) {
- usleep(100000ll);
+ if (err == OK) {
+ status_t finalStatus;
+ while (!player->reachedEOS(&finalStatus)) {
+ usleep(100000ll);
+ }
+ } else {
+ fprintf(stderr, "unable to start playback err=%d (0x%08x)\n", err, err);
}
delete player;
@@ -651,7 +655,8 @@
MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9,
MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, MEDIA_MIMETYPE_VIDEO_HEVC,
- MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4
+ MEDIA_MIMETYPE_AUDIO_EAC3, MEDIA_MIMETYPE_AUDIO_AC4,
+ MEDIA_MIMETYPE_VIDEO_AV1
};
const char *codecType = queryDecoders? "decoder" : "encoder";
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 2532275..2600a2c 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -58,22 +58,26 @@
return drm_perm_labels[index];
}
-bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm) {
+bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm) {
if (selinux_enabled <= 0) {
return true;
}
- char *sctx;
+ char *sctx = NULL;
const char *selinux_class = "drmservice";
const char *str_perm = get_perm_label(perm);
- if (getpidcon(spid, &sctx) != 0) {
- ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid);
- return false;
+ if (ssid == NULL) {
+ android_errorWriteLog(0x534e4554, "121035042");
+
+ if (getpidcon(spid, &sctx) != 0) {
+ ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid);
+ return false;
+ }
}
- bool allowed = (selinux_check_access(sctx, drmserver_context, selinux_class,
- str_perm, NULL) == 0);
+ bool allowed = (selinux_check_access(ssid ? ssid : sctx, drmserver_context,
+ selinux_class, str_perm, NULL) == 0);
freecon(sctx);
return allowed;
@@ -86,10 +90,11 @@
IPCThreadState* ipcState = IPCThreadState::self();
uid_t uid = ipcState->getCallingUid();
pid_t spid = ipcState->getCallingPid();
+ const char* ssid = ipcState->getCallingSid();
for (unsigned int i = 0; i < trustedUids.size(); ++i) {
if (trustedUids[i] == uid) {
- return selinuxIsProtectedCallAllowed(spid, perm);
+ return selinuxIsProtectedCallAllowed(spid, ssid, perm);
}
}
return false;
@@ -97,7 +102,9 @@
void DrmManagerService::instantiate() {
ALOGV("instantiate");
- defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
+ sp<DrmManagerService> service = new DrmManagerService();
+ service->setRequestingSid(true);
+ defaultServiceManager()->addService(String16("drm.drmManager"), service);
if (0 >= trustedUids.size()) {
// TODO
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index 7aaeab5..2e27a3c 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -60,7 +60,7 @@
static const char *get_perm_label(drm_perm_t perm);
- static bool selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm);
+ static bool selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm);
static bool isProtectedCallAllowed(drm_perm_t perm);
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 28a78aa..bb9d7ec 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -29,8 +29,7 @@
srcs: ["src/FwdLockEngine.cpp"],
shared_libs: [
- "libicui18n",
- "libicuuc",
+ "libandroidicu",
"libutils",
"liblog",
"libdl",
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 3035c5a..4dda5d7 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -30,16 +30,16 @@
#include <media/stagefright/MediaErrors.h>
#include <mediadrm/CryptoHal.h>
+using drm::V1_0::BufferType;
+using drm::V1_0::DestinationBuffer;
+using drm::V1_0::ICryptoFactory;
+using drm::V1_0::ICryptoPlugin;
+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::drm::V1_0::BufferType;
-using ::android::hardware::drm::V1_0::DestinationBuffer;
-using ::android::hardware::drm::V1_0::ICryptoFactory;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::drm::V1_0::Mode;
-using ::android::hardware::drm::V1_0::Pattern;
-using ::android::hardware::drm::V1_0::SharedBuffer;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_memory;
@@ -50,6 +50,7 @@
using ::android::hidl::manager::V1_0::IServiceManager;
using ::android::sp;
+typedef drm::V1_2::Status Status_V1_2;
namespace android {
@@ -76,6 +77,18 @@
}
}
+static status_t toStatusT_1_2(Status_V1_2 status) {
+ switch (status) {
+ case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
+ return ERROR_DRM_SESSION_LOST_STATE;;
+ case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ default:
+ return toStatusT(static_cast<Status>(status));
+ }
+}
static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
hidl_vec<uint8_t> vec;
@@ -196,6 +209,9 @@
for (size_t i = 0; i < mFactories.size(); i++) {
if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
+ if (mPlugin != NULL) {
+ mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
+ }
}
}
@@ -216,6 +232,7 @@
}
mPlugin.clear();
+ mPluginV1_2.clear();
return OK;
}
@@ -389,21 +406,33 @@
status_t err = UNKNOWN_ERROR;
uint32_t bytesWritten = 0;
- Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode,
- hPattern, hSubSamples, hSource, offset, hDestination,
- [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
- if (status == Status::OK) {
- bytesWritten = hBytesWritten;
- *errorDetailMsg = toString8(hDetailedError);
- }
- err = toStatusT(status);
- }
- );
+ Return<void> hResult;
- if (!hResult.isOk()) {
- err = DEAD_OBJECT;
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv),
+ hMode, hPattern, hSubSamples, hSource, offset, hDestination,
+ [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+ if (status == Status_V1_2::OK) {
+ bytesWritten = hBytesWritten;
+ *errorDetailMsg = toString8(hDetailedError);
+ }
+ err = toStatusT_1_2(status);
+ }
+ );
+ } else {
+ hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv),
+ hMode, hPattern, hSubSamples, hSource, offset, hDestination,
+ [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
+ if (status == Status::OK) {
+ bytesWritten = hBytesWritten;
+ *errorDetailMsg = toString8(hDetailedError);
+ }
+ err = toStatusT(status);
+ }
+ );
}
+ err = hResult.isOk() ? err : DEAD_OBJECT;
if (err == OK) {
return bytesWritten;
}
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 14ff493..f4c0341 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -24,7 +24,7 @@
#include <binder/IServiceManager.h>
#include <android/hardware/drm/1.2/types.h>
-#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/ServiceManagement.h>
#include <media/EventMetric.h>
@@ -41,6 +41,7 @@
using drm::V1_0::KeyedVector;
using drm::V1_0::KeyStatusType;
+using drm::V1_0::KeyRequestType;
using drm::V1_0::KeyType;
using drm::V1_0::KeyValue;
using drm::V1_0::SecureStop;
@@ -60,6 +61,9 @@
using ::android::os::PersistableBundle;
using ::android::sp;
+typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
+typedef drm::V1_2::Status Status_V1_2;
+
namespace {
// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
@@ -239,7 +243,7 @@
return ERROR_DRM_CANNOT_HANDLE;
break;
case Status::ERROR_DRM_INVALID_STATE:
- return ERROR_DRM_TAMPER_DETECTED;
+ return ERROR_DRM_INVALID_STATE;
break;
case Status::BAD_VALUE:
return BAD_VALUE;
@@ -260,6 +264,19 @@
}
}
+static status_t toStatusT_1_2(Status_V1_2 status) {
+ switch (status) {
+ case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION:
+ return ERROR_DRM_RESOURCE_CONTENTION;
+ case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
+ return ERROR_DRM_FRAME_TOO_LARGE;
+ case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
+ return ERROR_DRM_INSUFFICIENT_SECURITY;
+ default:
+ return toStatusT(static_cast<Status>(status));
+ }
+}
+
Mutex DrmHal::mLock;
@@ -319,8 +336,11 @@
setListener(NULL);
mInitCheck = NO_INIT;
-
- if (mPlugin != NULL) {
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(NULL).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (mPlugin != NULL) {
if (!mPlugin->setListener(NULL).isOk()) {
mInitCheck = DEAD_OBJECT;
}
@@ -333,10 +353,10 @@
Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
Vector<sp<IDrmFactory>> factories;
- auto manager = hardware::defaultServiceManager();
+ auto manager = hardware::defaultServiceManager1_2();
if (manager != NULL) {
- manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
+ manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = drm::V1_0::IDrmFactory::getService(instance);
@@ -346,7 +366,7 @@
}
}
);
- manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
+ manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = drm::V1_1::IDrmFactory::getService(instance);
@@ -532,6 +552,22 @@
return Void();
}
+Return<void> DrmHal::sendSessionLostState(
+ const hidl_vec<uint8_t>& sessionId) {
+
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+ }
+ return Void();
+}
+
bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
Mutex::Autolock autoLock(mLock);
@@ -553,12 +589,14 @@
const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
- for (size_t i = 0; i < mFactories.size(); i++) {
+ for (size_t i = mFactories.size() - 1; i >= 0; i--) {
if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
- mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
- if (mPlugin != NULL) {
+ auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
+ if (plugin != NULL) {
+ mPlugin = plugin;
mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
+ break;
}
}
}
@@ -566,13 +604,22 @@
if (mPlugin == NULL) {
mInitCheck = ERROR_UNSUPPORTED;
} else {
- if (!mPlugin->setListener(this).isOk()) {
+ mInitCheck = OK;
+ if (mPluginV1_2 != NULL) {
+ if (!mPluginV1_2->setListener(this).isOk()) {
+ mInitCheck = DEAD_OBJECT;
+ }
+ } else if (!mPlugin->setListener(this).isOk()) {
mInitCheck = DEAD_OBJECT;
- } else {
- mInitCheck = OK;
+ }
+ if (mInitCheck != OK) {
+ mPlugin.clear();
+ mPluginV1_1.clear();
+ mPluginV1_2.clear();
}
}
+
return mInitCheck;
}
@@ -689,6 +736,39 @@
return DEAD_OBJECT;
}
+static DrmPlugin::KeyRequestType toKeyRequestType(
+ KeyRequestType keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType::INITIAL:
+ return DrmPlugin::kKeyRequestType_Initial;
+ break;
+ case KeyRequestType::RENEWAL:
+ return DrmPlugin::kKeyRequestType_Renewal;
+ break;
+ case KeyRequestType::RELEASE:
+ return DrmPlugin::kKeyRequestType_Release;
+ break;
+ default:
+ return DrmPlugin::kKeyRequestType_Unknown;
+ break;
+ }
+}
+
+static DrmPlugin::KeyRequestType toKeyRequestType_1_1(
+ KeyRequestType_V1_1 keyRequestType) {
+ switch (keyRequestType) {
+ case KeyRequestType_V1_1::NONE:
+ return DrmPlugin::kKeyRequestType_None;
+ break;
+ case KeyRequestType_V1_1::UPDATE:
+ return DrmPlugin::kKeyRequestType_Update;
+ break;
+ default:
+ return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType));
+ break;
+ }
+}
+
status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
Vector<uint8_t> const &initData, String8 const &mimeType,
DrmPlugin::KeyType keyType, KeyedVector<String8,
@@ -715,73 +795,51 @@
::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
- if (mPluginV1_1 != NULL) {
- Return<void> hResult =
- mPluginV1_1->getKeyRequest_1_1(
+ if (mPluginV1_2 != NULL) {
+ hResult = mPluginV1_2->getKeyRequest_1_2(
+ toHidlVec(sessionId), toHidlVec(initData),
+ toHidlString(mimeType), hKeyType, hOptionalParameters,
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType_V1_1 hKeyRequestType,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
+ }
+ err = toStatusT_1_2(status);
+ });
+ } else if (mPluginV1_1 != NULL) {
+ hResult = mPluginV1_1->getKeyRequest_1_1(
toHidlVec(sessionId), toHidlVec(initData),
toHidlString(mimeType), hKeyType, hOptionalParameters,
[&](Status status, const hidl_vec<uint8_t>& hRequest,
- drm::V1_1::KeyRequestType hKeyRequestType,
- const hidl_string& hDefaultUrl) {
-
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
-
- switch (hKeyRequestType) {
- case drm::V1_1::KeyRequestType::INITIAL:
- *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
- break;
- case drm::V1_1::KeyRequestType::RENEWAL:
- *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
- break;
- case drm::V1_1::KeyRequestType::RELEASE:
- *keyRequestType = DrmPlugin::kKeyRequestType_Release;
- break;
- case drm::V1_1::KeyRequestType::NONE:
- *keyRequestType = DrmPlugin::kKeyRequestType_None;
- break;
- case drm::V1_1::KeyRequestType::UPDATE:
- *keyRequestType = DrmPlugin::kKeyRequestType_Update;
- break;
- default:
- *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
- break;
- }
- err = toStatusT(status);
- }
- });
- return hResult.isOk() ? err : DEAD_OBJECT;
- }
-
- Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
- toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- drm::V1_0::KeyRequestType hKeyRequestType,
- const hidl_string& hDefaultUrl) {
-
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
-
- switch (hKeyRequestType) {
- case drm::V1_0::KeyRequestType::INITIAL:
- *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
- break;
- case drm::V1_0::KeyRequestType::RENEWAL:
- *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
- break;
- case drm::V1_0::KeyRequestType::RELEASE:
- *keyRequestType = DrmPlugin::kKeyRequestType_Release;
- break;
- default:
- *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
- break;
+ KeyRequestType_V1_1 hKeyRequestType,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType_1_1(hKeyRequestType);
}
err = toStatusT(status);
- }
- });
+ });
+ } else {
+ hResult = mPlugin->getKeyRequest(
+ toHidlVec(sessionId), toHidlVec(initData),
+ toHidlString(mimeType), hKeyType, hOptionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ KeyRequestType hKeyRequestType,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ *keyRequestType = toKeyRequestType(hKeyRequestType);
+ }
+ err = toStatusT(status);
+ });
+ }
err = hResult.isOk() ? err : DEAD_OBJECT;
keyRequestTimer.SetAttribute(err);
@@ -863,18 +921,33 @@
INIT_CHECK();
status_t err = UNKNOWN_ERROR;
+ Return<void> hResult;
- Return<void> hResult = mPlugin->getProvisionRequest(
- toHidlString(certType), toHidlString(certAuthority),
- [&](Status status, const hidl_vec<uint8_t>& hRequest,
- const hidl_string& hDefaultUrl) {
- if (status == Status::OK) {
- request = toVector(hRequest);
- defaultUrl = toString8(hDefaultUrl);
+ if (mPluginV1_2 != NULL) {
+ Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2(
+ toHidlString(certType), toHidlString(certAuthority),
+ [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status_V1_2::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT_1_2(status);
}
- err = toStatusT(status);
- }
- );
+ );
+ } else {
+ Return<void> hResult = mPlugin->getProvisionRequest(
+ toHidlString(certType), toHidlString(certAuthority),
+ [&](Status status, const hidl_vec<uint8_t>& hRequest,
+ const hidl_string& hDefaultUrl) {
+ if (status == Status::OK) {
+ request = toVector(hRequest);
+ defaultUrl = toString8(hDefaultUrl);
+ }
+ err = toStatusT(status);
+ }
+ );
+ }
err = hResult.isOk() ? err : DEAD_OBJECT;
mMetrics.mGetProvisionRequestCounter.Increment(err);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index a488f86..fc0cceb 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -42,10 +42,42 @@
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);
+ if (status == Status::OK) {
+ 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(
+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,
@@ -55,17 +87,17 @@
const SharedBuffer& source,
uint64_t offset,
const DestinationBuffer& destination,
- decrypt_cb _hidl_cb) {
+ decrypt_1_2_cb _hidl_cb) {
UNUSED(pattern);
if (secure) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"Secure decryption is not supported with ClearKey.");
return Void();
}
if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"source decrypt buffer base not set");
return Void();
}
@@ -73,7 +105,7 @@
if (destination.type == BufferType::SHARED_MEMORY) {
const SharedBuffer& dest = destination.nonsecureMemory;
if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"destination decrypt buffer base not set");
return Void();
}
@@ -81,12 +113,12 @@
sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
if (sourceBase == nullptr) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
return Void();
}
if (source.offset + offset + source.size > sourceBase->getSize()) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
@@ -98,12 +130,12 @@
const SharedBuffer& destBuffer = destination.nonsecureMemory;
sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
if (destBase == nullptr) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
return Void();
}
if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
@@ -128,7 +160,7 @@
if (mode == Mode::UNENCRYPTED) {
if (haveEncryptedSubsamples) {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"Encrypted subsamples found in allegedly unencrypted data.");
return Void();
}
@@ -144,22 +176,21 @@
}
}
- _hidl_cb(Status::OK, static_cast<ssize_t>(offset), "");
+ _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), "");
return Void();
} else if (mode == Mode::AES_CTR) {
size_t bytesDecrypted;
- Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
+ Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
- if (res == Status::OK) {
- _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), "");
+ if (res == Status_V1_2::OK) {
+ _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), "");
return Void();
} else {
- _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res),
- "Decryption Error");
+ _hidl_cb(res, 0, "Decryption Error");
return Void();
}
} else {
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
"Selected encryption mode is not supported by the ClearKey DRM Plugin.");
return Void();
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 7184b53..badb99e 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -61,15 +61,23 @@
namespace V1_2 {
namespace clearkey {
-using ::android::hardware::drm::V1_2::KeySetId;
-using ::android::hardware::drm::V1_2::OfflineLicenseState;
+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) {
+ mNextSecureStopId(kSecureStopIdStart),
+ mMockError(Status_V1_2::OK) {
mPlayPolicy.clear();
initProperties();
mSecureStops.clear();
@@ -84,6 +92,7 @@
mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
+ mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
std::vector<uint8_t> valueVector;
valueVector.clear();
@@ -112,6 +121,7 @@
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);
@@ -123,6 +133,7 @@
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);
@@ -138,6 +149,10 @@
sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
if (session.get()) {
+ if (session->getMockError() != Status_V1_2::OK) {
+ sendSessionLostState(sessionId);
+ return Status::ERROR_DRM_INVALID_STATE;
+ }
mCloseSessionOkCount++;
mSessionLibrary->destroySession(session);
return Status::OK;
@@ -146,13 +161,13 @@
return Status::ERROR_DRM_SESSION_NOT_OPENED;
}
-Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
+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 *keyRequestType,
+ KeyRequestType_V1_1 *keyRequestType,
std::string *defaultUrl) {
UNUSED(optionalParameters);
@@ -161,18 +176,18 @@
// 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::ERROR_DRM_CANNOT_HANDLE;
+ return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
}
*defaultUrl = "";
- *keyRequestType = KeyRequestType::UNKNOWN;
+ *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::BAD_VALUE;
+ return Status_V1_2::BAD_VALUE;
}
const std::vector<uint8_t> scopeId = toVector(scope);
@@ -181,12 +196,16 @@
std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
session = mSessionLibrary->findSession(sessionId);
if (!session.get()) {
- return Status::ERROR_DRM_SESSION_NOT_OPENED;
+ return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
+ } else if (session->getMockError() != Status_V1_2::OK) {
+ return session->getMockError();
}
- *keyRequestType = KeyRequestType::INITIAL;
+
+ *keyRequestType = KeyRequestType_V1_1::INITIAL;
}
- Status status = session->getKeyRequest(initData, mimeType, keyType, request);
+ 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());
@@ -198,7 +217,7 @@
DeviceFiles::kLicenseStateReleasing,
emptyResponse)) {
ALOGE("Problem releasing offline license");
- return Status::ERROR_DRM_UNKNOWN;
+ return Status_V1_2::ERROR_DRM_UNKNOWN;
}
if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
sp<Session> session = mSessionLibrary->createSession();
@@ -209,7 +228,7 @@
} else {
ALOGE("Offline license not found, nothing to release");
}
- *keyRequestType = KeyRequestType::RELEASE;
+ *keyRequestType = KeyRequestType_V1_1::RELEASE;
}
return status;
}
@@ -223,15 +242,15 @@
getKeyRequest_cb _hidl_cb) {
UNUSED(optionalParameters);
- KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
+ KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
std::string defaultUrl("");
std::vector<uint8_t> request;
- Status status = getKeyRequestCommon(
+ Status_V1_2 status = getKeyRequestCommon(
scope, initData, mimeType, keyType, optionalParameters,
&request, &keyRequestType, &defaultUrl);
- _hidl_cb(status, toHidlVec(request),
- static_cast<drm::V1_0::KeyRequestType>(keyRequestType),
+ _hidl_cb(toStatus_1_0(status), toHidlVec(request),
+ toKeyRequestType_V1_0(keyRequestType),
hidl_string(defaultUrl));
return Void();
}
@@ -245,10 +264,31 @@
getKeyRequest_1_1_cb _hidl_cb) {
UNUSED(optionalParameters);
- KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
+ KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
std::string defaultUrl("");
std::vector<uint8_t> request;
- Status status = getKeyRequestCommon(
+ 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);
@@ -434,6 +474,8 @@
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, "");
@@ -478,6 +520,16 @@
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;
+ }
+ }
+
mStringProperties[key] = std::string(value.c_str());
return Status::OK;
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
index f4c49b9..a9d7016 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
@@ -68,25 +68,30 @@
}
}
-Status Session::decrypt(
+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::ERROR_DRM_NO_LICENSE;
+ return Status_V1_2::ERROR_DRM_NO_LICENSE;
}
AesCtrDecryptor decryptor;
- return decryptor.decrypt(
+ Status status = decryptor.decrypt(
itr->second /*key*/, iv, srcPtr, destPtr, subSamples,
subSamples.size(), bytesDecryptedOut);
+ return static_cast<Status_V1_2>(status);
}
} // namespace clearkey
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
index f83903c..1bbc822 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
@@ -35,6 +35,11 @@
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 kDeviceIdKey("deviceId");
static const uint8_t kTestDeviceIdData[] =
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
index 7e9b6bd..2dafa36 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
@@ -17,7 +17,7 @@
#ifndef CLEARKEY_MACROS_H_
#define CLEARKEY_MACROS_H_
-#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/drm/1.2/types.h>
#include <map>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
index 480dc7e..8680f0c 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
@@ -17,7 +17,7 @@
#ifndef CLEARKEY_CRYPTO_PLUGIN_H_
#define CLEARKEY_CRYPTO_PLUGIN_H_
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include "ClearKeyTypes.h"
@@ -35,13 +35,14 @@
namespace V1_2 {
namespace clearkey {
-using ::android::hardware::drm::V1_0::DestinationBuffer;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::drm::V1_0::Mode;
-using ::android::hardware::drm::V1_0::Pattern;
-using ::android::hardware::drm::V1_0::SharedBuffer;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
+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;
@@ -51,7 +52,9 @@
using ::android::hidl::memory::V1_0::IMemory;
using ::android::sp;
-struct CryptoPlugin : public ICryptoPlugin {
+typedef drm::V1_2::Status Status_V1_2;
+
+struct CryptoPlugin : public drm::V1_2::ICryptoPlugin {
explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) {
mInitStatus = setMediaDrmSession(sessionId);
}
@@ -80,6 +83,18 @@
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);
+
Return<void> setSharedBufferBase(const hidl_memory& base,
uint32_t bufferId);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 256c5d6..a9b897b 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -18,6 +18,7 @@
#define CLEARKEY_DRM_PLUGIN_H_
#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
#include <map>
#include <stdio.h>
@@ -34,22 +35,24 @@
namespace V1_2 {
namespace clearkey {
-using ::android::hardware::drm::V1_0::EventType;
-using ::android::hardware::drm::V1_0::IDrmPluginListener;
-using ::android::hardware::drm::V1_0::KeyStatus;
-using ::android::hardware::drm::V1_0::KeyType;
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::SecureStop;
-using ::android::hardware::drm::V1_0::SecureStopId;
-using ::android::hardware::drm::V1_0::SessionId;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_1::DrmMetricGroup;
-using ::android::hardware::drm::V1_1::HdcpLevel;
-using ::android::hardware::drm::V1_1::KeyRequestType;
-using ::android::hardware::drm::V1_1::SecureStopRelease;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::drm::V1_2::IDrmPlugin;
-using ::android::hardware::drm::V1_2::OfflineLicenseState;
+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::IDrmPlugin;
+using drm::V1_2::KeySetId;
+using drm::V1_2::OfflineLicenseState;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -57,6 +60,10 @@
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::Status Status_V1_2;
+
struct DrmPlugin : public IDrmPlugin {
explicit DrmPlugin(SessionLibrary* sessionLibrary);
@@ -84,6 +91,14 @@
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,
@@ -116,6 +131,18 @@
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) {
@@ -256,12 +283,17 @@
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,
+ Return<void> sendEvent(
+ EventType eventType,
+ const hidl_vec<uint8_t>& sessionId,
const hidl_vec<uint8_t>& data) {
- if (mListener != NULL) {
+ 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");
@@ -269,8 +301,12 @@
return Void();
}
- Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
- if (mListener != NULL) {
+ 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");
@@ -278,9 +314,12 @@
return Void();
}
- Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ Return<void> sendKeysChange(
+ const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
- if (mListener != NULL) {
+ 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");
@@ -288,6 +327,14 @@
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,
@@ -314,13 +361,13 @@
Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
SecurityLevel level);
- Status getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
+ 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 *getKeyRequestType,
+ KeyRequestType_V1_1 *getKeyRequestType,
std::string *defaultUrl);
struct ClearkeySecureStop {
@@ -335,12 +382,21 @@
std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
sp<IDrmPluginListener> mListener;
+ sp<IDrmPluginListener_V1_2> mListenerV1_2;
SessionLibrary *mSessionLibrary;
int64_t mOpenSessionOkCount;
int64_t mCloseSessionOkCount;
int64_t mCloseSessionNotOpenedCount;
uint32_t mNextSecureStopId;
+ // 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;
CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
index f35560d..a159e5a 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
@@ -30,13 +30,16 @@
namespace V1_2 {
namespace clearkey {
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
+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) {}
+ : mSessionId(sessionId), mMockError(Status_V1_2::OK) {}
virtual ~Session() {}
const std::vector<uint8_t>& sessionId() const { return mSessionId; }
@@ -50,17 +53,23 @@
Status provideKeyResponse(
const std::vector<uint8_t>& response);
- Status decrypt(
+ 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
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
index f6d30c9..b0f8607 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
@@ -68,6 +68,17 @@
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_2
} // namespace drm
diff --git a/include/media/DataSource.h b/include/media/DataSource.h
index 905bec1..198b27e 120000
--- a/include/media/DataSource.h
+++ b/include/media/DataSource.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/DataSource.h
\ No newline at end of file
+stagefright/DataSource.h
\ No newline at end of file
diff --git a/include/media/DataSourceBase.h b/include/media/DataSourceBase.h
index 54c8047..d2ab2f1 120000
--- a/include/media/DataSourceBase.h
+++ b/include/media/DataSourceBase.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/DataSourceBase.h
\ No newline at end of file
+stagefright/DataSourceBase.h
\ No newline at end of file
diff --git a/include/media/ExtractorUtils.h b/include/media/ExtractorUtils.h
deleted file mode 120000
index e2dd082..0000000
--- a/include/media/ExtractorUtils.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmediaextractor/include/media/ExtractorUtils.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/ExtractorUtils.h b/include/media/ExtractorUtils.h
similarity index 100%
rename from media/libmediaextractor/include/media/ExtractorUtils.h
rename to include/media/ExtractorUtils.h
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index 854bf83..916472c 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -135,8 +135,16 @@
const char *extractor_name;
union {
- SnifferFunc v2;
- } sniff;
+ struct {
+ SnifferFunc sniff;
+ } v2;
+ struct {
+ SnifferFunc sniff;
+ // a NULL terminated list of container mime types and/or file extensions
+ // that this extractor supports
+ const char **supported_types;
+ } v3;
+ } u;
};
// the C++ based API which first shipped in P and is no longer supported
@@ -145,7 +153,10 @@
// the first C/NDK based API
const uint32_t EXTRACTORDEF_VERSION_NDK_V1 = 2;
-const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V1;
+// the second C/NDK based API
+const uint32_t EXTRACTORDEF_VERSION_NDK_V2 = 3;
+
+const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_NDK_V2;
// each plugin library exports one function of this type
typedef ExtractorDef (*GetExtractorDef)();
diff --git a/include/media/MediaSource.h b/include/media/MediaSource.h
index 2e147c4..34bf65d 120000
--- a/include/media/MediaSource.h
+++ b/include/media/MediaSource.h
@@ -1 +1 @@
-../../media/libmediaextractor/include/media/MediaSource.h
\ No newline at end of file
+../../media/libstagefright/include/media/stagefright/MediaSource.h
\ No newline at end of file
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index f1e815b..dfb1a3f 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -16,3 +16,6 @@
stop audioserver
on property:vts.native_server.on=0
start audioserver
+
+on init
+ mkdir /dev/socket/audioserver 0775 audioserver audioserver
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index aeefbdb..87730ae 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -468,7 +468,8 @@
if (outargs.numOutBytes > 0) {
mInputSize = 0;
- int consumed = ((capacity / sizeof(int16_t)) - inargs.numInSamples);
+ int consumed = (capacity / sizeof(int16_t)) - inargs.numInSamples
+ + outargs.numInSamples;
mInputTimeUs = work->input.ordinal.timestamp
+ (consumed * 1000000ll / channelCount / sampleRate);
buffer = createLinearBuffer(block, 0, outargs.numOutBytes);
diff --git a/media/codec2/components/aom/Android.bp b/media/codec2/components/aom/Android.bp
new file mode 100644
index 0000000..0fabf5c
--- /dev/null
+++ b/media/codec2/components/aom/Android.bp
@@ -0,0 +1,14 @@
+cc_library_shared {
+ name: "libcodec2_soft_av1dec",
+ defaults: [
+ "libcodec2_soft-defaults",
+ "libcodec2_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["C2SoftAomDec.cpp"],
+ static_libs: ["libaom"],
+
+ include_dirs: [
+ "external/libaom/",
+ ],
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
new file mode 100644
index 0000000..6be1807
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -0,0 +1,750 @@
+/*
+ * 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 "C2SoftAomDec"
+#include <log/log.h>
+
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <SimpleC2Interface.h>
+
+#include "C2SoftAomDec.h"
+
+namespace android {
+
+constexpr char COMPONENT_NAME[] = "c2.android.av1.decoder";
+
+class C2SoftAomDec::IntfImpl : public SimpleInterface<void>::BaseParams {
+ public:
+ explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
+ : SimpleInterface<void>::BaseParams(
+ helper, COMPONENT_NAME, C2Component::KIND_DECODER,
+ C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
+ noPrivateBuffers(); // TODO: account for our buffers here
+ noInputReferences();
+ noOutputReferences();
+ noInputLatency();
+ noTimeStretch();
+
+ addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
+ .withConstValue(new C2ComponentAttributesSetting(
+ C2Component::ATTRIB_IS_TEMPORAL))
+ .build());
+
+ addParameter(
+ DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
+ .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
+ .withFields({
+ C2F(mSize, width).inRange(2, 2048, 2),
+ C2F(mSize, height).inRange(2, 2048, 2),
+ })
+ .withSetter(SizeSetter)
+ .build());
+
+ addParameter(
+ DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+ .withDefault(new C2StreamProfileLevelInfo::input(0u,
+ C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
+ .withFields({
+ C2F(mProfileLevel, profile).oneOf({
+ C2Config::PROFILE_AV1_0,
+ C2Config::PROFILE_AV1_1}),
+ C2F(mProfileLevel, level).oneOf({
+ C2Config::LEVEL_AV1_2,
+ C2Config::LEVEL_AV1_2_1,
+ C2Config::LEVEL_AV1_2_2,
+ C2Config::LEVEL_AV1_3,
+ C2Config::LEVEL_AV1_3_1,
+ C2Config::LEVEL_AV1_3_2,
+ })
+ })
+ .withSetter(ProfileLevelSetter, mSize)
+ .build());
+
+ addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
+ .withDefault(new C2StreamMaxPictureSizeTuning::output(
+ 0u, 320, 240))
+ .withFields({
+ C2F(mSize, width).inRange(2, 2048, 2),
+ C2F(mSize, height).inRange(2, 2048, 2),
+ })
+ .withSetter(MaxPictureSizeSetter, mSize)
+ .build());
+
+ addParameter(
+ DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
+ .withDefault(
+ new C2StreamMaxBufferSizeInfo::input(0u, 320 * 240 * 3 / 4))
+ .withFields({
+ C2F(mMaxInputSize, value).any(),
+ })
+ .calculatedAs(MaxInputSizeSetter, mMaxSize)
+ .build());
+
+ C2ChromaOffsetStruct locations[1] = {
+ C2ChromaOffsetStruct::ITU_YUV_420_0()};
+ std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
+ C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
+ memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
+
+ defaultColorInfo = C2StreamColorInfo::output::AllocShared(
+ {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
+ C2Color::YUV_420);
+ helper->addStructDescriptors<C2ChromaOffsetStruct>();
+
+ addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
+ .withConstValue(defaultColorInfo)
+ .build());
+
+ addParameter(
+ DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
+ .withDefault(new C2StreamColorAspectsTuning::output(
+ 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+ .withFields({
+ C2F(mDefaultColorAspects, range).inRange(
+ C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+ C2F(mDefaultColorAspects, primaries).inRange(
+ C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
+ C2F(mDefaultColorAspects, transfer).inRange(
+ C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
+ C2F(mDefaultColorAspects, matrix).inRange(
+ C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
+ })
+ .withSetter(DefaultColorAspectsSetter)
+ .build());
+
+ // TODO: support more formats?
+ addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
+ .withConstValue(new C2StreamPixelFormatInfo::output(
+ 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
+ .build());
+ }
+
+ static C2R SizeSetter(bool mayBlock,
+ const C2P<C2StreamPictureSizeInfo::output>& oldMe,
+ C2P<C2VideoSizeStreamInfo::output>& me) {
+ (void)mayBlock;
+ C2R res = C2R::Ok();
+ if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+ res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+ me.set().width = oldMe.v.width;
+ }
+ if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+ res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
+ me.set().height = oldMe.v.height;
+ }
+ return res;
+ }
+
+ static C2R MaxPictureSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
+ const C2P<C2StreamPictureSizeInfo::output>& size) {
+ (void)mayBlock;
+ // TODO: get max width/height from the size's field helpers vs.
+ // hardcoding
+ me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
+ me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
+ return C2R::Ok();
+ }
+
+ static C2R MaxInputSizeSetter(
+ bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
+ const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
+ (void)mayBlock;
+ // assume compression ratio of 2
+ me.set().value = (((maxSize.v.width + 63) / 64) *
+ ((maxSize.v.height + 63) / 64) * 3072);
+ return C2R::Ok();
+ }
+ static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
+ (void)mayBlock;
+ if (me.v.range > C2Color::RANGE_OTHER) {
+ me.set().range = C2Color::RANGE_OTHER;
+ }
+ if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+ me.set().primaries = C2Color::PRIMARIES_OTHER;
+ }
+ if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+ me.set().transfer = C2Color::TRANSFER_OTHER;
+ }
+ if (me.v.matrix > C2Color::MATRIX_OTHER) {
+ me.set().matrix = C2Color::MATRIX_OTHER;
+ }
+ return C2R::Ok();
+ }
+
+ static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
+ const C2P<C2StreamPictureSizeInfo::output> &size) {
+ (void)mayBlock;
+ (void)size;
+ (void)me; // TODO: validate
+ return C2R::Ok();
+ }
+ std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
+ return mDefaultColorAspects;
+ }
+
+ private:
+ std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
+ std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
+ std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
+ std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
+ std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
+ std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+ std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+};
+
+C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
+ const std::shared_ptr<IntfImpl>& intfImpl)
+ : SimpleC2Component(
+ std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
+ mIntf(intfImpl),
+ mCodecCtx(nullptr){
+
+ GENERATE_FILE_NAMES();
+ CREATE_DUMP_FILE(mInFile);
+ CREATE_DUMP_FILE(mOutFile);
+
+ gettimeofday(&mTimeStart, nullptr);
+ gettimeofday(&mTimeEnd, nullptr);
+}
+
+C2SoftAomDec::~C2SoftAomDec() {
+ onRelease();
+}
+
+c2_status_t C2SoftAomDec::onInit() {
+ status_t err = initDecoder();
+ return err == OK ? C2_OK : C2_CORRUPTED;
+}
+
+c2_status_t C2SoftAomDec::onStop() {
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+ return C2_OK;
+}
+
+void C2SoftAomDec::onReset() {
+ (void)onStop();
+ c2_status_t err = onFlush_sm();
+ if (err != C2_OK) {
+ ALOGW("Failed to flush decoder. Try to hard reset decoder.");
+ destroyDecoder();
+ (void)initDecoder();
+ }
+}
+
+void C2SoftAomDec::onRelease() {
+ destroyDecoder();
+}
+
+c2_status_t C2SoftAomDec::onFlush_sm() {
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ return C2_CORRUPTED;
+ }
+
+ aom_codec_iter_t iter = nullptr;
+ while (aom_codec_get_frame(mCodecCtx, &iter)) {
+ }
+
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+
+ return C2_OK;
+}
+
+static int GetCPUCoreCount() {
+ int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+ CHECK(cpuCoreCount >= 1);
+ ALOGV("Number of CPU cores: %d", cpuCoreCount);
+ return cpuCoreCount;
+}
+
+status_t C2SoftAomDec::initDecoder() {
+ mSignalledError = false;
+ mSignalledOutputEos = false;
+ if (!mCodecCtx) {
+ mCodecCtx = new aom_codec_ctx_t;
+ }
+
+ if (!mCodecCtx) {
+ ALOGE("mCodecCtx is null");
+ return NO_MEMORY;
+ }
+
+ aom_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t));
+ cfg.threads = GetCPUCoreCount();
+ cfg.allow_lowbitdepth = 1;
+
+ aom_codec_flags_t flags;
+ memset(&flags, 0, sizeof(aom_codec_flags_t));
+
+ aom_codec_err_t err;
+ if ((err = aom_codec_dec_init(mCodecCtx, aom_codec_av1_dx(), &cfg, 0))) {
+ ALOGE("av1 decoder failed to initialize. (%d)", err);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+status_t C2SoftAomDec::destroyDecoder() {
+ if (mCodecCtx) {
+ aom_codec_destroy(mCodecCtx);
+ delete mCodecCtx;
+ mCodecCtx = nullptr;
+ }
+ return OK;
+}
+
+void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
+ uint32_t flags = 0;
+ if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ ALOGV("signalling eos");
+ }
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+}
+
+void C2SoftAomDec::finishWork(uint64_t index,
+ const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2GraphicBlock>& block) {
+ std::shared_ptr<C2Buffer> buffer =
+ createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+ auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {
+ uint32_t flags = 0;
+ if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
+ (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ ALOGV("signalling eos");
+ }
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.buffers.push_back(buffer);
+ work->worklets.front()->output.ordinal = work->input.ordinal;
+ work->workletsProcessed = 1u;
+ };
+ if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
+ fillWork(work);
+ } else {
+ finish(index, fillWork);
+ }
+}
+
+void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2BlockPool>& pool) {
+ work->result = C2_OK;
+ work->workletsProcessed = 0u;
+ work->worklets.front()->output.configUpdate.clear();
+ work->worklets.front()->output.flags = work->input.flags;
+ if (mSignalledError || mSignalledOutputEos) {
+ work->result = C2_BAD_VALUE;
+ return;
+ }
+
+ size_t inOffset = 0u;
+ size_t inSize = 0u;
+ C2ReadView rView = mDummyReadView;
+ if (!work->input.buffers.empty()) {
+ rView =
+ work->input.buffers[0]->data().linearBlocks().front().map().get();
+ inSize = rView.capacity();
+ if (inSize && rView.error()) {
+ ALOGE("read view map failed %d", rView.error());
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ }
+
+ bool codecConfig =
+ ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
+ bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
+
+ ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
+ inSize, (int)work->input.ordinal.timestamp.peeku(),
+ (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
+
+ if (codecConfig) {
+ fillEmptyWork(work);
+ return;
+ }
+
+ int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
+ if (inSize) {
+ uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
+ int32_t decodeTime = 0;
+ int32_t delay = 0;
+
+ DUMP_TO_FILE(mOutFile, bitstream, inSize);
+ GETTIME(&mTimeStart, nullptr);
+ TIME_DIFF(mTimeEnd, mTimeStart, delay);
+
+ aom_codec_err_t err =
+ aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
+
+ GETTIME(&mTimeEnd, nullptr);
+ TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
+ ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
+
+ if (err != AOM_CODEC_OK) {
+ ALOGE("av1 decoder failed to decode frame err: %d", err);
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ mSignalledError = true;
+ return;
+ }
+
+ } else {
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ mSignalledError = true;
+ return;
+ }
+ }
+
+ (void)outputBuffer(pool, work);
+
+ if (eos) {
+ drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+ mSignalledOutputEos = true;
+ } else if (!inSize) {
+ fillEmptyWork(work);
+ }
+}
+
+static void copyOutputBufferToYV12Frame(uint8_t *dst,
+ const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ uint32_t width, uint32_t height) {
+ size_t dstYStride = align(width, 16);
+ size_t dstUVStride = align(dstYStride / 2, 16);
+ uint8_t* dstStart = dst;
+
+
+ for (size_t i = 0; i < height; ++i) {
+ memcpy(dst, srcY, width);
+ srcY += srcYStride;
+ dst += dstYStride;
+ }
+
+ dst = dstStart + dstYStride * height;
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dst, srcV, width / 2);
+ srcV += srcVStride;
+ dst += dstUVStride;
+ }
+
+ dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dst, srcU, width / 2);
+ srcU += srcUStride;
+ dst += dstUVStride;
+ }
+}
+
+static void convertYUV420Planar16ToY410(uint32_t *dst,
+ const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ size_t dstStride, size_t width, size_t height) {
+
+ // Converting two lines at a time, slightly faster
+ for (size_t y = 0; y < height; y += 2) {
+ uint32_t *dstTop = (uint32_t *) dst;
+ uint32_t *dstBot = (uint32_t *) (dst + dstStride);
+ uint16_t *ySrcTop = (uint16_t*) srcY;
+ uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
+ uint16_t *uSrc = (uint16_t*) srcU;
+ uint16_t *vSrc = (uint16_t*) srcV;
+
+ uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
+ size_t x = 0;
+ for (; x < width - 3; x += 4) {
+
+ u01 = *((uint32_t*)uSrc); uSrc += 2;
+ v01 = *((uint32_t*)vSrc); vSrc += 2;
+
+ y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+ y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
+ y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+ y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
+
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
+
+ *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
+ *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
+
+ *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
+ *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
+ }
+
+ // There should be at most 2 more pixels to process. Note that we don't
+ // need to consider odd case as the buffer is always aligned to even.
+ if (x < width) {
+ u01 = *uSrc;
+ v01 = *vSrc;
+ y01 = *((uint32_t*)ySrcTop);
+ y45 = *((uint32_t*)ySrcBot);
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = ((y01 >> 16) << 10) | uv0;
+ *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = ((y45 >> 16) << 10) | uv0;
+ }
+
+ srcY += srcYStride * 2;
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dst += dstStride * 2;
+ }
+
+ return;
+}
+
+static void convertYUV420Planar16ToYUV420Planar(uint8_t *dst,
+ const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
+ size_t srcYStride, size_t srcUStride, size_t srcVStride,
+ size_t dstStride, size_t width, size_t height) {
+
+ uint8_t *dstY = (uint8_t *)dst;
+ size_t dstYSize = dstStride * height;
+ size_t dstUVStride = align(dstStride / 2, 16);
+ size_t dstUVSize = dstUVStride * height / 2;
+ uint8_t *dstV = dstY + dstYSize;
+ uint8_t *dstU = dstV + dstUVSize;
+
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = (uint8_t)(srcY[x] >> 2);
+ }
+
+ srcY += srcYStride;
+ dstY += dstStride;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstU[x] = (uint8_t)(srcU[x] >> 2);
+ dstV[x] = (uint8_t)(srcV[x] >> 2);
+ }
+
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstU += dstUVStride;
+ dstV += dstUVStride;
+ }
+ return;
+}
+bool C2SoftAomDec::outputBuffer(
+ const std::shared_ptr<C2BlockPool> &pool,
+ const std::unique_ptr<C2Work> &work)
+{
+ if (!(work && pool)) return false;
+
+ aom_codec_iter_t iter = nullptr;
+ aom_image_t* img = aom_codec_get_frame(mCodecCtx, &iter);
+
+ if (!img) return false;
+
+ if (img->d_w != mWidth || img->d_h != mHeight) {
+ mWidth = img->d_w;
+ mHeight = img->d_h;
+
+ C2VideoSizeStreamInfo::output size(0u, mWidth, mHeight);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+ if (err == C2_OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(size));
+ } else {
+ ALOGE("Config update size failed");
+ mSignalledError = true;
+ work->result = C2_CORRUPTED;
+ work->workletsProcessed = 1u;
+ return false;
+ }
+ }
+
+ CHECK(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I42016);
+
+ std::shared_ptr<C2GraphicBlock> block;
+ uint32_t format = HAL_PIXEL_FORMAT_YV12;
+ if (img->fmt == AOM_IMG_FMT_I42016) {
+ IntfImpl::Lock lock = mIntf->lock();
+ std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects = mIntf->getDefaultColorAspects_l();
+
+ if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+ defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+ defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+ format = HAL_PIXEL_FORMAT_RGBA_1010102;
+ }
+ }
+ C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+ c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight,
+ format, usage, &block);
+
+ if (err != C2_OK) {
+ ALOGE("fetchGraphicBlock for Output failed with status %d", err);
+ work->result = err;
+ return false;
+ }
+
+ C2GraphicView wView = block->map().get();
+
+ if (wView.error()) {
+ ALOGE("graphic view map failed %d", wView.error());
+ work->result = C2_CORRUPTED;
+ return false;
+ }
+
+ ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
+ block->width(), block->height(), mWidth, mHeight,
+ (int)*(int64_t*)img->user_priv);
+
+ uint8_t* dst = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
+ size_t srcYStride = img->stride[AOM_PLANE_Y];
+ size_t srcUStride = img->stride[AOM_PLANE_U];
+ size_t srcVStride = img->stride[AOM_PLANE_V];
+
+ if (img->fmt == AOM_IMG_FMT_I42016) {
+ const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
+ const uint16_t *srcU = (const uint16_t *)img->planes[AOM_PLANE_U];
+ const uint16_t *srcV = (const uint16_t *)img->planes[AOM_PLANE_V];
+
+ if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
+ convertYUV420Planar16ToY410((uint32_t *)dst, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2,
+ align(mWidth, 16),
+ mWidth, mHeight);
+ } else {
+ convertYUV420Planar16ToYUV420Planar(dst, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2,
+ align(mWidth, 16),
+ mWidth, mHeight);
+ }
+ } else {
+ const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
+ const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
+ const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
+ copyOutputBufferToYV12Frame(dst, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, mWidth, mHeight);
+ }
+ finishWork(*(int64_t*)img->user_priv, work, std::move(block));
+ block = nullptr;
+ return true;
+}
+
+c2_status_t C2SoftAomDec::drainInternal(
+ uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work) {
+ if (drainMode == NO_DRAIN) {
+ ALOGW("drain with NO_DRAIN: no-op");
+ return C2_OK;
+ }
+ if (drainMode == DRAIN_CHAIN) {
+ ALOGW("DRAIN_CHAIN not supported");
+ return C2_OMITTED;
+ }
+
+ if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
+ ALOGE("Failed to flush av1 decoder.");
+ return C2_CORRUPTED;
+ }
+
+ while ((outputBuffer(pool, work))) {
+ }
+
+ if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
+ work->workletsProcessed == 0u) {
+ fillEmptyWork(work);
+ }
+
+ return C2_OK;
+}
+
+c2_status_t C2SoftAomDec::drain(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool) {
+ return drainInternal(drainMode, pool, nullptr);
+}
+
+class C2SoftAomFactory : public C2ComponentFactory {
+ public:
+ C2SoftAomFactory()
+ : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+ GetCodec2PlatformComponentStore()->getParamReflector())) {}
+
+ virtual c2_status_t createComponent(
+ c2_node_id_t id, std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(
+ new C2SoftAomDec(COMPONENT_NAME, id,
+ std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+ deleter);
+ return C2_OK;
+ }
+
+ virtual c2_status_t createInterface(
+ c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = std::shared_ptr<C2ComponentInterface>(
+ new SimpleInterface<C2SoftAomDec::IntfImpl>(
+ COMPONENT_NAME, id,
+ std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
+ deleter);
+ return C2_OK;
+ }
+
+ virtual ~C2SoftAomFactory() override = default;
+
+ private:
+ std::shared_ptr<C2ReflectorHelper> mHelper;
+};
+
+} // namespace android
+
+extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
+ ALOGV("in %s", __func__);
+ return new ::android::C2SoftAomFactory();
+}
+
+extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
+ ALOGV("in %s", __func__);
+ delete factory;
+}
diff --git a/media/codec2/components/aom/C2SoftAomDec.h b/media/codec2/components/aom/C2SoftAomDec.h
new file mode 100644
index 0000000..4c82647
--- /dev/null
+++ b/media/codec2/components/aom/C2SoftAomDec.h
@@ -0,0 +1,137 @@
+/*
+ * 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 ANDROID_C2_SOFT_AV1_DEC_H_
+#define ANDROID_C2_SOFT_AV1_DEC_H_
+
+#include <SimpleC2Component.h>
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
+
+#define GETTIME(a, b) gettimeofday(a, b);
+#define TIME_DIFF(start, end, diff) \
+ diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
+ ((end).tv_usec - (start).tv_usec);
+
+namespace android {
+
+struct C2SoftAomDec : public SimpleC2Component {
+ class IntfImpl;
+
+ C2SoftAomDec(const char* name, c2_node_id_t id,
+ const std::shared_ptr<IntfImpl>& intfImpl);
+ virtual ~C2SoftAomDec();
+
+ // From SimpleC2Component
+ c2_status_t onInit() override;
+ c2_status_t onStop() override;
+ void onReset() override;
+ void onRelease() override;
+ c2_status_t onFlush_sm() override;
+ void process(const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2BlockPool>& pool) override;
+ c2_status_t drain(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool) override;
+
+ private:
+ std::shared_ptr<IntfImpl> mIntf;
+ aom_codec_ctx_t* mCodecCtx;
+
+ uint32_t mWidth;
+ uint32_t mHeight;
+ bool mSignalledOutputEos;
+ bool mSignalledError;
+
+ #ifdef FILE_DUMP_ENABLE
+ char mInFile[200];
+ char mOutFile[200];
+ #endif /* FILE_DUMP_ENABLE */
+
+ struct timeval mTimeStart; // Time at the start of decode()
+ struct timeval mTimeEnd; // Time at the end of decode()
+
+ status_t initDecoder();
+ status_t destroyDecoder();
+ void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
+ const std::shared_ptr<C2GraphicBlock>& block);
+ bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work);
+
+ c2_status_t drainInternal(uint32_t drainMode,
+ const std::shared_ptr<C2BlockPool>& pool,
+ const std::unique_ptr<C2Work>& work);
+
+ C2_DO_NOT_COPY(C2SoftAomDec);
+};
+
+#ifdef FILE_DUMP_ENABLE
+
+#define INPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define INPUT_DUMP_EXT "webm"
+#define OUTPUT_DUMP_PATH "/data/local/tmp/temp/av1"
+#define OUTPUT_DUMP_EXT "av1"
+#define GENERATE_FILE_NAMES() \
+ { \
+ GETTIME(&mTimeStart, NULL); \
+ strcpy(mInFile, ""); \
+ ALOGD("GENERATE_FILE_NAMES"); \
+ sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, mTimeStart.tv_sec, \
+ mTimeStart.tv_usec, INPUT_DUMP_EXT); \
+ strcpy(mOutFile, ""); \
+ sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH, \
+ mTimeStart.tv_sec, mTimeStart.tv_usec, OUTPUT_DUMP_EXT); \
+ }
+
+#define CREATE_DUMP_FILE(m_filename) \
+ { \
+ FILE* fp = fopen(m_filename, "wb"); \
+ if (fp != NULL) { \
+ ALOGD("Opened file %s", m_filename); \
+ fclose(fp); \
+ } else { \
+ ALOGD("Could not open file %s", m_filename); \
+ } \
+ }
+#define DUMP_TO_FILE(m_filename, m_buf, m_size) \
+ { \
+ FILE* fp = fopen(m_filename, "ab"); \
+ if (fp != NULL && m_buf != NULL) { \
+ int i; \
+ ALOGD("Dump to file!"); \
+ i = fwrite(m_buf, 1, m_size, fp); \
+ if (i != (int)m_size) { \
+ ALOGD("Error in fwrite, returned %d", i); \
+ perror("Error in write to file"); \
+ } \
+ fclose(fp); \
+ } else { \
+ ALOGD("Could not write to file %s", m_filename); \
+ if (fp != NULL) fclose(fp); \
+ } \
+ }
+#else /* FILE_DUMP_ENABLE */
+#define INPUT_DUMP_PATH
+#define INPUT_DUMP_EXT
+#define OUTPUT_DUMP_PATH
+#define OUTPUT_DUMP_EXT
+#define GENERATE_FILE_NAMES()
+#define CREATE_DUMP_FILE(m_filename)
+#define DUMP_TO_FILE(m_filename, m_buf, m_size)
+#endif /* FILE_DUMP_ENABLE */
+
+} // namespace android
+
+#endif // ANDROID_C2_SOFT_AV1_DEC_H_
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 50b4d20..b8baec8 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -132,6 +132,56 @@
}
}
+class SimpleC2Component::BlockingBlockPool : public C2BlockPool {
+public:
+ BlockingBlockPool(const std::shared_ptr<C2BlockPool>& base): mBase{base} {}
+
+ virtual local_id_t getLocalId() const override {
+ return mBase->getLocalId();
+ }
+
+ virtual C2Allocator::id_t getAllocatorId() const override {
+ return mBase->getAllocatorId();
+ }
+
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchLinearBlock(capacity, usage, block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+ virtual c2_status_t fetchCircularBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2CircularBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchCircularBlock(capacity, usage, block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width, uint32_t height, uint32_t format,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicBlock>* block) {
+ c2_status_t status;
+ do {
+ status = mBase->fetchGraphicBlock(width, height, format, usage,
+ block);
+ } while (status == C2_TIMED_OUT);
+ return status;
+ }
+
+private:
+ std::shared_ptr<C2BlockPool> mBase;
+};
+
////////////////////////////////////////////////////////////////////////////////
namespace {
@@ -446,12 +496,16 @@
}
}
- err = GetCodec2BlockPool(poolId, shared_from_this(), &mOutputBlockPool);
+ std::shared_ptr<C2BlockPool> blockPool;
+ err = GetCodec2BlockPool(poolId, shared_from_this(), &blockPool);
ALOGD("Using output block pool with poolID %llu => got %llu - %d",
(unsigned long long)poolId,
(unsigned long long)(
- mOutputBlockPool ? mOutputBlockPool->getLocalId() : 111000111),
+ blockPool ? blockPool->getLocalId() : 111000111),
err);
+ if (err == C2_OK) {
+ mOutputBlockPool = std::make_shared<BlockingBlockPool>(blockPool);
+ }
return err;
}();
if (err != C2_OK) {
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index b3a98f4..43029a9 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -234,7 +234,8 @@
typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
Mutexed<PendingWork> mPendingWork;
- std::shared_ptr<C2BlockPool> mOutputBlockPool;
+ class BlockingBlockPool;
+ std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
SimpleC2Component() = delete;
};
diff --git a/media/codec2/components/cmds/Android.bp b/media/codec2/components/cmds/Android.bp
index 6b0977b..35f689e 100644
--- a/media/codec2/components/cmds/Android.bp
+++ b/media/codec2/components/cmds/Android.bp
@@ -15,7 +15,6 @@
"libcutils",
"libgui",
"liblog",
- "libmediaextractor",
"libstagefright",
"libstagefright_foundation",
"libui",
diff --git a/media/codec2/components/flac/Android.bp b/media/codec2/components/flac/Android.bp
index d485964..e5eb51d 100644
--- a/media/codec2/components/flac/Android.bp
+++ b/media/codec2/components/flac/Android.bp
@@ -23,5 +23,8 @@
srcs: ["C2SoftFlacEnc.cpp"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
}
diff --git a/media/codec2/components/flac/C2SoftFlacDec.cpp b/media/codec2/components/flac/C2SoftFlacDec.cpp
index f1e2f51..86b16e8 100644
--- a/media/codec2/components/flac/C2SoftFlacDec.cpp
+++ b/media/codec2/components/flac/C2SoftFlacDec.cpp
@@ -83,8 +83,21 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 32768))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::output(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
+
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
std::shared_ptr<C2StreamFormatConfig::output> mOutputFormat;
@@ -94,6 +107,7 @@
std::shared_ptr<C2StreamChannelCountInfo::output> mChannelCount;
std::shared_ptr<C2BitrateTuning::input> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::output> mPcmEncodingInfo;
};
C2SoftFlacDec::C2SoftFlacDec(
@@ -263,11 +277,11 @@
return;
}
- size_t outSize;
- if (mHasStreamInfo)
- outSize = mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(short);
- else
- outSize = kMaxBlockSize * FLACDecoder::kMaxChannels * sizeof(short);
+ const bool outputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(short);
+ size_t outSize = mHasStreamInfo ?
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+ : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
std::shared_ptr<C2LinearBlock> block;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
@@ -284,9 +298,8 @@
return;
}
- short *output = reinterpret_cast<short *>(wView.data());
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- input, inSize, output, &outSize);
+ input, inSize, wView.data(), &outSize, outputFloat);
if (decoderErr != OK) {
ALOGE("process: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index e4192c7..4ea35c2 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "C2SoftFlacEnc"
#include <log/log.h>
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/MediaDefs.h>
#include <C2PlatformSupport.h>
@@ -72,11 +73,23 @@
DefineParam(mInputMaxBufSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
.withConstValue(new C2StreamMaxBufferSizeInfo::input(0u, 4608))
.build());
+
+ addParameter(
+ DefineParam(mPcmEncodingInfo, C2_PARAMKEY_PCM_ENCODING)
+ .withDefault(new C2StreamPcmEncodingInfo::input(0u, C2Config::PCM_16))
+ .withFields({C2F(mPcmEncodingInfo, value).oneOf({
+ C2Config::PCM_16,
+ // C2Config::PCM_8,
+ C2Config::PCM_FLOAT})
+ })
+ .withSetter((Setter<decltype(*mPcmEncodingInfo)>::StrictValueWithNoDeps))
+ .build());
}
uint32_t getSampleRate() const { return mSampleRate->value; }
uint32_t getChannelCount() const { return mChannelCount->value; }
uint32_t getBitrate() const { return mBitrate->value; }
+ int32_t getPcmEncodingInfo() const { return mPcmEncodingInfo->value; }
private:
std::shared_ptr<C2StreamFormatConfig::input> mInputFormat;
@@ -87,6 +100,7 @@
std::shared_ptr<C2StreamChannelCountInfo::input> mChannelCount;
std::shared_ptr<C2BitrateTuning::output> mBitrate;
std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mInputMaxBufSize;
+ std::shared_ptr<C2StreamPcmEncodingInfo::input> mPcmEncodingInfo;
};
constexpr char COMPONENT_NAME[] = "c2.android.flac.encoder";
@@ -224,12 +238,15 @@
mWroteHeader = true;
}
- uint32_t sampleRate = mIntf->getSampleRate();
- uint32_t channelCount = mIntf->getChannelCount();
- uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
+ const uint32_t sampleRate = mIntf->getSampleRate();
+ const uint32_t channelCount = mIntf->getChannelCount();
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const unsigned frameSize = channelCount * sampleSize;
+ const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
size_t outCapacity = inSize;
- outCapacity += mBlockSize * channelCount * sizeof(int16_t);
+ outCapacity += mBlockSize * frameSize;
C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
c2_status_t err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
@@ -250,14 +267,19 @@
size_t inPos = 0;
while (inPos < inSize) {
const uint8_t *inPtr = rView.data() + inOffset;
- size_t processSize = MIN(kInBlockSize * channelCount * sizeof(int16_t), (inSize - inPos));
- const unsigned nbInputFrames = processSize / (channelCount * sizeof(int16_t));
- const unsigned nbInputSamples = processSize / sizeof(int16_t);
- const int16_t *pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
- ALOGV("about to encode %zu bytes", processSize);
+ const size_t processSize = MIN(kInBlockSize * frameSize, (inSize - inPos));
+ const unsigned nbInputFrames = processSize / frameSize;
+ const unsigned nbInputSamples = processSize / sampleSize;
- for (unsigned i = 0; i < nbInputSamples; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ ALOGV("about to encode %zu bytes", processSize);
+ if (inputFloat) {
+ const float * const pcmFloat = reinterpret_cast<const float *>(inPtr + inPos);
+ memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ const int16_t * const pcm16 = reinterpret_cast<const int16_t *>(inPtr + inPos);
+ for (unsigned i = 0; i < nbInputSamples; i++) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
FLAC__bool ok = FLAC__stream_encoder_process_interleaved(
@@ -342,10 +364,12 @@
return UNKNOWN_ERROR;
}
+ const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
+ const int bitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mIntf->getChannelCount());
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mIntf->getSampleRate());
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
if (!ok) {
diff --git a/media/codec2/core/include/C2Component.h b/media/codec2/core/include/C2Component.h
index 8810725..ecf8d2e 100644
--- a/media/codec2/core/include/C2Component.h
+++ b/media/codec2/core/include/C2Component.h
@@ -409,12 +409,13 @@
kind_t kind; ///< component kind
rank_t rank; ///< component rank
C2String mediaType; ///< media type supported by the component
+ C2String owner; ///< name of the component store owning this component
/**
* name alias(es) for backward compatibility.
* \note Multiple components can have the same alias as long as their media-type differs.
*/
- std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
+ std::vector<C2String> aliases; ///< name aliases for backward compatibility
};
// METHODS AVAILABLE WHEN RUNNING
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 27aa064..cf1f6cf 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -392,6 +392,7 @@
_C2_PL_HEVC_BASE = 0x6000,
_C2_PL_VP9_BASE = 0x7000,
_C2_PL_DV_BASE = 0x8000,
+ _C2_PL_AV1_BASE = 0x9000,
C2_PROFILE_LEVEL_VENDOR_START = 0x70000000,
};
@@ -539,6 +540,11 @@
PROFILE_DV_HE_07 = _C2_PL_DV_BASE + 7, ///< Dolby Vision dvhe.07 profile
PROFILE_DV_HE_08 = _C2_PL_DV_BASE + 8, ///< Dolby Vision dvhe.08 profile
PROFILE_DV_AV_09 = _C2_PL_DV_BASE + 9, ///< Dolby Vision dvav.09 profile
+
+ // AV1 profiles
+ PROFILE_AV1_0 = _C2_PL_AV1_BASE, ///< AV1 Profile 0 (4:2:0, 8 to 10 bit)
+ PROFILE_AV1_1, ///< AV1 Profile 1 (8 to 10 bit)
+ PROFILE_AV1_2, ///< AV1 Profile 2 (8 to 12 bit)
};
enum C2Config::level_t : uint32_t {
@@ -652,6 +658,31 @@
LEVEL_DV_HIGH_UHD_30, ///< Dolby Vision high tier uhd30
LEVEL_DV_HIGH_UHD_48, ///< Dolby Vision high tier uhd48
LEVEL_DV_HIGH_UHD_60, ///< Dolby Vision high tier uhd60
+
+ LEVEL_AV1_2 = _C2_PL_AV1_BASE , ///< AV1 Level 2
+ LEVEL_AV1_2_1, ///< AV1 Level 2.1
+ LEVEL_AV1_2_2, ///< AV1 Level 2.2
+ LEVEL_AV1_2_3, ///< AV1 Level 2.3
+ LEVEL_AV1_3, ///< AV1 Level 3
+ LEVEL_AV1_3_1, ///< AV1 Level 3.1
+ LEVEL_AV1_3_2, ///< AV1 Level 3.2
+ LEVEL_AV1_3_3, ///< AV1 Level 3.3
+ LEVEL_AV1_4, ///< AV1 Level 4
+ LEVEL_AV1_4_1, ///< AV1 Level 4.1
+ LEVEL_AV1_4_2, ///< AV1 Level 4.2
+ LEVEL_AV1_4_3, ///< AV1 Level 4.3
+ LEVEL_AV1_5, ///< AV1 Level 5
+ LEVEL_AV1_5_1, ///< AV1 Level 5.1
+ LEVEL_AV1_5_2, ///< AV1 Level 5.2
+ LEVEL_AV1_5_3, ///< AV1 Level 5.3
+ LEVEL_AV1_6, ///< AV1 Level 6
+ LEVEL_AV1_6_1, ///< AV1 Level 6.1
+ LEVEL_AV1_6_2, ///< AV1 Level 6.2
+ LEVEL_AV1_6_3, ///< AV1 Level 6.3
+ LEVEL_AV1_7, ///< AV1 Level 7
+ LEVEL_AV1_7_1, ///< AV1 Level 7.1
+ LEVEL_AV1_7_2, ///< AV1 Level 7.2
+ LEVEL_AV1_7_3, ///< AV1 Level 7.3
};
struct C2ProfileLevelStruct {
diff --git a/media/codec2/core/include/C2Param.h b/media/codec2/core/include/C2Param.h
index 40be3b3..efc5c89 100644
--- a/media/codec2/core/include/C2Param.h
+++ b/media/codec2/core/include/C2Param.h
@@ -988,7 +988,10 @@
/** specialization for easy enums */
template<typename E>
inline static NamedValuesType namedValuesFor(const C2EasyEnum<E> &) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
return namedValuesFor(*(E*)nullptr);
+#pragma GCC diagnostic pop
}
private:
@@ -1104,7 +1107,10 @@
template<typename B>
struct C2FieldDescriptor::_NamedValuesGetter<B, true> {
inline static C2FieldDescriptor::NamedValuesType getNamedValues() {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
return C2FieldDescriptor::namedValuesFor(*(B*)nullptr);
+#pragma GCC diagnostic pop
}
};
@@ -1599,11 +1605,13 @@
/// \internal
/// \todo: create separate values vs. flags initializer as for flags we want
/// to list both allowed and required flags
- template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)0))>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnull-dereference"
+ template<typename T, typename E=decltype(C2FieldDescriptor::namedValuesFor(*(T*)nullptr))>
C2FieldSupportedValues(bool flags, const T*)
: type(flags ? FLAGS : VALUES),
range{(T)0, (T)0, (T)0, (T)0, (T)0} {
- C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)0);
+ C2FieldDescriptor::NamedValuesType named = C2FieldDescriptor::namedValuesFor(*(T*)nullptr);
if (flags) {
values.emplace_back(0); // min-mask defaults to 0
}
@@ -1612,6 +1620,7 @@
}
}
};
+#pragma GCC diagnostic pop
/**
* Supported values for a specific field.
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
index 1e87f38..d4b973f 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
@@ -330,57 +330,72 @@
}
}
+// number of elementary streams per component
+#define STREAM_COUNT 2
+
// LookUpTable of clips and metadata for component testing
void GetURLForComponent(Codec2AudioDecHidlTest::standardComp comp, char* mURL,
- char* info) {
+ char* info, size_t streamIndex = 0) {
struct CompToURL {
Codec2AudioDecHidlTest::standardComp comp;
- const char* mURL;
- const char* info;
+ const char mURL[STREAM_COUNT][512];
+ const char info[STREAM_COUNT][512];
};
+ ASSERT_TRUE(streamIndex < STREAM_COUNT);
+
static const CompToURL kCompToURL[] = {
{Codec2AudioDecHidlTest::standardComp::xaac,
- "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.info"},
+ {"bbb_aac_stereo_128kbps_48000hz.aac",
+ "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::mp3,
- "bbb_mp3_stereo_192kbps_48000hz.mp3",
- "bbb_mp3_stereo_192kbps_48000hz.info"},
+ {"bbb_mp3_stereo_192kbps_48000hz.mp3",
+ "bbb_mp3_stereo_192kbps_48000hz.mp3"},
+ {"bbb_mp3_stereo_192kbps_48000hz.info",
+ "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::aac,
- "bbb_aac_stereo_128kbps_48000hz.aac",
- "bbb_aac_stereo_128kbps_48000hz.info"},
+ {"bbb_aac_stereo_128kbps_48000hz.aac",
+ "bbb_aac_stereo_128kbps_48000hz.aac"},
+ {"bbb_aac_stereo_128kbps_48000hz.info",
+ "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::amrnb,
- "sine_amrnb_1ch_12kbps_8000hz.amrnb",
- "sine_amrnb_1ch_12kbps_8000hz.info"},
+ {"sine_amrnb_1ch_12kbps_8000hz.amrnb",
+ "sine_amrnb_1ch_12kbps_8000hz.amrnb"},
+ {"sine_amrnb_1ch_12kbps_8000hz.info",
+ "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::amrwb,
- "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
- "bbb_amrwb_1ch_14kbps_16000hz.info"},
+ {"bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+ "bbb_amrwb_1ch_14kbps_16000hz.amrwb"},
+ {"bbb_amrwb_1ch_14kbps_16000hz.info",
+ "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}},
{Codec2AudioDecHidlTest::standardComp::vorbis,
- "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
- "bbb_vorbis_stereo_128kbps_48000hz.info"},
+ {"bbb_vorbis_stereo_128kbps_48000hz.vorbis", ""},
+ {"bbb_vorbis_stereo_128kbps_48000hz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::opus,
- "bbb_opus_stereo_128kbps_48000hz.opus",
- "bbb_opus_stereo_128kbps_48000hz.info"},
+ {"bbb_opus_stereo_128kbps_48000hz.opus", ""},
+ {"bbb_opus_stereo_128kbps_48000hz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::g711alaw,
- "bbb_g711alaw_1ch_8khz.raw",
- "bbb_g711alaw_1ch_8khz.info"},
+ {"bbb_g711alaw_1ch_8khz.raw", ""},
+ {"bbb_g711alaw_1ch_8khz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::g711mlaw,
- "bbb_g711mulaw_1ch_8khz.raw",
- "bbb_g711mulaw_1ch_8khz.info"},
+ {"bbb_g711mulaw_1ch_8khz.raw", ""},
+ {"bbb_g711mulaw_1ch_8khz.info", ""}},
{Codec2AudioDecHidlTest::standardComp::gsm,
- "bbb_gsm_1ch_8khz_13kbps.raw",
- "bbb_gsm_1ch_8khz_13kbps.info"},
+ {"bbb_gsm_1ch_8khz_13kbps.raw", ""},
+ {"bbb_gsm_1ch_8khz_13kbps.info", ""}},
{Codec2AudioDecHidlTest::standardComp::raw,
- "bbb_raw_1ch_8khz_s32le.raw",
- "bbb_raw_1ch_8khz_s32le.info"},
+ {"bbb_raw_1ch_8khz_s32le.raw", ""},
+ {"bbb_raw_1ch_8khz_s32le.info", ""}},
{Codec2AudioDecHidlTest::standardComp::flac,
- "bbb_flac_stereo_680kbps_48000hz.flac",
- "bbb_flac_stereo_680kbps_48000hz.info"},
+ {"bbb_flac_stereo_680kbps_48000hz.flac", ""},
+ {"bbb_flac_stereo_680kbps_48000hz.info", ""}},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
if (kCompToURL[i].comp == comp) {
- strcat(mURL, kCompToURL[i].mURL);
- strcat(info, kCompToURL[i].info);
+ strcat(mURL, kCompToURL[i].mURL[streamIndex]);
+ strcat(info, kCompToURL[i].info[streamIndex]);
return;
}
}
@@ -491,10 +506,15 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, DecodeTest) {
+class Codec2AudioDecDecodeTest : public Codec2AudioDecHidlTest,
+ public ::testing::WithParamInterface<int32_t> {
+};
+
+TEST_P(Codec2AudioDecDecodeTest, DecodeTest) {
description("Decodes input file");
if (mDisableTest) return;
+ uint32_t streamIndex = GetParam();
ASSERT_EQ(mComponent->start(), C2_OK);
mTimestampDevTest = true;
char mURL[512], info[512];
@@ -502,7 +522,12 @@
strcpy(mURL, gEnv->getRes().c_str());
strcpy(info, gEnv->getRes().c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mCompName, mURL, info, streamIndex);
+ if (!strcmp(mURL, gEnv->getRes().c_str())) {
+ ALOGV("EMPTY INPUT gEnv->getRes().c_str() %s mURL %s ",
+ gEnv->getRes().c_str(), mURL);
+ return;
+ }
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true);
@@ -521,6 +546,9 @@
Info.push_back({bytesCount, flags, timestamp});
}
eleInfo.close();
+ // Reset total no of frames received
+ mFramesReceived = 0;
+ mTimestampUs = 0;
int32_t bitStreamInfo[2] = {0};
if (mCompName == raw) {
bitStreamInfo[0] = 8000;
@@ -577,6 +605,9 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2AudioDecDecodeTest,
+ ::testing::Values(0, 1));
+
// thumbnail test
TEST_F(Codec2AudioDecHidlTest, ThumbnailTest) {
description("Test Request for thumbnail");
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..182af20
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info
@@ -0,0 +1,443 @@
+5 32 0
+5 32 0
+337 1 0
+322 1 21333
+279 1 42666
+563 1 64000
+635 1 106666
+634 1 149333
+629 1 192000
+680 1 234666
+688 1 277333
+1036 1 320000
+1040 1 384000
+1009 1 448000
+1020 1 512000
+1357 1 576000
+1353 1 661333
+1351 1 746666
+1351 1 832000
+343 1 917333
+335 1 938666
+339 1 960000
+342 1 981333
+348 1 1002666
+350 1 1024000
+351 1 1045333
+342 1 1066666
+366 1 1088000
+340 1 1109333
+354 1 1130666
+340 1 1152000
+334 1 1173333
+338 1 1194666
+340 1 1216000
+351 1 1237333
+346 1 1258666
+331 1 1280000
+321 1 1301333
+343 1 1322666
+342 1 1344000
+345 1 1365333
+326 1 1386666
+342 1 1408000
+356 1 1429333
+351 1 1450666
+343 1 1472000
+347 1 1493333
+349 1 1514666
+350 1 1536000
+330 1 1557333
+341 1 1578666
+340 1 1600000
+330 1 1621333
+340 1 1642666
+335 1 1664000
+344 1 1685333
+359 1 1706666
+337 1 1728000
+346 1 1749333
+330 1 1770666
+351 1 1792000
+355 1 1813333
+352 1 1834666
+325 1 1856000
+342 1 1877333
+327 1 1898666
+349 1 1920000
+326 1 1941333
+337 1 1962666
+378 1 1984000
+321 1 2005333
+319 1 2026666
+346 1 2048000
+352 1 2069333
+349 1 2090666
+331 1 2112000
+330 1 2133333
+329 1 2154666
+333 1 2176000
+367 1 2197333
+362 1 2218666
+337 1 2240000
+337 1 2261333
+360 1 2282666
+333 1 2304000
+317 1 2325333
+344 1 2346666
+335 1 2368000
+337 1 2389333
+349 1 2410666
+336 1 2432000
+348 1 2453333
+349 1 2474666
+342 1 2496000
+359 1 2517333
+340 1 2538666
+340 1 2560000
+348 1 2581333
+334 1 2602666
+328 1 2624000
+341 1 2645333
+339 1 2666666
+337 1 2688000
+350 1 2709333
+326 1 2730666
+360 1 2752000
+344 1 2773333
+340 1 2794666
+343 1 2816000
+361 1 2837333
+329 1 2858666
+345 1 2880000
+345 1 2901333
+330 1 2922666
+342 1 2944000
+344 1 2965333
+330 1 2986666
+329 1 3008000
+335 1 3029333
+366 1 3050666
+328 1 3072000
+349 1 3093333
+339 1 3114666
+340 1 3136000
+335 1 3157333
+327 1 3178666
+348 1 3200000
+339 1 3221333
+334 1 3242666
+350 1 3264000
+325 1 3285333
+361 1 3306666
+338 1 3328000
+350 1 3349333
+353 1 3370666
+327 1 3392000
+346 1 3413333
+348 1 3434666
+339 1 3456000
+342 1 3477333
+334 1 3498666
+350 1 3520000
+354 1 3541333
+363 1 3562666
+322 1 3584000
+337 1 3605333
+355 1 3626666
+329 1 3648000
+324 1 3669333
+338 1 3690666
+356 1 3712000
+330 1 3733333
+321 1 3754666
+337 1 3776000
+345 1 3797333
+335 1 3818666
+348 1 3840000
+342 1 3861333
+348 1 3882666
+335 1 3904000
+344 1 3925333
+357 1 3946666
+368 1 3968000
+324 1 3989333
+343 1 4010666
+341 1 4032000
+329 1 4053333
+356 1 4074666
+317 1 4096000
+351 1 4117333
+340 1 4138666
+340 1 4160000
+332 1 4181333
+355 1 4202666
+357 1 4224000
+327 1 4245333
+338 1 4266666
+323 1 4288000
+346 1 4309333
+352 1 4330666
+347 1 4352000
+343 1 4373333
+311 1 4394666
+338 1 4416000
+365 1 4437333
+349 1 4458666
+327 1 4480000
+355 1 4501333
+319 1 4522666
+349 1 4544000
+351 1 4565333
+337 1 4586666
+340 1 4608000
+349 1 4629333
+316 1 4650666
+344 1 4672000
+334 1 4693333
+344 1 4714666
+347 1 4736000
+348 1 4757333
+334 1 4778666
+338 1 4800000
+331 1 4821333
+344 1 4842666
+342 1 4864000
+336 1 4885333
+326 1 4906666
+364 1 4928000
+350 1 4949333
+350 1 4970666
+363 1 4992000
+358 1 5013333
+305 1 5034666
+344 1 5056000
+346 1 5077333
+342 1 5098666
+330 1 5120000
+318 1 5141333
+361 1 5162666
+354 1 5184000
+313 1 5205333
+330 1 5226666
+350 1 5248000
+347 1 5269333
+346 1 5290666
+357 1 5312000
+325 1 5333333
+335 1 5354666
+331 1 5376000
+366 1 5397333
+329 1 5418666
+349 1 5440000
+371 1 5461333
+326 1 5482666
+333 1 5504000
+319 1 5525333
+327 1 5546666
+353 1 5568000
+356 1 5589333
+348 1 5610666
+338 1 5632000
+331 1 5653333
+341 1 5674666
+362 1 5696000
+326 1 5717333
+359 1 5738666
+315 1 5760000
+376 1 5781333
+343 1 5802666
+354 1 5824000
+353 1 5845333
+344 1 5866666
+334 1 5888000
+345 1 5909333
+355 1 5930666
+322 1 5952000
+334 1 5973333
+353 1 5994666
+338 1 6016000
+351 1 6037333
+334 1 6058666
+339 1 6080000
+345 1 6101333
+347 1 6122666
+355 1 6144000
+312 1 6165333
+352 1 6186666
+354 1 6208000
+318 1 6229333
+344 1 6250666
+363 1 6272000
+321 1 6293333
+339 1 6314666
+356 1 6336000
+334 1 6357333
+354 1 6378666
+325 1 6400000
+321 1 6421333
+341 1 6442666
+337 1 6464000
+351 1 6485333
+343 1 6506666
+341 1 6528000
+344 1 6549333
+341 1 6570666
+364 1 6592000
+319 1 6613333
+348 1 6634666
+332 1 6656000
+333 1 6677333
+343 1 6698666
+348 1 6720000
+347 1 6741333
+350 1 6762666
+342 1 6784000
+341 1 6805333
+326 1 6826666
+351 1 6848000
+329 1 6869333
+323 1 6890666
+350 1 6912000
+361 1 6933333
+326 1 6954666
+345 1 6976000
+345 1 6997333
+311 1 7018666
+349 1 7040000
+358 1 7061333
+352 1 7082666
+347 1 7104000
+364 1 7125333
+328 1 7146666
+318 1 7168000
+351 1 7189333
+340 1 7210666
+341 1 7232000
+355 1 7253333
+336 1 7274666
+352 1 7296000
+341 1 7317333
+334 1 7338666
+348 1 7360000
+342 1 7381333
+335 1 7402666
+342 1 7424000
+359 1 7445333
+349 1 7466666
+329 1 7488000
+356 1 7509333
+292 1 7530666
+316 1 7552000
+318 1 7573333
+320 1 7594666
+342 1 7616000
+285 1 7637333
+326 1 7658666
+352 1 7680000
+392 1 7701333
+364 1 7722666
+384 1 7744000
+334 1 7765333
+317 1 7786666
+326 1 7808000
+373 1 7829333
+354 1 7850666
+329 1 7872000
+347 1 7893333
+353 1 7914666
+338 1 7936000
+317 1 7957333
+354 1 7978666
+345 1 8000000
+350 1 8021333
+351 1 8042666
+332 1 8064000
+358 1 8085333
+315 1 8106666
+336 1 8128000
+358 1 8149333
+343 1 8170666
+319 1 8192000
+370 1 8213333
+344 1 8234666
+361 1 8256000
+343 1 8277333
+337 1 8298666
+354 1 8320000
+332 1 8341333
+348 1 8362666
+328 1 8384000
+345 1 8405333
+340 1 8426666
+346 1 8448000
+341 1 8469333
+344 1 8490666
+342 1 8512000
+341 1 8533333
+345 1 8554666
+337 1 8576000
+335 1 8597333
+335 1 8618666
+340 1 8640000
+345 1 8661333
+341 1 8682666
+342 1 8704000
+338 1 8725333
+343 1 8746666
+336 1 8768000
+338 1 8789333
+353 1 8810666
+339 1 8832000
+329 1 8853333
+349 1 8874666
+323 1 8896000
+351 1 8917333
+359 1 8938666
+357 1 8960000
+341 1 8981333
+333 1 9002666
+335 1 9024000
+328 1 9045333
+347 1 9066666
+343 1 9088000
+369 1 9109333
+331 1 9130666
+344 1 9152000
+330 1 9173333
+346 1 9194666
+337 1 9216000
+341 1 9237333
+338 1 9258666
+329 1 9280000
+360 1 9301333
+336 1 9322666
+341 1 9344000
+341 1 9365333
+345 1 9386666
+351 1 9408000
+349 1 9429333
+336 1 9450666
+326 1 9472000
+349 1 9493333
+343 1 9514666
+357 1 9536000
+342 1 9557333
+325 1 9578666
+346 1 9600000
+326 1 9621333
+402 1 9642666
+331 1 9664000
+339 1 9685333
+371 1 9706666
+314 1 9728000
+310 1 9749333
+364 1 9770666
+338 1 9792000
+339 1 9813333
+337 1 9834666
+355 1 9856000
+351 1 9877333
+332 1 9898666
+316 1 9920000
+474 1 9941333
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
new file mode 100644
index 0000000..c420009
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info
@@ -0,0 +1,460 @@
+41 1 0
+41 1 20000
+82 1 40000
+82 1 80000
+82 1 120000
+82 1 160000
+82 1 200000
+82 1 240000
+82 1 280000
+82 1 320000
+82 1 360000
+123 1 400000
+123 1 460000
+123 1 520000
+123 1 580000
+123 1 640000
+164 1 700000
+164 1 780000
+164 1 860000
+164 1 940000
+164 1 1020000
+41 1 1100000
+41 1 1120000
+41 1 1140000
+41 1 1160000
+41 1 1180000
+41 1 1200000
+41 1 1220000
+41 1 1240000
+41 1 1260000
+41 1 1280000
+41 1 1300000
+41 1 1320000
+41 1 1340000
+41 1 1360000
+41 1 1380000
+41 1 1400000
+41 1 1420000
+41 1 1440000
+41 1 1460000
+41 1 1480000
+41 1 1500000
+41 1 1520000
+41 1 1540000
+41 1 1560000
+41 1 1580000
+41 1 1600000
+41 1 1620000
+41 1 1640000
+41 1 1660000
+41 1 1680000
+41 1 1700000
+41 1 1720000
+41 1 1740000
+41 1 1760000
+41 1 1780000
+41 1 1800000
+41 1 1820000
+41 1 1840000
+41 1 1860000
+41 1 1880000
+41 1 1900000
+41 1 1920000
+41 1 1940000
+41 1 1960000
+41 1 1980000
+41 1 2000000
+41 1 2020000
+41 1 2040000
+41 1 2060000
+41 1 2080000
+41 1 2100000
+41 1 2120000
+41 1 2140000
+41 1 2160000
+41 1 2180000
+41 1 2200000
+41 1 2220000
+41 1 2240000
+41 1 2260000
+41 1 2280000
+41 1 2300000
+41 1 2320000
+41 1 2340000
+41 1 2360000
+41 1 2380000
+41 1 2400000
+41 1 2420000
+41 1 2440000
+41 1 2460000
+41 1 2480000
+41 1 2500000
+41 1 2520000
+41 1 2540000
+41 1 2560000
+41 1 2580000
+41 1 2600000
+41 1 2620000
+41 1 2640000
+41 1 2660000
+41 1 2680000
+41 1 2700000
+41 1 2720000
+41 1 2740000
+41 1 2760000
+41 1 2780000
+41 1 2800000
+41 1 2820000
+41 1 2840000
+41 1 2860000
+41 1 2880000
+41 1 2900000
+41 1 2920000
+41 1 2940000
+41 1 2960000
+41 1 2980000
+41 1 3000000
+41 1 3020000
+41 1 3040000
+41 1 3060000
+41 1 3080000
+41 1 3100000
+41 1 3120000
+41 1 3140000
+41 1 3160000
+41 1 3180000
+41 1 3200000
+41 1 3220000
+41 1 3240000
+41 1 3260000
+41 1 3280000
+41 1 3300000
+41 1 3320000
+41 1 3340000
+41 1 3360000
+41 1 3380000
+41 1 3400000
+41 1 3420000
+41 1 3440000
+41 1 3460000
+41 1 3480000
+41 1 3500000
+41 1 3520000
+41 1 3540000
+41 1 3560000
+41 1 3580000
+41 1 3600000
+41 1 3620000
+41 1 3640000
+41 1 3660000
+41 1 3680000
+41 1 3700000
+41 1 3720000
+41 1 3740000
+41 1 3760000
+41 1 3780000
+41 1 3800000
+41 1 3820000
+41 1 3840000
+41 1 3860000
+41 1 3880000
+41 1 3900000
+41 1 3920000
+41 1 3940000
+41 1 3960000
+41 1 3980000
+41 1 4000000
+41 1 4020000
+41 1 4040000
+41 1 4060000
+41 1 4080000
+41 1 4100000
+41 1 4120000
+41 1 4140000
+41 1 4160000
+41 1 4180000
+41 1 4200000
+41 1 4220000
+41 1 4240000
+41 1 4260000
+41 1 4280000
+41 1 4300000
+41 1 4320000
+41 1 4340000
+41 1 4360000
+41 1 4380000
+41 1 4400000
+41 1 4420000
+41 1 4440000
+41 1 4460000
+41 1 4480000
+41 1 4500000
+41 1 4520000
+41 1 4540000
+41 1 4560000
+41 1 4580000
+41 1 4600000
+41 1 4620000
+41 1 4640000
+41 1 4660000
+41 1 4680000
+41 1 4700000
+41 1 4720000
+41 1 4740000
+41 1 4760000
+41 1 4780000
+41 1 4800000
+41 1 4820000
+41 1 4840000
+41 1 4860000
+41 1 4880000
+41 1 4900000
+41 1 4920000
+41 1 4940000
+41 1 4960000
+41 1 4980000
+41 1 5000000
+41 1 5020000
+41 1 5040000
+41 1 5060000
+41 1 5080000
+41 1 5100000
+41 1 5120000
+41 1 5140000
+41 1 5160000
+41 1 5180000
+41 1 5200000
+41 1 5220000
+41 1 5240000
+41 1 5260000
+41 1 5280000
+41 1 5300000
+41 1 5320000
+41 1 5340000
+41 1 5360000
+41 1 5380000
+41 1 5400000
+41 1 5420000
+41 1 5440000
+41 1 5460000
+41 1 5480000
+41 1 5500000
+41 1 5520000
+41 1 5540000
+41 1 5560000
+41 1 5580000
+41 1 5600000
+41 1 5620000
+41 1 5640000
+41 1 5660000
+41 1 5680000
+41 1 5700000
+41 1 5720000
+41 1 5740000
+41 1 5760000
+41 1 5780000
+41 1 5800000
+41 1 5820000
+41 1 5840000
+41 1 5860000
+41 1 5880000
+41 1 5900000
+41 1 5920000
+41 1 5940000
+41 1 5960000
+41 1 5980000
+41 1 6000000
+41 1 6020000
+41 1 6040000
+41 1 6060000
+41 1 6080000
+41 1 6100000
+41 1 6120000
+41 1 6140000
+41 1 6160000
+41 1 6180000
+41 1 6200000
+41 1 6220000
+41 1 6240000
+41 1 6260000
+41 1 6280000
+41 1 6300000
+41 1 6320000
+41 1 6340000
+41 1 6360000
+41 1 6380000
+41 1 6400000
+41 1 6420000
+41 1 6440000
+41 1 6460000
+41 1 6480000
+41 1 6500000
+41 1 6520000
+41 1 6540000
+41 1 6560000
+41 1 6580000
+41 1 6600000
+41 1 6620000
+41 1 6640000
+41 1 6660000
+41 1 6680000
+41 1 6700000
+41 1 6720000
+41 1 6740000
+41 1 6760000
+41 1 6780000
+41 1 6800000
+41 1 6820000
+41 1 6840000
+41 1 6860000
+41 1 6880000
+41 1 6900000
+41 1 6920000
+41 1 6940000
+41 1 6960000
+41 1 6980000
+41 1 7000000
+41 1 7020000
+41 1 7040000
+41 1 7060000
+41 1 7080000
+41 1 7100000
+41 1 7120000
+41 1 7140000
+41 1 7160000
+41 1 7180000
+41 1 7200000
+41 1 7220000
+41 1 7240000
+41 1 7260000
+41 1 7280000
+41 1 7300000
+41 1 7320000
+41 1 7340000
+41 1 7360000
+41 1 7380000
+41 1 7400000
+41 1 7420000
+41 1 7440000
+41 1 7460000
+41 1 7480000
+41 1 7500000
+41 1 7520000
+41 1 7540000
+41 1 7560000
+41 1 7580000
+41 1 7600000
+41 1 7620000
+41 1 7640000
+41 1 7660000
+41 1 7680000
+41 1 7700000
+41 1 7720000
+41 1 7740000
+41 1 7760000
+41 1 7780000
+41 1 7800000
+41 1 7820000
+41 1 7840000
+41 1 7860000
+41 1 7880000
+41 1 7900000
+41 1 7920000
+41 1 7940000
+41 1 7960000
+41 1 7980000
+41 1 8000000
+41 1 8020000
+41 1 8040000
+41 1 8060000
+41 1 8080000
+41 1 8100000
+41 1 8120000
+41 1 8140000
+41 1 8160000
+41 1 8180000
+41 1 8200000
+41 1 8220000
+41 1 8240000
+41 1 8260000
+41 1 8280000
+41 1 8300000
+41 1 8320000
+41 1 8340000
+41 1 8360000
+41 1 8380000
+41 1 8400000
+41 1 8420000
+41 1 8440000
+41 1 8460000
+41 1 8480000
+41 1 8500000
+41 1 8520000
+41 1 8540000
+41 1 8560000
+41 1 8580000
+41 1 8600000
+41 1 8620000
+41 1 8640000
+41 1 8660000
+41 1 8680000
+41 1 8700000
+41 1 8720000
+41 1 8740000
+41 1 8760000
+41 1 8780000
+41 1 8800000
+41 1 8820000
+41 1 8840000
+41 1 8860000
+41 1 8880000
+41 1 8900000
+41 1 8920000
+41 1 8940000
+41 1 8960000
+41 1 8980000
+41 1 9000000
+41 1 9020000
+41 1 9040000
+41 1 9060000
+41 1 9080000
+41 1 9100000
+41 1 9120000
+41 1 9140000
+41 1 9160000
+41 1 9180000
+41 1 9200000
+41 1 9220000
+41 1 9240000
+41 1 9260000
+41 1 9280000
+41 1 9300000
+41 1 9320000
+41 1 9340000
+41 1 9360000
+41 1 9380000
+41 1 9400000
+41 1 9420000
+41 1 9440000
+41 1 9460000
+41 1 9480000
+41 1 9500000
+41 1 9520000
+41 1 9540000
+41 1 9560000
+41 1 9580000
+41 1 9600000
+41 1 9620000
+41 1 9640000
+41 1 9660000
+41 1 9680000
+41 1 9700000
+41 1 9720000
+41 1 9740000
+41 1 9760000
+41 1 9780000
+41 1 9800000
+41 1 9820000
+41 1 9840000
+41 1 9860000
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
new file mode 100644
index 0000000..575c75f
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info
@@ -0,0 +1,385 @@
+576 1 0
+576 1 24000
+1152 1 48000
+1152 1 96000
+1152 1 144000
+1152 1 192000
+1728 1 240000
+1728 1 312000
+1728 1 384000
+1728 1 456000
+1728 1 528000
+2304 1 600000
+2304 1 696000
+2304 1 792000
+2304 1 888000
+2304 1 984000
+576 1 1080000
+576 1 1104000
+576 1 1128000
+576 1 1152000
+576 1 1176000
+576 1 1200000
+576 1 1224000
+576 1 1248000
+576 1 1272000
+576 1 1296000
+576 1 1320000
+576 1 1344000
+576 1 1368000
+576 1 1392000
+576 1 1416000
+576 1 1440000
+576 1 1464000
+576 1 1488000
+576 1 1512000
+576 1 1536000
+576 1 1560000
+576 1 1584000
+576 1 1608000
+576 1 1632000
+576 1 1656000
+576 1 1680000
+576 1 1704000
+576 1 1728000
+576 1 1752000
+576 1 1776000
+576 1 1800000
+576 1 1824000
+576 1 1848000
+576 1 1872000
+576 1 1896000
+576 1 1920000
+576 1 1944000
+576 1 1968000
+576 1 1992000
+576 1 2016000
+576 1 2040000
+576 1 2064000
+576 1 2088000
+576 1 2112000
+576 1 2136000
+576 1 2160000
+576 1 2184000
+576 1 2208000
+576 1 2232000
+576 1 2256000
+576 1 2280000
+576 1 2304000
+576 1 2328000
+576 1 2352000
+576 1 2376000
+576 1 2400000
+576 1 2424000
+576 1 2448000
+576 1 2472000
+576 1 2496000
+576 1 2520000
+576 1 2544000
+576 1 2568000
+576 1 2592000
+576 1 2616000
+576 1 2640000
+576 1 2664000
+576 1 2688000
+576 1 2712000
+576 1 2736000
+576 1 2760000
+576 1 2784000
+576 1 2808000
+576 1 2832000
+576 1 2856000
+576 1 2880000
+576 1 2904000
+576 1 2928000
+576 1 2952000
+576 1 2976000
+576 1 3000000
+576 1 3024000
+576 1 3048000
+576 1 3072000
+576 1 3096000
+576 1 3120000
+576 1 3144000
+576 1 3168000
+576 1 3192000
+576 1 3216000
+576 1 3240000
+576 1 3264000
+576 1 3288000
+576 1 3312000
+576 1 3336000
+576 1 3360000
+576 1 3384000
+576 1 3408000
+576 1 3432000
+576 1 3456000
+576 1 3480000
+576 1 3504000
+576 1 3528000
+576 1 3552000
+576 1 3576000
+576 1 3600000
+576 1 3624000
+576 1 3648000
+576 1 3672000
+576 1 3696000
+576 1 3720000
+576 1 3744000
+576 1 3768000
+576 1 3792000
+576 1 3816000
+576 1 3840000
+576 1 3864000
+576 1 3888000
+576 1 3912000
+576 1 3936000
+576 1 3960000
+576 1 3984000
+576 1 4008000
+576 1 4032000
+576 1 4056000
+576 1 4080000
+576 1 4104000
+576 1 4128000
+576 1 4152000
+576 1 4176000
+576 1 4200000
+576 1 4224000
+576 1 4248000
+576 1 4272000
+576 1 4296000
+576 1 4320000
+576 1 4344000
+576 1 4368000
+576 1 4392000
+576 1 4416000
+576 1 4440000
+576 1 4464000
+576 1 4488000
+576 1 4512000
+576 1 4536000
+576 1 4560000
+576 1 4584000
+576 1 4608000
+576 1 4632000
+576 1 4656000
+576 1 4680000
+576 1 4704000
+576 1 4728000
+576 1 4752000
+576 1 4776000
+576 1 4800000
+576 1 4824000
+576 1 4848000
+576 1 4872000
+576 1 4896000
+576 1 4920000
+576 1 4944000
+576 1 4968000
+576 1 4992000
+576 1 5016000
+576 1 5040000
+576 1 5064000
+576 1 5088000
+576 1 5112000
+576 1 5136000
+576 1 5160000
+576 1 5184000
+576 1 5208000
+576 1 5232000
+576 1 5256000
+576 1 5280000
+576 1 5304000
+576 1 5328000
+576 1 5352000
+576 1 5376000
+576 1 5400000
+576 1 5424000
+576 1 5448000
+576 1 5472000
+576 1 5496000
+576 1 5520000
+576 1 5544000
+576 1 5568000
+576 1 5592000
+576 1 5616000
+576 1 5640000
+576 1 5664000
+576 1 5688000
+576 1 5712000
+576 1 5736000
+576 1 5760000
+576 1 5784000
+576 1 5808000
+576 1 5832000
+576 1 5856000
+576 1 5880000
+576 1 5904000
+576 1 5928000
+576 1 5952000
+576 1 5976000
+576 1 6000000
+576 1 6024000
+576 1 6048000
+576 1 6072000
+576 1 6096000
+576 1 6120000
+576 1 6144000
+576 1 6168000
+576 1 6192000
+576 1 6216000
+576 1 6240000
+576 1 6264000
+576 1 6288000
+576 1 6312000
+576 1 6336000
+576 1 6360000
+576 1 6384000
+576 1 6408000
+576 1 6432000
+576 1 6456000
+576 1 6480000
+576 1 6504000
+576 1 6528000
+576 1 6552000
+576 1 6576000
+576 1 6600000
+576 1 6624000
+576 1 6648000
+576 1 6672000
+576 1 6696000
+576 1 6720000
+576 1 6744000
+576 1 6768000
+576 1 6792000
+576 1 6816000
+576 1 6840000
+576 1 6864000
+576 1 6888000
+576 1 6912000
+576 1 6936000
+576 1 6960000
+576 1 6984000
+576 1 7008000
+576 1 7032000
+576 1 7056000
+576 1 7080000
+576 1 7104000
+576 1 7128000
+576 1 7152000
+576 1 7176000
+576 1 7200000
+576 1 7224000
+576 1 7248000
+576 1 7272000
+576 1 7296000
+576 1 7320000
+576 1 7344000
+576 1 7368000
+576 1 7392000
+576 1 7416000
+576 1 7440000
+576 1 7464000
+576 1 7488000
+576 1 7512000
+576 1 7536000
+576 1 7560000
+576 1 7584000
+576 1 7608000
+576 1 7632000
+576 1 7656000
+576 1 7680000
+576 1 7704000
+576 1 7728000
+576 1 7752000
+576 1 7776000
+576 1 7800000
+576 1 7824000
+576 1 7848000
+576 1 7872000
+576 1 7896000
+576 1 7920000
+576 1 7944000
+576 1 7968000
+576 1 7992000
+576 1 8016000
+576 1 8040000
+576 1 8064000
+576 1 8088000
+576 1 8112000
+576 1 8136000
+576 1 8160000
+576 1 8184000
+576 1 8208000
+576 1 8232000
+576 1 8256000
+576 1 8280000
+576 1 8304000
+576 1 8328000
+576 1 8352000
+576 1 8376000
+576 1 8400000
+576 1 8424000
+576 1 8448000
+576 1 8472000
+576 1 8496000
+576 1 8520000
+576 1 8544000
+576 1 8568000
+576 1 8592000
+576 1 8616000
+576 1 8640000
+576 1 8664000
+576 1 8688000
+576 1 8712000
+576 1 8736000
+576 1 8760000
+576 1 8784000
+576 1 8808000
+576 1 8832000
+576 1 8856000
+576 1 8880000
+576 1 8904000
+576 1 8928000
+576 1 8952000
+576 1 8976000
+576 1 9000000
+576 1 9024000
+576 1 9048000
+576 1 9072000
+576 1 9096000
+576 1 9120000
+576 1 9144000
+576 1 9168000
+576 1 9192000
+576 1 9216000
+576 1 9240000
+576 1 9264000
+576 1 9288000
+576 1 9312000
+576 1 9336000
+576 1 9360000
+576 1 9384000
+576 1 9408000
+576 1 9432000
+576 1 9456000
+576 1 9480000
+576 1 9504000
+576 1 9528000
+576 1 9552000
+576 1 9576000
+576 1 9600000
+576 1 9624000
+576 1 9648000
+576 1 9672000
+576 1 9696000
+576 1 9720000
+576 1 9744000
+576 1 9768000
+576 1 9792000
+576 1 9816000
+576 1 9840000
+576 1 9864000
+576 1 9888000
+576 1 9912000
diff --git a/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
new file mode 100644
index 0000000..0176eaf4
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info
@@ -0,0 +1,807 @@
+32 1 0
+32 1 20000
+64 1 40000
+64 1 80000
+64 1 120000
+96 1 160000
+96 1 220000
+96 1 280000
+96 1 340000
+128 1 400000
+128 1 480000
+128 1 560000
+128 1 640000
+128 1 720000
+32 1 800000
+32 1 820000
+32 1 840000
+32 1 860000
+32 1 880000
+32 1 900000
+32 1 920000
+32 1 940000
+32 1 960000
+32 1 980000
+32 1 1000000
+32 1 1020000
+32 1 1040000
+32 1 1060000
+32 1 1080000
+32 1 1100000
+32 1 1120000
+32 1 1140000
+32 1 1160000
+32 1 1180000
+32 1 1200000
+32 1 1220000
+32 1 1240000
+32 1 1260000
+32 1 1280000
+32 1 1300000
+32 1 1320000
+32 1 1340000
+32 1 1360000
+32 1 1380000
+32 1 1400000
+32 1 1420000
+32 1 1440000
+32 1 1460000
+32 1 1480000
+32 1 1500000
+32 1 1520000
+32 1 1540000
+32 1 1560000
+32 1 1580000
+32 1 1600000
+32 1 1620000
+32 1 1640000
+32 1 1660000
+32 1 1680000
+32 1 1700000
+32 1 1720000
+32 1 1740000
+32 1 1760000
+32 1 1780000
+32 1 1800000
+32 1 1820000
+32 1 1840000
+32 1 1860000
+32 1 1880000
+32 1 1900000
+32 1 1920000
+32 1 1940000
+32 1 1960000
+32 1 1980000
+32 1 2000000
+32 1 2020000
+32 1 2040000
+32 1 2060000
+32 1 2080000
+32 1 2100000
+32 1 2120000
+32 1 2140000
+32 1 2160000
+32 1 2180000
+32 1 2200000
+32 1 2220000
+32 1 2240000
+32 1 2260000
+32 1 2280000
+32 1 2300000
+32 1 2320000
+32 1 2340000
+32 1 2360000
+32 1 2380000
+32 1 2400000
+32 1 2420000
+32 1 2440000
+32 1 2460000
+32 1 2480000
+32 1 2500000
+32 1 2520000
+32 1 2540000
+32 1 2560000
+32 1 2580000
+32 1 2600000
+32 1 2620000
+32 1 2640000
+32 1 2660000
+32 1 2680000
+32 1 2700000
+32 1 2720000
+32 1 2740000
+32 1 2760000
+32 1 2780000
+32 1 2800000
+32 1 2820000
+32 1 2840000
+32 1 2860000
+32 1 2880000
+32 1 2900000
+32 1 2920000
+32 1 2940000
+32 1 2960000
+32 1 2980000
+32 1 3000000
+32 1 3020000
+32 1 3040000
+32 1 3060000
+32 1 3080000
+32 1 3100000
+32 1 3120000
+32 1 3140000
+32 1 3160000
+32 1 3180000
+32 1 3200000
+32 1 3220000
+32 1 3240000
+32 1 3260000
+32 1 3280000
+32 1 3300000
+32 1 3320000
+32 1 3340000
+32 1 3360000
+32 1 3380000
+32 1 3400000
+32 1 3420000
+32 1 3440000
+32 1 3460000
+32 1 3480000
+32 1 3500000
+32 1 3520000
+32 1 3540000
+32 1 3560000
+32 1 3580000
+32 1 3600000
+32 1 3620000
+32 1 3640000
+32 1 3660000
+32 1 3680000
+32 1 3700000
+32 1 3720000
+32 1 3740000
+32 1 3760000
+32 1 3780000
+32 1 3800000
+32 1 3820000
+32 1 3840000
+32 1 3860000
+32 1 3880000
+32 1 3900000
+32 1 3920000
+32 1 3940000
+32 1 3960000
+32 1 3980000
+32 1 4000000
+32 1 4020000
+32 1 4040000
+32 1 4060000
+32 1 4080000
+32 1 4100000
+32 1 4120000
+32 1 4140000
+32 1 4160000
+32 1 4180000
+32 1 4200000
+32 1 4220000
+32 1 4240000
+32 1 4260000
+32 1 4280000
+32 1 4300000
+32 1 4320000
+32 1 4340000
+32 1 4360000
+32 1 4380000
+32 1 4400000
+32 1 4420000
+32 1 4440000
+32 1 4460000
+32 1 4480000
+32 1 4500000
+32 1 4520000
+32 1 4540000
+32 1 4560000
+32 1 4580000
+32 1 4600000
+32 1 4620000
+32 1 4640000
+32 1 4660000
+32 1 4680000
+32 1 4700000
+32 1 4720000
+32 1 4740000
+32 1 4760000
+32 1 4780000
+32 1 4800000
+32 1 4820000
+32 1 4840000
+32 1 4860000
+32 1 4880000
+32 1 4900000
+32 1 4920000
+32 1 4940000
+32 1 4960000
+32 1 4980000
+32 1 5000000
+32 1 5020000
+32 1 5040000
+32 1 5060000
+32 1 5080000
+32 1 5100000
+32 1 5120000
+32 1 5140000
+32 1 5160000
+32 1 5180000
+32 1 5200000
+32 1 5220000
+32 1 5240000
+32 1 5260000
+32 1 5280000
+32 1 5300000
+32 1 5320000
+32 1 5340000
+32 1 5360000
+32 1 5380000
+32 1 5400000
+32 1 5420000
+32 1 5440000
+32 1 5460000
+32 1 5480000
+32 1 5500000
+32 1 5520000
+32 1 5540000
+32 1 5560000
+32 1 5580000
+32 1 5600000
+32 1 5620000
+32 1 5640000
+32 1 5660000
+32 1 5680000
+32 1 5700000
+32 1 5720000
+32 1 5740000
+32 1 5760000
+32 1 5780000
+32 1 5800000
+32 1 5820000
+32 1 5840000
+32 1 5860000
+32 1 5880000
+32 1 5900000
+32 1 5920000
+32 1 5940000
+32 1 5960000
+32 1 5980000
+32 1 6000000
+32 1 6020000
+32 1 6040000
+32 1 6060000
+32 1 6080000
+32 1 6100000
+32 1 6120000
+32 1 6140000
+32 1 6160000
+32 1 6180000
+32 1 6200000
+32 1 6220000
+32 1 6240000
+32 1 6260000
+32 1 6280000
+32 1 6300000
+32 1 6320000
+32 1 6340000
+32 1 6360000
+32 1 6380000
+32 1 6400000
+32 1 6420000
+32 1 6440000
+32 1 6460000
+32 1 6480000
+32 1 6500000
+32 1 6520000
+32 1 6540000
+32 1 6560000
+32 1 6580000
+32 1 6600000
+32 1 6620000
+32 1 6640000
+32 1 6660000
+32 1 6680000
+32 1 6700000
+32 1 6720000
+32 1 6740000
+32 1 6760000
+32 1 6780000
+32 1 6800000
+32 1 6820000
+32 1 6840000
+32 1 6860000
+32 1 6880000
+32 1 6900000
+32 1 6920000
+32 1 6940000
+32 1 6960000
+32 1 6980000
+32 1 7000000
+32 1 7020000
+32 1 7040000
+32 1 7060000
+32 1 7080000
+32 1 7100000
+32 1 7120000
+32 1 7140000
+32 1 7160000
+32 1 7180000
+32 1 7200000
+32 1 7220000
+32 1 7240000
+32 1 7260000
+32 1 7280000
+32 1 7300000
+32 1 7320000
+32 1 7340000
+32 1 7360000
+32 1 7380000
+32 1 7400000
+32 1 7420000
+32 1 7440000
+32 1 7460000
+32 1 7480000
+32 1 7500000
+32 1 7520000
+32 1 7540000
+32 1 7560000
+32 1 7580000
+32 1 7600000
+32 1 7620000
+32 1 7640000
+32 1 7660000
+32 1 7680000
+32 1 7700000
+32 1 7720000
+32 1 7740000
+32 1 7760000
+32 1 7780000
+32 1 7800000
+32 1 7820000
+32 1 7840000
+32 1 7860000
+32 1 7880000
+32 1 7900000
+32 1 7920000
+32 1 7940000
+32 1 7960000
+32 1 7980000
+32 1 8000000
+32 1 8020000
+32 1 8040000
+32 1 8060000
+32 1 8080000
+32 1 8100000
+32 1 8120000
+32 1 8140000
+32 1 8160000
+32 1 8180000
+32 1 8200000
+32 1 8220000
+32 1 8240000
+32 1 8260000
+32 1 8280000
+32 1 8300000
+32 1 8320000
+32 1 8340000
+32 1 8360000
+32 1 8380000
+32 1 8400000
+32 1 8420000
+32 1 8440000
+32 1 8460000
+32 1 8480000
+32 1 8500000
+32 1 8520000
+32 1 8540000
+32 1 8560000
+32 1 8580000
+32 1 8600000
+32 1 8620000
+32 1 8640000
+32 1 8660000
+32 1 8680000
+32 1 8700000
+32 1 8720000
+32 1 8740000
+32 1 8760000
+32 1 8780000
+32 1 8800000
+32 1 8820000
+32 1 8840000
+32 1 8860000
+32 1 8880000
+32 1 8900000
+32 1 8920000
+32 1 8940000
+32 1 8960000
+32 1 8980000
+32 1 9000000
+32 1 9020000
+32 1 9040000
+32 1 9060000
+32 1 9080000
+32 1 9100000
+32 1 9120000
+32 1 9140000
+32 1 9160000
+32 1 9180000
+32 1 9200000
+32 1 9220000
+32 1 9240000
+32 1 9260000
+32 1 9280000
+32 1 9300000
+32 1 9320000
+32 1 9340000
+32 1 9360000
+32 1 9380000
+32 1 9400000
+32 1 9420000
+32 1 9440000
+32 1 9460000
+32 1 9480000
+32 1 9500000
+32 1 9520000
+32 1 9540000
+32 1 9560000
+32 1 9580000
+32 1 9600000
+32 1 9620000
+32 1 9640000
+32 1 9660000
+32 1 9680000
+32 1 9700000
+32 1 9720000
+32 1 9740000
+32 1 9760000
+32 1 9780000
+32 1 9800000
+32 1 9820000
+32 1 9840000
+32 1 9860000
+32 1 9880000
+32 1 9900000
+32 1 9920000
+32 1 9940000
+32 1 9960000
+32 1 9980000
+32 1 10000000
+32 1 10020000
+32 1 10040000
+32 1 10060000
+32 1 10080000
+32 1 10100000
+32 1 10120000
+32 1 10140000
+32 1 10160000
+32 1 10180000
+32 1 10200000
+32 1 10220000
+32 1 10240000
+32 1 10260000
+32 1 10280000
+32 1 10300000
+32 1 10320000
+32 1 10340000
+32 1 10360000
+32 1 10380000
+32 1 10400000
+32 1 10420000
+32 1 10440000
+32 1 10460000
+32 1 10480000
+32 1 10500000
+32 1 10520000
+32 1 10540000
+32 1 10560000
+32 1 10580000
+32 1 10600000
+32 1 10620000
+32 1 10640000
+32 1 10660000
+32 1 10680000
+32 1 10700000
+32 1 10720000
+32 1 10740000
+32 1 10760000
+32 1 10780000
+32 1 10800000
+32 1 10820000
+32 1 10840000
+32 1 10860000
+32 1 10880000
+32 1 10900000
+32 1 10920000
+32 1 10940000
+32 1 10960000
+32 1 10980000
+32 1 11000000
+32 1 11020000
+32 1 11040000
+32 1 11060000
+32 1 11080000
+32 1 11100000
+32 1 11120000
+32 1 11140000
+32 1 11160000
+32 1 11180000
+32 1 11200000
+32 1 11220000
+32 1 11240000
+32 1 11260000
+32 1 11280000
+32 1 11300000
+32 1 11320000
+32 1 11340000
+32 1 11360000
+32 1 11380000
+32 1 11400000
+32 1 11420000
+32 1 11440000
+32 1 11460000
+32 1 11480000
+32 1 11500000
+32 1 11520000
+32 1 11540000
+32 1 11560000
+32 1 11580000
+32 1 11600000
+32 1 11620000
+32 1 11640000
+32 1 11660000
+32 1 11680000
+32 1 11700000
+32 1 11720000
+32 1 11740000
+32 1 11760000
+32 1 11780000
+32 1 11800000
+32 1 11820000
+32 1 11840000
+32 1 11860000
+32 1 11880000
+32 1 11900000
+32 1 11920000
+32 1 11940000
+32 1 11960000
+32 1 11980000
+32 1 12000000
+32 1 12020000
+32 1 12040000
+32 1 12060000
+32 1 12080000
+32 1 12100000
+32 1 12120000
+32 1 12140000
+32 1 12160000
+32 1 12180000
+32 1 12200000
+32 1 12220000
+32 1 12240000
+32 1 12260000
+32 1 12280000
+32 1 12300000
+32 1 12320000
+32 1 12340000
+32 1 12360000
+32 1 12380000
+32 1 12400000
+32 1 12420000
+32 1 12440000
+32 1 12460000
+32 1 12480000
+32 1 12500000
+32 1 12520000
+32 1 12540000
+32 1 12560000
+32 1 12580000
+32 1 12600000
+32 1 12620000
+32 1 12640000
+32 1 12660000
+32 1 12680000
+32 1 12700000
+32 1 12720000
+32 1 12740000
+32 1 12760000
+32 1 12780000
+32 1 12800000
+32 1 12820000
+32 1 12840000
+32 1 12860000
+32 1 12880000
+32 1 12900000
+32 1 12920000
+32 1 12940000
+32 1 12960000
+32 1 12980000
+32 1 13000000
+32 1 13020000
+32 1 13040000
+32 1 13060000
+32 1 13080000
+32 1 13100000
+32 1 13120000
+32 1 13140000
+32 1 13160000
+32 1 13180000
+32 1 13200000
+32 1 13220000
+32 1 13240000
+32 1 13260000
+32 1 13280000
+32 1 13300000
+32 1 13320000
+32 1 13340000
+32 1 13360000
+32 1 13380000
+32 1 13400000
+32 1 13420000
+32 1 13440000
+32 1 13460000
+32 1 13480000
+32 1 13500000
+32 1 13520000
+32 1 13540000
+32 1 13560000
+32 1 13580000
+32 1 13600000
+32 1 13620000
+32 1 13640000
+32 1 13660000
+32 1 13680000
+32 1 13700000
+32 1 13720000
+32 1 13740000
+32 1 13760000
+32 1 13780000
+32 1 13800000
+32 1 13820000
+32 1 13840000
+32 1 13860000
+32 1 13880000
+32 1 13900000
+32 1 13920000
+32 1 13940000
+32 1 13960000
+32 1 13980000
+32 1 14000000
+32 1 14020000
+32 1 14040000
+32 1 14060000
+32 1 14080000
+32 1 14100000
+32 1 14120000
+32 1 14140000
+32 1 14160000
+32 1 14180000
+32 1 14200000
+32 1 14220000
+32 1 14240000
+32 1 14260000
+32 1 14280000
+32 1 14300000
+32 1 14320000
+32 1 14340000
+32 1 14360000
+32 1 14380000
+32 1 14400000
+32 1 14420000
+32 1 14440000
+32 1 14460000
+32 1 14480000
+32 1 14500000
+32 1 14520000
+32 1 14540000
+32 1 14560000
+32 1 14580000
+32 1 14600000
+32 1 14620000
+32 1 14640000
+32 1 14660000
+32 1 14680000
+32 1 14700000
+32 1 14720000
+32 1 14740000
+32 1 14760000
+32 1 14780000
+32 1 14800000
+32 1 14820000
+32 1 14840000
+32 1 14860000
+32 1 14880000
+32 1 14900000
+32 1 14920000
+32 1 14940000
+32 1 14960000
+32 1 14980000
+32 1 15000000
+32 1 15020000
+32 1 15040000
+32 1 15060000
+32 1 15080000
+32 1 15100000
+32 1 15120000
+32 1 15140000
+32 1 15160000
+32 1 15180000
+32 1 15200000
+32 1 15220000
+32 1 15240000
+32 1 15260000
+32 1 15280000
+32 1 15300000
+32 1 15320000
+32 1 15340000
+32 1 15360000
+32 1 15380000
+32 1 15400000
+32 1 15420000
+32 1 15440000
+32 1 15460000
+32 1 15480000
+32 1 15500000
+32 1 15520000
+32 1 15540000
+32 1 15560000
+32 1 15580000
+32 1 15600000
+32 1 15620000
+32 1 15640000
+32 1 15660000
+32 1 15680000
+32 1 15700000
+32 1 15720000
+32 1 15740000
+32 1 15760000
+32 1 15780000
+32 1 15800000
+32 1 15820000
+32 1 15840000
+32 1 15860000
+32 1 15880000
+32 1 15900000
+32 1 15920000
+32 1 15940000
+32 1 15960000
+32 1 15980000
+32 1 16000000
+32 1 16020000
+32 1 16040000
+32 1 16060000
+32 1 16080000
+32 1 16100000
+32 1 16120000
+32 1 16140000
+32 1 16160000
+32 1 16180000
+32 1 16200000
+32 1 16220000
+32 1 16240000
+32 1 16260000
+32 1 16280000
+32 1 16300000
+32 1 16320000
+32 1 16340000
+32 1 16360000
+32 1 16380000
+32 1 16400000
+32 1 16420000
+32 1 16440000
+32 1 16460000
+32 1 16480000
+32 1 16500000
+32 1 16520000
+32 1 16540000
+32 1 16560000
+32 1 16580000
+32 1 16600000
+32 1 16620000
+32 1 16640000
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
index 9a42d72..8cbb7a7 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
@@ -421,17 +421,21 @@
ASSERT_EQ(mDisableTest, false);
}
+class Codec2VideoDecDecodeTest : public Codec2VideoDecHidlTest,
+ public ::testing::WithParamInterface<int32_t> {
+};
+
// Bitstream Test
-TEST_F(Codec2VideoDecHidlTest, DecodeTest) {
+TEST_P(Codec2VideoDecDecodeTest, DecodeTest) {
description("Decodes input file");
if (mDisableTest) return;
+ uint32_t streamIndex = GetParam();
char mURL[512], info[512];
std::ifstream eleStream, eleInfo;
-
strcpy(mURL, gEnv->getRes().c_str());
strcpy(info, gEnv->getRes().c_str());
- GetURLForComponent(mCompName, mURL, info);
+ GetURLForComponent(mCompName, mURL, info, streamIndex);
eleInfo.open(info);
ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
@@ -452,6 +456,9 @@
eleInfo.close();
ASSERT_EQ(mComponent->start(), C2_OK);
+ // Reset total no of frames received
+ mFramesReceived = 0;
+ mTimestampUs = 0;
ALOGV("mURL : %s", mURL);
eleStream.open(mURL, std::ifstream::binary);
ASSERT_EQ(eleStream.is_open(), true);
@@ -476,8 +483,11 @@
}
if (mTimestampDevTest) EXPECT_EQ(mTimestampUslist.empty(), true);
+ ASSERT_EQ(mComponent->stop(), C2_OK);
}
+INSTANTIATE_TEST_CASE_P(StreamIndexes, Codec2VideoDecDecodeTest,
+ ::testing::Values(0, 1));
// Adaptive Test
TEST_F(Codec2VideoDecHidlTest, AdaptiveDecodeTest) {
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index ff3e534..f5cc9ff 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -557,6 +557,7 @@
for (size_t i = 0; i < t.size(); ++i) {
c2_status_t status = objcpy(
&mTraitsList[i], &mAliasesBuffer[i], t[i]);
+ mTraitsList[i].owner = mInstanceName;
if (status != C2_OK) {
ALOGE("listComponents -- corrupted output.");
return;
diff --git a/media/codec2/sfplugin/Codec2InfoBuilder.cpp b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
index f36027e..a8cc62d 100644
--- a/media/codec2/sfplugin/Codec2InfoBuilder.cpp
+++ b/media/codec2/sfplugin/Codec2InfoBuilder.cpp
@@ -73,10 +73,10 @@
constexpr OMX_U32 kMaxIndicesToCheck = 32;
status_t queryOmxCapabilities(
- const char* name, const char* mime, bool isEncoder,
+ const char* name, const char* mediaType, bool isEncoder,
MediaCodecInfo::CapabilitiesWriter* caps) {
- const char *role = GetComponentRole(isEncoder, mime);
+ const char *role = GetComponentRole(isEncoder, mediaType);
if (role == nullptr) {
return BAD_VALUE;
}
@@ -128,8 +128,8 @@
return err;
}
- bool isVideo = hasPrefix(mime, "video/") == 0;
- bool isImage = hasPrefix(mime, "image/") == 0;
+ bool isVideo = hasPrefix(mediaType, "video/") == 0;
+ bool isImage = hasPrefix(mediaType, "image/") == 0;
if (isVideo || isImage) {
OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
@@ -149,7 +149,7 @@
// AVC components may not list the constrained profiles explicitly, but
// decoders that support a profile also support its constrained version.
// Encoders must explicitly support constrained profiles.
- if (!isEncoder && strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
+ if (!isEncoder && strcasecmp(mediaType, MEDIA_MIMETYPE_VIDEO_AVC) == 0) {
if (param.eProfile == OMX_VIDEO_AVCProfileHigh) {
caps->addProfileLevel(OMX_VIDEO_AVCProfileConstrainedHigh, param.eLevel);
} else if (param.eProfile == OMX_VIDEO_AVCProfileBaseline) {
@@ -193,7 +193,7 @@
asString(portFormat.eColorFormat), portFormat.eColorFormat);
}
}
- } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
+ } else if (strcasecmp(mediaType, MEDIA_MIMETYPE_AUDIO_AAC) == 0) {
// More audio codecs if they have profiles.
OMX_AUDIO_PARAM_ANDROID_PROFILETYPE param;
InitOMXParams(¶m);
@@ -228,14 +228,17 @@
if (omxNode->configureVideoTunnelMode(
kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
// tunneled playback includes adaptive playback
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
- | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
- } else if (omxNode->setPortMode(
- kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
- omxNode->prepareForAdaptivePlayback(
- kPortIndexOutput, OMX_TRUE,
- 1280 /* width */, 720 /* height */) == OK) {
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
+ } else {
+ // tunneled playback is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK);
+ if (omxNode->setPortMode(
+ kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
+ omxNode->prepareForAdaptivePlayback(
+ kPortIndexOutput, OMX_TRUE,
+ 1280 /* width */, 720 /* height */) != OK) {
+ // adaptive playback is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
+ }
}
}
@@ -243,11 +246,20 @@
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
InitOMXParams(¶ms);
params.nPortIndex = kPortIndexOutput;
- // TODO: should we verify if fallback is supported?
+
+ OMX_VIDEO_PARAM_INTRAREFRESHTYPE fallbackParams;
+ InitOMXParams(&fallbackParams);
+ fallbackParams.nPortIndex = kPortIndexOutput;
+ fallbackParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
+
if (omxNode->getConfig(
(OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
- ¶ms, sizeof(params)) == OK) {
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
+ ¶ms, sizeof(params)) != OK &&
+ omxNode->getParameter(
+ OMX_IndexParamVideoIntraRefresh, &fallbackParams,
+ sizeof(fallbackParams)) != OK) {
+ // intra refresh is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH);
}
}
@@ -270,12 +282,26 @@
writer->addMediaCodecInfo();
info->setName(name.c_str());
info->setOwner("default");
- info->setEncoder(encoder);
+ typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;
+ if (encoder) {
+ attrs |= MediaCodecInfo::kFlagIsEncoder;
+ }
+ // NOTE: we don't support software-only codecs in OMX
+ if (!hasPrefix(name, "OMX.google.")) {
+ attrs |= MediaCodecInfo::kFlagIsVendor;
+ if (properties.quirkSet.find("attribute::software-codec")
+ == properties.quirkSet.end()) {
+ attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+ }
+ }
+ info->setAttributes(attrs);
info->setRank(omxRank);
- for (const MediaCodecsXmlParser::Type& type : properties.typeMap) {
- const std::string &mime = type.first;
+ // OMX components don't have aliases
+ for (const MediaCodecsXmlParser::Type &type : properties.typeMap) {
+ const std::string &mediaType = type.first;
+
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
- info->addMime(mime.c_str());
+ info->addMediaType(mediaType.c_str());
const MediaCodecsXmlParser::AttributeMap &attrMap = type.second;
for (const MediaCodecsXmlParser::Attribute& attr : attrMap) {
const std::string &key = attr.first;
@@ -289,13 +315,13 @@
}
status_t err = queryOmxCapabilities(
name.c_str(),
- mime.c_str(),
+ mediaType.c_str(),
encoder,
caps.get());
if (err != OK) {
- ALOGE("Failed to query capabilities for %s (mime: %s). Error: %d",
+ ALOGI("Failed to query capabilities for %s (media type: %s). Error: %d",
name.c_str(),
- mime.c_str(),
+ mediaType.c_str(),
static_cast<int>(err));
}
}
@@ -407,20 +433,40 @@
break;
}
+ ALOGV("canonName = %s", canonName.c_str());
std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
codecInfo->setName(trait.name.c_str());
- codecInfo->setOwner("codec2");
+ codecInfo->setOwner(("codec2::" + trait.owner).c_str());
+ const MediaCodecsXmlParser::CodecProperties &codec = parser.getCodecMap().at(canonName);
+
bool encoder = trait.kind == C2Component::KIND_ENCODER;
- codecInfo->setEncoder(encoder);
+ typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs = 0;
+
+ if (encoder) {
+ attrs |= MediaCodecInfo::kFlagIsEncoder;
+ }
+ if (trait.owner == "software") {
+ attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
+ } else {
+ attrs |= MediaCodecInfo::kFlagIsVendor;
+ if (trait.owner == "vendor-software") {
+ attrs |= MediaCodecInfo::kFlagIsSoftwareOnly;
+ } else if (codec.quirkSet.find("attribute::software-codec") == codec.quirkSet.end()) {
+ attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+ }
+ }
+ codecInfo->setAttributes(attrs);
codecInfo->setRank(rank);
- const MediaCodecsXmlParser::CodecProperties &codec =
- parser.getCodecMap().at(canonName);
+
+ for (const std::string &alias : codec.aliases) {
+ codecInfo->addAlias(alias.c_str());
+ }
for (auto typeIt = codec.typeMap.begin(); typeIt != codec.typeMap.end(); ++typeIt) {
const std::string &mediaType = typeIt->first;
const MediaCodecsXmlParser::AttributeMap &attrMap = typeIt->second;
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
- codecInfo->addMime(mediaType.c_str());
+ codecInfo->addMediaType(mediaType.c_str());
for (auto attrIt = attrMap.begin(); attrIt != attrMap.end(); ++attrIt) {
std::string key, value;
std::tie(key, value) = *attrIt;
@@ -450,6 +496,23 @@
asString(err), asString(profileQuery[0].status));
if (err == C2_OK && profileQuery[0].status == C2_OK) {
if (profileQuery[0].values.type == C2FieldSupportedValues::VALUES) {
+ std::vector<std::shared_ptr<C2ParamDescriptor>> paramDescs;
+ c2_status_t err1 = intf->querySupportedParams(¶mDescs);
+ bool isHdr = false, isHdr10Plus = false;
+ if (err1 == C2_OK) {
+ for (const std::shared_ptr<C2ParamDescriptor> &desc : paramDescs) {
+ if ((uint32_t)desc->index() ==
+ C2StreamHdr10PlusInfo::output::PARAM_TYPE) {
+ isHdr10Plus = true;
+ } else if ((uint32_t)desc->index() ==
+ C2StreamHdrStaticInfo::output::PARAM_TYPE) {
+ isHdr = true;
+ }
+ }
+ }
+ // For VP9, the static info is always propagated by framework.
+ isHdr |= (mediaType == MIMETYPE_VIDEO_VP9);
+
for (C2Value::Primitive profile : profileQuery[0].values.values) {
pl.profile = (C2Config::profile_t)profile.ref<uint32_t>();
std::vector<std::unique_ptr<C2SettingResult>> failures;
@@ -473,6 +536,26 @@
caps->addProfileLevel(
(uint32_t)sdkProfile, (uint32_t)sdkLevel);
gotProfileLevels = true;
+ if (isHdr) {
+ auto hdrMapper = C2Mapper::GetHdrProfileLevelMapper(
+ trait.mediaType);
+ if (hdrMapper && hdrMapper->mapProfile(
+ pl.profile, &sdkProfile)) {
+ caps->addProfileLevel(
+ (uint32_t)sdkProfile,
+ (uint32_t)sdkLevel);
+ }
+ if (isHdr10Plus) {
+ hdrMapper = C2Mapper::GetHdrProfileLevelMapper(
+ trait.mediaType, true /*isHdr10Plus*/);
+ if (hdrMapper && hdrMapper->mapProfile(
+ pl.profile, &sdkProfile)) {
+ caps->addProfileLevel(
+ (uint32_t)sdkProfile,
+ (uint32_t)sdkLevel);
+ }
+ }
+ }
} else if (!mapper) {
caps->addProfileLevel(pl.profile, pl.level);
gotProfileLevels = true;
@@ -517,6 +600,13 @@
caps->addProfileLevel(VP9Profile2, VP9Level5);
caps->addProfileLevel(VP9Profile2HDR, VP9Level5);
}
+ } else if (mediaType == MIMETYPE_VIDEO_AV1 && !encoder) {
+ caps->addProfileLevel(AV1Profile0, AV1Level2);
+ caps->addProfileLevel(AV1Profile0, AV1Level21);
+ caps->addProfileLevel(AV1Profile1, AV1Level22);
+ caps->addProfileLevel(AV1Profile1, AV1Level3);
+ caps->addProfileLevel(AV1Profile2, AV1Level31);
+ caps->addProfileLevel(AV1Profile2, AV1Level32);
} else if (mediaType == MIMETYPE_VIDEO_HEVC && !encoder) {
caps->addProfileLevel(HEVCProfileMain, HEVCMainTierLevel51);
caps->addProfileLevel(HEVCProfileMainStill, HEVCMainTierLevel51);
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index 97e17e8..c369e16 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -253,6 +253,14 @@
{ C2Config::PROFILE_HEVC_MAIN_10_INTRA, HEVCProfileMain10 },
};
+ALookup<C2Config::profile_t, int32_t> sHevcHdrProfiles = {
+ { C2Config::PROFILE_HEVC_MAIN_10, HEVCProfileMain10HDR10 },
+};
+
+ALookup<C2Config::profile_t, int32_t> sHevcHdr10PlusProfiles = {
+ { C2Config::PROFILE_HEVC_MAIN_10, HEVCProfileMain10HDR10Plus },
+};
+
ALookup<C2Config::level_t, int32_t> sMpeg2Levels = {
{ C2Config::LEVEL_MP2V_LOW, MPEG2LevelLL },
{ C2Config::LEVEL_MP2V_MAIN, MPEG2LevelML },
@@ -324,8 +332,57 @@
{ C2Config::PROFILE_VP9_1, VP9Profile1 },
{ C2Config::PROFILE_VP9_2, VP9Profile2 },
{ C2Config::PROFILE_VP9_3, VP9Profile3 },
+ { C2Config::PROFILE_VP9_2, VP9Profile2HDR },
+ { C2Config::PROFILE_VP9_3, VP9Profile3HDR },
+ { C2Config::PROFILE_VP9_2, VP9Profile2HDR10Plus },
+ { C2Config::PROFILE_VP9_3, VP9Profile3HDR10Plus },
};
+ALookup<C2Config::profile_t, int32_t> sVp9HdrProfiles = {
+ { C2Config::PROFILE_VP9_2, VP9Profile2HDR },
+ { C2Config::PROFILE_VP9_3, VP9Profile3HDR },
+};
+
+ALookup<C2Config::profile_t, int32_t> sVp9Hdr10PlusProfiles = {
+ { C2Config::PROFILE_VP9_2, VP9Profile2HDR10Plus },
+ { C2Config::PROFILE_VP9_3, VP9Profile3HDR10Plus },
+};
+
+ALookup<C2Config::level_t, int32_t> sAv1Levels = {
+ { C2Config::LEVEL_AV1_2, AV1Level2 },
+ { C2Config::LEVEL_AV1_2_1, AV1Level21 },
+ { C2Config::LEVEL_AV1_2_2, AV1Level22 },
+ { C2Config::LEVEL_AV1_2_3, AV1Level23 },
+ { C2Config::LEVEL_AV1_3, AV1Level3 },
+ { C2Config::LEVEL_AV1_3_1, AV1Level31 },
+ { C2Config::LEVEL_AV1_3_2, AV1Level32 },
+ { C2Config::LEVEL_AV1_3_3, AV1Level33 },
+ { C2Config::LEVEL_AV1_4, AV1Level4 },
+ { C2Config::LEVEL_AV1_4_1, AV1Level41 },
+ { C2Config::LEVEL_AV1_4_2, AV1Level42 },
+ { C2Config::LEVEL_AV1_4_3, AV1Level43 },
+ { C2Config::LEVEL_AV1_5, AV1Level5 },
+ { C2Config::LEVEL_AV1_5_1, AV1Level51 },
+ { C2Config::LEVEL_AV1_5_2, AV1Level52 },
+ { C2Config::LEVEL_AV1_5_3, AV1Level53 },
+ { C2Config::LEVEL_AV1_6, AV1Level6 },
+ { C2Config::LEVEL_AV1_6_1, AV1Level61 },
+ { C2Config::LEVEL_AV1_6_2, AV1Level62 },
+ { C2Config::LEVEL_AV1_6_3, AV1Level63 },
+ { C2Config::LEVEL_AV1_7, AV1Level7 },
+ { C2Config::LEVEL_AV1_7_1, AV1Level71 },
+ { C2Config::LEVEL_AV1_7_2, AV1Level72 },
+ { C2Config::LEVEL_AV1_7_3, AV1Level73 },
+};
+
+
+ALookup<C2Config::profile_t, int32_t> sAv1Profiles = {
+ { C2Config::PROFILE_AV1_0, AV1Profile0 },
+ { C2Config::PROFILE_AV1_1, AV1Profile1 },
+ { C2Config::PROFILE_AV1_2, AV1Profile2 },
+};
+
+
/**
* A helper that passes through vendor extension profile and level values.
*/
@@ -426,6 +483,10 @@
};
struct HevcProfileLevelMapper : ProfileLevelMapperHelper {
+ HevcProfileLevelMapper(bool isHdr = false, bool isHdr10Plus = false) :
+ ProfileLevelMapperHelper(),
+ mIsHdr(isHdr), mIsHdr10Plus(isHdr10Plus) {}
+
virtual bool simpleMap(C2Config::level_t from, int32_t *to) {
return sHevcLevels.map(from, to);
}
@@ -433,11 +494,19 @@
return sHevcLevels.map(from, to);
}
virtual bool simpleMap(C2Config::profile_t from, int32_t *to) {
- return sHevcProfiles.map(from, to);
+ return mIsHdr10Plus ? sHevcHdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sHevcHdrProfiles.map(from, to) :
+ sHevcProfiles.map(from, to);
}
virtual bool simpleMap(int32_t from, C2Config::profile_t *to) {
- return sHevcProfiles.map(from, to);
+ return mIsHdr10Plus ? sHevcHdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sHevcHdrProfiles.map(from, to) :
+ sHevcProfiles.map(from, to);
}
+
+private:
+ bool mIsHdr;
+ bool mIsHdr10Plus;
};
struct Mpeg2ProfileLevelMapper : ProfileLevelMapperHelper {
@@ -492,6 +561,10 @@
};
struct Vp9ProfileLevelMapper : ProfileLevelMapperHelper {
+ Vp9ProfileLevelMapper(bool isHdr = false, bool isHdr10Plus = false) :
+ ProfileLevelMapperHelper(),
+ mIsHdr(isHdr), mIsHdr10Plus(isHdr10Plus) {}
+
virtual bool simpleMap(C2Config::level_t from, int32_t *to) {
return sVp9Levels.map(from, to);
}
@@ -499,11 +572,19 @@
return sVp9Levels.map(from, to);
}
virtual bool simpleMap(C2Config::profile_t from, int32_t *to) {
- return sVp9Profiles.map(from, to);
+ return mIsHdr10Plus ? sVp9Hdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sVp9HdrProfiles.map(from, to) :
+ sVp9Profiles.map(from, to);
}
virtual bool simpleMap(int32_t from, C2Config::profile_t *to) {
- return sVp9Profiles.map(from, to);
+ return mIsHdr10Plus ? sVp9Hdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sVp9HdrProfiles.map(from, to) :
+ sVp9Profiles.map(from, to);
}
+
+private:
+ bool mIsHdr;
+ bool mIsHdr10Plus;
};
} // namespace
@@ -535,6 +616,18 @@
}
// static
+std::shared_ptr<C2Mapper::ProfileLevelMapper>
+C2Mapper::GetHdrProfileLevelMapper(std::string mediaType, bool isHdr10Plus) {
+ std::transform(mediaType.begin(), mediaType.begin(), mediaType.end(), ::tolower);
+ if (mediaType == MIMETYPE_VIDEO_HEVC) {
+ return std::make_shared<HevcProfileLevelMapper>(true, isHdr10Plus);
+ } else if (mediaType == MIMETYPE_VIDEO_VP9) {
+ return std::make_shared<Vp9ProfileLevelMapper>(true, isHdr10Plus);
+ }
+ return nullptr;
+}
+
+// static
bool C2Mapper::map(C2Config::bitrate_mode_t from, int32_t *to) {
return sBitrateModes.map(from, to);
}
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.h b/media/codec2/sfplugin/utils/Codec2Mapper.h
index 1eeb92e..cec6f07 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.h
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.h
@@ -40,6 +40,9 @@
static std::shared_ptr<ProfileLevelMapper>
GetProfileLevelMapper(std::string mediaType);
+ static std::shared_ptr<ProfileLevelMapper>
+ GetHdrProfileLevelMapper(std::string mediaType, bool isHdr10Plus = false);
+
// convert between bitrates
static bool map(C2Config::bitrate_mode_t, int32_t*);
static bool map(int32_t, C2Config::bitrate_mode_t*);
diff --git a/media/codec2/vndk/C2Config.cpp b/media/codec2/vndk/C2Config.cpp
index da12903..782bec5 100644
--- a/media/codec2/vndk/C2Config.cpp
+++ b/media/codec2/vndk/C2Config.cpp
@@ -139,6 +139,9 @@
{ "vp9-1", C2Config::PROFILE_VP9_1 },
{ "vp9-2", C2Config::PROFILE_VP9_2 },
{ "vp9-3", C2Config::PROFILE_VP9_3 },
+ { "av1-0", C2Config::PROFILE_AV1_0 },
+ { "av1-1", C2Config::PROFILE_AV1_1 },
+ { "av1-2", C2Config::PROFILE_AV1_2 },
}))
DEFINE_C2_ENUM_VALUE_CUSTOM_HELPER(C2Config::level_t, ({
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 2d4e19e..a5dd203 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -821,6 +821,7 @@
emplace("c2.android.vp9.decoder", "libcodec2_soft_vp9dec.so");
emplace("c2.android.vp8.encoder", "libcodec2_soft_vp8enc.so");
emplace("c2.android.vp9.encoder", "libcodec2_soft_vp9enc.so");
+ emplace("c2.android.av1.decoder", "libcodec2_soft_av1dec.so");
emplace("c2.android.raw.decoder", "libcodec2_soft_rawdec.so");
emplace("c2.android.flac.decoder", "libcodec2_soft_flacdec.so");
emplace("c2.android.flac.encoder", "libcodec2_soft_flacenc.so");
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 4e9ac6e..beddad0 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -377,6 +377,10 @@
return NULL;
}
+static const char *extensions[] = {
+ "aac",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -387,7 +391,7 @@
UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
1, // version
"AAC Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 00d2a92..ffeff42 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -199,7 +199,7 @@
if (mInitCheck == OK) {
AMediaFormat_setString(meta,
- AMEDIAFORMAT_KEY_MIME, mIsWide ? "audio/amr-wb" : "audio/amr");
+ AMEDIAFORMAT_KEY_MIME, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : "audio/amr");
}
return AMEDIA_OK;
@@ -280,8 +280,8 @@
ReadOptions::SeekMode mode;
if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) {
size_t size;
- int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame.
- mCurrentTimeUs = seekFrame * 20000ll;
+ int64_t seekFrame = seekTimeUs / 20000LL; // 20ms per frame.
+ mCurrentTimeUs = seekFrame * 20000LL;
size_t index = seekFrame < 0 ? 0 : seekFrame / 50;
if (index >= mOffsetTableLength) {
@@ -358,6 +358,12 @@
////////////////////////////////////////////////////////////////////////////////
+static const char *extensions[] = {
+ "amr",
+ "awb",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -368,21 +374,24 @@
1,
"AMR Extractor",
{
- .v2 = [](
- CDataSource *source,
- float *confidence,
- void **,
- FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffAMR(&helper, nullptr, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new AMRExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
- }
- }
+ .v3 = {
+ [](
+ CDataSource *source,
+ float *confidence,
+ void **,
+ FreeMetaFunc *) -> CreatorFunc {
+ DataSourceHelper helper(source);
+ if (SniffAMR(&helper, nullptr, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new AMRExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
+ },
+ },
};
}
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index b5eaf9b..84fbcee 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -806,14 +806,42 @@
bool SniffFLAC(DataSourceHelper *source, float *confidence)
{
- // first 4 is the signature word
- // second 4 is the sizeof STREAMINFO
- // 042 is the mandatory STREAMINFO
- // no need to read rest of the header, as a premature EOF will be caught later
- uint8_t header[4+4];
- if (source->readAt(0, header, sizeof(header)) != sizeof(header)
- || memcmp("fLaC\0\0\0\042", header, 4+4))
- {
+ // Skip ID3 tags
+ off64_t pos = 0;
+ uint8_t header[10];
+ for (;;) {
+ if (source->readAt(pos, header, sizeof(header)) != sizeof(header)) {
+ return false; // no more file to read.
+ }
+
+ // check for ID3 tag
+ if (memcmp("ID3", header, 3) != 0) {
+ break; // not an ID3 tag.
+ }
+
+ // skip the ID3v2 data and check again
+ const unsigned id3Len = 10 +
+ (((header[6] & 0x7f) << 21)
+ | ((header[7] & 0x7f) << 14)
+ | ((header[8] & 0x7f) << 7)
+ | (header[9] & 0x7f));
+ pos += id3Len;
+
+ ALOGV("skipped ID3 tag of len %u new starting offset is %#016llx",
+ id3Len, (long long)pos);
+ }
+
+ // Check FLAC header.
+ // https://xiph.org/flac/format.html#stream
+ //
+ // Note: content stored big endian.
+ // byte offset bit size content
+ // 0 32 fLaC
+ // 4 8 metadata type STREAMINFO (0) (note: OR with 0x80 if last metadata)
+ // 5 24 size of metadata, for STREAMINFO (0x22).
+
+ if (memcmp("fLaC\x00\x00\x00\x22", header, 8) != 0 &&
+ memcmp("fLaC\x80\x00\x00\x22", header, 8) != 0) {
return false;
}
@@ -822,6 +850,11 @@
return true;
}
+static const char *extensions[] = {
+ "flac",
+ "fl",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -833,21 +866,24 @@
1,
"FLAC Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffFLAC(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new FLACExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffFLAC(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new FLACExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 0c74376..9f4f9e6 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -326,6 +326,18 @@
}
+static const char *extensions[] = {
+ "imy",
+ "mid",
+ "midi",
+ "mxmf",
+ "ota",
+ "rtttl",
+ "rtx",
+ "smf",
+ "xmf",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -337,20 +349,23 @@
1,
"MIDI Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- if (SniffMidi(source, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MidiExtractor(source));};
- }
- return NULL;
+ if (SniffMidi(source, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MidiExtractor(source));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 42a9c42..4200a46 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1463,6 +1463,8 @@
AMediaFormat_setBuffer(meta,
AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
}
+ } else if (!strcmp("V_AV1", codecID)) {
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AV1);
} else {
ALOGW("%s is not supported.", codecID);
continue;
@@ -1667,6 +1669,12 @@
return true;
}
+static const char *extensions[] = {
+ "mka",
+ "mkv",
+ "webm",
+ NULL
+};
extern "C" {
// This is the only symbol that needs to be exported
@@ -1678,19 +1686,22 @@
1,
"Matroska Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMatroska(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMatroska(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
}
};
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 20bcda8..61838f6 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -609,7 +609,7 @@
if (mInitCheck != OK) {
return AMEDIA_ERROR_UNKNOWN;
}
- AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, "audio/mpeg");
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
DataSourceHelper helper(mDataSource);
ID3 id3(&helper);
@@ -707,6 +707,14 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "mp3",
+ "mpeg",
+ "mpg",
+ "mpga",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -716,7 +724,7 @@
UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
1, // version
"MP3 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} }
};
}
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 9eb72a7..ca51b88 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -71,7 +71,7 @@
size_t numFrames = U32_AT(&vbriHeader[14]);
int64_t durationUs =
- numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
+ numFrames * 1000000LL * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
ALOGV("duration = %.2f secs", durationUs / 1E6);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 253f400..cc1534a 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -343,6 +343,8 @@
case FOURCC('a', 'l', 'a', 'c'):
return MEDIA_MIMETYPE_AUDIO_ALAC;
+ case FOURCC('a', 'v', '0', '1'):
+ return MEDIA_MIMETYPE_VIDEO_AV1;
default:
ALOGW("Unknown fourcc: %c%c%c%c",
(fourcc >> 24) & 0xff,
@@ -983,6 +985,22 @@
off64_t stop_offset = *offset + chunk_size;
*offset = data_offset;
while (*offset < stop_offset) {
+
+ // pass udata terminate
+ if (mIsQT && stop_offset - *offset == 4 && chunk_type == FOURCC("udta")) {
+ // handle the case that udta terminates with terminate code x00000000
+ // note that 0 terminator is optional and we just handle this case.
+ uint32_t terminate_code = 1;
+ mDataSource->readAt(*offset, &terminate_code, 4);
+ if (0 == terminate_code) {
+ *offset += 4;
+ ALOGD("Terminal code for udta");
+ continue;
+ } else {
+ ALOGW("invalid udta Terminal code");
+ }
+ }
+
status_t err = parseChunk(offset, depth + 1);
if (err != OK) {
if (isTrack) {
@@ -1754,6 +1772,7 @@
case FOURCC('a', 'v', 'c', '1'):
case FOURCC('h', 'v', 'c', '1'):
case FOURCC('h', 'e', 'v', '1'):
+ case FOURCC('a', 'v', '0', '1'):
{
uint8_t buffer[78];
if (chunk_data_size < (ssize_t)sizeof(buffer)) {
@@ -5139,7 +5158,7 @@
sampleCtsOffset = 0;
}
- if (size < (off64_t)(sampleCount * bytesPerSample)) {
+ if (size < (off64_t)sampleCount * bytesPerSample) {
return -EINVAL;
}
@@ -6017,6 +6036,7 @@
FOURCC('a', 'v', 'c', '1'),
FOURCC('h', 'v', 'c', '1'),
FOURCC('h', 'e', 'v', '1'),
+ FOURCC('a', 'v', '0', '1'),
FOURCC('3', 'g', 'p', '4'),
FOURCC('m', 'p', '4', '1'),
FOURCC('m', 'p', '4', '2'),
@@ -6179,6 +6199,19 @@
return NULL;
}
+static const char *extensions[] = {
+ "3g2",
+ "3gp",
+ "3gpp",
+ "3gpp2",
+ "m4a",
+ "m4r",
+ "m4v",
+ "mov",
+ "mp4",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -6188,7 +6221,7 @@
UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
2, // version
"MP4 Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index b816093..2a94671 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -28,9 +28,8 @@
static_libs: [
"libcrypto",
- "libstagefright_foundation",
+ "libstagefright_foundation_without_imemory",
"libstagefright_mpeg2support",
- "libmediaextractor",
"libutils",
"libstagefright",
"libstagefright_esds",
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 2f4196c..946a2a9 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <media/MediaExtractorPluginHelper.h>
+#include <media/stagefright/MediaDefs.h>
#include "MPEG2PSExtractor.h"
#include "MPEG2TSExtractor.h"
@@ -26,6 +27,12 @@
struct CDataSource;
+static const char *extensions[] = {
+ "m2p",
+ "ts",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -36,26 +43,29 @@
1,
"MPEG2-PS/TS Extractor",
{
- .v2 = [](
+ .v3 = {
+ [](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
- DataSourceHelper helper(source);
- if (SniffMPEG2TS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
- } else if (SniffMPEG2PS(&helper, confidence)) {
- return [](
- CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
- }
- return NULL;
+ DataSourceHelper helper(source);
+ if (SniffMPEG2TS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+ } else if (SniffMPEG2PS(&helper, confidence)) {
+ return [](
+ CDataSource *source,
+ void *) -> CMediaExtractor* {
+ return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
+ }
+ return NULL;
+ },
+ extensions
}
- }
+ },
};
}
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 554d252..731584d 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -734,6 +734,9 @@
if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
}
+ if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+ AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+ }
mbuf->release();
return AMEDIA_OK;
}
@@ -790,6 +793,7 @@
}
media_status_t MPEG2PSExtractor::WrappedTrack::start() {
+ mTrack->mBufferGroup = mBufferGroup;
return mTrack->start();
}
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 3bb2af7..e1509ee 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -224,6 +224,9 @@
if (inMeta.findData(kKeySEI, &bufType, &bufData, &bufSize)) {
AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_SEI, bufData, bufSize);
}
+ if (inMeta.findData(kKeyAudioPresentationInfo, &bufType, &bufData, &bufSize)) {
+ AMediaFormat_setBuffer(outMeta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, bufData, bufSize);
+ }
mbuf->release();
return AMEDIA_OK;
}
@@ -373,7 +376,7 @@
}
// Wait only for 2 seconds to detect audio/video streams.
- if (ALooper::GetNowUs() - startTime > 2000000ll) {
+ if (ALooper::GetNowUs() - startTime > 2000000LL) {
break;
}
}
@@ -385,7 +388,7 @@
List<int64_t> durations;
// Estimate duration --- stabilize until you get <500ms deviation.
while (feedMore() == OK
- && ALooper::GetNowUs() - startTime <= 2000000ll) {
+ && ALooper::GetNowUs() - startTime <= 2000000LL) {
if (mSeekSyncPoints->size() > prevSyncSize) {
prevSyncSize = mSeekSyncPoints->size();
int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index c3914f1..596c1c8 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -515,10 +515,10 @@
ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes",
sizeof(header), (long long)offset, n);
- if (n < 0) {
- return n;
- } else if (n == 0) {
+ if (n == 0 || n == ERROR_END_OF_STREAM) {
return AMEDIA_ERROR_END_OF_STREAM;
+ } else if (n < 0) {
+ return AMEDIA_ERROR_UNKNOWN;
} else {
return AMEDIA_ERROR_IO;
}
@@ -872,7 +872,7 @@
ALOGV("readPage returned %zd", n);
- return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM;
+ return (media_status_t) n;
}
// Prevent a harmless unsigned integer overflow by clamping to 0
@@ -1379,6 +1379,12 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "oga",
+ "ogg",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -1388,7 +1394,7 @@
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version
"Ogg Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 6f9f689..e58bd1f 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -616,6 +616,11 @@
return CreateExtractor;
}
+static const char *extensions[] = {
+ "wav",
+ NULL
+};
+
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
@@ -625,7 +630,7 @@
UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
1, // version
"WAV Extractor",
- { .v2 = Sniff }
+ { .v3 = {Sniff, extensions} },
};
}
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 1493b26..8e36c77 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -373,6 +373,13 @@
* so the recorded volume may be very low.
*/
AAUDIO_INPUT_PRESET_UNPROCESSED = 9,
+
+ /**
+ * Use this preset for capturing audio meant to be processed in real time
+ * and played back for live performance (e.g karaoke).
+ * The capture path will minimize latency and coupling with playback path.
+ */
+ AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
};
typedef int32_t aaudio_input_preset_t;
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index bd42697..88da53a 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -158,6 +158,7 @@
case AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION:
case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
case AAUDIO_INPUT_PRESET_UNPROCESSED:
+ case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
break; // valid
default:
ALOGE("input preset not valid = %d", mInputPreset);
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 40e22ac..f550089 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -486,6 +486,9 @@
int64_t *framePosition,
int64_t *timeNanoseconds) {
ExtendedTimestamp extendedTimestamp;
+ if (getState() != AAUDIO_STREAM_STATE_STARTED) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
if (status == WOULD_BLOCK) {
return AAUDIO_ERROR_INVALID_STATE;
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index f5b3ad4..723cbf1 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -210,6 +210,7 @@
STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_RECOGNITION == AUDIO_SOURCE_VOICE_RECOGNITION);
STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION == AUDIO_SOURCE_VOICE_COMMUNICATION);
STATIC_ASSERT(AAUDIO_INPUT_PRESET_UNPROCESSED == AUDIO_SOURCE_UNPROCESSED);
+ STATIC_ASSERT(AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE == AUDIO_SOURCE_VOICE_PERFORMANCE);
if (preset == AAUDIO_UNSPECIFIED) {
preset = AAUDIO_INPUT_PRESET_VOICE_RECOGNITION;
}
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index b01af25..dbf8712 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -130,6 +130,7 @@
AAUDIO_INPUT_PRESET_VOICE_RECOGNITION,
AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION,
AAUDIO_INPUT_PRESET_UNPROCESSED,
+ AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE,
};
static void checkAttributesUsage(aaudio_performance_mode_t perfMode) {
diff --git a/media/libaaudio/tests/test_timestamps.cpp b/media/libaaudio/tests/test_timestamps.cpp
index dfa7815..7b1dfd3 100644
--- a/media/libaaudio/tests/test_timestamps.cpp
+++ b/media/libaaudio/tests/test_timestamps.cpp
@@ -35,6 +35,7 @@
#define NUM_SECONDS 1
#define NUM_LOOPS 4
+#define MAX_TESTS 20
typedef struct TimestampInfo {
int64_t framesTotal;
@@ -53,6 +54,49 @@
bool forceUnderruns = false;
} TimestampCallbackData_t;
+struct TimeStampTestLog {
+ aaudio_policy_t isMmap;
+ aaudio_sharing_mode_t sharingMode;
+ aaudio_performance_mode_t performanceMode;
+ aaudio_direction_t direction;
+ aaudio_result_t result;
+};
+
+static int s_numTests = 0;
+// Use a plain old array because we reference this from the callback and do not want any
+// automatic memory allocation.
+static TimeStampTestLog s_testLogs[MAX_TESTS]{};
+
+static void logTestResult(bool isMmap,
+ aaudio_sharing_mode_t sharingMode,
+ aaudio_performance_mode_t performanceMode,
+ aaudio_direction_t direction,
+ aaudio_result_t result) {
+ if(s_numTests >= MAX_TESTS) {
+ printf("ERROR - MAX_TESTS too small = %d\n", MAX_TESTS);
+ return;
+ }
+ s_testLogs[s_numTests].isMmap = isMmap;
+ s_testLogs[s_numTests].sharingMode = sharingMode;
+ s_testLogs[s_numTests].performanceMode = performanceMode;
+ s_testLogs[s_numTests].direction = direction;
+ s_testLogs[s_numTests].result = result;
+ s_numTests++;
+}
+
+static void printTestResults() {
+ for (int i = 0; i < s_numTests; i++) {
+ TimeStampTestLog *log = &s_testLogs[i];
+ printf("%2d: mmap = %3s, sharing = %9s, perf = %11s, dir = %6s ---- %4s\n",
+ i,
+ log->isMmap ? "yes" : "no",
+ getSharingModeText(log->sharingMode),
+ getPerformanceModeText(log->performanceMode),
+ getDirectionText(log->direction),
+ log->result ? "FAIL" : "pass");
+ }
+}
+
// Callback function that fills the audio output buffer.
aaudio_data_callback_result_t timestampDataCallbackProc(
AAudioStream *stream,
@@ -115,6 +159,7 @@
int32_t originalBufferSize = 0;
int32_t requestedBufferSize = 0;
int32_t finalBufferSize = 0;
+ bool isMmap = false;
aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
aaudio_sharing_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
@@ -124,7 +169,8 @@
memset(&sTimestampData, 0, sizeof(sTimestampData));
- printf("------------ testTimeStamps(policy = %d, sharing = %s, perf = %s, dir = %s) -----------\n",
+ printf("\n=================================================================================\n");
+ printf("--------- testTimeStamps(policy = %d, sharing = %s, perf = %s, dir = %s) --------\n",
mmapPolicy,
getSharingModeText(sharingMode),
getPerformanceModeText(performanceMode),
@@ -177,8 +223,8 @@
printf(" chans = %3d, rate = %6d format = %d\n",
actualChannelCount, actualSampleRate, actualDataFormat);
- printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(aaudioStream)
- ? "yes" : "no");
+ isMmap = AAudioStream_isMMapUsed(aaudioStream);
+ printf(" Is MMAP used? %s\n", isMmap ? "yes" : "no");
// This is the number of frames that are read in one chunk by a DMA controller
// or a DSP or a mixer.
@@ -218,7 +264,7 @@
for (int second = 0; second < NUM_SECONDS; second++) {
// Give AAudio callback time to run in the background.
- sleep(1);
+ usleep(200 * 1000);
// Periodically print the progress so we know it hasn't died.
printf("framesWritten = %d, XRuns = %d\n",
@@ -234,18 +280,25 @@
}
printf("timestampCount = %d\n", sTimestampData.timestampCount);
- int printed = 0;
- for (int i = 0; i < sTimestampData.timestampCount; i++) {
+ int printedGood = 0;
+ int printedBad = 0;
+ for (int i = 1; i < sTimestampData.timestampCount; i++) {
TimestampInfo *timestamp = &sTimestampData.timestamps[i];
- bool posChanged = (timestamp->timestampPosition != (timestamp - 1)->timestampPosition);
- bool timeChanged = (timestamp->timestampNanos != (timestamp - 1)->timestampNanos);
- if ((printed < 20) && ((i < 10) || posChanged || timeChanged)) {
- printf(" %3d : frames %8lld, xferd %8lld", i,
- (long long) timestamp->framesTotal,
- (long long) timestamp->appPosition);
- if (timestamp->result != AAUDIO_OK) {
- printf(", result = %s\n", AAudio_convertResultToText(timestamp->result));
- } else {
+ if (timestamp->result != AAUDIO_OK) {
+ if (printedBad < 5) {
+ printf(" %3d : frames %8lld, xferd %8lld, result = %s\n",
+ i,
+ (long long) timestamp->framesTotal,
+ (long long) timestamp->appPosition,
+ AAudio_convertResultToText(timestamp->result));
+ printedBad++;
+ }
+ } else {
+ const bool posChanged = (timestamp->timestampPosition !=
+ (timestamp - 1)->timestampPosition);
+ const bool timeChanged = (timestamp->timestampNanos
+ != (timestamp - 1)->timestampNanos);
+ if ((printedGood < 20) && (posChanged || timeChanged)) {
bool negative = timestamp->timestampPosition < 0;
bool retro = (i > 0 && (timestamp->timestampPosition <
(timestamp - 1)->timestampPosition));
@@ -253,17 +306,39 @@
: (retro ? " <= RETROGRADE!" : "");
double latency = calculateLatencyMillis(timestamp->timestampPosition,
- timestamp->timestampNanos,
- timestamp->appPosition,
- timestamp->appNanoseconds,
- actualSampleRate);
- printf(", STAMP: pos = %8lld, nanos = %8lld, lat = %7.1f msec %s\n",
+ timestamp->timestampNanos,
+ timestamp->appPosition,
+ timestamp->appNanoseconds,
+ actualSampleRate);
+ printf(" %3d : frames %8lld, xferd %8lld",
+ i,
+ (long long) timestamp->framesTotal,
+ (long long) timestamp->appPosition);
+ printf(" STAMP: pos = %8lld, nanos = %8lld, lat = %7.1f msec %s\n",
(long long) timestamp->timestampPosition,
(long long) timestamp->timestampNanos,
latency,
message);
+ printedGood++;
}
- printed++;
+ }
+ }
+
+ if (printedGood == 0) {
+ printf("ERROR - AAudioStream_getTimestamp() never gave us a valid timestamp\n");
+ result = AAUDIO_ERROR_INTERNAL;
+ } else {
+ // Make sure we do not get timestamps when stopped.
+ int64_t position;
+ int64_t time;
+ aaudio_result_t tempResult = AAudioStream_getTimestamp(aaudioStream,
+ CLOCK_MONOTONIC,
+ &position, &time);
+ if (tempResult != AAUDIO_ERROR_INVALID_STATE) {
+ printf("ERROR - AAudioStream_getTimestamp() should return"
+ " INVALID_STATE when stopped! %s\n",
+ AAudio_convertResultToText(tempResult));
+ result = AAUDIO_ERROR_INTERNAL;
}
}
@@ -273,12 +348,14 @@
}
finish:
+
+ logTestResult(isMmap, sharingMode, performanceMode, direction, result);
+
if (aaudioStream != nullptr) {
AAudioStream_close(aaudioStream);
}
AAudioStreamBuilder_delete(aaudioBuilder);
printf("result = %d = %s\n", result, AAudio_convertResultToText(result));
-
return result;
}
@@ -292,7 +369,7 @@
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("Test Timestamps V0.1.3\n");
+ printf("Test Timestamps V0.1.4\n");
// Legacy
aaudio_policy_t policy = AAUDIO_POLICY_NEVER;
@@ -332,5 +409,7 @@
AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,
AAUDIO_DIRECTION_OUTPUT);
+ printTestResults();
+
return (result == AAUDIO_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 827df6a..1417aaf 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -50,6 +50,7 @@
"libmediametrics",
"libmediautils",
"libnblog",
+ "libprocessgroup",
"libutils",
],
export_shared_lib_headers: ["libbinder"],
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index d1f7525..3ab38cd 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -22,6 +22,22 @@
namespace android {
//
+// AudioDeviceTypeAddr implementation
+//
+status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
+ mType = (audio_devices_t) parcel->readInt32();
+ mAddress = parcel->readString8();
+ return NO_ERROR;
+}
+
+status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32((int32_t) mType);
+ parcel->writeString8(mAddress);
+ return NO_ERROR;
+}
+
+
+//
// AudioMixMatchCriterion implementation
//
AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
@@ -40,11 +56,22 @@
status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
{
mRule = parcel->readInt32();
- if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
- mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
- mValue.mUsage = (audio_usage_t)parcel->readInt32();
- } else {
- mValue.mSource = (audio_source_t)parcel->readInt32();
+ switch (mRule) {
+ case RULE_MATCH_ATTRIBUTE_USAGE:
+ case RULE_EXCLUDE_ATTRIBUTE_USAGE:
+ mValue.mUsage = (audio_usage_t) parcel->readInt32();
+ break;
+ case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+ case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
+ mValue.mSource = (audio_source_t) parcel->readInt32();
+ break;
+ case RULE_MATCH_UID:
+ case RULE_EXCLUDE_UID:
+ mValue.mUid = (uid_t) parcel->readInt32();
+ break;
+ default:
+ ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
+ return BAD_VALUE;
}
return NO_ERROR;
}
@@ -116,4 +143,18 @@
return NO_ERROR;
}
+void AudioMix::setExcludeUid(uid_t uid) const {
+ AudioMixMatchCriterion crit;
+ crit.mRule = RULE_EXCLUDE_UID;
+ crit.mValue.mUid = uid;
+ mCriteria.add(crit);
+}
+
+void AudioMix::setMatchUid(uid_t uid) const {
+ AudioMixMatchCriterion crit;
+ crit.mRule = RULE_MATCH_UID;
+ crit.mValue.mUid = uid;
+ mCriteria.add(crit);
+}
+
} // namespace android
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 3223647..72a23e3 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -26,6 +26,7 @@
#include <media/AudioRecord.h>
#include <utils/Log.h>
#include <private/media/AudioTrackShared.h>
+#include <processgroup/sched_policy.h>
#include <media/IAudioFlinger.h>
#include <media/MediaAnalyticsItem.h>
#include <media/TypeConverter.h>
@@ -1398,6 +1399,17 @@
return mAudioRecord->getActiveMicrophones(activeMicrophones).transactionError();
}
+status_t AudioRecord::setMicrophoneDirection(audio_microphone_direction_t direction)
+{
+ AutoMutex lock(mLock);
+ return mAudioRecord->setMicrophoneDirection(direction).transactionError();
+}
+
+status_t AudioRecord::setMicrophoneFieldDimension(float zoom) {
+ AutoMutex lock(mLock);
+ return mAudioRecord->setMicrophoneFieldDimension(zoom).transactionError();
+}
+
// =========================================================================
void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index dc7531c..baeae8b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1236,6 +1236,19 @@
return aps->registerPolicyMixes(mixes, registration);
}
+status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioSystem::removeUidDeviceAffinities(uid_t uid) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->removeUidDeviceAffinities(uid);
+}
+
status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index b444d2d..e9a0e22 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -29,6 +29,7 @@
#include <media/AudioTrack.h>
#include <utils/Log.h>
#include <private/media/AudioTrackShared.h>
+#include <processgroup/sched_policy.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioPolicyService.h>
#include <media/AudioParameter.h>
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 0ce8b16..272415c 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -90,6 +90,8 @@
SET_ASSISTANT_UID,
SET_A11Y_SERVICES_UIDS,
IS_HAPTIC_PLAYBACK_SUPPORTED,
+ SET_UID_DEVICE_AFFINITY,
+ REMOVE_UID_DEVICE_AFFINITY,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -990,6 +992,50 @@
return reply.readBool();
}
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) uid);
+ size_t size = devices.size();
+ size_t sizePosition = data.dataPosition();
+ data.writeInt32((int32_t) size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = data.dataPosition();
+ if (devices[i].writeToParcel(&data) != NO_ERROR) {
+ data.setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = data.dataPosition();
+ data.setDataPosition(sizePosition);
+ data.writeInt32(finalSize);
+ data.setDataPosition(position);
+ }
+
+ status_t status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+
+ data.writeInt32((int32_t) uid);
+
+ status_t status = remote()->transact(REMOVE_UID_DEVICE_AFFINITY, data, &reply);
+ if (status == NO_ERROR) {
+ status = (status_t)reply.readInt32();
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1048,7 +1094,9 @@
case GET_SURROUND_FORMATS:
case SET_SURROUND_FORMAT_ENABLED:
case SET_ASSISTANT_UID:
- case SET_A11Y_SERVICES_UIDS: {
+ case SET_A11Y_SERVICES_UIDS:
+ case SET_UID_DEVICE_AFFINITY:
+ case REMOVE_UID_DEVICE_AFFINITY: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1811,6 +1859,30 @@
CHECK_INTERFACE(IAudioPolicyService, data, reply);
bool isSupported = isHapticPlaybackSupported();
reply->writeBool(isSupported);
+ return NO_ERROR;
+ }
+
+ case SET_UID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const uid_t uid = (uid_t) data.readInt32();
+ Vector<AudioDeviceTypeAddr> devices;
+ size_t size = (size_t)data.readInt32();
+ for (size_t i = 0; i < size; i++) {
+ AudioDeviceTypeAddr device;
+ if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
+ devices.add(device);
+ }
+ }
+ status_t status = setUidDeviceAffinities(uid, devices);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
+ case REMOVE_UID_DEVICE_AFFINITY: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ const uid_t uid = (uid_t) data.readInt32();
+ status_t status = removeUidDeviceAffinities(uid);
+ reply->writeInt32(status);
return NO_ERROR;
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 01e0a71..cf9c7f4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -36,4 +36,12 @@
/* Get a list of current active microphones.
*/
void getActiveMicrophones(out MicrophoneInfo[] activeMicrophones);
+
+ /* Set the microphone direction (for processing).
+ */
+ void setMicrophoneDirection(int /*audio_microphone_direction_t*/ direction);
+
+ /* Set the microphone zoom (for processing).
+ */
+ void setMicrophoneFieldDimension(float zoom);
}
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index 8da0069..786fb9a 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -56,6 +56,19 @@
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
+class AudioDeviceTypeAddr {
+public:
+ AudioDeviceTypeAddr() {}
+ AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
+ mType(type), mAddress(address) {}
+
+ status_t readFromParcel(Parcel *parcel);
+ status_t writeToParcel(Parcel *parcel) const;
+
+ audio_devices_t mType;
+ String8 mAddress;
+};
+
class AudioMixMatchCriterion {
public:
AudioMixMatchCriterion() {}
@@ -87,7 +100,10 @@
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
- Vector<AudioMixMatchCriterion> mCriteria;
+ void setExcludeUid(uid_t uid) const;
+ void setMatchUid(uid_t uid) const;
+
+ mutable Vector<AudioMixMatchCriterion> mCriteria;
uint32_t mMixType;
audio_config_t mFormat;
uint32_t mRouteFlags;
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 35a7e05..ebee124 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -534,6 +534,14 @@
*/
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ /* Set the Microphone direction (for processing purposes).
+ */
+ status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+
+ /* Set the Microphone zoom factor (for processing purposes).
+ */
+ status_t setMicrophoneFieldDimension(float zoom);
+
/* Get the unique port ID assigned to this AudioRecord instance by audio policy manager.
* The ID is unique across all audioserver clients and can change during the life cycle
* of a given AudioRecord instance if the connection to audioserver is restored.
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index b0da5b8..781e9df 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -325,6 +325,10 @@
static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ static status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+ static status_t removeUidDeviceAffinities(uid_t uid);
+
static status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 61f3b27..fb4fe93 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -167,6 +167,11 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration) = 0;
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ = 0;
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId) = 0;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 7a9e843..a1e869f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -268,6 +268,8 @@
audio_input_flags_t flags,
const char *address,
audio_source_t source,
+ audio_devices_t outputDevice,
+ const char *outputDeviceAddress,
sp<StreamInHalInterface> *inStream) {
if (mDevice == 0) return NO_INIT;
DeviceAddress hidlDevice;
@@ -283,6 +285,17 @@
// for now, only send the main source at 1dbfs
SinkMetadata sinkMetadata = {{{ .source = AudioSource(source), .gain = 1 }}};
#endif
+#if MAJOR_VERSION < 5
+ (void)outputDevice;
+ (void)outputDeviceAddress;
+#else
+ if (outputDevice != AUDIO_DEVICE_NONE) {
+ DeviceAddress hidlOutputDevice;
+ status = deviceAddressFromHal(outputDevice, outputDeviceAddress, &hidlOutputDevice);
+ if (status != OK) return status;
+ sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
+ }
+#endif
Return<void> ret = mDevice->openInputStream(
handle,
hidlDevice,
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 291c88f..f7d465f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -86,6 +86,8 @@
audio_input_flags_t flags,
const char *address,
audio_source_t source,
+ audio_devices_t outputDevice,
+ const char *outputDeviceAddress,
sp<StreamInHalInterface> *inStream);
// Returns whether createAudioPatch and releaseAudioPatch operations are supported.
diff --git a/media/libaudiohal/impl/DeviceHalLocal.cpp b/media/libaudiohal/impl/DeviceHalLocal.cpp
index dffe9da..ee68252 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.cpp
+++ b/media/libaudiohal/impl/DeviceHalLocal.cpp
@@ -131,6 +131,8 @@
audio_input_flags_t flags,
const char *address,
audio_source_t source,
+ audio_devices_t /*outputDevice*/,
+ const char */*outputDeviceAddress*/,
sp<StreamInHalInterface> *inStream) {
audio_stream_in_t *halStream;
ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 18bd879..36db72e 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -79,6 +79,8 @@
audio_input_flags_t flags,
const char *address,
audio_source_t source,
+ audio_devices_t outputDevice,
+ const char *outputDeviceAddress,
sp<StreamInHalInterface> *inStream);
// Returns whether createAudioPatch and releaseAudioPatch operations are supported.
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index c12b362..2e35be6 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -854,5 +854,29 @@
}
#endif
+#if MAJOR_VERSION < 5
+status_t StreamInHalHidl::setMicrophoneDirection(audio_microphone_direction_t direction __unused) {
+ if (mStream == 0) return NO_INIT;
+ return INVALID_OPERATION;
+}
+
+status_t StreamInHalHidl::setMicrophoneFieldDimension(float zoom __unused) {
+ if (mStream == 0) return NO_INIT;
+ return INVALID_OPERATION;
+}
+#else
+status_t StreamInHalHidl::setMicrophoneDirection(audio_microphone_direction_t direction) {
+ if (!mStream) return NO_INIT;
+ return processReturn("setMicrophoneDirection",
+ mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
+}
+
+status_t StreamInHalHidl::setMicrophoneFieldDimension(float zoom) {
+ if (!mStream) return NO_INIT;
+ return processReturn("setMicrophoneFieldDimension",
+ mStream->setMicrophoneFieldDimension(zoom));
+}
+#endif
+
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index f7b507e..9ac1067 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -220,6 +220,12 @@
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ // Set microphone direction (for processing)
+ virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) override;
+
+ // Set microphone zoom (for processing)
+ virtual status_t setMicrophoneFieldDimension(float zoom) override;
+
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 26d30d4..fcb809b 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -368,5 +368,26 @@
}
#endif
+#if MAJOR_VERSION < 5
+status_t StreamInHalLocal::setMicrophoneDirection(audio_microphone_direction_t direction __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t StreamInHalLocal::setMicrophoneFieldDimension(float zoom __unused) {
+ return INVALID_OPERATION;
+}
+#else
+status_t StreamInHalLocal::setMicrophoneDirection(audio_microphone_direction_t direction) {
+ if (mStream->set_microphone_direction == NULL) return INVALID_OPERATION;
+ return mStream->set_microphone_direction(mStream, direction);
+}
+
+status_t StreamInHalLocal::setMicrophoneFieldDimension(float zoom) {
+ if (mStream->set_microphone_field_dimension == NULL) return INVALID_OPERATION;
+ return mStream->set_microphone_field_dimension(mStream, zoom);
+
+}
+#endif
+
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index 4fd1960..3d6c50e 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -204,6 +204,12 @@
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ // Sets microphone direction (for processing)
+ virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+
+ // Sets microphone zoom (for processing)
+ virtual status_t setMicrophoneFieldDimension(float zoom);
+
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 7de8eb3..e565237 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -84,6 +84,8 @@
audio_input_flags_t flags,
const char *address,
audio_source_t source,
+ audio_devices_t outputDevice,
+ const char *outputDeviceAddress,
sp<StreamInHalInterface> *inStream) = 0;
// Returns whether createAudioPatch and releaseAudioPatch operations are supported.
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index bd71dc0..ed8282f 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -179,6 +179,12 @@
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+ // Set direction for capture processing
+ virtual status_t setMicrophoneDirection(audio_microphone_direction_t) = 0;
+
+ // Set zoom factor for capture stream
+ virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
+
struct SinkMetadata {
std::vector<record_track_metadata_t> tracks;
};
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 76b4adc..f39eb0c 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -115,6 +115,7 @@
{AUDIO_SOURCE_VOICE_RECOGNITION, "voice_recognition"},
{AUDIO_SOURCE_VOICE_COMMUNICATION, "voice_communication"},
{AUDIO_SOURCE_UNPROCESSED, "unprocessed"},
+ {AUDIO_SOURCE_VOICE_PERFORMANCE, "voice_performance"},
};
/** Find the stream type enum corresponding to the stream type name or return false */
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index b5860de..0c6f8de 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -1544,7 +1544,7 @@
int VirtualizerIsConfigurationSupported(audio_channel_mask_t channelMask,
audio_devices_t deviceType) {
uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
- if (channelCount < 1 || channelCount > LVM_MAX_CHANNELS) {
+ if (channelCount < 1 || channelCount > FCC_2) { // TODO: update to 8 channels when supported.
return -EINVAL;
}
return VirtualizerIsDeviceSupported(deviceType);
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 6002e95..68dae56 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -213,15 +213,14 @@
"android.hidl.token@1.0-utils",
"liblog",
"libcutils",
+ "libprocessgroup",
"libutils",
"libbinder",
"libsonivox",
- "libicuuc",
- "libicui18n",
+ "libandroidicu",
"libexpat",
"libcamera_client",
"libstagefright_foundation",
- "libmediaextractor",
"libgui",
"libdl",
"libaudioutils",
@@ -232,8 +231,7 @@
export_shared_lib_headers: [
"libaudioclient",
"libbinder",
- "libicuuc",
- "libicui18n",
+ "libandroidicu",
"libsonivox",
"libmedia_omx",
],
@@ -279,7 +277,6 @@
"libbinder",
"libcutils",
"liblog",
- "libmediaextractor",
"libmediandk",
"libnativewindow",
"libmediandk_utils",
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index e9a6230..fb6d3a2 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <stdint.h>
+#include <time.h>
#include <sys/types.h>
#include <binder/IPCThreadState.h>
@@ -219,10 +220,16 @@
Vector<wp<IMediaSource>> tracks;
Vector<String8> trackDescriptions;
String8 toString() const;
+ time_t when;
} ExtractorInstance;
String8 ExtractorInstance::toString() const {
- String8 str = name;
+ String8 str;
+ char timeString[32];
+ strftime(timeString, sizeof(timeString), "%m-%d %T", localtime(&when));
+ str.append(timeString);
+ str.append(": ");
+ str.append(name);
str.append(" for mime ");
str.append(mime);
str.append(", source ");
@@ -287,6 +294,7 @@
ex.sourceDescription = source->toString();
ex.owner = IPCThreadState::self()->getCallingPid();
ex.extractor = extractor;
+ ex.when = time(NULL);
{
Mutex::Autolock lock(sExtractorsLock);
diff --git a/media/libmedia/IMediaExtractorService.cpp b/media/libmedia/IMediaExtractorService.cpp
index 0295abc..243b09d 100644
--- a/media/libmedia/IMediaExtractorService.cpp
+++ b/media/libmedia/IMediaExtractorService.cpp
@@ -29,6 +29,7 @@
enum {
MAKE_EXTRACTOR = IBinder::FIRST_CALL_TRANSACTION,
MAKE_IDATA_SOURCE_FD,
+ GET_SUPPORTED_TYPES,
};
class BpMediaExtractorService : public BpInterface<IMediaExtractorService>
@@ -68,6 +69,24 @@
}
return nullptr;
}
+
+ virtual std::unordered_set<std::string> getSupportedTypes() {
+ std::unordered_set<std::string> supportedTypes;
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaExtractorService::getInterfaceDescriptor());
+ status_t ret = remote()->transact(GET_SUPPORTED_TYPES, data, &reply);
+ if (ret == NO_ERROR) {
+ // process reply
+ while(true) {
+ const char *ext = reply.readCString();
+ if (!ext) {
+ break;
+ }
+ supportedTypes.insert(std::string(ext));
+ }
+ }
+ return supportedTypes;
+ }
};
IMPLEMENT_META_INTERFACE(MediaExtractorService, "android.media.IMediaExtractorService");
@@ -113,6 +132,15 @@
return NO_ERROR;
}
+ case GET_SUPPORTED_TYPES:
+ {
+ CHECK_INTERFACE(IMediaExtractorService, data, reply);
+ std::unordered_set<std::string> supportedTypes = getSupportedTypes();
+ for (auto it = supportedTypes.begin(); it != supportedTypes.end(); ++it) {
+ reply->writeCString((*it).c_str());
+ }
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 590ba1a..f9fa86e 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -23,6 +23,7 @@
#include <media/IDataSource.h>
#include <media/IMediaHTTPService.h>
#include <media/IMediaMetadataRetriever.h>
+#include <processgroup/sched_policy.h>
#include <utils/String8.h>
#include <utils/KeyedVector.h>
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index 5308e1c..86ad997 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -28,6 +28,15 @@
namespace android {
+/** This redundant redeclaration is needed for C++ pre 14 */
+constexpr char MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_DYNAMIC_TIMESTAMP[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_FRAME_PARSING[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_MULTIPLE_FRAMES[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_SECURE_PLAYBACK[];
+constexpr char MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK[];
+
void MediaCodecInfo::Capabilities::getSupportedProfileLevels(
Vector<ProfileLevel> *profileLevels) const {
profileLevels->clear();
@@ -40,16 +49,11 @@
colorFormats->appendVector(mColorFormats);
}
-uint32_t MediaCodecInfo::Capabilities::getFlags() const {
- return mFlags;
-}
-
const sp<AMessage> MediaCodecInfo::Capabilities::getDetails() const {
return mDetails;
}
-MediaCodecInfo::Capabilities::Capabilities()
- : mFlags(0) {
+MediaCodecInfo::Capabilities::Capabilities() {
mDetails = new AMessage;
}
@@ -73,12 +77,10 @@
caps->mColorFormats.push_back(color);
}
}
- uint32_t flags = static_cast<uint32_t>(parcel.readInt32());
sp<AMessage> details = AMessage::FromParcel(parcel);
if (details == NULL)
return NULL;
if (caps != NULL) {
- caps->mFlags = flags;
caps->mDetails = details;
}
return caps;
@@ -96,7 +98,6 @@
for (size_t i = 0; i < mColorFormats.size(); i++) {
parcel->writeInt32(mColorFormats.itemAt(i));
}
- parcel->writeInt32(mFlags);
mDetails->writeToParcel(parcel);
return OK;
}
@@ -111,6 +112,14 @@
mCap->mDetails->setInt32(key, value);
}
+void MediaCodecInfo::CapabilitiesWriter::removeDetail(const char* key) {
+ if (mCap->mDetails->removeEntryAt(mCap->mDetails->findEntryByName(key)) == OK) {
+ ALOGD("successfully removed detail %s", key);
+ } else {
+ ALOGD("detail %s wasn't present to remove", key);
+ }
+}
+
void MediaCodecInfo::CapabilitiesWriter::addProfileLevel(
uint32_t profile, uint32_t level) {
ProfileLevel profileLevel;
@@ -129,32 +138,32 @@
}
}
-void MediaCodecInfo::CapabilitiesWriter::addFlags(uint32_t flags) {
- mCap->mFlags |= flags;
-}
-
MediaCodecInfo::CapabilitiesWriter::CapabilitiesWriter(
MediaCodecInfo::Capabilities* cap) : mCap(cap) {
}
-bool MediaCodecInfo::isEncoder() const {
- return mIsEncoder;
+MediaCodecInfo::Attributes MediaCodecInfo::getAttributes() const {
+ return mAttributes;
}
-uint32_t MediaCodecInfo::rank() const {
+uint32_t MediaCodecInfo::getRank() const {
return mRank;
}
-void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
- mimes->clear();
+void MediaCodecInfo::getAliases(Vector<AString> *aliases) const {
+ *aliases = mAliases;
+}
+
+void MediaCodecInfo::getSupportedMediaTypes(Vector<AString> *mediaTypes) const {
+ mediaTypes->clear();
for (size_t ix = 0; ix < mCaps.size(); ix++) {
- mimes->push_back(mCaps.keyAt(ix));
+ mediaTypes->push_back(mCaps.keyAt(ix));
}
}
const sp<MediaCodecInfo::Capabilities>
-MediaCodecInfo::getCapabilitiesFor(const char *mime) const {
- ssize_t ix = getCapabilityIndex(mime);
+MediaCodecInfo::getCapabilitiesFor(const char *mediaType) const {
+ ssize_t ix = getCapabilityIndex(mediaType);
if (ix >= 0) {
return mCaps.valueAt(ix);
}
@@ -173,21 +182,26 @@
sp<MediaCodecInfo> MediaCodecInfo::FromParcel(const Parcel &parcel) {
AString name = AString::FromParcel(parcel);
AString owner = AString::FromParcel(parcel);
- bool isEncoder = static_cast<bool>(parcel.readInt32());
+ Attributes attributes = static_cast<Attributes>(parcel.readInt32());
uint32_t rank = parcel.readUint32();
sp<MediaCodecInfo> info = new MediaCodecInfo;
info->mName = name;
info->mOwner = owner;
- info->mIsEncoder = isEncoder;
+ info->mAttributes = attributes;
info->mRank = rank;
+ size_t numAliases = static_cast<size_t>(parcel.readInt32());
+ for (size_t i = 0; i < numAliases; i++) {
+ AString alias = AString::FromParcel(parcel);
+ info->mAliases.add(alias);
+ }
size_t size = static_cast<size_t>(parcel.readInt32());
for (size_t i = 0; i < size; i++) {
- AString mime = AString::FromParcel(parcel);
+ AString mediaType = AString::FromParcel(parcel);
sp<Capabilities> caps = Capabilities::FromParcel(parcel);
if (caps == NULL)
return NULL;
if (info != NULL) {
- info->mCaps.add(mime, caps);
+ info->mCaps.add(mediaType, caps);
}
}
return info;
@@ -196,8 +210,12 @@
status_t MediaCodecInfo::writeToParcel(Parcel *parcel) const {
mName.writeToParcel(parcel);
mOwner.writeToParcel(parcel);
- parcel->writeInt32(mIsEncoder);
+ parcel->writeInt32(mAttributes);
parcel->writeUint32(mRank);
+ parcel->writeInt32(mAliases.size());
+ for (const AString &alias : mAliases) {
+ alias.writeToParcel(parcel);
+ }
parcel->writeInt32(mCaps.size());
for (size_t i = 0; i < mCaps.size(); i++) {
mCaps.keyAt(i).writeToParcel(parcel);
@@ -206,10 +224,10 @@
return OK;
}
-ssize_t MediaCodecInfo::getCapabilityIndex(const char *mime) const {
- if (mime) {
+ssize_t MediaCodecInfo::getCapabilityIndex(const char *mediaType) const {
+ if (mediaType) {
for (size_t ix = 0; ix < mCaps.size(); ix++) {
- if (mCaps.keyAt(ix).equalsIgnoreCase(mime)) {
+ if (mCaps.keyAt(ix).equalsIgnoreCase(mediaType)) {
return ix;
}
}
@@ -217,19 +235,26 @@
return -1;
}
-MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
+MediaCodecInfo::MediaCodecInfo()
+ : mAttributes((MediaCodecInfo::Attributes)0),
+ mRank(0x100) {
}
void MediaCodecInfoWriter::setName(const char* name) {
mInfo->mName = name;
}
+void MediaCodecInfoWriter::addAlias(const char* name) {
+ mInfo->mAliases.add(name);
+}
+
void MediaCodecInfoWriter::setOwner(const char* owner) {
mInfo->mOwner = owner;
}
-void MediaCodecInfoWriter::setEncoder(bool isEncoder) {
- mInfo->mIsEncoder = isEncoder;
+void MediaCodecInfoWriter::setAttributes(
+ typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes) {
+ mInfo->mAttributes = (MediaCodecInfo::Attributes)attributes;
}
void MediaCodecInfoWriter::setRank(uint32_t rank) {
@@ -237,21 +262,21 @@
}
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
- MediaCodecInfoWriter::addMime(const char *mime) {
- ssize_t ix = mInfo->getCapabilityIndex(mime);
+ MediaCodecInfoWriter::addMediaType(const char *mediaType) {
+ ssize_t ix = mInfo->getCapabilityIndex(mediaType);
if (ix >= 0) {
return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
new MediaCodecInfo::CapabilitiesWriter(
mInfo->mCaps.valueAt(ix).get()));
}
sp<MediaCodecInfo::Capabilities> caps = new MediaCodecInfo::Capabilities();
- mInfo->mCaps.add(AString(mime), caps);
+ mInfo->mCaps.add(AString(mediaType), caps);
return std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>(
new MediaCodecInfo::CapabilitiesWriter(caps.get()));
}
-bool MediaCodecInfoWriter::removeMime(const char *mime) {
- ssize_t ix = mInfo->getCapabilityIndex(mime);
+bool MediaCodecInfoWriter::removeMediaType(const char *mediaType) {
+ ssize_t ix = mInfo->getCapabilityIndex(mediaType);
if (ix >= 0) {
mInfo->mCaps.removeItemsAt(ix);
return true;
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 156991e..6dbc9b8 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -1249,7 +1249,11 @@
if (mAMediaExtractor == NULL) {
return NULL;
}
- return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
+ AMediaCodecCryptoInfo *cryptoInfo = AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor);
+ if (cryptoInfo == NULL) {
+ return NULL;
+ }
+ return new AMediaCodecCryptoInfoWrapper(cryptoInfo);
}
AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index b5a7172..c24e046 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -74,6 +74,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI_ARC),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
@@ -93,6 +94,8 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ECHO_REFERENCE),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
// STUB must be after DEFAULT, so the latter is picked up by toString first.
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_STUB),
@@ -357,6 +360,8 @@
MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_COMMUNICATION),
MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_REMOTE_SUBMIX),
MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_UNPROCESSED),
+ MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_VOICE_PERFORMANCE),
+ MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_ECHO_REFERENCE),
MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_FM_TUNER),
MAKE_STRING_FROM_ENUM(AUDIO_SOURCE_HOTWORD),
TERMINATOR
diff --git a/media/libmedia/include/media/CryptoHal.h b/media/libmedia/include/media/CryptoHal.h
index ff8789d..73c029f 100644
--- a/media/libmedia/include/media/CryptoHal.h
+++ b/media/libmedia/include/media/CryptoHal.h
@@ -21,6 +21,7 @@
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/ICryptoPlugin.h>
#include <mediadrm/ICrypto.h>
#include <utils/KeyedVector.h>
@@ -72,6 +73,7 @@
const Vector<sp<ICryptoFactory>> mFactories;
sp<ICryptoPlugin> mPlugin;
+ sp<drm::V1_2::ICryptoPlugin> mPluginV1_2;
/**
* mInitCheck is:
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index 3302982..de0f3c7 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -20,11 +20,11 @@
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
-#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.1/IDrmFactory.h>
#include <android/hardware/drm/1.1/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmFactory.h>
#include <android/hardware/drm/1.2/IDrmPlugin.h>
+#include <android/hardware/drm/1.2/IDrmPluginListener.h>
#include <media/MediaAnalyticsItem.h>
#include <mediadrm/DrmMetrics.h>
@@ -43,6 +43,8 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
+typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
+
namespace android {
struct DrmSessionClientInterface;
@@ -54,7 +56,7 @@
struct DrmHal : public BnDrm,
public IBinder::DeathRecipient,
- public IDrmPluginListener {
+ public IDrmPluginListener_V1_2 {
DrmHal();
virtual ~DrmHal();
@@ -176,6 +178,8 @@
Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey);
+ Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
+
virtual void binderDied(const wp<IBinder> &the_late_who);
private:
diff --git a/media/libmedia/include/media/IMediaExtractorService.h b/media/libmedia/include/media/IMediaExtractorService.h
index 45e9620..5ce2cdb 100644
--- a/media/libmedia/include/media/IMediaExtractorService.h
+++ b/media/libmedia/include/media/IMediaExtractorService.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_IMEDIAEXTRACTORSERVICE_H
#define ANDROID_IMEDIAEXTRACTORSERVICE_H
+#include <unordered_set>
+
#include <binder/IInterface.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
@@ -33,6 +35,8 @@
virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime) = 0;
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length) = 0;
+
+ virtual std::unordered_set<std::string> getSupportedTypes() = 0;
};
class BnMediaExtractorService: public BnInterface<IMediaExtractorService>
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index b3777d3..54f565a 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -30,6 +30,8 @@
#include <utils/Vector.h>
#include <utils/StrongPointer.h>
+#include <type_traits>
+
namespace android {
struct AMessage;
@@ -51,21 +53,47 @@
struct CapabilitiesWriter;
+ enum Attributes : int32_t {
+ // attribute flags
+ kFlagIsEncoder = 1 << 0,
+ kFlagIsVendor = 1 << 1,
+ kFlagIsSoftwareOnly = 1 << 2,
+ kFlagIsHardwareAccelerated = 1 << 3,
+ };
+
struct Capabilities : public RefBase {
- enum {
- // decoder flags
- kFlagSupportsAdaptivePlayback = 1 << 0,
- kFlagSupportsSecurePlayback = 1 << 1,
- kFlagSupportsTunneledPlayback = 1 << 2,
+ constexpr static char FEATURE_ADAPTIVE_PLAYBACK[] = "feature-adaptive-playback";
+ constexpr static char FEATURE_DYNAMIC_TIMESTAMP[] = "feature-dynamic-timestamp";
+ constexpr static char FEATURE_FRAME_PARSING[] = "feature-frame-parsing";
+ constexpr static char FEATURE_INTRA_REFRESH[] = "feature-frame-parsing";
+ constexpr static char FEATURE_MULTIPLE_FRAMES[] = "feature-multiple-frames";
+ constexpr static char FEATURE_SECURE_PLAYBACK[] = "feature-secure-playback";
+ constexpr static char FEATURE_TUNNELED_PLAYBACK[] = "feature-tunneled-playback";
- // encoder flags
- kFlagSupportsIntraRefresh = 1 << 0,
-
- };
-
+ /**
+ * Returns the supported levels for each supported profile in a target array.
+ *
+ * @param profileLevels target array for the profile levels.
+ */
void getSupportedProfileLevels(Vector<ProfileLevel> *profileLevels) const;
+
+ /**
+ * Returns the supported color formats in a target array. Only used for video/image
+ * components.
+ *
+ * @param colorFormats target array for the color formats.
+ */
void getSupportedColorFormats(Vector<uint32_t> *colorFormats) const;
- uint32_t getFlags() const;
+
+ /**
+ * Returns metadata associated with this codec capability.
+ *
+ * This contains:
+ * - features,
+ * - performance data.
+ *
+ * TODO: expose this as separate API-s and wrap here.
+ */
const sp<AMessage> getDetails() const;
protected:
@@ -73,7 +101,6 @@
SortedVector<ProfileLevel> mProfileLevelsSorted;
Vector<uint32_t> mColorFormats;
SortedVector<uint32_t> mColorFormatsSorted;
- uint32_t mFlags;
sp<AMessage> mDetails;
Capabilities();
@@ -93,8 +120,7 @@
/**
* This class is used for modifying information inside a `Capabilities`
* object. An object of type `CapabilitiesWriter` can be obtained by calling
- * `MediaCodecInfoWriter::addMime()` or
- * `MediaCodecInfoWriter::updateMime()`.
+ * `MediaCodecInfoWriter::addMediaType()`.
*/
struct CapabilitiesWriter {
/**
@@ -122,6 +148,13 @@
*/
void addDetail(const char* key, int32_t value);
/**
+ * Removes a key-value pair from the list of details. If the key is not
+ * present, this call does nothing.
+ *
+ * @param key The key.
+ */
+ void removeDetail(const char* key);
+ /**
* Add a profile-level pair. If this profile-level pair already exists,
* it will be ignored.
*
@@ -136,13 +169,7 @@
* @param format The color format.
*/
void addColorFormat(uint32_t format);
- /**
- * Add flags. The underlying operation is bitwise-or. In other words,
- * bits that have already been set will be ignored.
- *
- * @param flags The additional flags.
- */
- void addFlags(uint32_t flags);
+
private:
/**
* The associated `Capabilities` object.
@@ -158,19 +185,42 @@
friend MediaCodecInfoWriter;
};
- bool isEncoder() const;
- void getSupportedMimes(Vector<AString> *mimes) const;
- const sp<Capabilities> getCapabilitiesFor(const char *mime) const;
+ inline bool isEncoder() const {
+ return getAttributes() & kFlagIsEncoder;
+ }
+
+ Attributes getAttributes() const;
+ void getSupportedMediaTypes(Vector<AString> *mediaTypes) const;
+ const sp<Capabilities> getCapabilitiesFor(const char *mediaType) const;
const char *getCodecName() const;
/**
+ * Returns a vector containing alternate names for the codec.
+ *
+ * \param aliases the destination array for the aliases. This is cleared.
+ *
+ * Multiple codecs may share alternate names as long as their supported media types are
+ * distinct; however, these will result in different aliases for the MediaCodec user as
+ * the canonical codec has to be resolved without knowing the media type in
+ * MediaCodec::CreateByComponentName.
+ */
+ void getAliases(Vector<AString> *aliases) const;
+
+ /**
* Return the name of the service that hosts the codec. This value is not
* visible at the Java level.
*
* Currently, this is the "instance name" of the IOmx service.
*/
const char *getOwnerName() const;
- uint32_t rank() const;
+
+ /**
+ * Returns the rank of the component.
+ *
+ * Technically this is defined to be per media type, but that makes ordering the MediaCodecList
+ * impossible as MediaCodecList is ordered by codec name.
+ */
+ uint32_t getRank() const;
/**
* Serialization over Binder
@@ -181,11 +231,12 @@
private:
AString mName;
AString mOwner;
- bool mIsEncoder;
+ Attributes mAttributes;
KeyedVector<AString, sp<Capabilities> > mCaps;
+ Vector<AString> mAliases;
uint32_t mRank;
- ssize_t getCapabilityIndex(const char *mime) const;
+ ssize_t getCapabilityIndex(const char *mediaType) const;
/**
* Construct an `MediaCodecInfo` object. After the construction, its
@@ -219,6 +270,13 @@
*/
void setName(const char* name);
/**
+ * Adds an alias (alternate name) for the codec. Multiple codecs can share an alternate name
+ * as long as their supported media types are distinct.
+ *
+ * @param name an alternate name.
+ */
+ void addAlias(const char* name);
+ /**
* Set the owner name of the codec.
*
* This "owner name" is the name of the `IOmx` instance that supports this
@@ -228,32 +286,32 @@
*/
void setOwner(const char* owner);
/**
- * Set whether this codec is an encoder or a decoder.
+ * Sets codec attributes.
*
- * @param isEncoder Whether this codec is an encoder or a decoder.
+ * @param attributes Codec attributes.
*/
- void setEncoder(bool isEncoder = true);
+ void setAttributes(typename std::underlying_type<MediaCodecInfo::Attributes>::type attributes);
/**
- * Add a mime to an indexed list and return a `CapabilitiesWriter` object
+ * Add a media type to an indexed list and return a `CapabilitiesWriter` object
* that can be used for modifying the associated `Capabilities`.
*
- * If the mime already exists, this function will return the
- * `CapabilitiesWriter` associated with the mime.
+ * If the media type already exists, this function will return the
+ * `CapabilitiesWriter` associated with the media type.
*
- * @param[in] mime The name of a new mime to add.
+ * @param[in] mediaType The name of a new media type to add.
* @return writer The `CapabilitiesWriter` object for modifying the
- * `Capabilities` associated with the mime. `writer` will be valid
- * regardless of whether `mime` already exists or not.
+ * `Capabilities` associated with the media type. `writer` will be valid
+ * regardless of whether `mediaType` already exists or not.
*/
- std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMime(
- const char* mime);
+ std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> addMediaType(
+ const char* mediaType);
/**
- * Remove a mime.
+ * Remove a media type.
*
- * @param mime The name of the mime to remove.
- * @return `true` if `mime` is removed; `false` if `mime` is not found.
+ * @param mediaType The name of the media type to remove.
+ * @return `true` if `mediaType` is removed; `false` if `mediaType` is not found.
*/
- bool removeMime(const char* mime);
+ bool removeMediaType(const char* mediaType);
/**
* Set rank of the codec. MediaCodecList will stable-sort the list according
* to rank in non-descending order.
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index caa0186..33be559 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -115,9 +115,6 @@
* The state machine of the media_recorder.
*/
enum media_recorder_states {
- // Error state.
- MEDIA_RECORDER_ERROR = 0,
-
// Recorder was just created.
MEDIA_RECORDER_IDLE = 1 << 0,
@@ -132,6 +129,9 @@
// Recording is in progress.
MEDIA_RECORDER_RECORDING = 1 << 4,
+
+ // Error state.
+ MEDIA_RECORDER_ERROR = 1 << 5,
};
// The "msg" code passed to the listener in notify.
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
deleted file mode 100644
index 4758cd6..0000000
--- a/media/libmediaextractor/Android.bp
+++ /dev/null
@@ -1,60 +0,0 @@
-cc_library {
- name: "libmediaextractor",
-
- include_dirs: [
- "frameworks/av/include",
- "frameworks/av/media/libmediaextractor/include",
- ],
-
- export_include_dirs: ["include"],
-
- cflags: [
- "-Wno-multichar",
- "-Werror",
- "-Wall",
- ],
-
- static: {
- cflags: [
- "-Wno-multichar",
- "-Werror",
- "-Wall",
- "-DNO_IMEMORY",
- ],
- },
-
- shared_libs: [
- "libbinder",
- "libstagefright_foundation",
- "libutils",
- "liblog",
- ],
-
- header_libs: [
- "media_ndk_headers",
- ],
-
- export_header_lib_headers: [
- "media_ndk_headers",
- ],
-
- srcs: [
- "DataSourceBase.cpp",
- "MediaBuffer.cpp",
- "MediaBufferBase.cpp",
- "MediaBufferGroup.cpp",
- "MediaSource.cpp",
- "MetaData.cpp",
- "MetaDataBase.cpp",
- ],
-
- clang: true,
-
- sanitize: {
- misc_undefined: [
- "unsigned-integer-overflow",
- "signed-integer-overflow",
- ],
- cfi: true,
- },
-}
diff --git a/media/libmediaplayer2/Android.bp b/media/libmediaplayer2/Android.bp
index 54309ee..b3f7404 100644
--- a/media/libmediaplayer2/Android.bp
+++ b/media/libmediaplayer2/Android.bp
@@ -16,11 +16,11 @@
"libandroid_runtime",
"libaudioclient",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libgui",
"liblog",
"libmedia_omx",
- "libmediaextractor",
"libstagefright_foundation",
"libui",
"libutils",
diff --git a/media/libmediaplayer2/JavaVMHelper.cpp b/media/libmediaplayer2/JavaVMHelper.cpp
index 90aaa7f..8d03ed0 100644
--- a/media/libmediaplayer2/JavaVMHelper.cpp
+++ b/media/libmediaplayer2/JavaVMHelper.cpp
@@ -19,6 +19,7 @@
#include "mediaplayer2/JavaVMHelper.h"
#include <media/stagefright/foundation/ADebug.h>
+#include <utils/threads.h>
#include <stdlib.h>
@@ -27,6 +28,109 @@
// static
std::atomic<JavaVM *> JavaVMHelper::sJavaVM(NULL);
+/*
+ * Makes the current thread visible to the VM.
+ *
+ * The JNIEnv pointer returned is only valid for the current thread, and
+ * thus must be tucked into thread-local storage.
+ */
+static int javaAttachThread(const char* threadName, JNIEnv** pEnv) {
+ JavaVMAttachArgs args;
+ JavaVM* vm;
+ jint result;
+
+ vm = JavaVMHelper::getJavaVM();
+ if (vm == NULL) {
+ return JNI_ERR;
+ }
+
+ args.version = JNI_VERSION_1_4;
+ args.name = (char*) threadName;
+ args.group = NULL;
+
+ result = vm->AttachCurrentThread(pEnv, (void*) &args);
+ if (result != JNI_OK) {
+ ALOGI("NOTE: attach of thread '%s' failed\n", threadName);
+ }
+
+ return result;
+}
+
+/*
+ * Detach the current thread from the set visible to the VM.
+ */
+static int javaDetachThread(void) {
+ JavaVM* vm;
+ jint result;
+
+ vm = JavaVMHelper::getJavaVM();
+ if (vm == NULL) {
+ return JNI_ERR;
+ }
+
+ result = vm->DetachCurrentThread();
+ if (result != JNI_OK) {
+ ALOGE("ERROR: thread detach failed\n");
+ }
+ return result;
+}
+
+/*
+ * When starting a native thread that will be visible from the VM, we
+ * bounce through this to get the right attach/detach action.
+ * Note that this function calls free(args)
+ */
+static int javaThreadShell(void* args) {
+ void* start = ((void**)args)[0];
+ void* userData = ((void **)args)[1];
+ char* name = (char*) ((void **)args)[2]; // we own this storage
+ free(args);
+ JNIEnv* env;
+ int result;
+
+ /* hook us into the VM */
+ if (javaAttachThread(name, &env) != JNI_OK) {
+ return -1;
+ }
+
+ /* start the thread running */
+ result = (*(android_thread_func_t)start)(userData);
+
+ /* unhook us */
+ javaDetachThread();
+ free(name);
+
+ return result;
+}
+
+/*
+ * This is invoked from androidCreateThreadEtc() via the callback
+ * set with androidSetCreateThreadFunc().
+ *
+ * We need to create the new thread in such a way that it gets hooked
+ * into the VM before it really starts executing.
+ */
+static int javaCreateThreadEtc(
+ android_thread_func_t entryFunction,
+ void* userData,
+ const char* threadName,
+ int32_t threadPriority,
+ size_t threadStackSize,
+ android_thread_id_t* threadId) {
+ void** args = (void**) malloc(3 * sizeof(void*)); // javaThreadShell must free
+ int result;
+
+ LOG_ALWAYS_FATAL_IF(threadName == nullptr, "threadName not provided to javaCreateThreadEtc");
+
+ args[0] = (void*) entryFunction;
+ args[1] = userData;
+ args[2] = (void*) strdup(threadName); // javaThreadShell must free
+
+ result = androidCreateRawThreadEtc(javaThreadShell, args,
+ threadName, threadPriority, threadStackSize, threadId);
+ return result;
+}
+
// static
JNIEnv *JavaVMHelper::getJNIEnv() {
JNIEnv *env;
@@ -40,9 +144,19 @@
return env;
}
+//static
+JavaVM *JavaVMHelper::getJavaVM() {
+ return sJavaVM.load();
+}
+
// static
void JavaVMHelper::setJavaVM(JavaVM *vm) {
sJavaVM.store(vm);
+
+ // Ensure that Thread(/*canCallJava*/ true) in libutils is attached to the VM.
+ // This is supposed to be done by runtime, but when libutils is used with linker
+ // namespace, CreateThreadFunc should be initialized separately within the namespace.
+ androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
}
} // namespace android
diff --git a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h b/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
index 35091b7..4b56aca 100644
--- a/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
+++ b/media/libmediaplayer2/include/mediaplayer2/JavaVMHelper.h
@@ -26,6 +26,7 @@
struct JavaVMHelper {
static JNIEnv *getJNIEnv();
+ static JavaVM *getJavaVM();
static void setJavaVM(JavaVM *vm);
private:
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index 5e98589..0c8d016 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -30,7 +30,6 @@
#include <media/AudioSystem.h>
#include <media/AudioTimestamp.h>
#include <media/BufferingSettings.h>
-#include <media/Metadata.h>
#include <media/stagefright/foundation/AHandler.h>
#include <mediaplayer2/MediaPlayer2Types.h>
@@ -224,18 +223,6 @@
// @return OK if the call was successful.
virtual status_t invoke(const PlayerMessage &request, PlayerMessage *reply) = 0;
- // The Client in the MetadataPlayerService calls this method on
- // the native player to retrieve all or a subset of metadata.
- //
- // @param ids SortedList of metadata ID to be fetch. If empty, all
- // the known metadata should be returned.
- // @param[inout] records Parcel where the player appends its metadata.
- // @return OK if the call was successful.
- virtual status_t getMetadata(const media::Metadata::Filter& /* ids */,
- Parcel* /* records */) {
- return INVALID_OPERATION;
- };
-
void setListener(const sp<MediaPlayer2InterfaceListener> &listener) {
Mutex::Autolock autoLock(mListenerLock);
mListener = listener;
diff --git a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
index a945ffd..78865c4 100644
--- a/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
+++ b/media/libmediaplayer2/include/mediaplayer2/mediaplayer2.h
@@ -20,7 +20,6 @@
#include <media/AVSyncSettings.h>
#include <media/AudioResamplerPublic.h>
#include <media/BufferingSettings.h>
-#include <media/Metadata.h>
#include <media/mediaplayer_common.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
#include <mediaplayer2/MediaPlayer2Types.h>
@@ -55,7 +54,7 @@
public:
~MediaPlayer2();
- static sp<MediaPlayer2> Create(int32_t sessionId);
+ static sp<MediaPlayer2> Create(int32_t sessionId, jobject context);
static status_t DumpAll(int fd, const Vector<String16>& args);
void disconnect();
@@ -118,7 +117,7 @@
status_t dump(int fd, const Vector<String16>& args);
private:
- MediaPlayer2(int32_t sessionId);
+ MediaPlayer2(int32_t sessionId, jobject context);
bool init();
// Disconnect from the currently connected ANativeWindow.
@@ -154,6 +153,7 @@
int mVideoHeight;
int32_t mAudioSessionId;
sp<JObjectHolder> mAudioAttributes;
+ sp<JObjectHolder> mContext;
float mSendLevel;
sp<ANativeWindowWrapper> mConnectedWindow;
};
diff --git a/media/libmediaplayer2/mediaplayer2.cpp b/media/libmediaplayer2/mediaplayer2.cpp
index f432059..f75380c 100644
--- a/media/libmediaplayer2/mediaplayer2.cpp
+++ b/media/libmediaplayer2/mediaplayer2.cpp
@@ -18,14 +18,11 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaPlayer2Native"
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-
+#include <android/binder_ibinder.h>
#include <media/AudioSystem.h>
#include <media/DataSourceDesc.h>
#include <media/MediaAnalyticsItem.h>
#include <media/MemoryLeakTrackUtil.h>
-#include <media/Metadata.h>
#include <media/NdkWrapper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooperRoster.h>
@@ -103,114 +100,110 @@
String8 result;
SortedVector< sp<MediaPlayer2> > players; //to serialise the mutex unlock & client destruction.
- if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
- snprintf(buffer, SIZE, "Permission Denial: can't dump MediaPlayer2\n");
- result.append(buffer);
+ {
+ Mutex::Autolock lock(sRecordLock);
+ ensureInit_l();
+ for (int i = 0, n = sPlayers->size(); i < n; ++i) {
+ sp<MediaPlayer2> p = (*sPlayers)[i].promote();
+ if (p != 0) {
+ p->dump(fd, args);
+ }
+ players.add(p);
+ }
+ }
+
+ result.append(" Files opened and/or mapped:\n");
+ snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
+ FILE *f = fopen(buffer, "r");
+ if (f) {
+ while (!feof(f)) {
+ fgets(buffer, SIZE, f);
+ if (strstr(buffer, " /storage/") ||
+ strstr(buffer, " /system/sounds/") ||
+ strstr(buffer, " /data/") ||
+ strstr(buffer, " /system/media/")) {
+ result.append(" ");
+ result.append(buffer);
+ }
+ }
+ fclose(f);
} else {
- {
- Mutex::Autolock lock(sRecordLock);
- ensureInit_l();
- for (int i = 0, n = sPlayers->size(); i < n; ++i) {
- sp<MediaPlayer2> p = (*sPlayers)[i].promote();
- if (p != 0) {
- p->dump(fd, args);
- }
- players.add(p);
- }
- }
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
- result.append(" Files opened and/or mapped:\n");
- snprintf(buffer, SIZE, "/proc/%d/maps", getpid());
- FILE *f = fopen(buffer, "r");
- if (f) {
- while (!feof(f)) {
- fgets(buffer, SIZE, f);
- if (strstr(buffer, " /storage/") ||
- strstr(buffer, " /system/sounds/") ||
- strstr(buffer, " /data/") ||
- strstr(buffer, " /system/media/")) {
- result.append(" ");
- result.append(buffer);
- }
- }
- fclose(f);
- } else {
- result.append("couldn't open ");
- result.append(buffer);
- result.append("\n");
- }
-
- snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
- DIR *d = opendir(buffer);
- if (d) {
- struct dirent *ent;
- while((ent = readdir(d)) != NULL) {
- if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
- snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
- struct stat s;
- if (lstat(buffer, &s) == 0) {
- if ((s.st_mode & S_IFMT) == S_IFLNK) {
- char linkto[256];
- int len = readlink(buffer, linkto, sizeof(linkto));
- if(len > 0) {
- if(len > 255) {
- linkto[252] = '.';
- linkto[253] = '.';
- linkto[254] = '.';
- linkto[255] = 0;
- } else {
- linkto[len] = 0;
- }
- if (strstr(linkto, "/storage/") == linkto ||
- strstr(linkto, "/system/sounds/") == linkto ||
- strstr(linkto, "/data/") == linkto ||
- strstr(linkto, "/system/media/") == linkto) {
- result.append(" ");
- result.append(buffer);
- result.append(" -> ");
- result.append(linkto);
- result.append("\n");
- }
+ snprintf(buffer, SIZE, "/proc/%d/fd", getpid());
+ DIR *d = opendir(buffer);
+ if (d) {
+ struct dirent *ent;
+ while((ent = readdir(d)) != NULL) {
+ if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+ snprintf(buffer, SIZE, "/proc/%d/fd/%s", getpid(), ent->d_name);
+ struct stat s;
+ if (lstat(buffer, &s) == 0) {
+ if ((s.st_mode & S_IFMT) == S_IFLNK) {
+ char linkto[256];
+ int len = readlink(buffer, linkto, sizeof(linkto));
+ if(len > 0) {
+ if(len > 255) {
+ linkto[252] = '.';
+ linkto[253] = '.';
+ linkto[254] = '.';
+ linkto[255] = 0;
+ } else {
+ linkto[len] = 0;
}
- } else {
- result.append(" unexpected type for ");
- result.append(buffer);
- result.append("\n");
+ if (strstr(linkto, "/storage/") == linkto ||
+ strstr(linkto, "/system/sounds/") == linkto ||
+ strstr(linkto, "/data/") == linkto ||
+ strstr(linkto, "/system/media/") == linkto) {
+ result.append(" ");
+ result.append(buffer);
+ result.append(" -> ");
+ result.append(linkto);
+ result.append("\n");
+ }
}
+ } else {
+ result.append(" unexpected type for ");
+ result.append(buffer);
+ result.append("\n");
}
}
}
- closedir(d);
- } else {
- result.append("couldn't open ");
- result.append(buffer);
- result.append("\n");
}
+ closedir(d);
+ } else {
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
- gLooperRoster.dump(fd, args);
+ gLooperRoster.dump(fd, args);
- bool dumpMem = false;
- bool unreachableMemory = false;
- for (size_t i = 0; i < args.size(); i++) {
- if (args[i] == String16("-m")) {
- dumpMem = true;
- } else if (args[i] == String16("--unreachable")) {
- unreachableMemory = true;
- }
- }
- if (dumpMem) {
- result.append("\nDumping memory:\n");
- std::string s = dumpMemoryAddresses(100 /* limit */);
- result.append(s.c_str(), s.size());
- }
- if (unreachableMemory) {
- result.append("\nDumping unreachable memory:\n");
- // TODO - should limit be an argument parameter?
- // TODO: enable GetUnreachableMemoryString if it's part of stable API
- //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
- //result.append(s.c_str(), s.size());
+ bool dumpMem = false;
+ bool unreachableMemory = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ } else if (args[i] == String16("--unreachable")) {
+ unreachableMemory = true;
}
}
+ if (dumpMem) {
+ result.append("\nDumping memory:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ result.append(s.c_str(), s.size());
+ }
+ if (unreachableMemory) {
+ result.append("\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ // TODO: enable GetUnreachableMemoryString if it's part of stable API
+ //std::string s = GetUnreachableMemoryString(true /* contents */, 10000 /* limit */);
+ //result.append(s.c_str(), s.size());
+ }
+
write(fd, result.string(), result.size());
return NO_ERROR;
}
@@ -218,8 +211,8 @@
} // anonymous namespace
//static
-sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId) {
- sp<MediaPlayer2> player = new MediaPlayer2(sessionId);
+sp<MediaPlayer2> MediaPlayer2::Create(int32_t sessionId, jobject context) {
+ sp<MediaPlayer2> player = new MediaPlayer2(sessionId, context);
if (!player->init()) {
return NULL;
@@ -236,13 +229,14 @@
return dumpPlayers(fd, args);
}
-MediaPlayer2::MediaPlayer2(int32_t sessionId) {
+MediaPlayer2::MediaPlayer2(int32_t sessionId, jobject context) {
ALOGV("constructor");
mSrcId = 0;
mLockThreadId = 0;
mListener = NULL;
mStreamType = AUDIO_STREAM_MUSIC;
mAudioAttributes = NULL;
+ mContext = new JObjectHolder(context);
mCurrentPosition = -1;
mCurrentSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
mSeekPosition = -1;
@@ -253,9 +247,8 @@
mVideoWidth = mVideoHeight = 0;
mSendLevel = 0;
- // TODO: get pid and uid from JAVA
- mPid = IPCThreadState::self()->getCallingPid();
- mUid = IPCThreadState::self()->getCallingUid();
+ mPid = AIBinder_getCallingPid();
+ mUid = AIBinder_getCallingUid();
mAudioOutput = new MediaPlayer2AudioOutput(sessionId, mUid, mPid, NULL /*attributes*/);
}
@@ -334,15 +327,15 @@
sp<MediaPlayer2Interface> oldPlayer;
- Mutex::Autolock _l(mLock);
{
+ Mutex::Autolock _l(mLock);
if (!((mCurrentState & MEDIA_PLAYER2_IDLE)
|| mCurrentState == MEDIA_PLAYER2_STATE_ERROR)) {
ALOGE("setDataSource called in wrong state %d", mCurrentState);
return INVALID_OPERATION;
}
- sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid);
+ sp<MediaPlayer2Interface> player = new NuPlayer2Driver(mPid, mUid, mContext);
status_t err = player->initCheck();
if (err != NO_ERROR) {
ALOGE("Failed to create player object, initCheck failed(%d)", err);
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
index c9a1071..983d77e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.cpp
@@ -20,55 +20,50 @@
#include "JWakeLock.h"
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <powermanager/PowerManager.h>
-
namespace android {
-//TODO: use JAVA PowerManager, instead of binder
-JWakeLock::JWakeLock() :
- mPowerManager(NULL),
- mWakeLockToken(NULL),
+JWakeLock::JWakeLock(const sp<JObjectHolder> &context) :
mWakeLockCount(0),
- mDeathRecipient(new PMDeathRecipient(this)) {}
+ mWakeLock(NULL),
+ mContext(context) {}
JWakeLock::~JWakeLock() {
- if (mPowerManager != NULL) {
- sp<IBinder> binder = IInterface::asBinder(mPowerManager);
- binder->unlinkToDeath(mDeathRecipient);
- }
- clearPowerManager();
+ clearJavaWakeLock();
}
bool JWakeLock::acquire() {
if (mWakeLockCount == 0) {
- CHECK(mWakeLockToken == NULL);
- if (mPowerManager == NULL) {
- // use checkService() to avoid blocking if power service is not up yet
- sp<IBinder> binder =
- defaultServiceManager()->checkService(String16("power"));
- if (binder == NULL) {
- ALOGW("could not get the power manager service");
- } else {
- mPowerManager = interface_cast<IPowerManager>(binder);
- binder->linkToDeath(mDeathRecipient);
- }
+ if (mWakeLock == NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass jContextCls = env->FindClass("android/content/Context");
+ jclass jPowerManagerCls = env->FindClass("android/os/PowerManager");
+
+ jmethodID jGetSystemService = env->GetMethodID(jContextCls,
+ "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+ jobject javaPowerManagerObj = env->CallObjectMethod(mContext->getJObject(),
+ jGetSystemService, env->NewStringUTF("power"));
+
+ jfieldID jPARTIAL_WAKE_LOCK = env->GetStaticFieldID(jPowerManagerCls,
+ "PARTIAL_WAKE_LOCK", "I");
+ jint PARTIAL_WAKE_LOCK = env->GetStaticIntField(jPowerManagerCls, jPARTIAL_WAKE_LOCK);
+
+ jmethodID jNewWakeLock = env->GetMethodID(jPowerManagerCls,
+ "newWakeLock", "(ILjava/lang/String;)Landroid/os/PowerManager$WakeLock;");
+ jobject javaWakeLock = env->CallObjectMethod(javaPowerManagerObj,
+ jNewWakeLock, PARTIAL_WAKE_LOCK, env->NewStringUTF("JWakeLock"));
+ mWakeLock = new JObjectHolder(javaWakeLock);
+ env->DeleteLocalRef(javaPowerManagerObj);
+ env->DeleteLocalRef(javaWakeLock);
}
- if (mPowerManager != NULL) {
- sp<IBinder> binder = new BBinder();
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- status_t status = mPowerManager->acquireWakeLock(
- POWERMANAGER_PARTIAL_WAKE_LOCK,
- binder, String16("JWakeLock"), String16("media"));
- IPCThreadState::self()->restoreCallingIdentity(token);
- if (status == NO_ERROR) {
- mWakeLockToken = binder;
- mWakeLockCount++;
- return true;
- }
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jAcquire = env->GetMethodID(wakeLockCls, "acquire", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jAcquire);
+ mWakeLockCount++;
+ return true;
}
} else {
mWakeLockCount++;
@@ -86,25 +81,17 @@
mWakeLockCount = 1;
}
if (--mWakeLockCount == 0) {
- CHECK(mWakeLockToken != NULL);
- if (mPowerManager != NULL) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- mPowerManager->releaseWakeLock(mWakeLockToken, 0 /* flags */);
- IPCThreadState::self()->restoreCallingIdentity(token);
+ if (mWakeLock != NULL) {
+ JNIEnv *env = JavaVMHelper::getJNIEnv();
+ jclass wakeLockCls = env->FindClass("android/os/PowerManager$WakeLock");
+ jmethodID jRelease = env->GetMethodID(wakeLockCls, "release", "()V");
+ env->CallVoidMethod(mWakeLock->getJObject(), jRelease);
}
- mWakeLockToken.clear();
}
}
-void JWakeLock::clearPowerManager() {
+void JWakeLock::clearJavaWakeLock() {
release(true);
- mPowerManager.clear();
-}
-
-void JWakeLock::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused) {
- if (mWakeLock != NULL) {
- mWakeLock->clearPowerManager();
- }
}
} // namespace android
diff --git a/media/libmediaplayer2/nuplayer2/JWakeLock.h b/media/libmediaplayer2/nuplayer2/JWakeLock.h
index eace87e..36c542e 100644
--- a/media/libmediaplayer2/nuplayer2/JWakeLock.h
+++ b/media/libmediaplayer2/nuplayer2/JWakeLock.h
@@ -18,7 +18,7 @@
#define J_WAKELOCK_H_
#include <media/stagefright/foundation/ABase.h>
-#include <powermanager/IPowerManager.h>
+#include <mediaplayer2/JObjectHolder.h>
#include <utils/RefBase.h>
namespace android {
@@ -26,7 +26,7 @@
class JWakeLock : public RefBase {
public:
- JWakeLock();
+ JWakeLock(const sp<JObjectHolder> &context);
// NOTE: acquire and release are not thread safe
@@ -37,28 +37,11 @@
virtual ~JWakeLock();
private:
- sp<IPowerManager> mPowerManager;
- sp<IBinder> mWakeLockToken;
- uint32_t mWakeLockCount;
+ uint32_t mWakeLockCount;
+ sp<JObjectHolder> mWakeLock;
+ const sp<JObjectHolder> mContext;
- class PMDeathRecipient : public IBinder::DeathRecipient {
- public:
- explicit PMDeathRecipient(JWakeLock *wakeLock) : mWakeLock(wakeLock) {}
- virtual ~PMDeathRecipient() {}
-
- // IBinder::DeathRecipient
- virtual void binderDied(const wp<IBinder> &who);
-
- private:
- PMDeathRecipient(const PMDeathRecipient&);
- PMDeathRecipient& operator= (const PMDeathRecipient&);
-
- JWakeLock *mWakeLock;
- };
-
- const sp<PMDeathRecipient> mDeathRecipient;
-
- void clearPowerManager();
+ void clearJavaWakeLock();
DISALLOW_EVIL_CONSTRUCTORS(JWakeLock);
};
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
index 080d923..5da6e24 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.cpp
@@ -209,7 +209,8 @@
////////////////////////////////////////////////////////////////////////////////
-NuPlayer2::NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock)
+NuPlayer2::NuPlayer2(
+ pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context)
: mPID(pid),
mUID(uid),
mMediaClock(mediaClock),
@@ -240,7 +241,8 @@
mVideoDecoderError(false),
mPaused(false),
mPausedByClient(true),
- mPausedForBuffering(false) {
+ mPausedForBuffering(false),
+ mContext(context) {
CHECK(mediaClock != NULL);
clearFlushComplete();
}
@@ -1738,7 +1740,7 @@
sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
++mRendererGeneration;
notify->setInt32("generation", mRendererGeneration);
- mRenderer = new Renderer(mAudioSink, mMediaClock, notify, flags);
+ mRenderer = new Renderer(mAudioSink, mMediaClock, notify, mContext, flags);
mRendererLooper = new ALooper;
mRendererLooper->setName("NuPlayer2Renderer");
mRendererLooper->start(false, true, ANDROID_PRIORITY_AUDIO);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2.h b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
index fdc128f..798c725 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2.h
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <mediaplayer2/MediaPlayer2Interface.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "mediaplayer2.pb.h"
@@ -42,7 +43,8 @@
struct NuPlayer2Driver;
struct NuPlayer2 : public AHandler {
- explicit NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock);
+ explicit NuPlayer2(pid_t pid, uid_t uid,
+ const sp<MediaClock> &mediaClock, const sp<JObjectHolder> &context);
void setDriver(const wp<NuPlayer2Driver> &driver);
@@ -272,6 +274,9 @@
// Pause state as requested by source (internally) due to buffering
bool mPausedForBuffering;
+ // Passed from JAVA
+ const sp<JObjectHolder> mContext;
+
inline const sp<DecoderBase> &getDecoder(bool audio) {
return audio ? mAudioDecoder : mVideoDecoder;
}
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
index 2dab2dd..56e9471 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp
@@ -108,7 +108,7 @@
static const char *kPlayerRebufferingAtExit = "android.media.mediaplayer.rebufferExit";
-NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid)
+NuPlayer2Driver::NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context)
: mState(STATE_IDLE),
mAsyncResult(UNKNOWN_ERROR),
mSrcId(0),
@@ -123,7 +123,7 @@
mLooper(new ALooper),
mNuPlayer2Looper(new ALooper),
mMediaClock(new MediaClock),
- mPlayer(new NuPlayer2(pid, uid, mMediaClock)),
+ mPlayer(new NuPlayer2(pid, uid, mMediaClock, context)),
mPlayerFlags(0),
mAnalyticsItem(NULL),
mClientUid(uid),
@@ -662,33 +662,6 @@
return INVALID_OPERATION;
}
-status_t NuPlayer2Driver::getMetadata(
- const media::Metadata::Filter& /* ids */, Parcel *records) {
- Mutex::Autolock autoLock(mLock);
-
- using media::Metadata;
-
- Metadata meta(records);
-
- meta.appendBool(
- Metadata::kPauseAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_PAUSE);
-
- meta.appendBool(
- Metadata::kSeekBackwardAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_BACKWARD);
-
- meta.appendBool(
- Metadata::kSeekForwardAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK_FORWARD);
-
- meta.appendBool(
- Metadata::kSeekAvailable,
- mPlayerFlags & NuPlayer2::Source::FLAG_CAN_SEEK);
-
- return OK;
-}
-
void NuPlayer2Driver::notifyResetComplete(int64_t /* srcId */) {
ALOGD("notifyResetComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
index bb30c76..0ec3a4b 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.h
@@ -18,6 +18,7 @@
#include <media/MediaAnalyticsItem.h>
#include <media/stagefright/foundation/ABase.h>
+#include <mediaplayer2/JObjectHolder.h>
namespace android {
@@ -26,7 +27,7 @@
struct NuPlayer2;
struct NuPlayer2Driver : public MediaPlayer2Interface {
- explicit NuPlayer2Driver(pid_t pid, uid_t uid);
+ explicit NuPlayer2Driver(pid_t pid, uid_t uid, const sp<JObjectHolder> &context);
virtual status_t initCheck() override;
@@ -61,9 +62,6 @@
virtual status_t setParameter(int key, const Parcel &request) override;
virtual status_t getParameter(int key, Parcel *reply) override;
- virtual status_t getMetadata(
- const media::Metadata::Filter& ids, Parcel *records) override;
-
virtual status_t dump(int fd, const Vector<String16> &args) const override;
virtual void onMessageReceived(const sp<AMessage> &msg) override;
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index e3c9b4b..3be7e36 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -26,6 +26,8 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaClock.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
#include <media/stagefright/VideoFrameScheduler2.h>
@@ -86,10 +88,25 @@
// static
const int64_t NuPlayer2::Renderer::kMinPositionUpdateDelayUs = 100000LL;
+static audio_format_t constexpr audioFormatFromEncoding(int32_t pcmEncoding) {
+ switch (pcmEncoding) {
+ case kAudioEncodingPcmFloat:
+ return AUDIO_FORMAT_PCM_FLOAT;
+ case kAudioEncodingPcm16bit:
+ return AUDIO_FORMAT_PCM_16_BIT;
+ case kAudioEncodingPcm8bit:
+ return AUDIO_FORMAT_PCM_8_BIT; // TODO: do we want to support this?
+ default:
+ ALOGE("%s: Invalid encoding: %d", __func__, pcmEncoding);
+ return AUDIO_FORMAT_INVALID;
+ }
+}
+
NuPlayer2::Renderer::Renderer(
const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags)
: mAudioSink(sink),
mUseVirtualAudioSink(false),
@@ -131,7 +148,7 @@
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0),
mUseAudioCallback(false),
- mWakeLock(new JWakeLock()) {
+ mWakeLock(new JWakeLock(context)) {
CHECK(mediaClock != NULL);
mMediaClock->setPlaybackRate(mPlaybackSettings.mSpeed);
}
@@ -1269,10 +1286,10 @@
mAnchorTimeMediaUs = mediaTimeUs;
}
}
- mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+ mNextVideoTimeMediaUs = mediaTimeUs;
if (!mHasAudio) {
// smooth out videos >= 10fps
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
}
if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1406,9 +1423,15 @@
mHasAudio = false;
if (mNextVideoTimeMediaUs >= 0) {
int64_t mediaUs = 0;
- mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
- if (mNextVideoTimeMediaUs > mediaUs) {
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ int64_t nowUs = ALooper::GetNowUs();
+ status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+ if (result == OK) {
+ if (mNextVideoTimeMediaUs > mediaUs) {
+ mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ }
+ } else {
+ mMediaClock->updateAnchor(
+ mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
}
}
}
@@ -1864,8 +1887,13 @@
int32_t sampleRate;
CHECK(format->findInt32("sample-rate", &sampleRate));
+ // read pcm encoding from MediaCodec output format, if available
+ int32_t pcmEncoding;
+ audio_format_t audioFormat =
+ format->findInt32(KEY_PCM_ENCODING, &pcmEncoding) ?
+ audioFormatFromEncoding(pcmEncoding) : AUDIO_FORMAT_PCM_16_BIT;
+
if (offloadingAudio()) {
- audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
AString mime;
CHECK(format->findString("mime", &mime));
status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
@@ -1966,7 +1994,7 @@
const PcmInfo info = {
(audio_channel_mask_t)channelMask,
(audio_output_flags_t)pcmFlags,
- AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+ audioFormat,
numChannels,
sampleRate
};
@@ -1998,7 +2026,7 @@
sampleRate,
numChannels,
(audio_channel_mask_t)channelMask,
- AUDIO_FORMAT_PCM_16_BIT,
+ audioFormat,
mUseAudioCallback ? &NuPlayer2::Renderer::AudioSinkCallback : NULL,
mUseAudioCallback ? this : NULL,
(audio_output_flags_t)pcmFlags,
@@ -2054,4 +2082,3 @@
}
} // namespace android
-
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
index 484d9b7..d065dee 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.h
@@ -20,6 +20,7 @@
#include <media/AudioResamplerPublic.h>
#include <media/AVSyncSettings.h>
+#include <mediaplayer2/JObjectHolder.h>
#include "NuPlayer2.h"
@@ -38,6 +39,7 @@
Renderer(const sp<MediaPlayer2Interface::AudioSink> &sink,
const sp<MediaClock> &mediaClock,
const sp<AMessage> ¬ify,
+ const sp<JObjectHolder> &context,
uint32_t flags = 0);
static size_t AudioSinkCallback(
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 51879fd..55867a5 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -24,7 +24,6 @@
"liblog",
"libmedia",
"libmedia_omx",
- "libmediaextractor",
"libmediadrm",
"libmediametrics",
"libmediautils",
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e2aa8f8..1e85804 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -171,6 +171,7 @@
if (extractor == NULL) {
ALOGE("initFromDataSource, cannot create extractor!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
@@ -179,6 +180,7 @@
size_t numtracks = extractor->countTracks();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index c8f6738..c990b2a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1299,10 +1299,10 @@
mAnchorTimeMediaUs = mediaTimeUs;
}
}
- mNextVideoTimeMediaUs = mediaTimeUs + 100000;
+ mNextVideoTimeMediaUs = mediaTimeUs;
if (!mHasAudio) {
// smooth out videos >= 10fps
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
}
if (!mVideoSampleReceived || mediaTimeUs < mAudioFirstAnchorTimeMediaUs) {
@@ -1436,9 +1436,15 @@
mHasAudio = false;
if (mNextVideoTimeMediaUs >= 0) {
int64_t mediaUs = 0;
- mMediaClock->getMediaTime(ALooper::GetNowUs(), &mediaUs);
- if (mNextVideoTimeMediaUs > mediaUs) {
- mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ int64_t nowUs = ALooper::GetNowUs();
+ status_t result = mMediaClock->getMediaTime(nowUs, &mediaUs);
+ if (result == OK) {
+ if (mNextVideoTimeMediaUs > mediaUs) {
+ mMediaClock->updateMaxTimeMedia(mNextVideoTimeMediaUs);
+ }
+ } else {
+ mMediaClock->updateAnchor(
+ mNextVideoTimeMediaUs, nowUs, mNextVideoTimeMediaUs + 100000);
}
}
}
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index fd53090..f556e37 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -284,6 +284,15 @@
EntryIterator DumpReader::handleFormat(const FormatEntry &fmtEntry,
String8 *timestamp, String8 *body)
{
+ String8 timestampLocal;
+ String8 bodyLocal;
+ if (timestamp == nullptr) {
+ timestamp = ×tampLocal;
+ }
+ if (body == nullptr) {
+ body = &bodyLocal;
+ }
+
// log timestamp
const int64_t ts = fmtEntry.timestamp();
timestamp->clear();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 60b236d..a1a2660 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -566,8 +566,8 @@
mDequeueCounter(0),
mMetadataBuffersToSubmit(0),
mNumUndequeuedBuffers(0),
- mRepeatFrameDelayUs(-1ll),
- mMaxPtsGapUs(0ll),
+ mRepeatFrameDelayUs(-1LL),
+ mMaxPtsGapUs(0LL),
mMaxFps(-1),
mFps(-1.0),
mCaptureFps(-1.0),
@@ -1822,15 +1822,15 @@
if (!msg->findInt64(
"repeat-previous-frame-after",
&mRepeatFrameDelayUs)) {
- mRepeatFrameDelayUs = -1ll;
+ mRepeatFrameDelayUs = -1LL;
}
// only allow 32-bit value, since we pass it as U32 to OMX.
if (!msg->findInt64("max-pts-gap-to-encoder", &mMaxPtsGapUs)) {
- mMaxPtsGapUs = 0ll;
+ mMaxPtsGapUs = 0LL;
} else if (mMaxPtsGapUs > INT32_MAX || mMaxPtsGapUs < INT32_MIN) {
ALOGW("Unsupported value for max pts gap %lld", (long long) mMaxPtsGapUs);
- mMaxPtsGapUs = 0ll;
+ mMaxPtsGapUs = 0LL;
}
if (!msg->findFloat("max-fps-to-encoder", &mMaxFps)) {
@@ -1838,7 +1838,7 @@
}
// notify GraphicBufferSource to allow backward frames
- if (mMaxPtsGapUs < 0ll) {
+ if (mMaxPtsGapUs < 0LL) {
mMaxFps = -1;
}
@@ -2183,7 +2183,8 @@
err = setupG711Codec(encoder, sampleRate, numChannels);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
- int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
+ // numChannels needs to be set to properly communicate PCM values.
+ int32_t numChannels = 2, sampleRate = 44100, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
|| !msg->findInt32("sample-rate", &sampleRate))) {
@@ -2209,7 +2210,7 @@
}
}
err = setupFlacCodec(
- encoder, numChannels, sampleRate, compressionLevel);
+ encoder, numChannels, sampleRate, compressionLevel, pcmEncoding);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
int32_t numChannels, sampleRate;
@@ -2320,12 +2321,16 @@
(void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
mConverter[kPortIndexInput] = AudioConverter::Create(pcmEncoding, codecPcmEncoding);
if (mConverter[kPortIndexInput] != NULL) {
+ ALOGD("%s: encoder %s input format pcm encoding converter from %d to %d",
+ __func__, mComponentName.c_str(), pcmEncoding, codecPcmEncoding);
mInputFormat->setInt32("pcm-encoding", pcmEncoding);
}
} else {
(void)mOutputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
mConverter[kPortIndexOutput] = AudioConverter::Create(codecPcmEncoding, pcmEncoding);
if (mConverter[kPortIndexOutput] != NULL) {
+ ALOGD("%s: decoder %s output format pcm encoding converter from %d to %d",
+ __func__, mComponentName.c_str(), codecPcmEncoding, pcmEncoding);
mOutputFormat->setInt32("pcm-encoding", pcmEncoding);
}
}
@@ -3029,8 +3034,8 @@
}
status_t ACodec::setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel) {
-
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding) {
if (encoder) {
OMX_AUDIO_PARAM_FLACTYPE def;
InitOMXParams(&def);
@@ -3053,7 +3058,8 @@
return setupRawAudioFormat(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels,
+ encoding);
}
status_t ACodec::setupRawAudioFormat(
@@ -3111,6 +3117,7 @@
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
if (getOMXChannelMapping(numChannels, pcmParams.eChannelMapping) != OK) {
+ ALOGE("%s: incorrect numChannels: %d", __func__, numChannels);
return OMX_ErrorNone;
}
@@ -6700,7 +6707,7 @@
mCodec->mDequeueCounter = 0;
mCodec->mMetadataBuffersToSubmit = 0;
- mCodec->mRepeatFrameDelayUs = -1ll;
+ mCodec->mRepeatFrameDelayUs = -1LL;
mCodec->mInputFormat.clear();
mCodec->mOutputFormat.clear();
mCodec->mBaseOutputFormat.clear();
@@ -6842,7 +6849,7 @@
return err;
}
- if (mCodec->mRepeatFrameDelayUs > 0ll) {
+ if (mCodec->mRepeatFrameDelayUs > 0LL) {
err = statusFromBinderStatus(
mCodec->mGraphicBufferSource->setRepeatPreviousFrameDelayUs(
mCodec->mRepeatFrameDelayUs));
@@ -6855,7 +6862,7 @@
}
}
- if (mCodec->mMaxPtsGapUs != 0ll) {
+ if (mCodec->mMaxPtsGapUs != 0LL) {
OMX_PARAM_U32TYPE maxPtsGapParams;
InitOMXParams(&maxPtsGapParams);
maxPtsGapParams.nPortIndex = kPortIndexInput;
@@ -8675,14 +8682,17 @@
if (omxNode->configureVideoTunnelMode(
kPortIndexOutput, OMX_TRUE, 0, &sidebandHandle) == OK) {
// tunneled playback includes adaptive playback
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback
- | MediaCodecInfo::Capabilities::kFlagSupportsTunneledPlayback);
- } else if (omxNode->setPortMode(
- kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) == OK ||
- omxNode->prepareForAdaptivePlayback(
- kPortIndexOutput, OMX_TRUE,
- 1280 /* width */, 720 /* height */) == OK) {
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsAdaptivePlayback);
+ } else {
+ // tunneled playback is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_TUNNELED_PLAYBACK);
+ if (omxNode->setPortMode(
+ kPortIndexOutput, IOMX::kPortModeDynamicANWBuffer) != OK &&
+ omxNode->prepareForAdaptivePlayback(
+ kPortIndexOutput, OMX_TRUE,
+ 1280 /* width */, 720 /* height */) != OK) {
+ // adaptive playback is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_ADAPTIVE_PLAYBACK);
+ }
}
}
@@ -8690,11 +8700,20 @@
OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
InitOMXParams(¶ms);
params.nPortIndex = kPortIndexOutput;
- // TODO: should we verify if fallback is supported?
+
+ OMX_VIDEO_PARAM_INTRAREFRESHTYPE fallbackParams;
+ InitOMXParams(&fallbackParams);
+ fallbackParams.nPortIndex = kPortIndexOutput;
+ fallbackParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
+
if (omxNode->getConfig(
(OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
- ¶ms, sizeof(params)) == OK) {
- caps->addFlags(MediaCodecInfo::Capabilities::kFlagSupportsIntraRefresh);
+ ¶ms, sizeof(params)) != OK &&
+ omxNode->getParameter(
+ OMX_IndexParamVideoIntraRefresh, &fallbackParams,
+ sizeof(fallbackParams)) != OK) {
+ // intra refresh is not supported
+ caps->removeDetail(MediaCodecInfo::Capabilities::FEATURE_INTRA_REFRESH);
}
}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 249f2a4..f45cc58 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -94,6 +94,7 @@
"CameraSource.cpp",
"CameraSourceTimeLapse.cpp",
"DataConverter.cpp",
+ "DataSourceBase.cpp",
"DataSourceFactory.cpp",
"DataURISource.cpp",
"ClearFileSource.cpp",
@@ -113,6 +114,7 @@
"MediaCodecSource.cpp",
"MediaExtractor.cpp",
"MediaExtractorFactory.cpp",
+ "MediaSource.cpp",
"MediaSync.cpp",
"MediaTrack.cpp",
"http/ClearMediaHTTP.cpp",
@@ -150,7 +152,6 @@
"libmedia",
"libmedia_omx",
"libaudioclient",
- "libmediaextractor",
"libmediametrics",
"libmediautils",
"libui",
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index a6f0a0b..199b57b 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -118,6 +118,13 @@
}
sp<MetaData> format = mSource->getFormat();
+
+ if (format == NULL) {
+ ALOGE("No metadata b/118620871");
+ android_errorWriteLog(0x534e4554, "118620871");
+ return BAD_VALUE;
+ }
+
const char *mime;
bool success = format->findCString(kKeyMIMEType, &mime);
CHECK(success);
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 9de1e22..5027303 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -337,7 +337,7 @@
} else {
// This should not happen in normal case.
ALOGW("Failed to get audio timestamp, fallback to use systemclock");
- timeUs = systemTime() / 1000ll;
+ timeUs = systemTime() / 1000LL;
// Estimate the real sampling time of the 1st sample in this buffer
// from AudioRecord's latency. (Apply this adjustment first so that
// the start time logic is not affected.)
diff --git a/media/libmediaextractor/DataSourceBase.cpp b/media/libstagefright/DataSourceBase.cpp
similarity index 100%
rename from media/libmediaextractor/DataSourceBase.cpp
rename to media/libstagefright/DataSourceBase.cpp
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index c62c05a..42b98b1 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -39,7 +39,7 @@
namespace android {
-static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec
+static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
static const size_t kRetryCount = 50; // must be >0
sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta,
@@ -274,7 +274,7 @@
size_t retriesLeft = kRetryCount;
do {
size_t index;
- int64_t ptsUs = 0ll;
+ int64_t ptsUs = 0LL;
uint32_t flags = 0;
// Queue as many inputs as we possibly can, then block on dequeuing
@@ -406,7 +406,7 @@
: FrameDecoder(componentName, trackMeta, source),
mIsAvcOrHevc(false),
mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC),
- mTargetTimeUs(-1ll),
+ mTargetTimeUs(-1LL),
mNumFrames(0),
mNumFramesDecoded(0) {
}
@@ -487,7 +487,7 @@
const sp<MediaCodecBuffer> &videoFrameBuffer,
const sp<AMessage> &outputFormat,
int64_t timeUs, bool *done) {
- bool shouldOutput = (mTargetTimeUs < 0ll) || (timeUs >= mTargetTimeUs);
+ bool shouldOutput = (mTargetTimeUs < 0LL) || (timeUs >= mTargetTimeUs);
// If this is not the target frame, skip color convert.
if (!shouldOutput) {
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 770535c..a9715c9 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -240,7 +240,7 @@
size -= length;
}
- out->meta()->setInt64("timeUs", 0ll);
+ out->meta()->setInt64("timeUs", 0LL);
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kNotifyBuffer);
@@ -842,7 +842,7 @@
int64_t timeUs;
CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
- uint32_t PTS = (timeUs * 9ll) / 100ll;
+ uint32_t PTS = (timeUs * 9LL) / 100LL;
size_t PES_packet_length = accessUnit->size() + 8;
bool padding = (accessUnit->size() < (188 - 18));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b45eb03..7df1a2d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -487,7 +487,7 @@
mInterleaveDurationUs = 1000000;
- mStartTimestampUs = -1ll;
+ mStartTimestampUs = -1LL;
mStartTimeOffsetMs = -1;
mStartTimeOffsetBFramesUs = 0;
mPaused = false;
@@ -1745,7 +1745,7 @@
void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
ALOGI("setStartTimestampUs: %" PRId64, timeUs);
- CHECK_GE(timeUs, 0ll);
+ CHECK_GE(timeUs, 0LL);
Mutex::Autolock autoLock(mLock);
if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
mStartTimestampUs = timeUs;
@@ -3099,7 +3099,7 @@
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
- if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3120,7 +3120,7 @@
TimestampDebugHelperEntry timestampDebugEntry;
timestampUs -= previousPausedDurationUs;
timestampDebugEntry.pts = timestampUs;
- if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3159,7 +3159,7 @@
cttsOffsetTimeUs =
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
- if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(cttsOffsetTimeUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3217,7 +3217,7 @@
}
}
- if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ if (WARN_UNLESS(timestampUs >= 0LL, "for %s track", trackName)) {
copy->release();
mSource->stop();
mIsMalformed = true;
@@ -3238,7 +3238,7 @@
currDurationTicks =
((timestampUs * mTimeScale + 500000LL) / 1000000LL -
(lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
- if (currDurationTicks < 0ll) {
+ if (currDurationTicks < 0LL) {
ALOGE("do not support out of order frames (timestamp: %lld < last: %lld for %s track",
(long long)timestampUs, (long long)lastTimestampUs, trackName);
copy->release();
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 41dbfd4..4f9bc6d 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -28,7 +28,7 @@
// Maximum allowed time backwards from anchor change.
// If larger than this threshold, it's treated as discontinuity.
-static const int64_t kAnchorFluctuationAllowedUs = 10000ll;
+static const int64_t kAnchorFluctuationAllowedUs = 10000LL;
MediaClock::Timer::Timer(const sp<AMessage> ¬ify, int64_t mediaTimeUs, int64_t adjustRealUs)
: mNotify(notify),
@@ -110,7 +110,7 @@
if (mAnchorTimeRealUs != -1) {
int64_t oldNowMediaUs =
mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
- if (nowMediaUs < oldNowMediaUs
+ if (nowMediaUs < oldNowMediaUs + kAnchorFluctuationAllowedUs
&& nowMediaUs > oldNowMediaUs - kAnchorFluctuationAllowedUs) {
return;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd9e2bb..c7da7c7 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -862,9 +862,9 @@
//static
sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, const char *owner) {
if (owner) {
- if (strncmp(owner, "default", 8) == 0) {
+ if (strcmp(owner, "default") == 0) {
return new ACodec;
- } else if (strncmp(owner, "codec2", 7) == 0) {
+ } else if (strncmp(owner, "codec2", 6) == 0) {
return CreateCCodec();
}
}
@@ -911,10 +911,10 @@
continue;
}
mCodecInfo = mcl->getCodecInfo(codecIdx);
- Vector<AString> mimes;
- mCodecInfo->getSupportedMimes(&mimes);
- for (size_t i = 0; i < mimes.size(); i++) {
- if (mimes[i].startsWith("video/")) {
+ Vector<AString> mediaTypes;
+ mCodecInfo->getSupportedMediaTypes(&mediaTypes);
+ for (size_t i = 0; i < mediaTypes.size(); i++) {
+ if (mediaTypes[i].startsWith("video/")) {
mIsVideo = true;
break;
}
@@ -2699,7 +2699,7 @@
int64_t timeoutUs;
CHECK(msg->findInt64("timeoutUs", &timeoutUs));
- if (timeoutUs == 0ll) {
+ if (timeoutUs == 0LL) {
PostReplyWithError(replyID, -EAGAIN);
break;
}
@@ -2707,7 +2707,7 @@
mFlags |= kFlagDequeueInputPending;
mDequeueInputReplyID = replyID;
- if (timeoutUs > 0ll) {
+ if (timeoutUs > 0LL) {
sp<AMessage> timeoutMsg =
new AMessage(kWhatDequeueInputTimedOut, this);
timeoutMsg->setInt32(
@@ -2773,7 +2773,7 @@
int64_t timeoutUs;
CHECK(msg->findInt64("timeoutUs", &timeoutUs));
- if (timeoutUs == 0ll) {
+ if (timeoutUs == 0LL) {
PostReplyWithError(replyID, -EAGAIN);
break;
}
@@ -2781,7 +2781,7 @@
mFlags |= kFlagDequeueOutputPending;
mDequeueOutputReplyID = replyID;
- if (timeoutUs > 0ll) {
+ if (timeoutUs > 0LL) {
sp<AMessage> timeoutMsg =
new AMessage(kWhatDequeueOutputTimedOut, this);
timeoutMsg->setInt32(
@@ -3042,7 +3042,7 @@
msg->setSize("index", bufferIndex);
msg->setSize("offset", 0);
msg->setSize("size", csd->size());
- msg->setInt64("timeUs", 0ll);
+ msg->setInt64("timeUs", 0LL);
msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
msg->setPointer("errorDetailMsg", &errorDetailMsg);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index eaff283..93478e9 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -215,13 +215,9 @@
mCodecInfos.begin(),
mCodecInfos.end(),
[](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
- if (info2 == nullptr) {
- return false;
- } else if (info1 == nullptr) {
- return true;
- } else {
- return info1->rank() < info2->rank();
- }
+ // null is lowest
+ return info1 == nullptr
+ || (info2 != nullptr && info1->getRank() < info2->getRank());
});
}
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index cac53f4..dd7c3e6 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -228,18 +228,18 @@
continue;
}
- Vector<AString> mimes;
- info->getSupportedMimes(&mimes);
- for (size_t i = 0; i < mimes.size(); ++i) {
+ Vector<AString> mediaTypes;
+ info->getSupportedMediaTypes(&mediaTypes);
+ for (size_t i = 0; i < mediaTypes.size(); ++i) {
const sp<MediaCodecInfo::Capabilities> &caps =
- info->getCapabilitiesFor(mimes[i].c_str());
+ info->getCapabilitiesFor(mediaTypes[i].c_str());
if (!forceToMeasure &&
(caps->getDetails()->contains("max-supported-instances") ||
caps->getDetails()->contains("max-concurrent-instances"))) {
continue;
}
- size_t max = doProfileCodecs(info->isEncoder(), name, mimes[i], caps);
+ size_t max = doProfileCodecs(info->isEncoder(), name, mediaTypes[i], caps);
if (max > 0) {
CodecSettings settings;
char maxStr[32];
@@ -248,7 +248,7 @@
AString key = name;
key.append(" ");
- key.append(mimes[i]);
+ key.append(mediaTypes[i]);
if (info->isEncoder()) {
encoder_results->add(key, settings);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 20881a4..0f75822 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -372,7 +372,7 @@
msg->postAndAwaitResponse(&response);
int64_t timeUs;
if (!response->findInt64("time-us", &timeUs)) {
- timeUs = -1ll;
+ timeUs = -1LL;
}
return timeUs;
}
@@ -452,9 +452,9 @@
mEncoderDataSpace(0),
mPersistentSurface(persistentSurface),
mInputBufferTimeOffsetUs(0),
- mFirstSampleSystemTimeUs(-1ll),
+ mFirstSampleSystemTimeUs(-1LL),
mPausePending(false),
- mFirstSampleTimeUs(-1ll),
+ mFirstSampleTimeUs(-1LL),
mGeneration(0) {
CHECK(mLooper != NULL);
@@ -687,13 +687,13 @@
size_t bufferIndex = *mAvailEncoderInputIndices.begin();
mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
- int64_t timeUs = 0ll;
+ int64_t timeUs = 0LL;
uint32_t flags = 0;
size_t size = 0;
if (mbuf != NULL) {
CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
- if (mFirstSampleSystemTimeUs < 0ll) {
+ if (mFirstSampleSystemTimeUs < 0LL) {
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
@@ -767,7 +767,7 @@
}
int64_t startTimeUs;
if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
- startTimeUs = -1ll;
+ startTimeUs = -1LL;
}
if (mStarted) {
@@ -914,7 +914,7 @@
if (mIsVideo) {
int64_t decodingTimeUs;
if (mFlags & FLAG_USE_SURFACE_INPUT) {
- if (mFirstSampleSystemTimeUs < 0ll) {
+ if (mFirstSampleSystemTimeUs < 0LL) {
mFirstSampleSystemTimeUs = systemTime() / 1000;
if (mPausePending) {
mPausePending = false;
@@ -926,7 +926,7 @@
// Timestamp offset is already adjusted in GraphicBufferSource.
// GraphicBufferSource is supposed to discard samples
// queued before start, and offset timeUs by start time
- CHECK_GE(timeUs, 0ll);
+ CHECK_GE(timeUs, 0LL);
// TODO:
// Decoding time for surface source is unavailable,
// use presentation time for now. May need to move
@@ -954,7 +954,7 @@
}
mbuf->meta_data().setInt64(kKeyTime, timeUs);
} else {
- mbuf->meta_data().setInt64(kKeyTime, 0ll);
+ mbuf->meta_data().setInt64(kKeyTime, 0LL);
mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
}
if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
@@ -1081,7 +1081,7 @@
MetaData *params = static_cast<MetaData *>(obj.get());
int64_t pauseStartTimeUs = -1;
if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
- pauseStartTimeUs = -1ll;
+ pauseStartTimeUs = -1LL;
}
onPause(pauseStartTimeUs);
}
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2c7a4e5..86402ce 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/IMediaExtractor.h>
#include <media/IMediaExtractorService.h>
+#include <private/android_filesystem_config.h>
#include <cutils/properties.h>
#include <utils/String8.h>
#include <ziparchive/zip_archive.h>
@@ -106,7 +107,8 @@
}
MediaExtractor *ex = nullptr;
- if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1) {
+ if (creatorVersion == EXTRACTORDEF_VERSION_NDK_V1 ||
+ creatorVersion == EXTRACTORDEF_VERSION_NDK_V2) {
CMediaExtractor *ret = ((CreatorFunc)creator)(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
@@ -184,7 +186,10 @@
void *curCreator = NULL;
if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V1) {
- curCreator = (void*) (*it)->def.sniff.v2(
+ curCreator = (void*) (*it)->def.u.v2.sniff(
+ source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
+ } else if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ curCreator = (void*) (*it)->def.u.v3.sniff(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
}
@@ -214,7 +219,8 @@
void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
std::list<sp<ExtractorPlugin>> &pluginList) {
// sanity check check struct version, uuid, name
- if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1) {
+ if (plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V1 &&
+ plugin->def.def_version != EXTRACTORDEF_VERSION_NDK_V2) {
ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
return;
}
@@ -394,6 +400,8 @@
return strcmp(first->def.extractor_name, second->def.extractor_name) < 0;
}
+static std::unordered_set<std::string> gSupportedExtensions;
+
// static
void MediaExtractorFactory::UpdateExtractors(const char *newUpdateApkPath) {
Mutex::Autolock autoLock(gPluginMutex);
@@ -426,9 +434,37 @@
newList->sort(compareFunc);
gPlugins = newList;
+
+ for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ for (size_t i = 0;; i++) {
+ const char* ext = (*it)->def.u.v3.supported_types[i];
+ if (ext == nullptr) {
+ break;
+ }
+ gSupportedExtensions.insert(std::string(ext));
+ }
+ }
+ }
+
gPluginsRegistered = true;
}
+// static
+std::unordered_set<std::string> MediaExtractorFactory::getSupportedTypes() {
+ if (getuid() == AID_MEDIA_EX) {
+ return gSupportedExtensions;
+ }
+ ALOGV("get service manager");
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+ if (binder != 0) {
+ sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder));
+ return mediaExService->getSupportedTypes();
+ }
+ return std::unordered_set<std::string>();
+}
+
status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
Mutex::Autolock autoLock(gPluginMutex);
String8 out;
@@ -445,13 +481,25 @@
out.append("Available extractors:\n");
if (gPluginsRegistered) {
for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
- out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)\n",
+ out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)",
(*it)->def.extractor_name,
(*it)->def.def_version,
(*it)->uuidString.c_str(),
(*it)->def.extractor_version,
(*it)->libPath.c_str());
+ if ((*it)->def.def_version == EXTRACTORDEF_VERSION_NDK_V2) {
+ out.append(", supports: ");
+ for (size_t i = 0;; i++) {
+ const char* mime = (*it)->def.u.v3.supported_types[i];
+ if (mime == nullptr) {
+ break;
+ }
+ out.appendFormat("%s ", mime);
+ }
+ }
+ out.append("\n");
}
+ out.append("\n");
} else {
out.append(" (no plugins registered)\n");
}
diff --git a/media/libmediaextractor/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
similarity index 100%
rename from media/libmediaextractor/MediaSource.cpp
rename to media/libstagefright/MediaSource.cpp
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ba14e5d..a3f55da 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -36,7 +36,7 @@
// Maximum late time allowed for a video frame to be rendered. When a video
// frame arrives later than this number, it will be discarded without rendering.
-static const int64_t kMaxAllowedVideoLateTimeUs = 40000ll;
+static const int64_t kMaxAllowedVideoLateTimeUs = 40000LL;
namespace android {
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 1c1be30..036e79d 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -120,7 +120,7 @@
if (format->mFormat->findInt64("timeUs", &val64)) {
meta.setInt64(kKeyTime, val64);
}
- if (format->mFormat->findInt64("duration", &val64)) {
+ if (format->mFormat->findInt64("durationUs", &val64)) {
meta.setInt64(kKeyDuration, val64);
}
if (format->mFormat->findInt64("target-time", &val64)) {
@@ -172,6 +172,10 @@
meta.setData(kKeySEI,
MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
}
+ if (format->mFormat->findBuffer("audio-presentation-info", &valbuf)) {
+ meta.setData(kKeyAudioPresentationInfo,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
} else {
*buffer = nullptr;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 7025af7..522c81d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -440,12 +440,12 @@
if (mFetching) {
if (mFinalStatus != OK && mNumRetriesLeft > 0) {
// We failed this time and will try again in 3 seconds.
- delayUs = 3000000ll;
+ delayUs = 3000000LL;
} else {
delayUs = 0;
}
} else {
- delayUs = 100000ll;
+ delayUs = 100000LL;
}
(new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
@@ -740,7 +740,7 @@
}
if (keepAliveSecs >= 0) {
- mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+ mKeepAliveIntervalUs = keepAliveSecs * 1000000LL;
} else {
mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index f5178dd..83b87d9 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -41,7 +41,7 @@
NuMediaExtractor::Sample::Sample()
: mBuffer(NULL),
- mSampleTimeUs(-1ll) {
+ mSampleTimeUs(-1LL) {
}
NuMediaExtractor::Sample::Sample(MediaBufferBase *buffer, int64_t timeUs)
@@ -50,8 +50,8 @@
}
NuMediaExtractor::NuMediaExtractor()
- : mTotalBitrate(-1ll),
- mDurationUs(-1ll) {
+ : mTotalBitrate(-1LL),
+ mDurationUs(-1LL) {
}
NuMediaExtractor::~NuMediaExtractor() {
@@ -209,8 +209,8 @@
return ERROR_UNSUPPORTED;
}
- mTotalBitrate = 0ll;
- mDurationUs = -1ll;
+ mTotalBitrate = 0LL;
+ mDurationUs = -1LL;
for (size_t i = 0; i < mImpl->countTracks(); ++i) {
sp<MetaData> meta = mImpl->getTrackMetaData(i);
@@ -225,8 +225,8 @@
CHECK(meta->findCString(kKeyMIMEType, &mime));
ALOGV("track of type '%s' does not publish bitrate", mime);
- mTotalBitrate = -1ll;
- } else if (mTotalBitrate >= 0ll) {
+ mTotalBitrate = -1LL;
+ } else if (mTotalBitrate >= 0LL) {
mTotalBitrate += bitrate;
}
@@ -503,7 +503,7 @@
}
MediaSource::ReadOptions options;
- if (seekTimeUs >= 0ll) {
+ if (seekTimeUs >= 0LL) {
options.setSeekTo(seekTimeUs, mode);
info->mFinalResult = OK;
releaseTrackSamples(info);
@@ -768,7 +768,7 @@
off64_t size;
if (mDurationUs > 0 && mDataSource->getSize(&size) == OK) {
- *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ *bitrate = size * 8000000LL / mDurationUs; // in bits/sec
return true;
}
@@ -795,30 +795,34 @@
}
// Return OK if we have received an audio presentation info.
+// Return ERROR_END_OF_STREAM if no tracks are available.
// Return ERROR_UNSUPPORTED if the track has no audio presentation.
// Return INVALID_OPERATION if audio presentation metadata version does not match.
status_t NuMediaExtractor::getAudioPresentations(
- size_t trackIndex, AudioPresentationCollection *presentations) const {
+ size_t trackIndex, AudioPresentationCollection *presentations) {
Mutex::Autolock autoLock(mLock);
-
- if (mImpl == NULL) {
- return -EINVAL;
+ ssize_t minIndex = fetchAllTrackSamples();
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
}
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
- if (trackIndex >= mImpl->countTracks()) {
- return -ERANGE;
+ if (info->mTrackIndex == trackIndex) {
+ sp<MetaData> meta = new MetaData(info->mSamples.begin()->mBuffer->meta_data());
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
+ std::istringstream inStream(std::string(static_cast<const char*>(data), size));
+ return deserializeAudioPresentations(&inStream, presentations);
+ }
+ ALOGV("Track %zu does not contain any audio presentation", trackIndex);
+ return ERROR_UNSUPPORTED;
+ }
}
-
- sp<MetaData> meta = mImpl->getTrackMetaData(trackIndex);
-
- uint32_t type;
- const void *data;
- size_t size;
- if (meta != NULL && meta->findData(kKeyAudioPresentationInfo, &type, &data, &size)) {
- std::istringstream inStream(std::string(static_cast<const char*>(data), size));
- return deserializeAudioPresentations(&inStream, presentations);
- }
- ALOGE("Source does not contain any audio presentation");
+ ALOGV("Source does not contain any audio presentation");
return ERROR_UNSUPPORTED;
}
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index 96b896b..382c947 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -57,14 +57,9 @@
}
status_t queryCapabilities(
- const IOmxStore::NodeInfo& node, const char* mime, bool isEncoder,
+ const IOmxStore::NodeInfo& node, const char* mediaType, bool isEncoder,
MediaCodecInfo::CapabilitiesWriter* caps) {
sp<ACodec> codec = new ACodec();
- status_t err = codec->queryCapabilities(
- node.owner.c_str(), node.name.c_str(), mime, isEncoder, caps);
- if (err != OK) {
- return err;
- }
for (const auto& attribute : node.attributes) {
// All features have an int32 value except
// "feature-bitrate-modes", which has a string value.
@@ -81,6 +76,12 @@
attribute.key.c_str(), attribute.value.c_str());
}
}
+ // query capabilities may remove capabilities that are not actually supported by the codec
+ status_t err = codec->queryCapabilities(
+ node.owner.c_str(), node.name.c_str(), mediaType, isEncoder, caps);
+ if (err != OK) {
+ return err;
+ }
return OK;
}
@@ -163,7 +164,10 @@
info = c2i->second.get();
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
- info->setEncoder(isEncoder);
+ info->setAttributes(
+ // all OMX codecs are vendor codecs (in the vendor partition), but
+ // treat OMX.google codecs as non-hardware-accelerated and non-vendor
+ (isEncoder ? MediaCodecInfo::kFlagIsEncoder : 0));
info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
@@ -180,7 +184,19 @@
info = c2i->second.get();
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
- info->setEncoder(isEncoder);
+ typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs =
+ MediaCodecInfo::kFlagIsVendor;
+ if (isEncoder) {
+ attrs |= MediaCodecInfo::kFlagIsEncoder;
+ }
+ if (std::count_if(
+ node.attributes.begin(), node.attributes.end(),
+ [](const IOmxStore::Attribute &i) -> bool {
+ return i.key == "attribute::software-codec";
+ })) {
+ attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+ }
+ info->setAttributes(attrs);
info->setRank(defaultRank);
} else {
// If preferPlatformNodes is true, this node must be
@@ -195,12 +211,12 @@
}
}
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
- info->addMime(typeName.c_str());
+ info->addMediaType(typeName.c_str());
if (queryCapabilities(
node, typeName.c_str(), isEncoder, caps.get()) != OK) {
- ALOGW("Fail to add mime %s to codec %s",
+ ALOGW("Fail to add media type %s to codec %s",
typeName.c_str(), nodeName.c_str());
- info->removeMime(typeName.c_str());
+ info->removeMediaType(typeName.c_str());
}
}
@@ -219,7 +235,18 @@
info = c2i->second.get();
info->setName(nodeName.c_str());
info->setOwner(node->owner.c_str());
- info->setEncoder(isEncoder);
+ typename std::underlying_type<MediaCodecInfo::Attributes>::type attrs =
+ MediaCodecInfo::kFlagIsVendor;
+ if (isEncoder) {
+ attrs |= MediaCodecInfo::kFlagIsEncoder;
+ }
+ if (std::count_if(
+ node->attributes.begin(), node->attributes.end(),
+ [](const IOmxStore::Attribute &i) -> bool {
+ return i.key == "attribute::software-codec";
+ })) {
+ attrs |= MediaCodecInfo::kFlagIsHardwareAccelerated;
+ }
info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
@@ -227,13 +254,13 @@
info = c2i->second.get();
}
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter> caps =
- info->addMime(typeName.c_str());
+ info->addMediaType(typeName.c_str());
if (queryCapabilities(
*node, typeName.c_str(), isEncoder, caps.get()) != OK) {
- ALOGW("Fail to add mime %s to codec %s "
+ ALOGW("Fail to add media type %s to codec %s "
"after software codecs",
typeName.c_str(), nodeName.c_str());
- info->removeMime(typeName.c_str());
+ info->removeMediaType(typeName.c_str());
}
}
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 17187a8..cf4edae 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -22,6 +22,7 @@
#include <sys/stat.h>
#include <fcntl.h>
+#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/StagefrightMediaScanner.h>
#include <media/IMediaHTTPService.h>
@@ -34,25 +35,16 @@
StagefrightMediaScanner::~StagefrightMediaScanner() {}
-static bool FileHasAcceptableExtension(const char *extension) {
- static const char *kValidExtensions[] = {
- ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
- ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
- ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
- ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
- ".avi", ".mpeg", ".mpg", ".awb", ".mpga", ".mov",
- ".m4v", ".oga", ".m4r"
- };
- static const size_t kNumValidExtensions =
- sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
+static std::unordered_set<std::string> gSupportedExtensions;
- for (size_t i = 0; i < kNumValidExtensions; ++i) {
- if (!strcasecmp(extension, kValidExtensions[i])) {
- return true;
- }
+static bool FileHasAcceptableExtension(const char *extension) {
+
+ if (gSupportedExtensions.empty()) {
+ // get the list from the service
+ gSupportedExtensions = MediaExtractorFactory::getSupportedTypes();
}
- return false;
+ return gSupportedExtensions.count(std::string(extension + 1)) != 0;
}
MediaScanResult StagefrightMediaScanner::processFile(
@@ -135,6 +127,8 @@
{ "colorstandard", METADATA_KEY_COLOR_STANDARD },
{ "colortransfer", METADATA_KEY_COLOR_TRANSFER },
{ "colorrange", METADATA_KEY_COLOR_RANGE },
+ { "samplerate", METADATA_KEY_SAMPLERATE },
+ { "bitspersample", METADATA_KEY_BITS_PER_SAMPLE },
};
static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
index 7496752..49cea9e 100644
--- a/media/libstagefright/ThrottledSource.cpp
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -51,7 +51,7 @@
// How long would it have taken to transfer everything we ever
// transferred given the limited bandwidth.
int64_t durationUs =
- mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+ mTotalTransferred * 1000000LL / mBandwidthLimitBytesPerSecond;
int64_t whenUs = mStartTimeUs + durationUs;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 163cd05..49e485a 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -2020,7 +2020,7 @@
HLSTime::HLSTime(const sp<AMessage>& meta) :
mSeq(-1),
- mTimeUs(-1ll),
+ mTimeUs(-1LL),
mMeta(meta) {
if (meta != NULL) {
CHECK(meta->findInt32("discontinuitySeq", &mSeq));
@@ -2029,7 +2029,7 @@
}
int64_t HLSTime::getSegmentTimeUs() const {
- int64_t segmentStartTimeUs = -1ll;
+ int64_t segmentStartTimeUs = -1LL;
if (mMeta != NULL) {
CHECK(mMeta->findInt64("segmentStartTimeUs", &segmentStartTimeUs));
diff --git a/media/libstagefright/VideoFrameScheduler2.cpp b/media/libstagefright/VideoFrameScheduler2.cpp
index e02ae7d..fc76904 100644
--- a/media/libstagefright/VideoFrameScheduler2.cpp
+++ b/media/libstagefright/VideoFrameScheduler2.cpp
@@ -36,7 +36,7 @@
namespace android {
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr);
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr);
/* ======================================================================= */
/* VsyncTracker */
@@ -46,19 +46,19 @@
public:
VsyncTracker();
~VsyncTracker() {}
- long getVsyncPeriod();
- long getVsyncTime(long periodOffset);
- void addSample(long timestamp);
+ nsecs_t getVsyncPeriod();
+ nsecs_t getVsyncTime(nsecs_t periodOffset);
+ void addSample(nsecs_t timestamp);
private:
static const int kMaxSamples = 32;
static const int kMinSamplesForUpdate = 6;
int mNumSamples;
int mFirstSample;
- long mReferenceTime;
- long mPhase;
- long mPeriod;
- long mTimestampSamples[kMaxSamples];
+ nsecs_t mReferenceTime;
+ nsecs_t mPhase;
+ nsecs_t mPeriod;
+ nsecs_t mTimestampSamples[kMaxSamples];
Mutex mLock;
void updateModelLocked();
@@ -75,19 +75,39 @@
}
}
-long VsyncTracker::getVsyncPeriod() {
+nsecs_t VsyncTracker::getVsyncPeriod() {
Mutex::Autolock dataLock(mLock);
return mPeriod;
}
-long VsyncTracker::getVsyncTime(long periodOffset) {
+nsecs_t VsyncTracker::getVsyncTime(nsecs_t periodOffset) {
Mutex::Autolock dataLock(mLock);
- const long now = systemTime();
- long phase = mReferenceTime + mPhase;
- return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+ const nsecs_t now = systemTime();
+ nsecs_t phase = mReferenceTime + mPhase;
+
+ // result = (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase
+ // prevent overflow
+ nsecs_t result = (now - phase) / mPeriod;
+ if (result > LONG_LONG_MAX - periodOffset - 1) {
+ return LONG_LONG_MAX;
+ } else {
+ result += periodOffset + 1;
+ }
+ if (result > LONG_LONG_MAX / mPeriod) {
+ return LONG_LONG_MAX;
+ } else {
+ result *= mPeriod;
+ }
+ if (result > LONG_LONG_MAX - phase) {
+ return LONG_LONG_MAX;
+ } else {
+ result += phase;
+ }
+
+ return result;
}
-void VsyncTracker::addSample(long timestamp) {
+void VsyncTracker::addSample(nsecs_t timestamp) {
Mutex::Autolock dataLock(mLock);
if (mNumSamples == 0) {
mPhase = 0;
@@ -107,17 +127,17 @@
if (mNumSamples < kMinSamplesForUpdate) {
return;
}
- long durationSum = 0;
- long minDuration = LONG_MAX;
- long maxDuration = 0;
+ nsecs_t durationSum = 0;
+ nsecs_t minDuration = LONG_MAX;
+ nsecs_t maxDuration = 0;
for (int i = 1; i < mNumSamples; i++) {
int idx = (mFirstSample + i) % kMaxSamples;
int prev = (idx + kMaxSamples - 1) % kMaxSamples;
long duration = mTimestampSamples[idx] - mTimestampSamples[prev];
durationSum += duration;
- minDuration = min(minDuration, duration);
- maxDuration = max(maxDuration, duration);
+ if (minDuration > duration) { minDuration = duration; }
+ if (maxDuration < duration) { maxDuration = duration; }
}
durationSum -= (minDuration + maxDuration);
@@ -154,9 +174,9 @@
/* JNI */
/* ======================================================================= */
-static void getVsyncOffset(long* appVsyncOffsetPtr, long* sfVsyncOffsetPtr) {
- static const long kOneMillisecInNanosec = 1000000;
- static const long kOneSecInNanosec = kOneMillisecInNanosec * 1000;
+static void getVsyncOffset(nsecs_t* appVsyncOffsetPtr, nsecs_t* sfVsyncOffsetPtr) {
+ static const nsecs_t kOneMillisecInNanosec = 1000000;
+ static const nsecs_t kOneSecInNanosec = kOneMillisecInNanosec * 1000;
JNIEnv *env = JavaVMHelper::getJNIEnv();
jclass jDisplayManagerGlobalCls = env->FindClass(
@@ -178,19 +198,19 @@
jmethodID jGetRefreshRate = env->GetMethodID(jDisplayCls, "getRefreshRate", "()F");
jfloat javaRefreshRate = env->CallFloatMethod(javaDisplayObj, jGetRefreshRate);
- long vsyncPeriod = (long) (kOneSecInNanosec / (float) javaRefreshRate);
+ nsecs_t vsyncPeriod = (nsecs_t) (kOneSecInNanosec / (float) javaRefreshRate);
jmethodID jGetAppVsyncOffsetNanos = env->GetMethodID(
jDisplayCls, "getAppVsyncOffsetNanos", "()J");
jlong javaAppVsyncOffset = env->CallLongMethod(javaDisplayObj, jGetAppVsyncOffsetNanos);
- *appVsyncOffsetPtr = (long) javaAppVsyncOffset;
+ *appVsyncOffsetPtr = (nsecs_t) javaAppVsyncOffset;
jmethodID jGetPresentationDeadlineNanos = env->GetMethodID(
jDisplayCls, "getPresentationDeadlineNanos", "()J");
jlong javaPresentationDeadline = env->CallLongMethod(
javaDisplayObj, jGetPresentationDeadlineNanos);
- *sfVsyncOffsetPtr = vsyncPeriod - ((long) javaPresentationDeadline - kOneMillisecInNanosec);
+ *sfVsyncOffsetPtr = vsyncPeriod - ((nsecs_t) javaPresentationDeadline - kOneMillisecInNanosec);
}
/* ======================================================================= */
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/libstagefright/bqhelper/FrameDropper.cpp
index d2a2473..387ac5a 100644
--- a/media/libstagefright/bqhelper/FrameDropper.cpp
+++ b/media/libstagefright/bqhelper/FrameDropper.cpp
@@ -35,7 +35,7 @@
status_t FrameDropper::setMaxFrameRate(float maxFrameRate) {
if (maxFrameRate < 0) {
- mMinIntervalUs = -1ll;
+ mMinIntervalUs = -1LL;
return OK;
}
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 8c1da76..a4374c9 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -292,20 +292,20 @@
mSuspended(false),
mLastFrameTimestampUs(-1),
mStopTimeUs(-1),
- mLastActionTimeUs(-1ll),
- mSkipFramesBeforeNs(-1ll),
- mFrameRepeatIntervalUs(-1ll),
+ mLastActionTimeUs(-1LL),
+ mSkipFramesBeforeNs(-1LL),
+ mFrameRepeatIntervalUs(-1LL),
mRepeatLastFrameGeneration(0),
mOutstandingFrameRepeatCount(0),
mFrameRepeatBlockedOnCodecBuffer(false),
mFps(-1.0),
mCaptureFps(-1.0),
- mBaseCaptureUs(-1ll),
- mBaseFrameUs(-1ll),
+ mBaseCaptureUs(-1LL),
+ mBaseFrameUs(-1LL),
mFrameCount(0),
- mPrevCaptureUs(-1ll),
- mPrevFrameUs(-1ll),
- mInputBufferTimeOffsetUs(0ll) {
+ mPrevCaptureUs(-1LL),
+ mPrevFrameUs(-1LL),
+ mInputBufferTimeOffsetUs(0LL) {
ALOGV("GraphicBufferSource");
String8 name("GraphicBufferSource");
@@ -392,7 +392,7 @@
submitEndOfInputStream_l();
}
- if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) {
+ if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
mReflector = new AHandlerReflector<GraphicBufferSource>(this);
mLooper = new ALooper;
@@ -655,7 +655,7 @@
// only submit sample if start time is unspecified, or sample
// is queued after the specified start time
- if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) {
+ if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
// if start time is set, offset time stamp by start time
if (mSkipFramesBeforeNs > 0) {
item.mTimestampNs -= mSkipFramesBeforeNs;
@@ -677,7 +677,7 @@
} else {
// Don't set the last buffer id if we're not repeating,
// we'll be holding on to the last buffer for nothing.
- if (mFrameRepeatIntervalUs > 0ll) {
+ if (mFrameRepeatIntervalUs > 0LL) {
setLatestBuffer_l(item);
}
ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
@@ -755,7 +755,7 @@
&& (mFps > 2 * mCaptureFps
|| mCaptureFps > 2 * mFps)) {
// Time lapse or slow motion mode
- if (mPrevCaptureUs < 0ll) {
+ if (mPrevCaptureUs < 0LL) {
// first capture
mPrevCaptureUs = mBaseCaptureUs = timeUs;
// adjust the first sample timestamp.
@@ -1123,19 +1123,19 @@
mSuspended = false;
mEndOfStream = false;
mEndOfStreamSent = false;
- mSkipFramesBeforeNs = -1ll;
+ mSkipFramesBeforeNs = -1LL;
mFrameDropper.clear();
- mFrameRepeatIntervalUs = -1ll;
+ mFrameRepeatIntervalUs = -1LL;
mRepeatLastFrameGeneration = 0;
mOutstandingFrameRepeatCount = 0;
mLatestBuffer.mBuffer.reset();
mFrameRepeatBlockedOnCodecBuffer = false;
mFps = -1.0;
mCaptureFps = -1.0;
- mBaseCaptureUs = -1ll;
- mBaseFrameUs = -1ll;
- mPrevCaptureUs = -1ll;
- mPrevFrameUs = -1ll;
+ mBaseCaptureUs = -1LL;
+ mBaseFrameUs = -1LL;
+ mPrevCaptureUs = -1LL;
+ mPrevFrameUs = -1LL;
mFrameCount = 0;
mInputBufferTimeOffsetUs = 0;
mStopTimeUs = -1;
@@ -1201,7 +1201,7 @@
Mutex::Autolock autoLock(mMutex);
- if (mExecuting || repeatAfterUs <= 0ll) {
+ if (mExecuting || repeatAfterUs <= 0LL) {
return INVALID_OPERATION;
}
@@ -1213,7 +1213,7 @@
Mutex::Autolock autoLock(mMutex);
// timeOffsetUs must be negative for adjustment.
- if (timeOffsetUs >= 0ll) {
+ if (timeOffsetUs >= 0LL) {
return INVALID_OPERATION;
}
@@ -1247,7 +1247,7 @@
mSkipFramesBeforeNs =
(skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
- (skipFramesBeforeUs * 1000) : -1ll;
+ (skipFramesBeforeUs * 1000) : -1LL;
return OK;
}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index d393c7a..41bc16c 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -738,7 +738,7 @@
} else {
int64_t currentTime = mBufferTimestamps.top();
currentTime += mStreamInfo->aacSamplesPerFrame *
- 1000000ll / mStreamInfo->aacSampleRate;
+ 1000000LL / mStreamInfo->aacSampleRate;
mBufferTimestamps.add(currentTime);
}
} else {
@@ -989,7 +989,7 @@
// adjust/interpolate next time stamp
*currentBufLeft -= decodedSize;
*nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
- 1000000ll / mStreamInfo->aacSampleRate;
+ 1000000LL / mStreamInfo->aacSampleRate;
ALOGV("adjusted nextTimeStamp/size to %lld/%d",
(long long) *nextTimeStamp, *currentBufLeft);
} else {
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 96e668e..6e437cf 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -63,7 +63,7 @@
mInputSize(0),
mInputFrame(NULL),
mAllocatedFrameSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -587,7 +587,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / mSampleRate)
+ (copy * 1000000LL / mSampleRate)
/ (mNumChannels * sizeof(int16_t));
if (inHeader->nFilledLen == 0) {
@@ -725,7 +725,7 @@
mAllocatedFrameSize = 0;
mSentCodecSpecificData = false;
- mInputTimeUs = -1ll;
+ mInputTimeUs = -1LL;
mSawInputEOS = false;
mSignalledError = false;
}
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index b7e84ec..34dd011 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -505,7 +505,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
+ + (mNumSamplesOutput * 1000000LL) / kSampleRateNB;
mNumSamplesOutput += kNumSamplesPerFrameNB;
} else {
@@ -513,7 +513,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
+ + (mNumSamplesOutput * 1000000LL) / kSampleRateWB;
mNumSamplesOutput += kNumSamplesPerFrameWB;
}
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
index f97c44f..85ab64e 100644
--- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -49,7 +49,7 @@
mBitRate(0),
mMode(MR475),
mInputSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -340,7 +340,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+ (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
if (inHeader->nFilledLen == 0) {
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
index a644b66..7fb8a4c 100644
--- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -50,7 +50,7 @@
mBitRate(0),
mMode(VOAMRWB_MD66),
mInputSize(0),
- mInputTimeUs(-1ll),
+ mInputTimeUs(-1LL),
mSawInputEOS(false),
mSignalledError(false) {
initPorts();
@@ -387,7 +387,7 @@
// "Time" on the input buffer has in effect advanced by the
// number of audio frames we just advanced nOffset by.
inHeader->nTimeStamp +=
- (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+ (copy * 1000000LL / kSampleRate) / sizeof(int16_t);
if (inHeader->nFilledLen == 0) {
if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 3924fc2..bf5e243 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -607,7 +607,7 @@
timeTaken = mTimeEnd - mTimeStart;
ALOGV("timeTaken=%6lldus delay=%6lldus numBytes=%6d",
- (long long) (timeTaken / 1000ll), (long long) (timeDelay / 1000ll),
+ (long long) (timeTaken / 1000LL), (long long) (timeDelay / 1000LL),
s_dec_op.u4_num_bytes_consumed);
if (s_dec_op.u4_frame_decoded_flag && !mFlushNeeded) {
mFlushNeeded = true;
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
index 4db0060..842a7ce 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.cpp
@@ -89,12 +89,12 @@
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumOutputBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 4096 * FLACDecoder::kMaxChannels;
+ def.nBufferSize = kNumSamplesPerFrame * FLACDecoder::kMaxChannels * sizeof(float);
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -173,7 +173,7 @@
flacParams->nChannels = mStreamInfo.channels;
flacParams->nSampleRate = mStreamInfo.sample_rate;
} else {
- flacParams->nChannels = 1;
+ flacParams->nChannels = 2;
flacParams->nSampleRate = 44100;
}
@@ -195,10 +195,10 @@
return OMX_ErrorBadPortIndex;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -211,7 +211,7 @@
pcmParams->nChannels = mStreamInfo.channels;
pcmParams->nSamplingRate = mStreamInfo.sample_rate;
} else {
- pcmParams->nChannels = 1;
+ pcmParams->nChannels = 2;
pcmParams->nSamplingRate = 44100;
}
@@ -281,6 +281,19 @@
return OMX_ErrorBadPortIndex;
}
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("Invalid eNumData %d, nBitsPerSample %d",
+ pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
return OMX_ErrorNone;
}
@@ -301,11 +314,13 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool outputFloat = mNumericalData == OMX_NumericalDataFloat;
+
ALOGV("onQueueFilled %d/%d:", inQueue.empty(), outQueue.empty());
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mFinishedDecoder) {
BufferInfo *outInfo = *outQueue.begin();
OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
- int16_t *outBuffer = reinterpret_cast<int16_t *>(outHeader->pBuffer + outHeader->nOffset);
+ void *outBuffer = reinterpret_cast<void *>(outHeader->pBuffer + outHeader->nOffset);
size_t outBufferSize = outHeader->nAllocLen - outHeader->nOffset;
int64_t timeStamp = 0;
@@ -374,7 +389,7 @@
}
status_t decoderErr = mFLACDecoder->decodeOneFrame(
- inBuffer, inBufferLength, outBuffer, &outBufferSize);
+ inBuffer, inBufferLength, outBuffer, &outBufferSize, outputFloat);
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder decodeOneFrame returns error %d", decoderErr);
mSignalledError = true;
@@ -393,7 +408,9 @@
continue;
}
} else if (mSawInputEOS) {
- status_t decoderErr = mFLACDecoder->decodeOneFrame(NULL, 0, outBuffer, &outBufferSize);
+ status_t decoderErr = mFLACDecoder->decodeOneFrame(
+ nullptr /* inBuffer */, 0 /* inBufferLen */,
+ outBuffer, &outBufferSize, outputFloat);
mFinishedDecoder = true;
if (decoderErr != OK) {
ALOGE("onQueueFilled: FLACDecoder finish returns error %d", decoderErr);
@@ -456,7 +473,8 @@
mOutputPortSettingsChange = AWAITING_ENABLED;
PortInfo *info = editPortInfo(1 /* portIndex */);
if (!info->mDef.bEnabled) {
- info->mDef.nBufferSize = mStreamInfo.max_blocksize * mStreamInfo.channels * 2;
+ info->mDef.nBufferSize =
+ mStreamInfo.max_blocksize * mStreamInfo.channels * sizeof(float);
}
break;
}
diff --git a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
index b63f7ad..ba02074 100644
--- a/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
+++ b/media/libstagefright/codecs/flac/dec/SoftFlacDecoder.h
@@ -45,10 +45,14 @@
virtual void onReset() override;
private:
+ static constexpr unsigned int kNumSamplesPerFrame = 2048; // adjusted based on stream.
+
enum {
kNumInputBuffers = 4,
kNumOutputBuffers = 4,
};
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
FLACDecoder *mFLACDecoder;
FLAC__StreamMetadata_StreamInfo mStreamInfo;
diff --git a/media/libstagefright/codecs/flac/enc/Android.bp b/media/libstagefright/codecs/flac/enc/Android.bp
index 9b696da..b32ab08 100644
--- a/media/libstagefright/codecs/flac/enc/Android.bp
+++ b/media/libstagefright/codecs/flac/enc/Android.bp
@@ -28,7 +28,10 @@
],
header_libs: ["libbase_headers"],
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libaudioutils",
+ "libFLAC",
+ ],
name: "libstagefright_soft_flacenc",
vendor_available: true,
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 955f211..3add006 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -20,7 +20,7 @@
#include <utils/Log.h>
#include "SoftFlacEncoder.h"
-
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>
@@ -75,7 +75,9 @@
}
if (!mSignalledError) { // no use allocating input buffer if we had an error above
- mInputBufferPcm32 = (FLAC__int32*) malloc(sizeof(FLAC__int32) * 2 * kMaxNumSamplesPerFrame);
+ // 2x the pcm16 samples can exist with the same size as pcmFloat samples.
+ mInputBufferPcm32 = (FLAC__int32*) malloc(
+ sizeof(FLAC__int32) * kNumSamplesPerFrame * kMaxChannels * 2);
if (mInputBufferPcm32 == NULL) {
ALOGE("SoftFlacEncoder::SoftFlacEncoder(name=%s) error allocating internal input buffer", name);
mSignalledError = true;
@@ -115,14 +117,14 @@
// configure input port of the encoder
def.nPortIndex = 0;
def.eDir = OMX_DirInput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxInputBufferSize;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
def.bBuffersContiguous = OMX_FALSE;
- def.nBufferAlignment = 2;
+ def.nBufferAlignment = sizeof(float);
def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
def.format.audio.pNativeRender = NULL;
@@ -134,7 +136,7 @@
// configure output port of the encoder
def.nPortIndex = 1;
def.eDir = OMX_DirOutput;
- def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
+ def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
def.nBufferSize = kMaxOutputBufferSize;
def.bEnabled = OMX_TRUE;
@@ -193,10 +195,10 @@
return OMX_ErrorUndefined;
}
- pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eNumData = mNumericalData;
pcmParams->eEndian = OMX_EndianBig;
pcmParams->bInterleaved = OMX_TRUE;
- pcmParams->nBitPerSample = 16;
+ pcmParams->nBitPerSample = mBitsPerSample;
pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
@@ -270,12 +272,26 @@
return OMX_ErrorUndefined;
}
- if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
+ if (pcmParams->nChannels < 1 || pcmParams->nChannels > kMaxChannels) {
return OMX_ErrorUndefined;
}
mNumChannels = pcmParams->nChannels;
mSampleRate = pcmParams->nSamplingRate;
+
+ if (pcmParams->eNumData == OMX_NumericalDataFloat && pcmParams->nBitPerSample == 32) {
+ mNumericalData = OMX_NumericalDataFloat;
+ mBitsPerSample = 32;
+ } else if (pcmParams->eNumData == OMX_NumericalDataSigned
+ && pcmParams->nBitPerSample == 16) {
+ mNumericalData = OMX_NumericalDataSigned;
+ mBitsPerSample = 16;
+ } else {
+ ALOGE("%s: invalid eNumData %d, nBitsPerSample %d",
+ __func__, pcmParams->eNumData, pcmParams->nBitPerSample);
+ return OMX_ErrorUndefined;
+ }
+
ALOGV("will encode %d channels at %dHz", mNumChannels, mSampleRate);
return configureEncoder();
@@ -356,6 +372,10 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const size_t sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = sampleSize * mNumChannels;
+
FLAC__bool ok = true;
while ((!inQueue.empty() || mSawInputEOS) && !outQueue.empty() && !mSentOutputEOS) {
@@ -381,13 +401,21 @@
mEncoderReturnedNbBytes = 0;
mCurrentInputTimeStamp = inHeader->nTimeStamp;
- const unsigned nbInputFrames = inHeader->nFilledLen / (2 * mNumChannels);
- const unsigned nbInputSamples = inHeader->nFilledLen / 2;
- const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
+ const unsigned nbInputFrames = inHeader->nFilledLen / frameSize;
+ const unsigned nbInputSamples = inHeader->nFilledLen / sampleSize;
- CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
- for (unsigned i=0 ; i < nbInputSamples ; i++) {
- mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ if (inputFloat) {
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels);
+ const float * const pcmFloat = reinterpret_cast<float *>(inHeader->pBuffer);
+ memcpy_to_q8_23_from_float_with_clamp(
+ mInputBufferPcm32, pcmFloat, nbInputSamples);
+ } else {
+ // note nbInputSamples may be 2x as large for pcm16 data.
+ CHECK_LE(nbInputSamples, kNumSamplesPerFrame * kMaxChannels * 2);
+ const int16_t * const pcm16 = reinterpret_cast<int16_t *>(inHeader->pBuffer);
+ for (unsigned i = 0; i < nbInputSamples; ++i) {
+ mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
+ }
}
ALOGV(" about to encode %u samples per channel", nbInputFrames);
ok = FLAC__stream_encoder_process_interleaved(
@@ -526,10 +554,12 @@
return OMX_ErrorInvalidState;
}
+ const bool inputFloat = mNumericalData == OMX_NumericalDataFloat;
+ const int codecBitsPerSample = inputFloat ? 24 : 16;
FLAC__bool ok = true;
ok = ok && FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mNumChannels);
ok = ok && FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, mSampleRate);
- ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, 16);
+ ok = ok && FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, codecBitsPerSample);
ok = ok && FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder,
(unsigned)mCompressionLevel);
ok = ok && FLAC__stream_encoder_set_verify(mFlacStreamEncoder, false);
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 64a6b1e..722fc13 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -45,8 +45,10 @@
private:
const unsigned int kNumBuffers = 2;
- const unsigned int kMaxNumSamplesPerFrame = 1152;
- const unsigned int kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+ static constexpr unsigned int kMaxChannels = 2;
+ static constexpr unsigned int kNumSamplesPerFrame = 1152;
+ static constexpr unsigned int kMaxInputBufferSize =
+ kNumSamplesPerFrame * kMaxChannels * sizeof(float);
const unsigned int kMaxOutputBufferSize = 65536; //TODO check if this can be reduced
bool mSignalledError;
@@ -54,6 +56,8 @@
OMX_U32 mNumChannels;
OMX_U32 mSampleRate;
OMX_U32 mCompressionLevel;
+ OMX_NUMERICALDATATYPE mNumericalData = OMX_NumericalDataSigned;
+ OMX_U32 mBitsPerSample = 16;
// should the data received by the callback be written to the output port
bool mEncoderWriteData;
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 7a4cca9..c14983a 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -372,7 +372,7 @@
int32_t step = 4 << segment;
- int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+ int32_t abs = (0x80L << exponent) + step * mantissa + step / 2 - 4 * 33;
*out++ = (x < 0x80) ? -abs : abs;
}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index fda7028..a8fcdd1 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -382,6 +382,7 @@
if (portIndex == 0 && mInitialized) {
CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE);
}
+ mFramesConfigured = false;
}
void SoftMPEG4::onReset() {
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
index 53149c1..ecc3217 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
@@ -377,15 +377,15 @@
/* In/out : Nr, B, Rr */
/* Return : Void */
/* Modified : */
+/* Input argument "video" is guaranteed non-null by caller */
/* ======================================================================== */
-
PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip)
{
rateControl *rc = video->rc[currLayer];
MultiPass *pMP = video->pMP[currLayer];
- if (video == NULL || rc == NULL || pMP == NULL)
+ if (rc == NULL || pMP == NULL)
return PV_FAIL;
rc->VBV_fullness -= (Int)(rc->bitrate / rc->framerate * num_skip); //rc[currLayer]->Rp;
@@ -524,6 +524,7 @@
/* In/out : rc->T */
/* Return : Void */
/* Modified : */
+/* Input argument "input" is guaranteed non-null by caller */
/* ================================================================================ */
void targetBitCalculation(void *input)
@@ -537,7 +538,7 @@
Int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
/* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
- if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ if (currVol == NULL || pMP == NULL || rc == NULL)
return;
/* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
@@ -693,6 +694,7 @@
/* In/out : rc->T and rc->Qc */
/* Return : Void */
/* Modified : */
+/* Input argument "input" is guaranteed non-null by caller */
/* ================================================================================ */
/* Mad based variable bit allocation + QP calculation with a new quadratic method */
@@ -708,7 +710,7 @@
float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
- if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ if (currVol == NULL || pMP == NULL || rc == NULL)
return;
/* Mad based variable bit allocation */
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index cd984f0..80083f7 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -407,7 +407,7 @@
}
outHeader->nTimeStamp =
- mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
+ mAnchorTimeUs + (mNumFramesOutput * 1000000LL) / mSamplingRate;
if (inHeader) {
CHECK_GE((int32_t)inHeader->nFilledLen, mConfig->inputBufferUsedLength);
diff --git a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
index 942f850..4f61aa8 100644
--- a/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
+++ b/media/libstagefright/codecs/opus/dec/SoftOpus.cpp
@@ -430,6 +430,15 @@
return;
}
+ if (size < sizeof(int64_t)) {
+ // The 2nd and 3rd input buffer are expected to contain
+ // an int64_t (see below), so make sure we get at least
+ // that much. The first input buffer must contain 19 bytes,
+ // but that is checked already.
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
if (mInputBufferCount == 0) {
delete mHeader;
mHeader = new OpusHeader();
@@ -573,7 +582,7 @@
outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels;
outHeader->nTimeStamp = mAnchorTimeUs +
- (mNumFramesOutput * 1000000ll) /
+ (mNumFramesOutput * 1000000LL) /
kRate;
mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index ce8d458..76a400c 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -554,7 +554,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs
- + (mNumFramesOutput * 1000000ll) / mVi->rate;
+ + (mNumFramesOutput * 1000000LL) / mVi->rate;
mNumFramesOutput += numFrames;
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
index f352fba..8a86a0d 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.cpp
@@ -110,15 +110,22 @@
{
initPorts();
- CHECK_EQ(initDecoder(), (status_t)OK);
+ mMemoryVec.clear();
+ mDrcMemoryVec.clear();
+
+ CHECK_EQ(initDecoder(), IA_NO_ERROR);
}
SoftXAAC::~SoftXAAC() {
- int errCode = deInitXAACDecoder();
- if (0 != errCode) {
- ALOGE("deInitXAACDecoder() failed %d", errCode);
+ IA_ERRORCODE err_code = deInitXAACDecoder();
+ if (IA_NO_ERROR != err_code) {
+ ALOGE("deInitXAACDecoder() failed %d", err_code);
}
+ err_code = deInitMPEGDDDrc();
+ if (IA_NO_ERROR != err_code) {
+ ALOGE("deInitMPEGDDDrc() failed %d", err_code);
+ }
mIsCodecInitialized = false;
mIsCodecConfigFlushRequired = false;
}
@@ -164,36 +171,16 @@
addPort(def);
}
-status_t SoftXAAC::initDecoder() {
- status_t status = UNKNOWN_ERROR;
-
+IA_ERRORCODE SoftXAAC::initDecoder() {
int ui_drc_val;
IA_ERRORCODE err_code = IA_NO_ERROR;
int loop = 0;
err_code = initXAACDecoder();
if (err_code != IA_NO_ERROR) {
- if (NULL == mXheaacCodecHandle) {
- ALOGE("AAC decoder handle is null");
- }
- if (NULL == mMpegDDrcHandle) {
- ALOGE("MPEG-D DRC decoder handle is null");
- }
- for (loop = 1; loop < mMallocCount; loop++) {
- if (mMemoryArray[loop] == NULL) {
- ALOGE(" memory allocation error %d\n", loop);
- break;
- }
- }
- ALOGE("initXAACDecoder Failed");
-
- for (loop = 0; loop < mMallocCount; loop++) {
- if (mMemoryArray[loop]) free(mMemoryArray[loop]);
- }
- mMallocCount = 0;
- return status;
- } else {
- status = OK;
+ ALOGE("initXAACDecoder failed with error %d", err_code);
+ deInitXAACDecoder();
+ return err_code;
}
mEndOfInput = false;
@@ -274,7 +261,7 @@
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE");
#endif
- return status;
+ return IA_NO_ERROR;
}
OMX_ERRORTYPE SoftXAAC::internalGetParameter(OMX_INDEXTYPE index, OMX_PTR params) {
@@ -547,9 +534,6 @@
/* sample currently */
if (mIsCodecInitialized) {
numOutBytes = mOutputFrameLength * (mPcmWdSz / 8) * mNumChannels;
- if ((mPcmWdSz / 8) != 2) {
- ALOGE("XAAC assumes 2 bytes per sample! mPcmWdSz %d", mPcmWdSz);
- }
}
while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) {
@@ -569,8 +553,8 @@
inBufferLength = inHeader->nFilledLen;
/* GA header configuration sent to Decoder! */
- int err_code = configXAACDecoder(inBuffer, inBufferLength);
- if (0 != err_code) {
+ IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+ if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -665,7 +649,7 @@
mCurrentTimestamp = inHeader->nTimeStamp;
mLastInHeader = inHeader;
} else {
- mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000ll / mSampFreq;
+ mCurrentTimestamp = mPrevTimestamp + mOutputFrameLength * 1000000LL / mSampFreq;
}
} else {
inBuffer = inHeader->pBuffer + inHeader->nOffset;
@@ -682,8 +666,8 @@
/* which should initialize the codec. Once this state is reached, call the */
/* decodeXAACStream API with same frame to decode! */
if (!mIsCodecInitialized) {
- int err_code = configXAACDecoder(inBuffer, inBufferLength);
- if (0 != err_code) {
+ IA_ERRORCODE err_code = configXAACDecoder(inBuffer, inBufferLength);
+ if (IA_NO_ERROR != err_code) {
ALOGW("configXAACDecoder Failed 2 err_code = %d", err_code);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, err_code, NULL);
@@ -845,7 +829,7 @@
}
}
-int SoftXAAC::configflushDecode() {
+IA_ERRORCODE SoftXAAC::configflushDecode() {
IA_ERRORCODE err_code;
UWORD32 ui_init_done;
uint32_t inBufferLength = 8203;
@@ -871,16 +855,13 @@
"Found Codec with below config---\nsampFreq %d\nnumChannels %d\npcmWdSz "
"%d\nchannelMask %d\noutputFrameLength %d",
mSampFreq, mNumChannels, mPcmWdSz, mChannelMask, mOutputFrameLength);
- if (mNumChannels > MAX_CHANNEL_COUNT) {
- ALOGE(" No of channels are more than max channels\n");
- mIsCodecInitialized = false;
- } else
- mIsCodecInitialized = true;
+
+ mIsCodecInitialized = true;
}
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::drainDecoder() {
- return 0;
+IA_ERRORCODE SoftXAAC::drainDecoder() {
+ return IA_NO_ERROR;
}
void SoftXAAC::onReset() {
@@ -921,7 +902,7 @@
}
}
-int SoftXAAC::initXAACDecoder() {
+IA_ERRORCODE SoftXAAC::initXAACDecoder() {
LOOPIDX i;
/* Error code */
@@ -939,11 +920,11 @@
UWORD32 ui_proc_mem_tabs_size;
/* API size */
UWORD32 pui_api_size;
+ pVOID pv_alloc_ptr;
mInputBufferSize = 0;
mInputBuffer = 0;
mOutputBuffer = 0;
- mMallocCount = 0;
/* Process struct initing end */
/* ******************************************************************/
@@ -954,20 +935,13 @@
err_code = ixheaacd_dec_api(NULL, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
/* Allocate memory for API */
- mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ mXheaacCodecHandle = memalign(4, pui_api_size);
+ if (mXheaacCodecHandle == NULL) {
ALOGE("malloc for pui_api_size + 4 >> %d Failed", pui_api_size + 4);
return IA_FATAL_ERROR;
}
- /* Set API object with the memory allocated */
- mXheaacCodecHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ mMemoryVec.push(mXheaacCodecHandle);
/* Set the config params to default values */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -979,23 +953,16 @@
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_API_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
/* Allocate memory for API */
- mMemoryArray[mMallocCount] = memalign(4, pui_api_size);
+ mMpegDDrcHandle = memalign(4, pui_api_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ if (mMpegDDrcHandle == NULL) {
ALOGE("malloc for drc api structure Failed");
return IA_FATAL_ERROR;
}
- memset(mMemoryArray[mMallocCount], 0, pui_api_size);
+ mMemoryVec.push(mMpegDDrcHandle);
- /* Set API object with the memory allocated */
- mMpegDDrcHandle = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ memset(mMpegDDrcHandle, 0, pui_api_size);
/* Set the config params to default values */
err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT,
@@ -1021,23 +988,17 @@
&ui_proc_mem_tabs_size);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEMTABS_SIZE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
- mMemoryArray[mMallocCount] = memalign(4, ui_proc_mem_tabs_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ pv_alloc_ptr = memalign(4, ui_proc_mem_tabs_size);
+ if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_proc_mem_tabs_size + 4) = %d failed!",
ui_proc_mem_tabs_size + 4);
return IA_FATAL_ERROR;
}
- mMallocCount++;
- /* Set pointer for process memory tables */
- err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0,
- (pVOID)((WORD8*)mMemoryArray[mMallocCount - 1]));
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
+ mMemoryVec.push(pv_alloc_ptr);
+ /* Set pointer for process memory tables */
+ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEMTABS_PTR");
/* initialize the API, post config, fill memory tables */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT,
@@ -1066,17 +1027,12 @@
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(ui_alignment, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
+ pv_alloc_ptr = memalign(ui_alignment, ui_size);
+ if (pv_alloc_ptr == NULL) {
ALOGE("Malloc for size (ui_size + ui_alignment) = %d failed!", ui_size + ui_alignment);
return IA_FATAL_ERROR;
}
- pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
+ mMemoryVec.push(pv_alloc_ptr);
/* Set the buffer pointer */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
@@ -1095,7 +1051,7 @@
return IA_NO_ERROR;
}
-int SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
+IA_ERRORCODE SoftXAAC::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength) {
UWORD32 ui_init_done;
int32_t i_bytes_consumed;
@@ -1154,13 +1110,73 @@
return IA_NO_ERROR;
}
-int SoftXAAC::configMPEGDDrc() {
+IA_ERRORCODE SoftXAAC::initMPEGDDDrc() {
+ IA_ERRORCODE err_code = IA_NO_ERROR;
+ int i;
+
+ for (i = 0; i < (WORD32)2; i++) {
+ WORD32 ui_size, ui_alignment, ui_type;
+ pVOID pv_alloc_ptr;
+
+ /* Get memory size */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
+
+ /* Get memory alignment */
+ err_code =
+ ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
+
+ /* Get memory type */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
+
+ pv_alloc_ptr = memalign(4, ui_size);
+ if (pv_alloc_ptr == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(pv_alloc_ptr);
+
+ /* Set the buffer pointer */
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
+
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+ }
+
+ WORD32 ui_size;
+ ui_size = 8192 * 2;
+
+ mDrcInBuf = (int8_t*)memalign(4, ui_size);
+ if (mDrcInBuf == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(mDrcInBuf);
+
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+ mDrcOutBuf = (int8_t*)memalign(4, ui_size);
+ if (mDrcOutBuf == NULL) {
+ ALOGE(" Cannot create requested memory %d", ui_size);
+ return IA_FATAL_ERROR;
+ }
+ mDrcMemoryVec.push(mDrcOutBuf);
+
+ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf);
+ RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+
+ return IA_NO_ERROR;
+}
+IA_ERRORCODE SoftXAAC::configMPEGDDrc() {
IA_ERRORCODE err_code = IA_NO_ERROR;
int i_effect_type;
int i_loud_norm;
int i_target_loudness;
unsigned int i_sbr_mode;
- int n_mems;
int i;
#ifdef ENABLE_MPEG_D_DRC
@@ -1217,78 +1233,16 @@
RETURN_IF_FATAL(err_code, "IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS");
- for (i = 0; i < (WORD32)2; i++) {
- WORD32 ui_size, ui_alignment, ui_type;
- pVOID pv_alloc_ptr;
+ /* Free any memory that is allocated for MPEG D Drc so far */
+ deInitMPEGDDDrc();
- /* Get memory size */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_SIZE");
-
- /* Get memory alignment */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i,
- &ui_alignment);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_ALIGNMENT");
-
- /* Get memory type */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_GET_MEM_INFO_TYPE");
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
-
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
- pv_alloc_ptr = (pVOID)((WORD8*)mMemoryArray[mMallocCount]);
- mMallocCount++;
-
- /* Set the buffer pointer */
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr);
-
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
+ err_code = initMPEGDDDrc();
+ if (err_code != IA_NO_ERROR) {
+ ALOGE("initMPEGDDDrc failed with error %d", err_code);
+ deInitMPEGDDDrc();
+ return err_code;
}
- {
- WORD32 ui_size;
- ui_size = 8192 * 2;
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
-
- mDrcInBuf = (int8_t*)mMemoryArray[mMallocCount];
- mMallocCount++;
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2,
- /*mOutputBuffer*/ mDrcInBuf);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
-
- if (mMallocCount == MAX_MEM_ALLOCS) {
- ALOGE("mMemoryArray is full");
- return IA_FATAL_ERROR;
- }
- mMemoryArray[mMallocCount] = memalign(4, ui_size);
- if (mMemoryArray[mMallocCount] == NULL) {
- ALOGE(" Cannot create requested memory %d", ui_size);
- return IA_FATAL_ERROR;
- }
-
- mDrcOutBuf = (int8_t*)mMemoryArray[mMallocCount];
- mMallocCount++;
- err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3,
- /*mOutputBuffer*/ mDrcOutBuf);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_SET_MEM_PTR");
- }
/* DRC buffers
buf[0] - contains extension element pay load loudness related
buf[1] - contains extension element pay load*/
@@ -1423,10 +1377,10 @@
}
#endif
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
- int32_t* outBytes) {
+IA_ERRORCODE SoftXAAC::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+ int32_t* bytesConsumed, int32_t* outBytes) {
if (mInputBufferSize < inBufferLength) {
ALOGE("Cannot config AAC, input buffer size %d < inBufferLength %d", mInputBufferSize,
inBufferLength);
@@ -1516,24 +1470,33 @@
memcpy(mOutputBuffer, mDrcOutBuf, *outBytes);
}
#endif
- return err_code;
+ return IA_NO_ERROR;
}
-int SoftXAAC::deInitXAACDecoder() {
+IA_ERRORCODE SoftXAAC::deInitXAACDecoder() {
ALOGI("deInitXAACDecoder");
/* Tell that the input is over in this buffer */
IA_ERRORCODE err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INPUT_OVER, 0, NULL);
- RETURN_IF_FATAL(err_code, "IA_API_CMD_INPUT_OVER");
- for (int i = 0; i < mMallocCount; i++) {
- if (mMemoryArray[i]) free(mMemoryArray[i]);
+ /* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated memory */
+ for (void* buf : mMemoryVec) {
+ free(buf);
}
- mMallocCount = 0;
-
+ mMemoryVec.clear();
return err_code;
}
+IA_ERRORCODE SoftXAAC::deInitMPEGDDDrc() {
+ ALOGI("deInitMPEGDDDrc");
+
+ for (void* buf : mDrcMemoryVec) {
+ free(buf);
+ }
+ mDrcMemoryVec.clear();
+ return IA_NO_ERROR;
+}
+
IA_ERRORCODE SoftXAAC::getXAACStreamInfo() {
IA_ERRORCODE err_code = IA_NO_ERROR;
@@ -1546,11 +1509,19 @@
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS");
+ if (mNumChannels > MAX_CHANNEL_COUNT) {
+ ALOGE(" No of channels are more than max channels\n");
+ return IA_FATAL_ERROR;
+ }
/* PCM word size */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz);
RETURN_IF_FATAL(err_code, "IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ");
+ if ((mPcmWdSz / 8) != 2) {
+ ALOGE("Invalid Number of bytes per sample: %d, Expected is 2", mPcmWdSz);
+ return IA_FATAL_ERROR;
+ }
/* channel mask to tell the arrangement of channels in bit stream */
err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM,
diff --git a/media/libstagefright/codecs/xaacdec/SoftXAAC.h b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
index 6176082..a62a797 100644
--- a/media/libstagefright/codecs/xaacdec/SoftXAAC.h
+++ b/media/libstagefright/codecs/xaacdec/SoftXAAC.h
@@ -33,8 +33,6 @@
#include "impd_apicmd_standards.h"
#include "impd_drc_config_params.h"
-#define MAX_MEM_ALLOCS 100
-
extern "C" IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
pVOID pv_value);
extern "C" IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx,
@@ -80,18 +78,19 @@
enum { NONE, AWAITING_DISABLED, AWAITING_ENABLED } mOutputPortSettingsChange;
void initPorts();
- status_t initDecoder();
+ IA_ERRORCODE initDecoder();
bool isConfigured() const;
- int drainDecoder();
- int initXAACDecoder();
- int deInitXAACDecoder();
+ IA_ERRORCODE drainDecoder();
+ IA_ERRORCODE initXAACDecoder();
+ IA_ERRORCODE deInitXAACDecoder();
+ IA_ERRORCODE initMPEGDDDrc();
+ IA_ERRORCODE deInitMPEGDDDrc();
+ IA_ERRORCODE configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
+ IA_ERRORCODE configMPEGDDrc();
+ IA_ERRORCODE decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength,
+ int32_t* bytesConsumed, int32_t* outBytes);
- int configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength);
- int configMPEGDDrc();
- int decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed,
- int32_t* outBytes);
-
- int configflushDecode();
+ IA_ERRORCODE configflushDecode();
IA_ERRORCODE getXAACStreamInfo();
IA_ERRORCODE setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel,
int32_t drcHeavyCompression
@@ -120,9 +119,8 @@
int8_t* mDrcOutBuf;
int32_t mMpegDDRCPresent;
int32_t mDRCFlag;
-
- void* mMemoryArray[MAX_MEM_ALLOCS];
- int32_t mMallocCount;
+ Vector<void*> mMemoryVec;
+ Vector<void*> mDrcMemoryVec;
DISALLOW_EVIL_CONSTRUCTORS(SoftXAAC);
};
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index 86bd9d6..d136d9e 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -27,6 +27,7 @@
#include "libyuv/convert_from.h"
#include "libyuv/convert_argb.h"
+#include "libyuv/planar_functions.h"
#include "libyuv/video_common.h"
#include <functional>
#include <sys/time.h>
@@ -91,10 +92,17 @@
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
- case OMX_COLOR_FormatYUV420SemiPlanar:
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
return mDstFormat == OMX_COLOR_Format16bitRGB565;
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+ return mDstFormat == OMX_COLOR_Format16bitRGB565
+ || mDstFormat == OMX_COLOR_Format32BitRGBA8888;
+#else
+ return mDstFormat == OMX_COLOR_Format16bitRGB565;
+#endif
+
default:
return false;
}
@@ -236,7 +244,11 @@
break;
case OMX_COLOR_FormatYUV420SemiPlanar:
+#ifdef USE_LIBYUV
+ err = convertYUV420SemiPlanarUseLibYUV(src, dst);
+#else
err = convertYUV420SemiPlanar(src, dst);
+#endif
break;
case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
@@ -365,6 +377,36 @@
return OK;
}
+status_t ColorConverter::convertYUV420SemiPlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src.mBits + src.mStride * src.mHeight
+ + (src.mCropTop / 2) * src.mStride + src.mCropLeft;
+
+ switch (mDstFormat) {
+ case OMX_COLOR_Format16bitRGB565:
+ libyuv::NV12ToRGB565(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+ dst.mStride, src.cropWidth(), src.cropHeight());
+ break;
+
+ case OMX_COLOR_Format32BitRGBA8888:
+ libyuv::NV12ToARGB(src_y, src.mStride, src_u, src.mStride, (uint8 *)dst_ptr,
+ dst.mStride, src.cropWidth(), src.cropHeight());
+ break;
+
+ default:
+ return ERROR_UNSUPPORTED;
+ }
+
+ return OK;
+}
+
std::function<void (void *, void *, void *, size_t,
signed *, signed *, signed *, signed *)>
getReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) {
@@ -852,7 +894,7 @@
const uint8_t *src_u =
(const uint8_t *)src.mBits + src.mHeight * src.mStride +
- src.mCropTop * src.mStride / 2 + src.mCropLeft;
+ (src.mCropTop / 2) * src.mStride + src.mCropLeft;
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/libstagefright/flac/dec/Android.bp
index 751b053..307c9b0 100644
--- a/media/libstagefright/flac/dec/Android.bp
+++ b/media/libstagefright/flac/dec/Android.bp
@@ -27,11 +27,17 @@
},
static: {
- whole_static_libs: ["libFLAC"],
+ whole_static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared: {
- static_libs: ["libFLAC"],
+ static_libs: [
+ "libFLAC",
+ "libaudioutils",
+ ],
},
shared_libs: [
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/libstagefright/flac/dec/FLACDecoder.cpp
index dfdc41c..cef0bc6 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.cpp
+++ b/media/libstagefright/flac/dec/FLACDecoder.cpp
@@ -20,6 +20,7 @@
#include "FLACDecoder.h"
+#include <audio_utils/primitives.h> // float_from_i32
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaDefs.h>
@@ -117,104 +118,43 @@
mErrorStatus = status;
}
-// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
+// Copy samples from FLAC native 32-bit non-interleaved to 16-bit signed
+// or 32-bit float interleaved.
+// TODO: Consider moving to audio_utils. See similar code at FLACExtractor.cpp
// These are candidates for optimization if needed.
-static void copyMono8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyTo16Signed(
+ short *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- }
-}
-
-static void copyStereo8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] << 8;
- *dst++ = src[1][i] << 8;
- }
-}
-
-static void copyMultiCh8(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] << 8;
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const int leftShift = 16 - (int)bitsPerSample; // cast to int to prevent unsigned overflow.
+ if (leftShift >= 0) {
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] << leftShift;
+ }
+ }
+ } else {
+ const int rightShift = -leftShift;
+ for (unsigned i = 0; i < nSamples; ++i) {
+ for (unsigned c = 0; c < nChannels; ++c) {
+ *dst++ = src[c][i] >> rightShift;
+ }
}
}
}
-static void copyMono16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
+static void copyToFloat(
+ float *dst,
+ const int *const *src,
unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- }
-}
-
-static void copyStereo16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i];
- *dst++ = src[1][i];
- }
-}
-
-static void copyMultiCh16(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
+ unsigned nChannels,
+ unsigned bitsPerSample) {
+ const unsigned leftShift = 32 - bitsPerSample;
for (unsigned i = 0; i < nSamples; ++i) {
for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i];
- }
- }
-}
-
-// TODO: 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
-static void copyMono24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- }
-}
-
-static void copyStereo24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned /* nChannels */) {
- for (unsigned i = 0; i < nSamples; ++i) {
- *dst++ = src[0][i] >> 8;
- *dst++ = src[1][i] >> 8;
- }
-}
-
-static void copyMultiCh24(
- int16_t *dst,
- const int * src[FLACDecoder::kMaxChannels],
- unsigned nSamples,
- unsigned nChannels) {
- for (unsigned i = 0; i < nSamples; ++i) {
- for (unsigned c = 0; c < nChannels; ++c) {
- *dst++ = src[c][i] >> 8;
+ *dst++ = float_from_i32(src[c][i] << leftShift);
}
}
}
@@ -238,8 +178,7 @@
mStreamInfoValid(false),
mWriteRequested(false),
mWriteCompleted(false),
- mErrorStatus((FLAC__StreamDecoderErrorStatus) -1),
- mCopy(nullptr) {
+ mErrorStatus((FLAC__StreamDecoderErrorStatus) -1) {
ALOGV("ctor:");
memset(&mStreamInfo, 0, sizeof(mStreamInfo));
memset(&mWriteHeader, 0, sizeof(mWriteHeader));
@@ -379,6 +318,7 @@
case 8:
case 16:
case 24:
+ case 32: // generally rare, but is supported in the framework
break;
default:
@@ -387,31 +327,6 @@
return ERROR_MALFORMED;
}
- // configure the appropriate copy function, defaulting to trespass
- static const struct {
- unsigned mChannels;
- unsigned mBitsPerSample;
- void (*mCopy)(int16_t *dst, const int * src[kMaxChannels],
- unsigned nSamples, unsigned nChannels);
- } table[] = {
- { 1, 8, copyMono8 },
- { 2, 8, copyStereo8 },
- { 8, 8, copyMultiCh8 },
- { 1, 16, copyMono16 },
- { 2, 16, copyStereo16 },
- { 8, 16, copyMultiCh16 },
- { 1, 24, copyMono24 },
- { 2, 24, copyStereo24 },
- { 8, 24, copyMultiCh24 },
- };
- for (const auto &entry : table) {
- if (entry.mChannels >= getChannels() &&
- entry.mBitsPerSample == getBitsPerSample()) {
- mCopy = entry.mCopy;
- break;
- }
- }
-
// Now we have all metadata blocks.
mBufferPos = 0;
mBufferDataSize = 0;
@@ -420,7 +335,7 @@
}
status_t FLACDecoder::decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen) {
+ void *outBuffer, size_t *outBufferLen, bool outputFloat) {
ALOGV("decodeOneFrame: input size(%zu)", inBufferLen);
if (!mStreamInfoValid) {
@@ -469,21 +384,33 @@
return ERROR_MALFORMED;
}
- size_t bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ const unsigned channels = getChannels();
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+ const size_t frameSize = channels * sampleSize;
+ size_t bufferSize = blocksize * frameSize;
if (bufferSize > *outBufferLen) {
ALOGW("decodeOneFrame: output buffer holds only partial frame %zu:%zu",
*outBufferLen, bufferSize);
- blocksize = *outBufferLen / (getChannels() * sizeof(int16_t));
- bufferSize = blocksize * getChannels() * sizeof(int16_t);
+ blocksize = *outBufferLen / frameSize;
+ bufferSize = blocksize * frameSize;
}
- if (mCopy == nullptr) {
- ALOGE("decodeOneFrame: format is not supported: channels(%d), BitsPerSample(%d)",
- getChannels(), getBitsPerSample());
- return ERROR_UNSUPPORTED;
- }
// copy PCM from FLAC write buffer to output buffer, with interleaving
- (*mCopy)(outBuffer, mWriteBuffer, blocksize, getChannels());
+
+ const unsigned bitsPerSample = getBitsPerSample();
+ if (outputFloat) {
+ copyToFloat(reinterpret_cast<float*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ } else {
+ copyTo16Signed(reinterpret_cast<short*>(outBuffer),
+ mWriteBuffer,
+ blocksize,
+ channels,
+ bitsPerSample);
+ }
*outBufferLen = bufferSize;
return OK;
}
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/libstagefright/flac/dec/FLACDecoder.h
index af419a2..694fccb 100644
--- a/media/libstagefright/flac/dec/FLACDecoder.h
+++ b/media/libstagefright/flac/dec/FLACDecoder.h
@@ -41,7 +41,7 @@
status_t parseMetadata(const uint8_t *inBuffer, size_t inBufferLen);
status_t decodeOneFrame(const uint8_t *inBuffer, size_t inBufferLen,
- int16_t *outBuffer, size_t *outBufferLen);
+ void *outBuffer, size_t *outBufferLen, bool outputFloat = false);
void flush();
virtual ~FLACDecoder();
@@ -89,8 +89,6 @@
// most recent error reported by libFLAC decoder
FLAC__StreamDecoderErrorStatus mErrorStatus;
- void (*mCopy)(int16_t *dst, const int *src[kMaxChannels], unsigned nSamples, unsigned nChannels);
-
status_t init();
// FLAC stream decoder callbacks as C++ instance methods
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
index 768cbd6..a276722 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -66,7 +66,7 @@
// static
int64_t ALooper::GetNowUs() {
- return systemTime(SYSTEM_TIME_MONOTONIC) / 1000ll;
+ return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
}
ALooper::ALooper()
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index dcf1ab8..dd1d904 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -4,8 +4,8 @@
vendor_available: true,
}
-cc_library {
- name: "libstagefright_foundation",
+cc_defaults {
+ name: "libstagefright_foundation_defaults",
vendor_available: true,
vndk: {
enabled: true,
@@ -25,6 +25,7 @@
header_libs: [
"libhardware_headers",
"libstagefright_foundation_headers",
+ "media_ndk_headers",
"media_plugin_headers",
],
@@ -64,8 +65,13 @@
"AudioPresentationInfo.cpp",
"ByteUtils.cpp",
"ColorUtils.cpp",
+ "MediaBuffer.cpp",
+ "MediaBufferBase.cpp",
+ "MediaBufferGroup.cpp",
"MediaDefs.cpp",
"MediaKeys.cpp",
+ "MetaData.cpp",
+ "MetaDataBase.cpp",
"avc_utils.cpp",
"base64.cpp",
"hexdump.cpp",
@@ -81,3 +87,20 @@
cfi: true,
},
}
+
+cc_library {
+ name: "libstagefright_foundation",
+ defaults: ["libstagefright_foundation_defaults"],
+}
+
+cc_library_static {
+ name: "libstagefright_foundation_without_imemory",
+ defaults: ["libstagefright_foundation_defaults"],
+
+ cflags: [
+ "-Wno-multichar",
+ "-Werror",
+ "-Wall",
+ "-DNO_IMEMORY",
+ ],
+}
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libstagefright/foundation/MediaBuffer.cpp
similarity index 93%
rename from media/libmediaextractor/MediaBuffer.cpp
rename to media/libstagefright/foundation/MediaBuffer.cpp
index bab3a03..9beac05 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libstagefright/foundation/MediaBuffer.cpp
@@ -59,9 +59,11 @@
#ifndef NO_IMEMORY
} else {
ALOGV("creating memoryDealer");
- sp<MemoryDealer> memoryDealer =
- new MemoryDealer(size + sizeof(SharedControl), "MediaBuffer");
- mMemory = memoryDealer->allocate(size + sizeof(SharedControl));
+ size_t newSize = 0;
+ if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) {
+ sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer");
+ mMemory = memoryDealer->allocate(newSize);
+ }
if (mMemory == NULL) {
ALOGW("Failed to allocate shared memory, trying regular allocation!");
mData = malloc(size);
diff --git a/media/libmediaextractor/MediaBufferBase.cpp b/media/libstagefright/foundation/MediaBufferBase.cpp
similarity index 100%
rename from media/libmediaextractor/MediaBufferBase.cpp
rename to media/libstagefright/foundation/MediaBufferBase.cpp
diff --git a/media/libmediaextractor/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
similarity index 100%
rename from media/libmediaextractor/MediaBufferGroup.cpp
rename to media/libstagefright/foundation/MediaBufferGroup.cpp
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index aba44bb..9d1ec1f 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -23,6 +23,7 @@
const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+const char *MEDIA_MIMETYPE_VIDEO_AV1 = "video/av01";
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
const char *MEDIA_MIMETYPE_VIDEO_HEVC = "video/hevc";
const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
diff --git a/media/libmediaextractor/MetaData.cpp b/media/libstagefright/foundation/MetaData.cpp
similarity index 100%
rename from media/libmediaextractor/MetaData.cpp
rename to media/libstagefright/foundation/MetaData.cpp
diff --git a/media/libmediaextractor/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
similarity index 100%
rename from media/libmediaextractor/MetaDataBase.cpp
rename to media/libstagefright/foundation/MetaDataBase.cpp
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 8edddcc..e68852d 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -25,6 +25,7 @@
extern const char *MEDIA_MIMETYPE_VIDEO_VP8;
extern const char *MEDIA_MIMETYPE_VIDEO_VP9;
+extern const char *MEDIA_MIMETYPE_VIDEO_AV1;
extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
extern const char *MEDIA_MIMETYPE_VIDEO_HEVC;
extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index c4a072b..c0ee14e 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -32,7 +32,6 @@
"libcrypto",
"libcutils",
"libmedia",
- "libmediaextractor",
"libmediandk",
"libstagefright",
"libstagefright_foundation",
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 86872c5..2ecfa43 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -44,10 +44,10 @@
// static
// Bandwidth Switch Mark Defaults
-const int64_t LiveSession::kUpSwitchMarkUs = 15000000ll;
-const int64_t LiveSession::kDownSwitchMarkUs = 20000000ll;
-const int64_t LiveSession::kUpSwitchMarginUs = 5000000ll;
-const int64_t LiveSession::kResumeThresholdUs = 100000ll;
+const int64_t LiveSession::kUpSwitchMarkUs = 15000000LL;
+const int64_t LiveSession::kDownSwitchMarkUs = 20000000LL;
+const int64_t LiveSession::kUpSwitchMarginUs = 5000000LL;
+const int64_t LiveSession::kResumeThresholdUs = 100000LL;
//TODO: redefine this mark to a fair value
// default buffer underflow mark
@@ -66,9 +66,9 @@
// Bandwidth estimation parameters
static const int32_t kShortTermBandwidthItems = 3;
static const int32_t kMinBandwidthHistoryItems = 20;
- static const int64_t kMinBandwidthHistoryWindowUs = 5000000ll; // 5 sec
- static const int64_t kMaxBandwidthHistoryWindowUs = 30000000ll; // 30 sec
- static const int64_t kMaxBandwidthHistoryAgeUs = 60000000ll; // 60 sec
+ static const int64_t kMinBandwidthHistoryWindowUs = 5000000LL; // 5 sec
+ static const int64_t kMaxBandwidthHistoryWindowUs = 30000000LL; // 30 sec
+ static const int64_t kMaxBandwidthHistoryAgeUs = 60000000LL; // 60 sec
struct BandwidthEntry {
int64_t mTimestampUs;
@@ -284,7 +284,7 @@
mPrevBufferPercentage(-1),
mCurBandwidthIndex(-1),
mOrigBandwidthIndex(-1),
- mLastBandwidthBps(-1ll),
+ mLastBandwidthBps(-1LL),
mLastBandwidthStable(false),
mBandwidthEstimator(new BandwidthEstimator()),
mMaxWidth(720),
@@ -294,8 +294,8 @@
mSwapMask(0),
mSwitchGeneration(0),
mSubtitleGeneration(0),
- mLastDequeuedTimeUs(0ll),
- mRealTimeBaseUs(0ll),
+ mLastDequeuedTimeUs(0LL),
+ mRealTimeBaseUs(0LL),
mReconfigurationInProgress(false),
mSwitchInProgress(false),
mUpSwitchMark(kUpSwitchMarkUs),
@@ -844,7 +844,7 @@
// (If we don't have that cushion we'd rather cancel and try again.)
int64_t delayUs =
switchUp ?
- (kUnderflowMarkMs * 1000ll + 1000000ll)
+ (kUnderflowMarkMs * 1000LL + 1000000LL)
: 0;
bool needResumeUntil = false;
sp<AMessage> stopParams = msg;
@@ -954,7 +954,7 @@
// static
bool LiveSession::isBandwidthValid(const BandwidthItem &item) {
- static const int64_t kBlacklistWindowUs = 300 * 1000000ll;
+ static const int64_t kBlacklistWindowUs = 300 * 1000000LL;
return item.mLastFailureUs < 0
|| ALooper::GetNowUs() - item.mLastFailureUs > kBlacklistWindowUs;
}
@@ -1060,7 +1060,7 @@
BandwidthItem item;
item.mPlaylistIndex = i;
- item.mLastFailureUs = -1ll;
+ item.mLastFailureUs = -1LL;
sp<AMessage> meta;
AString uri;
@@ -1114,7 +1114,7 @@
mPlaylist->pickRandomMediaItems();
changeConfiguration(
- 0ll /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
+ 0LL /* timeUs */, initialBandwidthIndex, false /* pickTrack */);
}
void LiveSession::finishDisconnect() {
@@ -1175,7 +1175,7 @@
FetcherInfo info;
info.mFetcher = new PlaylistFetcher(
notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
- info.mDurationUs = -1ll;
+ info.mDurationUs = -1LL;
info.mToBeRemoved = false;
info.mToBeResumed = false;
mFetcherLooper->registerHandler(info.mFetcher);
@@ -1466,7 +1466,7 @@
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
- int64_t maxDurationUs = -1ll;
+ int64_t maxDurationUs = -1LL;
for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
int64_t fetcherDurationUs = mFetcherInfos.valueAt(i).mDurationUs;
@@ -1592,7 +1592,7 @@
// Delay fetcher removal if not picking tracks, AND old fetcher
// has stream mask that overlaps new variant. (Okay to discard
// old fetcher now, if completely no overlap.)
- if (discardFetcher && timeUs < 0ll && !pickTrack
+ if (discardFetcher && timeUs < 0LL && !pickTrack
&& (fetcher->getStreamTypeMask() & streamMask)) {
discardFetcher = false;
delayRemoval = true;
@@ -1604,7 +1604,7 @@
} else {
float threshold = 0.0f; // default to pause after current block (47Kbytes)
bool disconnect = false;
- if (timeUs >= 0ll) {
+ if (timeUs >= 0LL) {
// seeking, no need to finish fetching
disconnect = true;
} else if (delayRemoval) {
@@ -1620,7 +1620,7 @@
}
sp<AMessage> msg;
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
// skip onChangeConfiguration2 (decoder destruction) if not seeking.
msg = new AMessage(kWhatChangeConfiguration3, this);
} else {
@@ -1654,9 +1654,9 @@
if (!mReconfigurationInProgress) {
int32_t pickTrack = 0;
msg->findInt32("pickTrack", &pickTrack);
- changeConfiguration(-1ll /* timeUs */, -1, pickTrack);
+ changeConfiguration(-1LL /* timeUs */, -1, pickTrack);
} else {
- msg->post(1000000ll); // retry in 1 sec
+ msg->post(1000000LL); // retry in 1 sec
}
}
@@ -1788,7 +1788,7 @@
CHECK(msg->findInt64("timeUs", &timeUs));
CHECK(msg->findInt32("pickTrack", &pickTrack));
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
if (!pickTrack) {
// mSwapMask contains streams that are in both old and new variant,
// (in mNewStreamMask & mStreamMask) but with different URIs
@@ -2062,7 +2062,7 @@
void LiveSession::schedulePollBuffering() {
sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
msg->setInt32("generation", mPollBufferingGeneration);
- msg->post(1000000ll);
+ msg->post(1000000LL);
}
void LiveSession::cancelPollBuffering() {
@@ -2208,13 +2208,13 @@
int64_t readyMarkUs =
(mInPreparationPhase ?
mBufferingSettings.mInitialMarkMs :
- mBufferingSettings.mResumePlaybackMarkMs) * 1000ll;
+ mBufferingSettings.mResumePlaybackMarkMs) * 1000LL;
if (bufferedDurationUs > readyMarkUs
|| mPacketSources[i]->isFinished(0)) {
++readyCount;
}
if (!mPacketSources[i]->isFinished(0)) {
- if (bufferedDurationUs < kUnderflowMarkMs * 1000ll) {
+ if (bufferedDurationUs < kUnderflowMarkMs * 1000LL) {
++underflowCount;
}
if (bufferedDurationUs > mUpSwitchMark) {
@@ -2300,7 +2300,7 @@
ssize_t lowestValid = getLowestValidBandwidthIndex();
if (mCurBandwidthIndex > lowestValid) {
cancelBandwidthSwitch();
- changeConfiguration(-1ll, lowestValid);
+ changeConfiguration(-1LL, lowestValid);
return true;
}
}
@@ -2370,7 +2370,7 @@
// if not yet prepared, just restart again with new bw index.
// this is faster and playback experience is cleaner.
changeConfiguration(
- mInPreparationPhase ? 0 : -1ll, bandwidthIndex);
+ mInPreparationPhase ? 0 : -1LL, bandwidthIndex);
return true;
}
}
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index d06d9f2..16179d3 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -258,7 +258,7 @@
mIsEvent(false),
mFirstSeqNumber(-1),
mLastSeqNumber(-1),
- mTargetDurationUs(-1ll),
+ mTargetDurationUs(-1LL),
mDiscontinuitySeq(0),
mDiscontinuityCount(0),
mSelectedIndex(-1) {
@@ -716,7 +716,7 @@
ALOGE("Media playlist missing #EXT-X-TARGETDURATION");
return ERROR_MALFORMED;
}
- mTargetDurationUs = targetDurationSecs * 1000000ll;
+ mTargetDurationUs = targetDurationSecs * 1000000LL;
mFirstSeqNumber = 0;
if (mMeta != NULL) {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 823f90e..562c625 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -50,8 +50,8 @@
namespace android {
// static
-const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000ll;
-const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000ll;
+const int64_t PlaylistFetcher::kMinBufferedDurationUs = 30000000LL;
+const int64_t PlaylistFetcher::kMaxMonitorDelayUs = 3000000LL;
// LCM of 188 (size of a TS packet) & 1k works well
const int32_t PlaylistFetcher::kDownloadBlockSize = 47 * 1024;
@@ -152,25 +152,25 @@
mURI(uri),
mFetcherID(id),
mStreamTypeMask(0),
- mStartTimeUs(-1ll),
- mSegmentStartTimeUs(-1ll),
- mDiscontinuitySeq(-1ll),
+ mStartTimeUs(-1LL),
+ mSegmentStartTimeUs(-1LL),
+ mDiscontinuitySeq(-1LL),
mStartTimeUsRelative(false),
- mLastPlaylistFetchTimeUs(-1ll),
- mPlaylistTimeUs(-1ll),
+ mLastPlaylistFetchTimeUs(-1LL),
+ mPlaylistTimeUs(-1LL),
mSeqNumber(-1),
mNumRetries(0),
mStartup(true),
mIDRFound(false),
mSeekMode(LiveSession::kSeekModeExactPosition),
mTimeChangeSignaled(false),
- mNextPTSTimeUs(-1ll),
+ mNextPTSTimeUs(-1LL),
mMonitorQueueGeneration(0),
mSubtitleGeneration(subtitleGeneration),
- mLastDiscontinuitySeq(-1ll),
+ mLastDiscontinuitySeq(-1LL),
mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY),
mFirstPTSValid(false),
- mFirstTimeUs(-1ll),
+ mFirstTimeUs(-1LL),
mVideoBuffer(new AnotherPacketSource(NULL)),
mSampleAesKeyItemChanged(false),
mThresholdRatio(-1.0f),
@@ -200,7 +200,7 @@
CHECK_GE(seqNumber, firstSeqNumberInPlaylist);
CHECK_LE(seqNumber, lastSeqNumberInPlaylist);
- int64_t segmentStartUs = 0ll;
+ int64_t segmentStartUs = 0LL;
for (int32_t index = 0;
index < seqNumber - firstSeqNumberInPlaylist; ++index) {
sp<AMessage> itemMeta;
@@ -240,13 +240,13 @@
int64_t PlaylistFetcher::delayUsToRefreshPlaylist() const {
int64_t nowUs = ALooper::GetNowUs();
- if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0ll) {
+ if (mPlaylist == NULL || mLastPlaylistFetchTimeUs < 0LL) {
CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
- return 0ll;
+ return 0LL;
}
if (mPlaylist->isComplete()) {
- return (~0llu >> 1);
+ return (~0LLU >> 1);
}
int64_t targetDurationUs = mPlaylist->getTargetDuration();
@@ -295,7 +295,7 @@
}
int64_t delayUs = mLastPlaylistFetchTimeUs + minPlaylistAgeUs - nowUs;
- return delayUs > 0ll ? delayUs : 0ll;
+ return delayUs > 0LL ? delayUs : 0LL;
}
status_t PlaylistFetcher::decryptBuffer(
@@ -857,7 +857,7 @@
targetDurationUs = mPlaylist->getTargetDuration();
}
- int64_t bufferedDurationUs = 0ll;
+ int64_t bufferedDurationUs = 0LL;
status_t finalResult = OK;
if (mStreamTypeMask == LiveSession::STREAMTYPE_SUBTITLES) {
sp<AnotherPacketSource> packetSource =
@@ -870,7 +870,7 @@
// enqueued to prevent us from waiting on a non-existent stream;
// when we cannot make out from the manifest what streams are included in
// a playlist we might assume extra streams.
- bufferedDurationUs = -1ll;
+ bufferedDurationUs = -1LL;
for (size_t i = 0; i < mPacketSources.size(); ++i) {
if ((mStreamTypeMask & mPacketSources.keyAt(i)) == 0
|| mPacketSources[i]->getLatestEnqueuedMeta() == NULL) {
@@ -882,13 +882,13 @@
FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
- if (bufferedDurationUs == -1ll
+ if (bufferedDurationUs == -1LL
|| bufferedStreamDurationUs < bufferedDurationUs) {
bufferedDurationUs = bufferedStreamDurationUs;
}
}
- if (bufferedDurationUs == -1ll) {
- bufferedDurationUs = 0ll;
+ if (bufferedDurationUs == -1LL) {
+ bufferedDurationUs = 0LL;
}
}
@@ -901,12 +901,12 @@
// onDownloadNext();
sp<AMessage> msg = new AMessage(kWhatDownloadNext, this);
msg->setInt32("generation", mMonitorQueueGeneration);
- msg->post(1000l);
+ msg->post(1000L);
} else {
// We'd like to maintain buffering above durationToBufferUs, so try
// again when buffer just about to go below durationToBufferUs
// (or after targetDurationUs / 2, whichever is smaller).
- int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000ll;
+ int64_t delayUs = bufferedDurationUs - kMinBufferedDurationUs + 1000000LL;
if (delayUs > targetDurationUs / 2) {
delayUs = targetDurationUs / 2;
}
@@ -1073,10 +1073,10 @@
}
}
- mSegmentFirstPTS = -1ll;
+ mSegmentFirstPTS = -1LL;
if (mPlaylist != NULL && mSeqNumber < 0) {
- CHECK_GE(mStartTimeUs, 0ll);
+ CHECK_GE(mStartTimeUs, 0LL);
if (mSegmentStartTimeUs < 0) {
if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
@@ -1379,7 +1379,7 @@
& (LiveSession::STREAMTYPE_AUDIO
| LiveSession::STREAMTYPE_VIDEO))) {
mSession->addBandwidthMeasurement(bytesRead, delayUs);
- if (delayUs > 2000000ll) {
+ if (delayUs > 2000000LL) {
FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
bytesRead, (double)delayUs / 1.0e6);
}
@@ -1553,7 +1553,7 @@
// if the previous fetcher paused in the middle of a segment, we
// want to start at a segment that overlaps the last sample
minDiffUs = -mPlaylist->getTargetDuration();
- maxDiffUs = 0ll;
+ maxDiffUs = 0LL;
} else {
// if the previous fetcher paused at the end of a segment, ideally
// we want to start at the segment that's roughly aligned with its
@@ -1704,7 +1704,7 @@
mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
}
- if (mNextPTSTimeUs >= 0ll) {
+ if (mNextPTSTimeUs >= 0LL) {
sp<AMessage> extra = new AMessage;
// Since we are using absolute timestamps, signal an offset of 0 to prevent
// ATSParser from skewing the timestamps of access units.
@@ -1719,7 +1719,7 @@
mTSParser->signalDiscontinuity(
ATSParser::DISCONTINUITY_TIME, extra);
- mNextPTSTimeUs = -1ll;
+ mNextPTSTimeUs = -1LL;
}
if (mSampleAesKeyItemChanged) {
@@ -1740,7 +1740,7 @@
// setRange to indicate consumed bytes.
buffer->setRange(buffer->offset() + offset, buffer->size() - offset);
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
// get the smallest first PTS from all streams present in this parser
for (size_t i = mPacketSources.size(); i > 0;) {
i--;
@@ -1764,12 +1764,12 @@
if (meta != NULL) {
int64_t timeUs;
CHECK(meta->findInt64("timeUs", &timeUs));
- if (mSegmentFirstPTS < 0ll || timeUs < mSegmentFirstPTS) {
+ if (mSegmentFirstPTS < 0LL || timeUs < mSegmentFirstPTS) {
mSegmentFirstPTS = timeUs;
}
}
}
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
// didn't find any TS packet, can return early
return OK;
}
@@ -1988,8 +1988,8 @@
return OK;
}
- if (mNextPTSTimeUs >= 0ll) {
- mNextPTSTimeUs = -1ll;
+ if (mNextPTSTimeUs >= 0LL) {
+ mNextPTSTimeUs = -1LL;
}
// This better be an ISO 13818-7 (AAC) or ISO 13818-1 (MPEG) audio
@@ -2088,17 +2088,17 @@
packetSource->setFormat(meta);
}
- int64_t numSamples = 0ll;
+ int64_t numSamples = 0LL;
int32_t sampleRate;
CHECK(packetSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
- int64_t timeUs = (PTS * 100ll) / 9ll;
+ int64_t timeUs = (PTS * 100LL) / 9LL;
if (mStartup && !mFirstPTSValid) {
mFirstPTSValid = true;
mFirstTimeUs = timeUs;
}
- if (mSegmentFirstPTS < 0ll) {
+ if (mSegmentFirstPTS < 0LL) {
mSegmentFirstPTS = timeUs;
if (!mStartTimeUsRelative) {
// Duplicated logic from how we handle .ts playlists.
@@ -2148,7 +2148,7 @@
CHECK_LE(offset + aac_frame_length, buffer->size());
- int64_t unitTimeUs = timeUs + numSamples * 1000000ll / sampleRate;
+ int64_t unitTimeUs = timeUs + numSamples * 1000000LL / sampleRate;
offset += aac_frame_length;
// Each AAC frame encodes 1024 samples.
@@ -2209,7 +2209,7 @@
}
void PlaylistFetcher::updateDuration() {
- int64_t durationUs = 0ll;
+ int64_t durationUs = 0LL;
for (size_t index = 0; index < mPlaylist->size(); ++index) {
sp<AMessage> itemMeta;
CHECK(mPlaylist->itemAt(
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index b489183..792a68a 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -43,7 +43,7 @@
}
virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
- off64_t available = (offset >= (off64_t)mSize) ? 0ll : mSize - offset;
+ off64_t available = (offset >= (off64_t)mSize) ? 0LL : mSize - offset;
size_t copy = (available > (off64_t)size) ? size : available;
memcpy(data, mData + offset, copy);
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 9b2853e..9d46d2d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -488,7 +488,8 @@
status_t setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels);
status_t setupFlacCodec(
- bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel);
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t compressionLevel,
+ AudioEncoding encoding);
status_t setupRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels,
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 6d4c1bf..75b0d8e 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -90,6 +90,9 @@
status_t convertYUV420PlanarUseLibYUV(
const BitmapParams &src, const BitmapParams &dst);
+ status_t convertYUV420SemiPlanarUseLibYUV(
+ const BitmapParams &src, const BitmapParams &dst);
+
status_t convertYUV420Planar16(
const BitmapParams &src, const BitmapParams &dst);
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
similarity index 100%
rename from media/libmediaextractor/include/media/DataSource.h
rename to media/libstagefright/include/media/stagefright/DataSource.h
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libstagefright/include/media/stagefright/DataSourceBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/DataSourceBase.h
rename to media/libstagefright/include/media/stagefright/DataSourceBase.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
deleted file mode 120000
index 1d49c1a..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBuffer.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBuffer.h
rename to media/libstagefright/include/media/stagefright/MediaBuffer.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferBase.h b/media/libstagefright/include/media/stagefright/MediaBufferBase.h
deleted file mode 120000
index 80e49b0..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBufferBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBufferBase.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libstagefright/include/media/stagefright/MediaBufferBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
rename to media/libstagefright/include/media/stagefright/MediaBufferBase.h
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
deleted file mode 120000
index 009b3d9..0000000
--- a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MediaBufferGroup.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
rename to media/libstagefright/include/media/stagefright/MediaBufferGroup.h
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 704bfdd..c06c288 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -31,6 +31,21 @@
constexpr int32_t AVCProfileConstrainedBaseline = 0x10000;
constexpr int32_t AVCProfileConstrainedHigh = 0x80000;
+inline static const char *asString_AVCProfile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case AVCProfileBaseline: return "Baseline";
+ case AVCProfileMain: return "Main";
+ case AVCProfileExtended: return "Extended";
+ case AVCProfileHigh: return "High";
+ case AVCProfileHigh10: return "High10";
+ case AVCProfileHigh422: return "High422";
+ case AVCProfileHigh444: return "High444";
+ case AVCProfileConstrainedBaseline: return "ConstrainedBaseline";
+ case AVCProfileConstrainedHigh: return "ConstrainedHigh";
+ default: return def;
+ }
+}
+
constexpr int32_t AVCLevel1 = 0x01;
constexpr int32_t AVCLevel1b = 0x02;
constexpr int32_t AVCLevel11 = 0x04;
@@ -48,6 +63,35 @@
constexpr int32_t AVCLevel5 = 0x4000;
constexpr int32_t AVCLevel51 = 0x8000;
constexpr int32_t AVCLevel52 = 0x10000;
+constexpr int32_t AVCLevel6 = 0x20000;
+constexpr int32_t AVCLevel61 = 0x40000;
+constexpr int32_t AVCLevel62 = 0x80000;
+
+inline static const char *asString_AVCLevel(int32_t i, const char *def = "??") {
+ switch (i) {
+ case AVCLevel1: return "1";
+ case AVCLevel1b: return "1b";
+ case AVCLevel11: return "1.1";
+ case AVCLevel12: return "1.2";
+ case AVCLevel13: return "1.3";
+ case AVCLevel2: return "2";
+ case AVCLevel21: return "2.1";
+ case AVCLevel22: return "2.2";
+ case AVCLevel3: return "3";
+ case AVCLevel31: return "3.1";
+ case AVCLevel32: return "3.2";
+ case AVCLevel4: return "4";
+ case AVCLevel41: return "4.1";
+ case AVCLevel42: return "4.2";
+ case AVCLevel5: return "5";
+ case AVCLevel51: return "5.1";
+ case AVCLevel52: return "5.2";
+ case AVCLevel6: return "6";
+ case AVCLevel61: return "6.1";
+ case AVCLevel62: return "6.2";
+ default: return def;
+ }
+}
constexpr int32_t H263ProfileBaseline = 0x01;
constexpr int32_t H263ProfileH320Coding = 0x02;
@@ -59,6 +103,21 @@
constexpr int32_t H263ProfileInterlace = 0x80;
constexpr int32_t H263ProfileHighLatency = 0x100;
+inline static const char *asString_H263Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case H263ProfileBaseline: return "Baseline";
+ case H263ProfileH320Coding: return "H320Coding";
+ case H263ProfileBackwardCompatible: return "BackwardCompatible";
+ case H263ProfileISWV2: return "ISWV2";
+ case H263ProfileISWV3: return "ISWV3";
+ case H263ProfileHighCompression: return "HighCompression";
+ case H263ProfileInternet: return "Internet";
+ case H263ProfileInterlace: return "Interlace";
+ case H263ProfileHighLatency: return "HighLatency";
+ default: return def;
+ }
+}
+
constexpr int32_t H263Level10 = 0x01;
constexpr int32_t H263Level20 = 0x02;
constexpr int32_t H263Level30 = 0x04;
@@ -68,6 +127,20 @@
constexpr int32_t H263Level60 = 0x40;
constexpr int32_t H263Level70 = 0x80;
+inline static const char *asString_H263Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case H263Level10: return "10";
+ case H263Level20: return "20";
+ case H263Level30: return "30";
+ case H263Level40: return "40";
+ case H263Level45: return "45";
+ case H263Level50: return "50";
+ case H263Level60: return "60";
+ case H263Level70: return "70";
+ default: return def;
+ }
+}
+
constexpr int32_t MPEG4ProfileSimple = 0x01;
constexpr int32_t MPEG4ProfileSimpleScalable = 0x02;
constexpr int32_t MPEG4ProfileCore = 0x04;
@@ -85,6 +158,28 @@
constexpr int32_t MPEG4ProfileAdvancedScalable = 0x4000;
constexpr int32_t MPEG4ProfileAdvancedSimple = 0x8000;
+inline static const char *asString_MPEG4Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case MPEG4ProfileSimple: return "Simple";
+ case MPEG4ProfileSimpleScalable: return "SimpleScalable";
+ case MPEG4ProfileCore: return "Core";
+ case MPEG4ProfileMain: return "Main";
+ case MPEG4ProfileNbit: return "Nbit";
+ case MPEG4ProfileScalableTexture: return "ScalableTexture";
+ case MPEG4ProfileSimpleFace: return "SimpleFace";
+ case MPEG4ProfileSimpleFBA: return "SimpleFBA";
+ case MPEG4ProfileBasicAnimated: return "BasicAnimated";
+ case MPEG4ProfileHybrid: return "Hybrid";
+ case MPEG4ProfileAdvancedRealTime: return "AdvancedRealTime";
+ case MPEG4ProfileCoreScalable: return "CoreScalable";
+ case MPEG4ProfileAdvancedCoding: return "AdvancedCoding";
+ case MPEG4ProfileAdvancedCore: return "AdvancedCore";
+ case MPEG4ProfileAdvancedScalable: return "AdvancedScalable";
+ case MPEG4ProfileAdvancedSimple: return "AdvancedSimple";
+ default: return def;
+ }
+}
+
constexpr int32_t MPEG4Level0 = 0x01;
constexpr int32_t MPEG4Level0b = 0x02;
constexpr int32_t MPEG4Level1 = 0x04;
@@ -96,6 +191,22 @@
constexpr int32_t MPEG4Level5 = 0x80;
constexpr int32_t MPEG4Level6 = 0x100;
+inline static const char *asString_MPEG4Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case MPEG4Level0: return "0";
+ case MPEG4Level0b: return "0b";
+ case MPEG4Level1: return "1";
+ case MPEG4Level2: return "2";
+ case MPEG4Level3: return "3";
+ case MPEG4Level3b: return "3b";
+ case MPEG4Level4: return "4";
+ case MPEG4Level4a: return "4a";
+ case MPEG4Level5: return "5";
+ case MPEG4Level6: return "6";
+ default: return def;
+ }
+}
+
constexpr int32_t MPEG2ProfileSimple = 0x00;
constexpr int32_t MPEG2ProfileMain = 0x01;
constexpr int32_t MPEG2Profile422 = 0x02;
@@ -103,12 +214,35 @@
constexpr int32_t MPEG2ProfileSpatial = 0x04;
constexpr int32_t MPEG2ProfileHigh = 0x05;
+inline static const char *asString_MPEG2Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case MPEG2ProfileSimple: return "Simple";
+ case MPEG2ProfileMain: return "Main";
+ case MPEG2Profile422: return "422";
+ case MPEG2ProfileSNR: return "SNR";
+ case MPEG2ProfileSpatial: return "Spatial";
+ case MPEG2ProfileHigh: return "High";
+ default: return def;
+ }
+}
+
constexpr int32_t MPEG2LevelLL = 0x00;
constexpr int32_t MPEG2LevelML = 0x01;
constexpr int32_t MPEG2LevelH14 = 0x02;
constexpr int32_t MPEG2LevelHL = 0x03;
constexpr int32_t MPEG2LevelHP = 0x04;
+inline static const char *asString_MPEG2Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case MPEG2LevelLL: return "LL";
+ case MPEG2LevelML: return "ML";
+ case MPEG2LevelH14: return "H14";
+ case MPEG2LevelHL: return "HL";
+ case MPEG2LevelHP: return "HP";
+ default: return def;
+ }
+}
+
constexpr int32_t AACObjectMain = 1;
constexpr int32_t AACObjectLC = 2;
constexpr int32_t AACObjectSSR = 3;
@@ -122,13 +256,48 @@
constexpr int32_t AACObjectELD = 39;
constexpr int32_t AACObjectXHE = 42;
+inline static const char *asString_AACObject(int32_t i, const char *def = "??") {
+ switch (i) {
+ case AACObjectMain: return "Main";
+ case AACObjectLC: return "LC";
+ case AACObjectSSR: return "SSR";
+ case AACObjectLTP: return "LTP";
+ case AACObjectHE: return "HE";
+ case AACObjectScalable: return "Scalable";
+ case AACObjectERLC: return "ERLC";
+ case AACObjectERScalable: return "ERScalable";
+ case AACObjectLD: return "LD";
+ case AACObjectHE_PS: return "HE_PS";
+ case AACObjectELD: return "ELD";
+ case AACObjectXHE: return "XHE";
+ default: return def;
+ }
+}
+
constexpr int32_t VP8Level_Version0 = 0x01;
constexpr int32_t VP8Level_Version1 = 0x02;
constexpr int32_t VP8Level_Version2 = 0x04;
constexpr int32_t VP8Level_Version3 = 0x08;
+inline static const char *asString_VP8Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case VP8Level_Version0: return "V0";
+ case VP8Level_Version1: return "V1";
+ case VP8Level_Version2: return "V2";
+ case VP8Level_Version3: return "V3";
+ default: return def;
+ }
+}
+
constexpr int32_t VP8ProfileMain = 0x01;
+inline static const char *asString_VP8Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case VP8ProfileMain: return "Main";
+ default: return def;
+ }
+}
+
constexpr int32_t VP9Profile0 = 0x01;
constexpr int32_t VP9Profile1 = 0x02;
constexpr int32_t VP9Profile2 = 0x04;
@@ -138,6 +307,20 @@
constexpr int32_t VP9Profile2HDR10Plus = 0x4000;
constexpr int32_t VP9Profile3HDR10Plus = 0x8000;
+inline static const char *asString_VP9Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case VP9Profile0: return "0";
+ case VP9Profile1: return "1";
+ case VP9Profile2: return "2";
+ case VP9Profile3: return "3";
+ case VP9Profile2HDR: return "2HDR";
+ case VP9Profile3HDR: return "3HDR";
+ case VP9Profile2HDR10Plus: return "2HDRPlus";
+ case VP9Profile3HDR10Plus: return "3HDRPlus";
+ default: return def;
+ }
+}
+
constexpr int32_t VP9Level1 = 0x1;
constexpr int32_t VP9Level11 = 0x2;
constexpr int32_t VP9Level2 = 0x4;
@@ -153,12 +336,111 @@
constexpr int32_t VP9Level61 = 0x1000;
constexpr int32_t VP9Level62 = 0x2000;
+inline static const char *asString_VP9Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case VP9Level1: return "1";
+ case VP9Level11: return "1.1";
+ case VP9Level2: return "2";
+ case VP9Level21: return "2.1";
+ case VP9Level3: return "3";
+ case VP9Level31: return "3.1";
+ case VP9Level4: return "4";
+ case VP9Level41: return "4.1";
+ case VP9Level5: return "5";
+ case VP9Level51: return "5.1";
+ case VP9Level52: return "5.2";
+ case VP9Level6: return "6";
+ case VP9Level61: return "6.1";
+ case VP9Level62: return "6.2";
+ default: return def;
+ }
+}
+
+constexpr int32_t AV1Profile0 = 0x01;
+constexpr int32_t AV1Profile1 = 0x02;
+constexpr int32_t AV1Profile2 = 0x04;
+
+inline static const char *asString_AV1Profile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case AV1Profile0: return "0";
+ case AV1Profile1: return "1";
+ case AV1Profile2: return "2";
+ default: return def;
+ }
+}
+
+constexpr int32_t AV1Level2 = 0x1;
+constexpr int32_t AV1Level21 = 0x2;
+constexpr int32_t AV1Level22 = 0x4;
+constexpr int32_t AV1Level23 = 0x8;
+constexpr int32_t AV1Level3 = 0x10;
+constexpr int32_t AV1Level31 = 0x20;
+constexpr int32_t AV1Level32 = 0x40;
+constexpr int32_t AV1Level33 = 0x80;
+constexpr int32_t AV1Level4 = 0x100;
+constexpr int32_t AV1Level41 = 0x200;
+constexpr int32_t AV1Level42 = 0x400;
+constexpr int32_t AV1Level43 = 0x800;
+constexpr int32_t AV1Level5 = 0x1000;
+constexpr int32_t AV1Level51 = 0x2000;
+constexpr int32_t AV1Level52 = 0x4000;
+constexpr int32_t AV1Level53 = 0x8000;
+constexpr int32_t AV1Level6 = 0x10000;
+constexpr int32_t AV1Level61 = 0x20000;
+constexpr int32_t AV1Level62 = 0x40000;
+constexpr int32_t AV1Level63 = 0x80000;
+constexpr int32_t AV1Level7 = 0x100000;
+constexpr int32_t AV1Level71 = 0x200000;
+constexpr int32_t AV1Level72 = 0x400000;
+constexpr int32_t AV1Level73 = 0x800000;
+
+inline static const char *asString_AV1Level(int32_t i, const char *def = "??") {
+ switch (i) {
+ case AV1Level2: return "2";
+ case AV1Level21: return "2.1";
+ case AV1Level22: return "2.2";
+ case AV1Level23: return "2.3";
+ case AV1Level3: return "3";
+ case AV1Level31: return "3.1";
+ case AV1Level32: return "3.2";
+ case AV1Level33: return "3.3";
+ case AV1Level4: return "4";
+ case AV1Level41: return "4.1";
+ case AV1Level42: return "4.2";
+ case AV1Level43: return "4.3";
+ case AV1Level5: return "5";
+ case AV1Level51: return "5.1";
+ case AV1Level52: return "5.2";
+ case AV1Level53: return "5.3";
+ case AV1Level6: return "6";
+ case AV1Level61: return "6.1";
+ case AV1Level62: return "6.2";
+ case AV1Level63: return "6.3";
+ case AV1Level7: return "7";
+ case AV1Level71: return "7.1";
+ case AV1Level72: return "7.2";
+ case AV1Level73: return "7.3";
+ default: return def;
+ }
+}
+
constexpr int32_t HEVCProfileMain = 0x01;
constexpr int32_t HEVCProfileMain10 = 0x02;
constexpr int32_t HEVCProfileMainStill = 0x04;
constexpr int32_t HEVCProfileMain10HDR10 = 0x1000;
constexpr int32_t HEVCProfileMain10HDR10Plus = 0x2000;
+inline static const char *asString_HEVCProfile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case HEVCProfileMain: return "Main";
+ case HEVCProfileMain10: return "Main10";
+ case HEVCProfileMainStill: return "MainStill";
+ case HEVCProfileMain10HDR10: return "Main10HDR10";
+ case HEVCProfileMain10HDR10Plus: return "Main10HDR10Plus";
+ default: return def;
+ }
+}
+
constexpr int32_t HEVCMainTierLevel1 = 0x1;
constexpr int32_t HEVCHighTierLevel1 = 0x2;
constexpr int32_t HEVCMainTierLevel2 = 0x4;
@@ -186,6 +468,38 @@
constexpr int32_t HEVCMainTierLevel62 = 0x1000000;
constexpr int32_t HEVCHighTierLevel62 = 0x2000000;
+inline static const char *asString_HEVCTierLevel(int32_t i, const char *def = "??") {
+ switch (i) {
+ case HEVCMainTierLevel1: return "Main 1";
+ case HEVCHighTierLevel1: return "High 1";
+ case HEVCMainTierLevel2: return "Main 2";
+ case HEVCHighTierLevel2: return "High 2";
+ case HEVCMainTierLevel21: return "Main 2.1";
+ case HEVCHighTierLevel21: return "High 2.1";
+ case HEVCMainTierLevel3: return "Main 3";
+ case HEVCHighTierLevel3: return "High 3";
+ case HEVCMainTierLevel31: return "Main 3.1";
+ case HEVCHighTierLevel31: return "High 3.1";
+ case HEVCMainTierLevel4: return "Main 4";
+ case HEVCHighTierLevel4: return "High 4";
+ case HEVCMainTierLevel41: return "Main 4.1";
+ case HEVCHighTierLevel41: return "High 4.1";
+ case HEVCMainTierLevel5: return "Main 5";
+ case HEVCHighTierLevel5: return "High 5";
+ case HEVCMainTierLevel51: return "Main 5.1";
+ case HEVCHighTierLevel51: return "High 5.1";
+ case HEVCMainTierLevel52: return "Main 5.2";
+ case HEVCHighTierLevel52: return "High 5.2";
+ case HEVCMainTierLevel6: return "Main 6";
+ case HEVCHighTierLevel6: return "High 6";
+ case HEVCMainTierLevel61: return "Main 6.1";
+ case HEVCHighTierLevel61: return "High 6.1";
+ case HEVCMainTierLevel62: return "Main 6.2";
+ case HEVCHighTierLevel62: return "High 6.2";
+ default: return def;
+ }
+}
+
constexpr int32_t DolbyVisionProfileDvavPer = 0x1;
constexpr int32_t DolbyVisionProfileDvavPen = 0x2;
constexpr int32_t DolbyVisionProfileDvheDer = 0x4;
@@ -197,6 +511,22 @@
constexpr int32_t DolbyVisionProfileDvheSt = 0x100;
constexpr int32_t DolbyVisionProfileDvavSe = 0x200;
+inline static const char *asString_DolbyVisionProfile(int32_t i, const char *def = "??") {
+ switch (i) {
+ case DolbyVisionProfileDvavPer: return "DvavPer";
+ case DolbyVisionProfileDvavPen: return "DvavPen";
+ case DolbyVisionProfileDvheDer: return "DvheDer";
+ case DolbyVisionProfileDvheDen: return "DvheDen";
+ case DolbyVisionProfileDvheDtr: return "DvheDtr";
+ case DolbyVisionProfileDvheStn: return "DvheStn";
+ case DolbyVisionProfileDvheDth: return "DvheDth";
+ case DolbyVisionProfileDvheDtb: return "DvheDtb";
+ case DolbyVisionProfileDvheSt: return "DvheSt";
+ case DolbyVisionProfileDvavSe: return "DvavSe";
+ default: return def;
+ }
+}
+
constexpr int32_t DolbyVisionLevelHd24 = 0x1;
constexpr int32_t DolbyVisionLevelHd30 = 0x2;
constexpr int32_t DolbyVisionLevelFhd24 = 0x4;
@@ -207,10 +537,34 @@
constexpr int32_t DolbyVisionLevelUhd48 = 0x80;
constexpr int32_t DolbyVisionLevelUhd60 = 0x100;
+inline static const char *asString_DolbyVisionLevel(int32_t i, const char *def = "??") {
+ switch (i) {
+ case DolbyVisionLevelHd24: return "Hd24";
+ case DolbyVisionLevelHd30: return "Hd30";
+ case DolbyVisionLevelFhd24: return "Fhd24";
+ case DolbyVisionLevelFhd30: return "Fhd30";
+ case DolbyVisionLevelFhd60: return "Fhd60";
+ case DolbyVisionLevelUhd24: return "Uhd24";
+ case DolbyVisionLevelUhd30: return "Uhd30";
+ case DolbyVisionLevelUhd48: return "Uhd48";
+ case DolbyVisionLevelUhd60: return "Uhd60";
+ default: return def;
+ }
+}
+
constexpr int32_t BITRATE_MODE_CBR = 2;
constexpr int32_t BITRATE_MODE_CQ = 0;
constexpr int32_t BITRATE_MODE_VBR = 1;
+inline static const char *asString_BitrateMode(int32_t i, const char *def = "??") {
+ switch (i) {
+ case BITRATE_MODE_CBR: return "CBR";
+ case BITRATE_MODE_CQ: return "CQ";
+ case BITRATE_MODE_VBR: return "VBR";
+ default: return def;
+ }
+}
+
constexpr int32_t COLOR_Format12bitRGB444 = 3;
constexpr int32_t COLOR_Format16bitARGB1555 = 5;
constexpr int32_t COLOR_Format16bitARGB4444 = 4;
@@ -264,6 +618,64 @@
constexpr int32_t COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
constexpr int32_t COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
+inline static const char *asString_ColorFormat(int32_t i, const char *def = "??") {
+ switch (i) {
+ case COLOR_Format12bitRGB444: return "12bitRGB444";
+ case COLOR_Format16bitARGB1555: return "16bitARGB1555";
+ case COLOR_Format16bitARGB4444: return "16bitARGB4444";
+ case COLOR_Format16bitBGR565: return "16bitBGR565";
+ case COLOR_Format16bitRGB565: return "16bitRGB565";
+ case COLOR_Format18bitARGB1665: return "18bitARGB1665";
+ case COLOR_Format18BitBGR666: return "18BitBGR666";
+ case COLOR_Format18bitRGB666: return "18bitRGB666";
+ case COLOR_Format19bitARGB1666: return "19bitARGB1666";
+ case COLOR_Format24BitABGR6666: return "24BitABGR6666";
+ case COLOR_Format24bitARGB1887: return "24bitARGB1887";
+ case COLOR_Format24BitARGB6666: return "24BitARGB6666";
+ case COLOR_Format24bitBGR888: return "24bitBGR888";
+ case COLOR_Format24bitRGB888: return "24bitRGB888";
+ case COLOR_Format25bitARGB1888: return "25bitARGB1888";
+ case COLOR_Format32bitABGR8888: return "32bitABGR8888";
+ case COLOR_Format32bitARGB8888: return "32bitARGB8888";
+ case COLOR_Format32bitBGRA8888: return "32bitBGRA8888";
+ case COLOR_Format8bitRGB332: return "8bitRGB332";
+ case COLOR_FormatCbYCrY: return "CbYCrY";
+ case COLOR_FormatCrYCbY: return "CrYCbY";
+ case COLOR_FormatL16: return "L16";
+ case COLOR_FormatL2: return "L2";
+ case COLOR_FormatL24: return "L24";
+ case COLOR_FormatL32: return "L32";
+ case COLOR_FormatL4: return "L4";
+ case COLOR_FormatL8: return "L8";
+ case COLOR_FormatMonochrome: return "Monochrome";
+ case COLOR_FormatRawBayer10bit: return "RawBayer10bit";
+ case COLOR_FormatRawBayer8bit: return "RawBayer8bit";
+ case COLOR_FormatRawBayer8bitcompressed: return "RawBayer8bitcompressed";
+ case COLOR_FormatRGBAFlexible: return "RGBAFlexible";
+ case COLOR_FormatRGBFlexible: return "RGBFlexible";
+ case COLOR_FormatSurface: return "Surface";
+ case COLOR_FormatYCbYCr: return "YCbYCr";
+ case COLOR_FormatYCrYCb: return "YCrYCb";
+ case COLOR_FormatYUV411PackedPlanar: return "YUV411PackedPlanar";
+ case COLOR_FormatYUV411Planar: return "YUV411Planar";
+ case COLOR_FormatYUV420Flexible: return "YUV420Flexible";
+ case COLOR_FormatYUV420PackedPlanar: return "YUV420PackedPlanar";
+ case COLOR_FormatYUV420PackedSemiPlanar: return "YUV420PackedSemiPlanar";
+ case COLOR_FormatYUV420Planar: return "YUV420Planar";
+ case COLOR_FormatYUV420SemiPlanar: return "YUV420SemiPlanar";
+ case COLOR_FormatYUV422Flexible: return "YUV422Flexible";
+ case COLOR_FormatYUV422PackedPlanar: return "YUV422PackedPlanar";
+ case COLOR_FormatYUV422PackedSemiPlanar: return "YUV422PackedSemiPlanar";
+ case COLOR_FormatYUV422Planar: return "YUV422Planar";
+ case COLOR_FormatYUV422SemiPlanar: return "YUV422SemiPlanar";
+ case COLOR_FormatYUV444Flexible: return "YUV444Flexible";
+ case COLOR_FormatYUV444Interleaved: return "YUV444Interleaved";
+ case COLOR_QCOM_FormatYUV420SemiPlanar: return "QCOM_YUV420SemiPlanar";
+ case COLOR_TI_FormatYUV420PackedSemiPlanar: return "TI_YUV420PackedSemiPlanar";
+ default: return def;
+ }
+}
+
constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
constexpr char FEATURE_PartialFrame[] = "partial-frame";
@@ -273,6 +685,7 @@
// from MediaFormat.java
constexpr char MIMETYPE_VIDEO_VP8[] = "video/x-vnd.on2.vp8";
constexpr char MIMETYPE_VIDEO_VP9[] = "video/x-vnd.on2.vp9";
+constexpr char MIMETYPE_VIDEO_AV1[] = "video/av01";
constexpr char MIMETYPE_VIDEO_AVC[] = "video/avc";
constexpr char MIMETYPE_VIDEO_HEVC[] = "video/hevc";
constexpr char MIMETYPE_VIDEO_MPEG4[] = "video/mp4v-es";
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 6a5c6b6..09639e2 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -70,7 +70,12 @@
ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9,
ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10,
ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = DRM_ERROR_BASE - 11,
- ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 11,
+ ERROR_DRM_INSUFFICIENT_SECURITY = DRM_ERROR_BASE - 12,
+ ERROR_DRM_FRAME_TOO_LARGE = DRM_ERROR_BASE - 13,
+ ERROR_DRM_RESOURCE_CONTENTION = DRM_ERROR_BASE - 14,
+ ERROR_DRM_SESSION_LOST_STATE = DRM_ERROR_BASE - 15,
+ ERROR_DRM_INVALID_STATE = DRM_ERROR_BASE - 16,
+ ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 16,
ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500,
ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999,
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 84e01f3..ba6631c 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -19,6 +19,7 @@
#define MEDIA_EXTRACTOR_FACTORY_H_
#include <stdio.h>
+#include <unordered_set>
#include <media/IMediaExtractor.h>
@@ -35,6 +36,7 @@
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
static status_t dump(int fd, const Vector<String16>& args);
+ static std::unordered_set<std::string> getSupportedTypes();
static void SetLinkedLibraries(const std::string& linkedLibraries);
private:
diff --git a/media/libmediaextractor/include/media/MediaSource.h b/media/libstagefright/include/media/stagefright/MediaSource.h
similarity index 100%
rename from media/libmediaextractor/include/media/MediaSource.h
rename to media/libstagefright/include/media/stagefright/MediaSource.h
diff --git a/media/libstagefright/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
deleted file mode 120000
index 160f8d3..0000000
--- a/media/libstagefright/include/media/stagefright/MetaData.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MetaData.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MetaData.h b/media/libstagefright/include/media/stagefright/MetaData.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MetaData.h
rename to media/libstagefright/include/media/stagefright/MetaData.h
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
deleted file mode 120000
index 1e12193..0000000
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../libmediaextractor/include/media/stagefright/MetaDataBase.h
\ No newline at end of file
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
similarity index 100%
rename from media/libmediaextractor/include/media/stagefright/MetaDataBase.h
rename to media/libstagefright/include/media/stagefright/MetaDataBase.h
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 8dc8d38..f34f9b6 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -96,8 +96,7 @@
bool getCachedDuration(int64_t *durationUs, bool *eos) const;
- status_t getAudioPresentations(size_t trackIdx,
- AudioPresentationCollection *presentations) const;
+ status_t getAudioPresentations(size_t trackIdx, AudioPresentationCollection *presentations);
protected:
virtual ~NuMediaExtractor();
diff --git a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
index be911cc..891b9a0 100644
--- a/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
+++ b/media/libstagefright/include/media/stagefright/VideoFrameScheduler2.h
@@ -34,8 +34,8 @@
private:
void updateVsync() override;
- long mAppVsyncOffset;
- long mSfVsyncOffset;
+ nsecs_t mAppVsyncOffset;
+ nsecs_t mSfVsyncOffset;
sp<VsyncTracker> mVsyncTracker;
sp<ChoreographerThread> mChoreographerThread;
Mutex mLock;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index e9baa1a..1482072 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -217,6 +217,9 @@
sp<IDescrambler> mDescrambler;
AudioPresentationCollection mAudioPresentations;
+ // Send audio presentations along with access units.
+ void addAudioPresentations(const sp<ABuffer> &buffer);
+
// Flush accumulated payload if necessary --- i.e. at EOS or at the start of
// another payload. event is set if the flushed payload is PES with a sync
// frame.
@@ -758,21 +761,21 @@
// reasonable amount of time. To handle the wrap-around, use fancy math
// to get an extended PTS that is within [-0xffffffff, 0xffffffff]
// of the latest recovered PTS.
- if (mLastRecoveredPTS < 0ll) {
+ if (mLastRecoveredPTS < 0LL) {
// Use the original 33bit number for 1st frame, the reason is that
// if 1st frame wraps to negative that's far away from 0, we could
// never start. Only start wrapping around from 2nd frame.
mLastRecoveredPTS = static_cast<int64_t>(PTS_33bit);
} else {
mLastRecoveredPTS = static_cast<int64_t>(
- ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000ll)
+ ((mLastRecoveredPTS - static_cast<int64_t>(PTS_33bit) + 0x100000000LL)
& 0xfffffffe00000000ull) | PTS_33bit);
// We start from 0, but recovered PTS could be slightly below 0.
// Clamp it to 0 as rest of the pipeline doesn't take negative pts.
// (eg. video is read first and starts at 0, but audio starts at 0xfffffff0)
- if (mLastRecoveredPTS < 0ll) {
+ if (mLastRecoveredPTS < 0LL) {
ALOGI("Clamping negative recovered PTS (%" PRId64 ") to 0", mLastRecoveredPTS);
- mLastRecoveredPTS = 0ll;
+ mLastRecoveredPTS = 0LL;
}
}
@@ -822,7 +825,7 @@
int64_t timeUs = (PTS * 100) / 9;
- if (mParser->mAbsoluteTimeAnchorUs >= 0ll) {
+ if (mParser->mAbsoluteTimeAnchorUs >= 0LL) {
timeUs += mParser->mAbsoluteTimeAnchorUs;
}
@@ -1610,9 +1613,9 @@
detailedError = _detailedError;
});
- if (!returnVoid.isOk()) {
- ALOGE("[stream %d] descramble failed, trans=%s",
- mElementaryPID, returnVoid.description().c_str());
+ if (!returnVoid.isOk() || status != Status::OK) {
+ ALOGE("[stream %d] descramble failed, trans=%s, status=%d",
+ mElementaryPID, returnVoid.description().c_str(), status);
return UNKNOWN_ERROR;
}
@@ -1708,6 +1711,13 @@
return err;
}
+void ATSParser::Stream::addAudioPresentations(const sp<ABuffer> &buffer) {
+ std::ostringstream outStream(std::ios::out);
+ serializeAudioPresentations(mAudioPresentations, &outStream);
+ sp<ABuffer> ap = ABuffer::CreateAsCopy(outStream.str().data(), outStream.str().size());
+ buffer->meta()->setBuffer("audio-presentation-info", ap);
+}
+
void ATSParser::Stream::onPayloadData(
unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
unsigned PES_scrambling_control,
@@ -1723,7 +1733,7 @@
ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
- int64_t timeUs = 0ll; // no presentation timestamp available.
+ int64_t timeUs = 0LL; // no presentation timestamp available.
if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
timeUs = mProgram->convertPTSToTimestamp(PTS);
}
@@ -1758,8 +1768,10 @@
}
}
mSource = new AnotherPacketSource(meta);
+ if (mAudioPresentations.size() > 0) {
+ addAudioPresentations(accessUnit);
+ }
mSource->queueAccessUnit(accessUnit);
- mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
mElementaryPID, mStreamType);
}
@@ -1771,8 +1783,10 @@
if (mSource->getFormat() == NULL) {
mSource->setFormat(mQueue->getFormat());
}
+ if (mAudioPresentations.size() > 0) {
+ addAudioPresentations(accessUnit);
+ }
mSource->queueAccessUnit(accessUnit);
- mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
}
// Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
@@ -1855,10 +1869,10 @@
ATSParser::ATSParser(uint32_t flags)
: mFlags(flags),
- mAbsoluteTimeAnchorUs(-1ll),
+ mAbsoluteTimeAnchorUs(-1LL),
mTimeOffsetValid(false),
- mTimeOffsetUs(0ll),
- mLastRecoveredPTS(-1ll),
+ mTimeOffsetUs(0LL),
+ mLastRecoveredPTS(-1LL),
mNumTSPacketsParsed(0),
mNumPCRs(0) {
mPSISections.add(0 /* PID */, new PSISection);
@@ -1900,7 +1914,7 @@
if ((mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)
&& extra->findInt64(
kATSParserKeyRecentMediaTimeUs, &mediaTimeUs)) {
- if (mAbsoluteTimeAnchorUs >= 0ll) {
+ if (mAbsoluteTimeAnchorUs >= 0LL) {
mediaTimeUs -= mAbsoluteTimeAnchorUs;
}
if (mTimeOffsetValid) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index e2c5031..62e3a4b 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -35,7 +35,7 @@
namespace android {
-const int64_t kNearEOSMarkUs = 2000000ll; // 2 secs
+const int64_t kNearEOSMarkUs = 2000000LL; // 2 secs
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
: mIsAudio(false),
@@ -223,6 +223,12 @@
kKeyMpegUserData, 0, mpegUserData->data(), mpegUserData->size());
}
+ sp<ABuffer> ap;
+ if (buffer->meta()->findBuffer("audio-presentation-info", &ap) && ap != NULL) {
+ bufmeta.setData(
+ kKeyAudioPresentationInfo, 0, ap->data(), ap->size());
+ }
+
int32_t cryptoMode;
if (buffer->meta()->findInt32("cryptoMode", &cryptoMode)) {
int32_t cryptoKey;
@@ -293,7 +299,7 @@
if (buffer->meta()->findInt32("discontinuity", &discontinuity)){
ALOGV("queueing a discontinuity with queueAccessUnit");
- mLastQueuedTimeUs = 0ll;
+ mLastQueuedTimeUs = 0LL;
mEOSResult = OK;
mLatestEnqueuedMeta = NULL;
@@ -697,23 +703,4 @@
return firstMeta;
}
-void AnotherPacketSource::convertAudioPresentationInfoToMetadata(
- const AudioPresentationCollection& presentations) {
- sp<MetaData> meta = getFormat();
- if (meta == NULL) {
- return;
- }
- if (presentations.empty()) {
- // Clear audio presentation info in metadata.
- Mutex::Autolock autoLock(mLock);
- meta->remove(kKeyAudioPresentationInfo);
- } else {
- std::ostringstream outStream(std::ios::out);
- serializeAudioPresentations(presentations, &outStream);
- Mutex::Autolock autoLock(mLock);
- meta->setData(kKeyAudioPresentationInfo, MetaData::TYPE_NONE,
- outStream.str().data(), outStream.str().size());
- }
-}
-
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 57a6c33..f4a6acb 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -85,8 +85,6 @@
void trimBuffersAfterMeta(const sp<AMessage> &meta);
sp<AMessage> trimBuffersBeforeMeta(const sp<AMessage> &meta);
- void convertAudioPresentationInfoToMetadata(const AudioPresentationCollection &presentations);
-
protected:
virtual ~AnotherPacketSource();
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index fb8b9fd..b91edcd 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1111,7 +1111,7 @@
memcpy(accessUnit->data(), mBuffer->data() + 4, payloadSize);
int64_t timeUs = fetchTimestamp(payloadSize + 4);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1147,7 +1147,7 @@
return NULL;
}
- if (info.mTimestampUs < 0ll) {
+ if (info.mTimestampUs < 0LL) {
ALOGE("Negative info.mTimestampUs");
return NULL;
}
@@ -1317,7 +1317,7 @@
}
- if (timeUs == 0ll) {
+ if (timeUs == 0LL) {
ALOGV("Returning 0 timestamp");
}
@@ -1460,7 +1460,7 @@
mBuffer->setRange(0, mBuffer->size() - nextScan);
int64_t timeUs = fetchTimestamp(nextScan);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1545,7 +1545,7 @@
mBuffer->setRange(0, mBuffer->size() - frameSize);
int64_t timeUs = fetchTimestamp(frameSize);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1732,7 +1732,7 @@
mBuffer->setRange(0, mBuffer->size() - offset);
int64_t timeUs = fetchTimestamp(offset);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeUs");
return NULL;
}
@@ -1929,7 +1929,7 @@
mBuffer->setRange(0, size);
int64_t timeUs = fetchTimestamp(offset);
- if (timeUs < 0ll) {
+ if (timeUs < 0LL) {
ALOGE("Negative timeus");
return NULL;
}
diff --git a/media/libstagefright/omx/1.0/Omx.cpp b/media/libstagefright/omx/1.0/Omx.cpp
index 4e2d398..121bb1a 100644
--- a/media/libstagefright/omx/1.0/Omx.cpp
+++ b/media/libstagefright/omx/1.0/Omx.cpp
@@ -124,11 +124,11 @@
} else {
uint32_t quirks = 0;
for (const auto& quirk : codec->second.quirkSet) {
- if (quirk == "requires-allocate-on-input-ports") {
+ if (quirk == "quirk::requires-allocate-on-input-ports") {
quirks |= OMXNodeInstance::
kRequiresAllocateBufferOnInputPorts;
}
- if (quirk == "requires-allocate-on-output-ports") {
+ if (quirk == "quirk::requires-allocate-on-output-ports") {
quirks |= OMXNodeInstance::
kRequiresAllocateBufferOnOutputPorts;
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 68b375a..d7aacff 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -355,9 +355,9 @@
mQuirks(0),
mBufferIDCount(0),
mRestorePtsFailed(false),
- mMaxTimestampGapUs(0ll),
- mPrevOriginalTimeUs(-1ll),
- mPrevModifiedTimeUs(-1ll)
+ mMaxTimestampGapUs(0LL),
+ mPrevOriginalTimeUs(-1LL),
+ mPrevModifiedTimeUs(-1LL)
{
mName = ADebug::GetDebugName(name);
DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
@@ -1948,7 +1948,7 @@
int64_t OMXNodeInstance::getCodecTimestamp(OMX_TICKS timestamp) {
int64_t originalTimeUs = timestamp;
- if (mMaxTimestampGapUs > 0ll) {
+ if (mMaxTimestampGapUs > 0LL) {
/* Cap timestamp gap between adjacent frames to specified max
*
* In the scenario of cast mirroring, encoding could be suspended for
@@ -1956,7 +1956,7 @@
* where encoder's rate control logic produces huge frames after a
* long period of suspension.
*/
- if (mPrevOriginalTimeUs >= 0ll) {
+ if (mPrevOriginalTimeUs >= 0LL) {
int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
timestamp = (timestampGapUs < mMaxTimestampGapUs ?
timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
@@ -1964,7 +1964,7 @@
ALOGV("IN timestamp: %lld -> %lld",
static_cast<long long>(originalTimeUs),
static_cast<long long>(timestamp));
- } else if (mMaxTimestampGapUs < 0ll) {
+ } else if (mMaxTimestampGapUs < 0LL) {
/*
* Apply a fixed timestamp gap between adjacent frames.
*
@@ -1972,7 +1972,7 @@
* on frames could go forward or backward. Some encoders may silently
* drop frames when it goes backward (or even stay unchanged).
*/
- if (mPrevOriginalTimeUs >= 0ll) {
+ if (mPrevOriginalTimeUs >= 0LL) {
timestamp = mPrevModifiedTimeUs - mMaxTimestampGapUs;
}
ALOGV("IN timestamp: %lld -> %lld",
@@ -1983,7 +1983,7 @@
mPrevOriginalTimeUs = originalTimeUs;
mPrevModifiedTimeUs = timestamp;
- if (mMaxTimestampGapUs != 0ll && !mRestorePtsFailed) {
+ if (mMaxTimestampGapUs != 0LL && !mRestorePtsFailed) {
mOriginalTimeUs.add(timestamp, originalTimeUs);
}
@@ -2016,7 +2016,7 @@
void OMXNodeInstance::codecBufferFilled(omx_message &msg) {
Mutex::Autolock autoLock(mLock);
- if (mMaxTimestampGapUs == 0ll || mRestorePtsFailed) {
+ if (mMaxTimestampGapUs == 0LL || mRestorePtsFailed) {
return;
}
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
index b187035..1b8493a 100644
--- a/media/libstagefright/omx/OMXUtils.cpp
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -150,6 +150,8 @@
"video_decoder.vp8", "video_encoder.vp8" },
{ MEDIA_MIMETYPE_VIDEO_VP9,
"video_decoder.vp9", "video_encoder.vp9" },
+ { MEDIA_MIMETYPE_VIDEO_AV1,
+ "video_decoder.av1", "video_encoder.av1" },
{ MEDIA_MIMETYPE_AUDIO_RAW,
"audio_decoder.raw", "audio_encoder.raw" },
{ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION,
diff --git a/media/libstagefright/omx/tests/Android.bp b/media/libstagefright/omx/tests/Android.bp
index 31bc837..fb03229 100644
--- a/media/libstagefright/omx/tests/Android.bp
+++ b/media/libstagefright/omx/tests/Android.bp
@@ -9,7 +9,6 @@
"libbinder",
"libmedia",
"libmedia_omx",
- "libmediaextractor",
"libutils",
"liblog",
"libstagefright_foundation",
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 201a5df..b964bc0 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -417,7 +417,7 @@
if (sessionDesc->getDurationUs(&durationUs)) {
mFormat->setInt64(kKeyDuration, durationUs);
} else {
- mFormat->setInt64(kKeyDuration, -1ll);
+ mFormat->setInt64(kKeyDuration, -1LL);
}
mInitCheck = OK;
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
index c7a65c2..befc226 100644
--- a/media/libstagefright/rtsp/ARTPAssembler.cpp
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -36,7 +36,7 @@
if (status == WRONG_SEQUENCE_NUMBER) {
if (mFirstFailureTimeUs >= 0) {
- if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000ll) {
+ if (ALooper::GetNowUs() - mFirstFailureTimeUs > 10000LL) {
mFirstFailureTimeUs = -1;
// LOG(VERBOSE) << "waited too long for packet.";
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a86ab74..6a4706d 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -50,7 +50,7 @@
}
// static
-const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
struct ARTPConnection::StreamInfo {
int mRTPSocket;
@@ -118,7 +118,7 @@
bumpSocketBufferSize(*rtcpSocket);
/* rand() * 1000 may overflow int type, use long long */
- unsigned start = (unsigned)((rand()* 1000ll)/RAND_MAX) + 15550;
+ unsigned start = (unsigned)((rand()* 1000LL)/RAND_MAX) + 15550;
start &= ~1;
for (unsigned port = start; port < 65536; port += 2) {
@@ -307,7 +307,7 @@
int64_t nowUs = ALooper::GetNowUs();
if (mLastReceiverReportTimeUs <= 0
- || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
+ || mLastReceiverReportTimeUs + 5000000LL <= nowUs) {
sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
List<StreamInfo>::iterator it = mStreams.begin();
while (it != mStreams.end()) {
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 4827cd2..4afa6f4 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -180,7 +180,7 @@
}
int64_t nowUs = ALooper::GetNowUs();
- if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) {
+ if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000LL > nowUs) {
// Send FIR requests at most every 5 secs.
return;
}
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 49e01c0..4f86773 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -420,10 +420,10 @@
uint64_t ARTPWriter::GetNowNTP() {
uint64_t nowUs = ALooper::GetNowUs();
- nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+ nowUs += ((70LL * 365 + 17) * 24) * 60 * 60 * 1000000LL;
- uint64_t hi = nowUs / 1000000ll;
- uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+ uint64_t hi = nowUs / 1000000LL;
+ uint64_t lo = ((1LL << 32) * (nowUs % 1000000LL)) / 1000000LL;
return (hi << 32) | lo;
}
@@ -576,7 +576,7 @@
int64_t timeUs;
CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
const uint8_t *mediaData =
(const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
@@ -671,7 +671,7 @@
int64_t timeUs;
CHECK(mediaBuf->meta_data().findInt64(kKeyTime, &timeUs));
- uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100LL);
const uint8_t *mediaData =
(const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 33c1c18..20cb415 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -39,7 +39,7 @@
namespace android {
// static
-const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000LL;
// static
const AString ARTSPConnection::sUserAgent =
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 23269af..4b6f928 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -364,14 +364,14 @@
// adjust time-stamps after pause/resume
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
- CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+ CHECK_GE(durExcludingEarlierPausesUs, 0LL);
int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
CHECK_GE(pausedDurationUs, lastDurationUs);
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
timestampUs -= previousPausedDurationUs;
- CHECK_GE(timestampUs, 0ll);
+ CHECK_GE(timestampUs, 0LL);
int32_t isSync = false;
md.findInt32(kKeyIsSyncFrame, &isSync);
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 2dec9fa..6e541ba 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -26,8 +26,9 @@
#include <sys/stat.h>
#include <expat.h>
-#include <cctype>
#include <algorithm>
+#include <cctype>
+#include <string>
namespace android {
@@ -326,8 +327,8 @@
case SECTION_DECODER:
case SECTION_ENCODER:
{
- if (strEq(name, "Quirk")) {
- (void)addQuirk(attrs);
+ if (strEq(name, "Quirk") || strEq(name, "Attribute")) {
+ (void)addQuirk(attrs, name);
} else if (strEq(name, "Type")) {
(void)addTypeFromAttributes(attrs,
(mCurrentSection == SECTION_ENCODER));
@@ -348,6 +349,8 @@
if (outside &&
(strEq(name, "Limit") || strEq(name, "Feature"))) {
ALOGW("ignoring %s specified outside of a Type", name);
+ } else if (strEq(name, "Alias")) {
+ (void)addAlias(attrs);
} else if (strEq(name, "Limit")) {
(void)addLimit(attrs);
} else if (strEq(name, "Feature")) {
@@ -579,7 +582,7 @@
return OK;
}
-status_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
+status_t MediaCodecsXmlParser::addQuirk(const char **attrs, const char *tag) {
if (mCurrentCodec == mCodecMap.end()) {
return BAD_VALUE;
}
@@ -606,7 +609,12 @@
return BAD_VALUE;
}
- mCurrentCodec->second.quirkSet.emplace(name);
+ std::string tagString = tag;
+ std::transform(tagString.begin(), tagString.end(), tagString.begin(), ::tolower);
+ tagString.append("::");
+ tagString.append(name);
+ mCurrentCodec->second.quirkSet.emplace(tagString.c_str());
+ ALOGI("adding %s to %s", tagString.c_str(), mCurrentCodec->first.c_str());
return OK;
}
@@ -760,6 +768,7 @@
strEq(a_name, "quality") ||
strEq(a_name, "size") ||
strEq(a_name, "measured-blocks-per-second") ||
+ strHasPrefix(a_name, "performance-point-") ||
strHasPrefix(a_name, "measured-frame-rate-")) {
// "range" is specified in exactly one of the following forms:
// 1) min-max
@@ -964,6 +973,34 @@
return OK;
}
+status_t MediaCodecsXmlParser::addAlias(const char **attrs) {
+ size_t i = 0;
+ const char *name = nullptr;
+
+ while (attrs[i] != nullptr) {
+ if (strEq(attrs[i], "name")) {
+ if (attrs[++i] == nullptr) {
+ ALOGE("addAlias: name is null");
+ return BAD_VALUE;
+ }
+ name = attrs[i];
+ } else {
+ ALOGE("addAlias: unrecognized attribute: %s", attrs[i]);
+ return BAD_VALUE;
+ }
+ ++i;
+ }
+
+ // Every feature must have a name.
+ if (name == nullptr) {
+ ALOGE("alias with no 'name' attribute");
+ return BAD_VALUE;
+ }
+
+ mCurrentCodec->second.aliases.emplace_back(name);
+ return OK;
+}
+
const MediaCodecsXmlParser::AttributeMap&
MediaCodecsXmlParser::getServiceAttributeMap() const {
return mServiceAttributeMap;
@@ -1041,11 +1078,18 @@
NodeInfo nodeInfo;
nodeInfo.name = codecName;
+ // NOTE: no aliases are exposed in role info
+ // attribute quirks are exposed as node attributes
nodeInfo.attributeList.reserve(typeAttributeMap.size());
for (const auto& attribute : typeAttributeMap) {
nodeInfo.attributeList.push_back(
Attribute{attribute.first, attribute.second});
}
+ for (const std::string &quirk : codec.second.quirkSet) {
+ if (strHasPrefix(quirk.c_str(), "attribute::")) {
+ nodeInfo.attributeList.push_back(Attribute{quirk, "present"});
+ }
+ }
nodeList->insert(std::make_pair(
std::move(order), std::move(nodeInfo)));
}
diff --git a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
index cc69e52..fd949da 100644
--- a/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
+++ b/media/libstagefright/xmlparser/include/media/stagefright/xmlparser/MediaCodecsXmlParser.h
@@ -65,6 +65,7 @@
size_t order; ///< Order of appearance in the file (starting from 0)
QuirkSet quirkSet; ///< Set of quirks requested by this codec
TypeMap typeMap; ///< Map of types supported by this codec
+ std::vector<std::string> aliases; ///< Name aliases for this codec
};
typedef std::pair<std::string, CodecProperties> Codec;
@@ -76,6 +77,7 @@
struct NodeInfo {
std::string name;
std::vector<Attribute> attributeList;
+ // note: aliases are not exposed here as they are not part of the role map
};
/**
@@ -171,8 +173,9 @@
void addMediaCodec(bool encoder, const char *name,
const char *type = nullptr);
- status_t addQuirk(const char **attrs);
+ status_t addQuirk(const char **attrs, const char *tag);
status_t addTypeFromAttributes(const char **attrs, bool encoder);
+ status_t addAlias(const char **attrs);
status_t addLimit(const char **attrs);
status_t addFeature(const char **attrs);
void addType(const char *name);
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index f7597db..1fbb85e 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -20,7 +20,7 @@
libmediaplayerservice \
libutils \
libbinder \
- libicuuc \
+ libandroidicu \
android.hardware.media.omx@1.0 \
LOCAL_STATIC_LIBRARIES := \
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 73bd2ca..74754ea 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -78,7 +78,6 @@
"libmedia_omx",
"libmedia_jni",
"libmediadrm",
- "libmediaextractor",
"libstagefright",
"libstagefright_foundation",
"libstagefright_bufferqueue_helper",
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index b86ab42..1a0c3b1 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -357,8 +357,10 @@
it != mAcquiredImages.end(); it++) {
AImage* image = *it;
Mutex::Autolock _l(image->mLock);
- releaseImageLocked(image, /*releaseFenceFd*/-1);
+ // Do not alter mAcquiredImages while we are iterating on it
+ releaseImageLocked(image, /*releaseFenceFd*/-1, /*clearCache*/false);
}
+ mAcquiredImages.clear();
// Delete Buffer Items
for (auto it = mBuffers.begin();
@@ -497,7 +499,7 @@
}
void
-AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd) {
+AImageReader::releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache) {
BufferItem* buffer = image->mBuffer;
if (buffer == nullptr) {
// This should not happen, but is not fatal
@@ -521,6 +523,10 @@
image->mLockedBuffer = nullptr;
image->mIsClosed = true;
+ if (!clearCache) {
+ return;
+ }
+
bool found = false;
// cleanup acquired image list
for (auto it = mAcquiredImages.begin();
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 78152d2..e328cb1 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -88,7 +88,7 @@
media_status_t acquireImageLocked(/*out*/AImage** image, /*out*/int* fenceFd);
// Called by AImage/~AImageReader to close image. Caller is responsible to grab AImage::mLock
- void releaseImageLocked(AImage* image, int releaseFenceFd);
+ void releaseImageLocked(AImage* image, int releaseFenceFd, bool clearCache = true);
static int getBufferWidth(BufferItem* buffer);
static int getBufferHeight(BufferItem* buffer);
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index f697bd1..8296598 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -448,6 +448,16 @@
meta->setBuffer(AMEDIAFORMAT_KEY_MPEG_USER_DATA, mpegUserData);
}
+ const void *audioPresentationsPointer;
+ size_t audioPresentationsLength;
+ if (sampleMeta->findData(
+ kKeyAudioPresentationInfo, &dataType,
+ &audioPresentationsPointer, &audioPresentationsLength)) {
+ sp<ABuffer> audioPresentationsData = ABuffer::CreateAsCopy(
+ audioPresentationsPointer, audioPresentationsLength);
+ meta->setBuffer(AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO, audioPresentationsData);
+ }
+
return AMEDIA_OK;
}
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 92d3aef..fcb706d 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -298,7 +298,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
-EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-encrypted-sizes";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-plain-sizes";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
index 74897f7..433b12f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionController.aidl
@@ -48,9 +48,9 @@
PendingIntent getLaunchPendingIntent();
long getFlags();
ParcelableVolumeInfo getVolumeAttributes();
- void adjustVolume(String packageName, ISessionControllerCallback caller,
+ void adjustVolume(String packageName, String opPackageName, ISessionControllerCallback caller,
boolean asSystemService, int direction, int flags);
- void setVolumeTo(String packageName, ISessionControllerCallback caller,
+ void setVolumeTo(String packageName, String opPackageName, ISessionControllerCallback caller,
int value, int flags);
// These commands are for the TransportControls
diff --git a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
index 3578c16..d6c226f 100644
--- a/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
+++ b/packages/MediaComponents/apex/java/android/media/session/ISessionManager.aidl
@@ -17,7 +17,6 @@
import android.content.ComponentName;
import android.media.IRemoteVolumeController;
-import android.media.ISessionTokensListener;
import android.media.session.IActiveSessionsListener;
import android.media.session.ICallback;
import android.media.session.IOnMediaKeyListener;
@@ -36,9 +35,10 @@
List<IBinder> getSessions(in ComponentName compName, int userId);
void dispatchMediaKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
boolean needWakeLock);
- void dispatchVolumeKeyEvent(String packageName, boolean asSystemService, in KeyEvent keyEvent,
- int stream, boolean musicOnly);
- void dispatchAdjustVolume(String packageName, int suggestedStream, int delta, int flags);
+ void dispatchVolumeKeyEvent(String packageName, String opPackageName, boolean asSystemService,
+ in KeyEvent keyEvent, int stream, boolean musicOnly);
+ void dispatchAdjustVolume(String packageName, String opPackageName, int suggestedStream,
+ int delta, int flags);
void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
int userId);
void removeSessionsListener(in IActiveSessionsListener listener);
@@ -55,12 +55,4 @@
// MediaSession2
boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
- boolean createSession2(in Bundle sessionToken);
- void destroySession2(in Bundle sessionToken);
- List<Bundle> getSessionTokens(boolean activeSessionOnly, boolean sessionServiceOnly,
- String packageName);
-
- void addSessionTokensListener(in ISessionTokensListener listener, int userId,
- String packageName);
- void removeSessionTokensListener(in ISessionTokensListener listener, String packageName);
}
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaController.java b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
index c060aaf..65682a8 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaController.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaController.java
@@ -153,7 +153,7 @@
return false;
}
try {
- return mSessionBinder.sendMediaButton(mContext.getOpPackageName(), mCbStub,
+ return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
asSystemService, keyEvent);
} catch (RemoteException e) {
// System is dead. =(
@@ -186,8 +186,9 @@
break;
}
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true,
- direction, AudioManager.FLAG_SHOW_UI);
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, direction,
+ AudioManager.FLAG_SHOW_UI);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -197,8 +198,8 @@
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY;
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, true, 0,
- flags);
+ mSessionBinder.adjustVolume(mContext.getPackageName(),
+ mContext.getOpPackageName(), mCbStub, true, 0, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy", e);
}
@@ -367,7 +368,8 @@
*/
public void setVolumeTo(int value, int flags) {
try {
- mSessionBinder.setVolumeTo(mContext.getOpPackageName(), mCbStub, value, flags);
+ mSessionBinder.setVolumeTo(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, value, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling setVolumeTo.", e);
}
@@ -388,8 +390,8 @@
*/
public void adjustVolume(int direction, int flags) {
try {
- mSessionBinder.adjustVolume(mContext.getOpPackageName(), mCbStub, false, direction,
- flags);
+ mSessionBinder.adjustVolume(mContext.getPackageName(), mContext.getOpPackageName(),
+ mCbStub, false, direction, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
@@ -455,7 +457,7 @@
throw new IllegalArgumentException("command cannot be null or empty");
}
try {
- mSessionBinder.sendCommand(mContext.getOpPackageName(), mCbStub, command, args, cb);
+ mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCommand.", e);
}
@@ -521,7 +523,7 @@
if (!mCbRegistered) {
try {
- mSessionBinder.registerCallbackListener(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
mCbRegistered = true;
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerCallback", e);
@@ -668,7 +670,7 @@
*/
public void prepare() {
try {
- mSessionBinder.prepare(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare.", e);
}
@@ -692,7 +694,7 @@
"You must specify a non-empty String for prepareFromMediaId.");
}
try {
- mSessionBinder.prepareFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
+ mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
@@ -719,7 +721,7 @@
query = "";
}
try {
- mSessionBinder.prepareFromSearch(mContext.getOpPackageName(), mCbStub, query,
+ mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
@@ -744,7 +746,7 @@
"You must specify a non-empty Uri for prepareFromUri.");
}
try {
- mSessionBinder.prepareFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
+ mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
}
@@ -755,7 +757,7 @@
*/
public void play() {
try {
- mSessionBinder.play(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.play(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play.", e);
}
@@ -774,7 +776,7 @@
"You must specify a non-empty String for playFromMediaId.");
}
try {
- mSessionBinder.playFromMediaId(mContext.getOpPackageName(), mCbStub, mediaId,
+ mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
@@ -797,7 +799,7 @@
query = "";
}
try {
- mSessionBinder.playFromSearch(mContext.getOpPackageName(), mCbStub, query, extras);
+ mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + query + ").", e);
}
@@ -816,7 +818,7 @@
"You must specify a non-empty Uri for playFromUri.");
}
try {
- mSessionBinder.playFromUri(mContext.getOpPackageName(), mCbStub, uri, extras);
+ mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling play(" + uri + ").", e);
}
@@ -828,7 +830,7 @@
*/
public void skipToQueueItem(long id) {
try {
- mSessionBinder.skipToQueueItem(mContext.getOpPackageName(), mCbStub, id);
+ mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
}
@@ -840,7 +842,7 @@
*/
public void pause() {
try {
- mSessionBinder.pause(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.pause(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling pause.", e);
}
@@ -852,7 +854,7 @@
*/
public void stop() {
try {
- mSessionBinder.stop(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.stop(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling stop.", e);
}
@@ -865,7 +867,7 @@
*/
public void seekTo(long pos) {
try {
- mSessionBinder.seekTo(mContext.getOpPackageName(), mCbStub, pos);
+ mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling seekTo.", e);
}
@@ -877,7 +879,7 @@
*/
public void fastForward() {
try {
- mSessionBinder.fastForward(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling fastForward.", e);
}
@@ -888,7 +890,7 @@
*/
public void skipToNext() {
try {
- mSessionBinder.next(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.next(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling next.", e);
}
@@ -900,7 +902,7 @@
*/
public void rewind() {
try {
- mSessionBinder.rewind(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rewind.", e);
}
@@ -911,7 +913,7 @@
*/
public void skipToPrevious() {
try {
- mSessionBinder.previous(mContext.getOpPackageName(), mCbStub);
+ mSessionBinder.previous(mContext.getPackageName(), mCbStub);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling previous.", e);
}
@@ -926,7 +928,7 @@
*/
public void setRating(Rating rating) {
try {
- mSessionBinder.rate(mContext.getOpPackageName(), mCbStub, rating);
+ mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling rate.", e);
}
@@ -961,7 +963,7 @@
throw new IllegalArgumentException("CustomAction cannot be null.");
}
try {
- mSessionBinder.sendCustomAction(mContext.getOpPackageName(), mCbStub, action, args);
+ mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
} catch (RemoteException e) {
Log.d(TAG, "Dead object in sendCustomAction.", e);
}
@@ -1140,8 +1142,7 @@
private boolean mRegistered = false;
public MessageHandler(Looper looper, MediaController.Callback cb) {
- //TODO:(b/119539849) Uncomment below line and resolve the error.
- // super(looper, null, true);
+ super(looper);
mCallback = cb;
}
@@ -1180,6 +1181,7 @@
public void post(int what, Object obj, Bundle data) {
Message msg = obtainMessage(what, obj);
+ msg.setAsynchronous(true);
msg.setData(data);
msg.sendToTarget();
}
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index 943843d..73e16a6 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -1458,8 +1458,7 @@
private RemoteUserInfo mCurrentControllerInfo;
public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
- //TODO:(b/119539849) Uncomment below line and resolve the error.
- //super(looper, null, true);
+ super(looper);
mCallback = callback;
mCallback.mHandler = this;
}
@@ -1467,6 +1466,7 @@
public void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) {
Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj);
Message msg = obtainMessage(what, objWithCaller);
+ msg.setAsynchronous(true);
msg.setData(data);
if (delayMs > 0) {
sendMessageDelayed(msg, delayMs);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 26f76c0..0d6ef46 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2379,7 +2379,8 @@
return BAD_VALUE;
}
- sp<ThreadBase> thread = openInput_l(module, input, config, *devices, address, source, flags);
+ sp<ThreadBase> thread = openInput_l(
+ module, input, config, *devices, address, source, flags, AUDIO_DEVICE_NONE, String8{});
if (thread != 0) {
// notify client processes of the new input creation
@@ -2395,7 +2396,9 @@
audio_devices_t devices,
const String8& address,
audio_source_t source,
- audio_input_flags_t flags)
+ audio_input_flags_t flags,
+ audio_devices_t outputDevice,
+ const String8& outputDeviceAddress)
{
AudioHwDevice *inHwDev = findSuitableHwDev_l(module, devices);
if (inHwDev == NULL) {
@@ -2424,7 +2427,8 @@
sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
sp<StreamInHalInterface> inStream;
status_t status = inHwHal->openInputStream(
- *input, devices, &halconfig, flags, address.string(), source, &inStream);
+ *input, devices, &halconfig, flags, address.string(), source,
+ outputDevice, outputDeviceAddress, &inStream);
ALOGV("openInput_l() openInputStream returned input %p, devices %#x, SamplingRate %d"
", Format %#x, Channels %#x, flags %#x, status %d addr %s",
inStream.get(),
@@ -2447,7 +2451,8 @@
ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
inStream.clear();
status = inHwHal->openInputStream(
- *input, devices, &halconfig, flags, address.string(), source, &inStream);
+ *input, devices, &halconfig, flags, address.string(), source,
+ outputDevice, outputDeviceAddress, &inStream);
// FIXME log this new status; HAL should not propose any further changes
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6c698f6..c1169d2 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -579,6 +579,10 @@
virtual binder::Status stop();
virtual binder::Status getActiveMicrophones(
std::vector<media::MicrophoneInfo>* activeMicrophones);
+ virtual binder::Status setMicrophoneDirection(
+ int /*audio_microphone_direction_t*/ direction);
+ virtual binder::Status setMicrophoneFieldDimension(float zoom);
+
private:
const sp<RecordThread::RecordTrack> mRecordTrack;
@@ -620,7 +624,9 @@
audio_devices_t device,
const String8& address,
audio_source_t source,
- audio_input_flags_t flags);
+ audio_input_flags_t flags,
+ audio_devices_t outputDevice,
+ const String8& outputDeviceAddress);
sp<ThreadBase> openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 538a0eb..3381e4d 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -211,6 +211,8 @@
((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) &&
((patch->sinks[0].ext.device.hw_module != srcModule) ||
!audioHwDevice->supportsAudioPatches()))) {
+ audio_devices_t outputDevice = AUDIO_DEVICE_NONE;
+ String8 outputDeviceAddress;
if (patch->num_sources == 2) {
if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX ||
(patch->num_sinks != 0 && patch->sinks[0].ext.device.hw_module !=
@@ -261,6 +263,8 @@
goto exit;
}
newPatch.mPlayback.setThread(reinterpret_cast<PlaybackThread*>(thread.get()));
+ outputDevice = device;
+ outputDeviceAddress = address;
}
audio_devices_t device = patch->sources[0].ext.device.type;
String8 address = String8(patch->sources[0].ext.device.address);
@@ -293,7 +297,9 @@
device,
address,
AUDIO_SOURCE_MIC,
- flags);
+ flags,
+ outputDevice,
+ outputDeviceAddress);
ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x",
thread.get(), config.channel_mask);
if (thread == 0) {
@@ -322,6 +328,13 @@
}
}
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+ // remove stale audio patch with same input as sink if any
+ for (auto& iter : mPatches) {
+ if (iter.second.mAudioPatch.sinks[0].ext.mix.handle == thread->id()) {
+ mPatches.erase(iter.first);
+ break;
+ }
+ }
} else {
sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
status = hwDevice->createAudioPatch(patch->num_sources,
@@ -376,6 +389,14 @@
}
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
+
+ // remove stale audio patch with same output as source if any
+ for (auto& iter : mPatches) {
+ if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id()) {
+ mPatches.erase(iter.first);
+ break;
+ }
+ }
} break;
default:
status = BAD_VALUE;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 85f5456..32af7d5 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -71,6 +71,9 @@
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setMicrophoneFieldDimension(float zoom);
+
static bool checkServerLatencySupported(
audio_format_t format, audio_input_flags_t flags) {
return audio_is_linear_pcm(format)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c6941c0..31a8c7d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -494,6 +494,8 @@
case AUDIO_SOURCE_VOICE_COMMUNICATION: return "voice communication";
case AUDIO_SOURCE_REMOTE_SUBMIX: return "remote submix";
case AUDIO_SOURCE_UNPROCESSED: return "unprocessed";
+ case AUDIO_SOURCE_VOICE_PERFORMANCE: return "voice performance";
+ case AUDIO_SOURCE_ECHO_REFERENCE: return "echo reference";
case AUDIO_SOURCE_FM_TUNER: return "FM tuner";
case AUDIO_SOURCE_HOTWORD: return "hotword";
default: return "unknown";
@@ -3850,6 +3852,7 @@
type |= patch->sinks[i].ext.device.type;
}
+ audio_port_handle_t sinkPortId = patch->sinks[0].id;
#ifdef ADD_BATTERY_DATA
// when changing the audio output device, call addBatteryData to notify
// the change
@@ -3879,7 +3882,7 @@
// mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
// the thread is created so that the first patch creation triggers an ioConfigChanged callback
- bool configChanged = mPrevOutDevice != type;
+ bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
mOutDevice = type;
mPatch = *patch;
@@ -3908,6 +3911,7 @@
}
if (configChanged) {
mPrevOutDevice = type;
+ mDeviceId = sinkPortId;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
return status;
@@ -7578,6 +7582,20 @@
return status;
}
+status_t AudioFlinger::RecordThread::setMicrophoneDirection(audio_microphone_direction_t direction)
+{
+ ALOGV("RecordThread::setMicrophoneDirection");
+ AutoMutex _l(mLock);
+ return mInput->stream->setMicrophoneDirection(direction);
+}
+
+status_t AudioFlinger::RecordThread::setMicrophoneFieldDimension(float zoom)
+{
+ ALOGV("RecordThread::setMicrophoneFieldDimension");
+ AutoMutex _l(mLock);
+ return mInput->stream->setMicrophoneFieldDimension(zoom);
+}
+
void AudioFlinger::RecordThread::updateMetadata_l()
{
if (mInput == nullptr || mInput->stream == nullptr ||
@@ -8145,6 +8163,7 @@
// store new device and send to effects
mInDevice = patch->sources[0].ext.device.type;
+ audio_port_handle_t deviceId = patch->sources[0].id;
mPatch = *patch;
for (size_t i = 0; i < mEffectChains.size(); i++) {
mEffectChains[i]->setDevice_l(mInDevice);
@@ -8186,9 +8205,10 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (mInDevice != mPrevInDevice) {
+ if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
mPrevInDevice = mInDevice;
+ mDeviceId = deviceId;
}
return status;
@@ -8285,7 +8305,7 @@
audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
: ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
mSessionId(AUDIO_SESSION_NONE),
- mDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE),
+ mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
mActiveTracks(&this->mLocalLog),
mHalVolFloat(-1.0f), // Initialize to illegal value so it always gets set properly later.
@@ -8769,7 +8789,7 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (isOutput() && mPrevOutDevice != mOutDevice) {
+ if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
mPrevOutDevice = type;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
@@ -8780,7 +8800,7 @@
}
mDeviceId = deviceId;
}
- if (!isOutput() && mPrevInDevice != mInDevice) {
+ if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
mPrevInDevice = type;
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e8b2158..aab7601 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -485,6 +485,10 @@
audio_devices_t mPrevOutDevice; // previous output device
audio_devices_t mPrevInDevice; // previous input device
struct audio_patch mPatch;
+ /**
+ * @brief mDeviceId current device port unique identifier
+ */
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_source_t mAudioSource;
const audio_io_handle_t mId;
@@ -1541,6 +1545,9 @@
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+ status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+ status_t setMicrophoneFieldDimension(float zoom);
+
void updateMetadata_l() override;
bool fastTrackAvailable() const { return mFastTrackAvail; }
@@ -1704,7 +1711,6 @@
audio_attributes_t mAttr;
audio_session_t mSessionId;
- audio_port_handle_t mDeviceId;
audio_port_handle_t mPortId;
wp<MmapStreamCallback> mCallback;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9a7f1f1..d23d19d 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1710,6 +1710,18 @@
mRecordTrack->getActiveMicrophones(activeMicrophones));
}
+binder::Status AudioFlinger::RecordHandle::setMicrophoneDirection(
+ int /*audio_microphone_direction_t*/ direction) {
+ ALOGV("%s()", __func__);
+ return binder::Status::fromStatusT(mRecordTrack->setMicrophoneDirection(
+ static_cast<audio_microphone_direction_t>(direction)));
+}
+
+binder::Status AudioFlinger::RecordHandle::setMicrophoneFieldDimension(float zoom) {
+ ALOGV("%s()", __func__);
+ return binder::Status::fromStatusT(mRecordTrack->setMicrophoneFieldDimension(zoom));
+}
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::RecordTrack"
@@ -2004,6 +2016,27 @@
}
}
+status_t AudioFlinger::RecordThread::RecordTrack::setMicrophoneDirection(
+ audio_microphone_direction_t direction) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ RecordThread *recordThread = (RecordThread *)thread.get();
+ return recordThread->setMicrophoneDirection(direction);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioFlinger::RecordThread::RecordTrack::setMicrophoneFieldDimension(float zoom) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ RecordThread *recordThread = (RecordThread *)thread.get();
+ return recordThread->setMicrophoneFieldDimension(zoom);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
// ----------------------------------------------------------------------------
#undef LOG_TAG
#define LOG_TAG "AF::PatchRecord"
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index bfa1b5e..ebb4f3b 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -51,6 +51,7 @@
libcutils \
libutils \
liblog \
+ libaudioclient \
libsoundtrigger
ifeq ($(USE_CONFIGURABLE_AUDIO_POLICY), 1)
@@ -85,7 +86,7 @@
LOCAL_SHARED_LIBRARIES += libmedia_helper
LOCAL_SHARED_LIBRARIES += libmediametrics
-LOCAL_SHARED_LIBRARIES += libhidlbase libicuuc libxml2
+LOCAL_SHARED_LIBRARIES += libhidlbase libxml2
ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index ad12a90..1c2b9d7 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -210,6 +210,10 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
+ = 0;
+ virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId,
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
new file mode 100644
index 0000000..a94fd87
--- /dev/null
+++ b/services/audiopolicy/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "audiopolicy_tests"
+ },
+ {
+ "name": "systemaudio_tests"
+ }
+ ]
+}
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 30b0044..46a2a40 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -83,7 +83,10 @@
* @param[in] inputSource to consider. Valid sources are:
* - AUDIO_SOURCE_VOICE_COMMUNICATION
* - AUDIO_SOURCE_CAMCORDER
+ * - AUDIO_SOURCE_VOICE_PERFORMANCE
+ * - AUDIO_SOURCE_UNPROCESSED
* - AUDIO_SOURCE_MIC
+ * - AUDIO_SOURCE_ECHO_REFERENCE
* - AUDIO_SOURCE_FM_TUNER
* - AUDIO_SOURCE_VOICE_RECOGNITION
* - AUDIO_SOURCE_HOTWORD
@@ -96,10 +99,16 @@
{
switch (inputSource) {
case AUDIO_SOURCE_VOICE_COMMUNICATION:
- return 6;
+ return 9;
case AUDIO_SOURCE_CAMCORDER:
- return 5;
+ return 8;
+ case AUDIO_SOURCE_VOICE_PERFORMANCE:
+ return 7;
+ case AUDIO_SOURCE_UNPROCESSED:
+ return 6;
case AUDIO_SOURCE_MIC:
+ return 5;
+ case AUDIO_SOURCE_ECHO_REFERENCE:
return 4;
case AUDIO_SOURCE_FM_TUNER:
return 3;
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index d0b4973..e5ebab7 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -24,7 +24,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libicuuc",
"liblog",
"libmedia",
"libutils",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index fa9ba0b..d4cfd1e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -23,11 +23,12 @@
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
+#include "DeviceDescriptor.h"
#include "EffectDescriptor.h"
+#include "IOProfile.h"
namespace android {
-class IOProfile;
class AudioMix;
class AudioPolicyClientInterface;
@@ -42,10 +43,16 @@
audio_port_handle_t getId() const;
audio_module_handle_t getModuleHandle() const;
+ audio_devices_t getDeviceType() const { return (mDevice != nullptr) ?
+ mDevice->type() : AUDIO_DEVICE_NONE; }
+ sp<DeviceDescriptor> getDevice() const { return mDevice; }
+ void setDevice(const sp<DeviceDescriptor> &device) { mDevice = device; }
+ DeviceVector supportedDevices() const {
+ return mProfile != nullptr ? mProfile->getSupportedDevices() : DeviceVector(); }
+
void dump(String8 *dst) const override;
audio_io_handle_t mIoHandle = AUDIO_IO_HANDLE_NONE; // input handle
- audio_devices_t mDevice = AUDIO_DEVICE_NONE; // current device this input is routed to
AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
const sp<IOProfile> mProfile; // I/O profile this output derives from
@@ -61,6 +68,7 @@
bool isSourceActive(audio_source_t source) const;
audio_source_t source() const;
bool isSoundTrigger() const;
+ audio_attributes_t getHighestPriorityAttributes() const;
void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
int32_t activeCount() { return mGlobalActiveCount; }
void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
@@ -71,8 +79,7 @@
void setPatchHandle(audio_patch_handle_t handle) override;
status_t open(const audio_config_t *config,
- audio_devices_t device,
- const String8& address,
+ const sp<DeviceDescriptor> &device,
audio_source_t source,
audio_input_flags_t flags,
audio_io_handle_t *input);
@@ -99,6 +106,8 @@
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
+ sp<DeviceDescriptor> mDevice = nullptr; /**< current device this input is routed to */
+
// Because a preemptible capture session can preempt another one, we end up in an endless loop
// situation were each session is allowed to restart after being preempted,
// thus preempting the other one which restarts and so on.
@@ -120,8 +129,8 @@
sp<AudioInputDescriptor> getInputFromId(audio_port_handle_t id) const;
// count active capture sessions using one of the specified devices.
- // ignore devices if AUDIO_DEVICE_IN_DEFAULT is passed
- uint32_t activeInputsCountOnDevices(audio_devices_t devices = AUDIO_DEVICE_IN_DEFAULT) const;
+ // ignore devices if empty vector is passed
+ uint32_t activeInputsCountOnDevices(const DeviceVector &devices) const;
/**
* return io handle of active input or 0 if no input is active
@@ -130,8 +139,6 @@
*/
Vector<sp <AudioInputDescriptor> > getActiveInputs();
- audio_devices_t getSupportedDevices(audio_io_handle_t handle) const;
-
sp<AudioInputDescriptor> getInputForClient(audio_port_handle_t portId);
void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index ed995e0..14b995b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -26,13 +26,14 @@
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
+#include "DeviceDescriptor.h"
+#include <map>
namespace android {
class IOProfile;
class AudioMix;
class AudioPolicyClientInterface;
-class DeviceDescriptor;
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
@@ -48,14 +49,12 @@
void log(const char* indent);
audio_port_handle_t getId() const;
- virtual audio_devices_t device() const;
- virtual bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
- virtual audio_devices_t supportedDevices();
+ virtual DeviceVector devices() const { return mDevices; }
+ bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
+ virtual DeviceVector supportedDevices() const { return mDevices; }
virtual bool isDuplicated() const { return false; }
virtual uint32_t latency() { return 0; }
virtual bool isFixedVolume(audio_devices_t device);
- virtual sp<AudioOutputDescriptor> subOutput1() { return 0; }
- virtual sp<AudioOutputDescriptor> subOutput2() { return 0; }
virtual bool setVolume(float volume,
audio_stream_type_t stream,
audio_devices_t device,
@@ -119,7 +118,7 @@
return mActiveClients;
}
- audio_devices_t mDevice = AUDIO_DEVICE_NONE; // current device this output is routed to
+ DeviceVector mDevices; /**< current devices this output is routed to */
nsecs_t mStopTime[AUDIO_STREAM_CNT];
int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
@@ -151,14 +150,15 @@
virtual ~SwAudioOutputDescriptor() {}
void dump(String8 *dst) const override;
- virtual audio_devices_t device() const;
- virtual bool sharesHwModuleWith(const sp<AudioOutputDescriptor>& outputDesc);
- virtual audio_devices_t supportedDevices();
+ virtual DeviceVector devices() const;
+ void setDevices(const DeviceVector &devices) { mDevices = devices; }
+ bool sharesHwModuleWith(const sp<SwAudioOutputDescriptor>& outputDesc);
+ virtual DeviceVector supportedDevices() const;
virtual uint32_t latency();
virtual bool isDuplicated() const { return (mOutput1 != NULL && mOutput2 != NULL); }
virtual bool isFixedVolume(audio_devices_t device);
- virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; }
- virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; }
+ sp<SwAudioOutputDescriptor> subOutput1() { return mOutput1; }
+ sp<SwAudioOutputDescriptor> subOutput2() { return mOutput2; }
void changeStreamActiveCount(
const sp<TrackClientDescriptor>& client, int delta) override;
virtual bool setVolume(float volume,
@@ -171,22 +171,49 @@
const struct audio_port_config *srcConfig = NULL) const;
virtual void toAudioPort(struct audio_port *port) const;
- status_t open(const audio_config_t *config,
- audio_devices_t device,
- const String8& address,
- audio_stream_type_t stream,
- audio_output_flags_t flags,
- audio_io_handle_t *output);
- // Called when a stream is about to be started
- // Note: called before setClientActive(true);
- status_t start();
- // Called after a stream is stopped.
- // Note: called after setClientActive(false);
- void stop();
- void close();
- status_t openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
- const sp<SwAudioOutputDescriptor>& output2,
- audio_io_handle_t *ioHandle);
+ status_t open(const audio_config_t *config,
+ const DeviceVector &devices,
+ audio_stream_type_t stream,
+ audio_output_flags_t flags,
+ audio_io_handle_t *output);
+
+ // Called when a stream is about to be started
+ // Note: called before setClientActive(true);
+ status_t start();
+ // Called after a stream is stopped.
+ // Note: called after setClientActive(false);
+ void stop();
+ void close();
+ status_t openDuplicating(const sp<SwAudioOutputDescriptor>& output1,
+ const sp<SwAudioOutputDescriptor>& output2,
+ audio_io_handle_t *ioHandle);
+
+ /**
+ * @brief supportsDevice
+ * @param device to be checked against
+ * @return true if the device is supported by type (for non bus / remote submix devices),
+ * true if the device is supported (both type and address) for bus / remote submix
+ * false otherwise
+ */
+ bool supportsDevice(const sp<DeviceDescriptor> &device) const;
+
+ /**
+ * @brief supportsAllDevices
+ * @param devices to be checked against
+ * @return true if the device is weakly supported by type (e.g. for non bus / rsubmix devices),
+ * true if the device is supported (both type and address) for bus / remote submix
+ * false otherwise
+ */
+ bool supportsAllDevices(const DeviceVector &devices) const;
+
+ /**
+ * @brief filterSupportedDevices takes a vector of devices and filters them according to the
+ * device supported by this output (the profile from which this output derives from)
+ * @param devices reference device vector to be filtered
+ * @return vector of devices filtered from the supported devices of this output (weakly or not
+ * depending on the device type)
+ */
+ DeviceVector filterSupportedDevices(const DeviceVector &devices) const;
const sp<IOProfile> mProfile; // I/O profile this output derives from
audio_io_handle_t mIoHandle; // output handle
@@ -208,7 +235,6 @@
void dump(String8 *dst) const override;
- virtual audio_devices_t supportedDevices();
virtual bool setVolume(float volume,
audio_stream_type_t stream,
audio_devices_t device,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 5099ebb..d52eb3d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -133,18 +133,14 @@
mDefaultOutputDevice->attach(module);
defaultInputDevice->attach(module);
- sp<OutputProfile> outProfile;
- outProfile = new OutputProfile(String8("primary"));
- outProfile->attach(module);
+ sp<OutputProfile> outProfile = new OutputProfile(String8("primary"));
outProfile->addAudioProfile(
new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
outProfile->addSupportedDevice(mDefaultOutputDevice);
outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
module->addOutputProfile(outProfile);
- sp<InputProfile> inProfile;
- inProfile = new InputProfile(String8("primary"));
- inProfile->attach(module);
+ sp<InputProfile> inProfile = new InputProfile(String8("primary"));
inProfile->addAudioProfile(micProfile);
inProfile->addSupportedDevice(defaultInputDevice);
module->addInputProfile(inProfile);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 96c00ea..e6a62d9 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -16,6 +16,7 @@
#pragma once
+#include "DeviceDescriptor.h"
#include <utils/RefBase.h>
#include <media/AudioPolicy.h>
#include <utils/KeyedVector.h>
@@ -74,12 +75,16 @@
status_t getOutputForAttr(audio_attributes_t attributes, uid_t uid,
sp<SwAudioOutputDescriptor> &desc);
- audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource,
- audio_devices_t availableDeviceTypes,
- AudioMix **policyMix);
+ sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
+ const DeviceVector &availableDeviceTypes,
+ AudioMix **policyMix);
status_t getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix);
+ status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+ status_t removeUidDeviceAffinities(uid_t uid);
+ status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
+
void dump(String8 *dst) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index bb9cad8..1b5a2d6 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -65,6 +65,7 @@
uint32_t getFlags() const { return mFlags; }
virtual void attach(const sp<HwModule>& module);
+ virtual void detach();
bool isAttached() { return mModule != 0; }
// Audio port IDs are in a different namespace than AudioFlinger unique IDs
@@ -161,7 +162,7 @@
const struct audio_port_config *srcConfig = NULL) const = 0;
virtual sp<AudioPort> getAudioPort() const = 0;
virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
- return (other != 0) &&
+ return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
(other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
}
unsigned int mSamplingRate = 0u;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index d02123c..b581665 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -53,6 +53,8 @@
// AudioPort
virtual void attach(const sp<HwModule>& module);
+ virtual void detach();
+
virtual void toAudioPort(struct audio_port *port) const;
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
@@ -164,6 +166,23 @@
return !operator==(right);
}
+ /**
+ * @brief getFirstValidAddress
+ * @return the first valid address of a list of device, "" if no device with valid address
+ * found.
+ * This helper function helps maintaining compatibility with legacy where we used to have a
+ * devices mask and an address.
+ */
+ String8 getFirstValidAddress() const
+ {
+ for (const auto &device : *this) {
+ if (device->address() != "") {
+ return device->address();
+ }
+ }
+ return String8("");
+ }
+
std::string toString() const;
void dump(String8 *dst, const String8 &tag, int spaces = 0, bool verbose = true) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 2b57fa9..d7dc4b0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -46,6 +46,22 @@
const DeviceVector &getDeclaredDevices() const { return mDeclaredDevices; }
void setDeclaredDevices(const DeviceVector &devices);
+ DeviceVector getAllDevices() const
+ {
+ DeviceVector devices = mDeclaredDevices;
+ devices.merge(mDynamicDevices);
+ return devices;
+ }
+ void addDynamicDevice(const sp<DeviceDescriptor> &device)
+ {
+ mDynamicDevices.add(device);
+ }
+
+ bool removeDynamicDevice(const sp<DeviceDescriptor> &device)
+ {
+ return mDynamicDevices.remove(device) >= 0;
+ }
+ DeviceVector getDynamicDevices() const { return mDynamicDevices; }
const InputProfileCollection &getInputProfiles() const { return mInputProfiles; }
const OutputProfileCollection &getOutputProfiles() const { return mOutputProfiles; }
@@ -104,6 +120,7 @@
InputProfileCollection mInputProfiles; // input profiles exposed by this module
uint32_t mHalVersion; // audio HAL API version
DeviceVector mDeclaredDevices; // devices declared in audio_policy configuration file.
+ DeviceVector mDynamicDevices; /**< devices that can be added/removed at runtime (e.g. rsbumix)*/
AudioRouteVector mRoutes;
AudioPortVector mPorts;
};
@@ -113,13 +130,58 @@
public:
sp<HwModule> getModuleFromName(const char *name) const;
- sp<HwModule> getModuleForDevice(audio_devices_t device) const;
+ sp<HwModule> getModuleForDeviceTypes(audio_devices_t device) const;
- sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t device,
- const char *device_address,
- const char *device_name,
+ sp<HwModule> getModuleForDevice(const sp<DeviceDescriptor> &device) const;
+
+ DeviceVector getAvailableDevicesFromModuleName(const char *name,
+ const DeviceVector &availableDevices) const;
+
+ /**
+ * @brief getDeviceDescriptor returns a device descriptor associated to the device type and
+ * device address (if matchAddress is true).
+ * It may loop twice on all modules to check if allowToCreate is true
+ * -first loop will check if the device is found on a module since declared in the list
+ * of device port in configuration file
+ * -(allowToCreate is true)second loop will check if the device is weakly supported by one
+ * or more profiles on a given module and will add as a supported device for this module.
+ * The device will also be added to the dynamic list of device of this module
+ * @param type of the device requested
+ * @param address of the device requested
+ * @param name of the device that requested
+ * @param matchAddress true if a strong match is required
+ * @param allowToCreate true if allowed to create dynamic device (e.g. hdmi, usb...)
+ * @return device descriptor associated to the type (and address if matchAddress is true)
+ */
+ sp<DeviceDescriptor> getDeviceDescriptor(const audio_devices_t type,
+ const char *address,
+ const char *name,
+ bool allowToCreate = false,
bool matchAddress = true) const;
+ /**
+ * @brief createDevice creates a new device from the type and address given. It checks that
+ * according to the device type, a module is supporting this device (weak check).
+ * This concerns only dynamic device, aka device with a specific address and not
+ * already supported by module/underlying profiles.
+ * @param type of the device to be created
+ * @param address of the device to be created
+ * @param name of the device to be created
+ * @return device descriptor if a module is supporting this type, nullptr otherwise.
+ */
+ sp<DeviceDescriptor> createDevice(const audio_devices_t type,
+ const char *address,
+ const char *name) const;
+
+ /**
+ * @brief cleanUpForDevice: loop on all profiles of all modules to remove device from
+ * the list of supported device. If this device is a dynamic device (aka a device not in the
+ * xml file with a runtime address), it is also removed from the module collection of dynamic
+ * devices.
+ * @param device that has been disconnected
+ */
+ void cleanUpForDevice(const sp<DeviceDescriptor> &device);
+
void dump(String8 *dst) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index ca6ca56..d0c05a5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -57,12 +57,25 @@
}
}
- // This method is used for input and direct output, and is not used for other output.
- // If parameter updatedSamplingRate is non-NULL, it is assigned the actual sample rate.
- // For input, flags is interpreted as audio_input_flags_t.
- // TODO: merge audio_output_flags_t and audio_input_flags_t.
- bool isCompatibleProfile(audio_devices_t device,
- const String8& address,
+ /**
+ * @brief isCompatibleProfile: This method is used for input and direct output,
+ * and is not used for other output.
+ * Checks if the IO profile is compatible with specified parameters.
+ * For input, flags is interpreted as audio_input_flags_t.
+ * TODO: merge audio_output_flags_t and audio_input_flags_t.
+ *
+ * @param devices vector of devices to be checked for compatibility
+ * @param samplingRate to be checked for compatibility. Must be specified
+ * @param updatedSamplingRate if non-NULL, it is assigned the actual sample rate.
+ * @param format to be checked for compatibility. Must be specified
+ * @param updatedFormat if non-NULL, it is assigned the actual format
+ * @param channelMask to be checked for compatibility. Must be specified
+ * @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
+ * @param flags to be checked for compatibility
+ * @param exactMatchRequiredForInputFlags true if exact match is required on flags
+ * @return true if the profile is compatible, false otherwise.
+ */
+ bool isCompatibleProfile(const DeviceVector &devices,
uint32_t samplingRate,
uint32_t *updatedSamplingRate,
audio_format_t format,
@@ -78,7 +91,7 @@
bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
- bool supportDevice(audio_devices_t device) const
+ bool supportsDeviceTypes(audio_devices_t device) const
{
if (audio_is_output_devices(device)) {
return mSupportedDevices.types() & device;
@@ -86,41 +99,37 @@
return mSupportedDevices.types() & (device & ~AUDIO_DEVICE_BIT_IN);
}
- bool supportDeviceAddress(const String8 &address) const
+ /**
+ * @brief supportsDevice
+ * @param device to be checked against
+ * forceCheckOnAddress if true, check on type and address whatever the type, otherwise
+ * the address enforcement is limited to "offical devices" that distinguishe on address
+ * @return true if the device is supported by type (for non bus / remote submix devices),
+ * true if the device is supported (both type and address) for bus / remote submix
+ * false otherwise
+ */
+ bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
{
- return mSupportedDevices[0]->address() == address;
- }
-
- // chose first device present in mSupportedDevices also part of deviceType
- audio_devices_t getSupportedDeviceForType(audio_devices_t deviceType) const
- {
- for (size_t k = 0; k < mSupportedDevices.size(); k++) {
- audio_devices_t profileType = mSupportedDevices[k]->type();
- if (profileType & deviceType) {
- return profileType;
- }
+ if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
+ return supportsDeviceTypes(device->type());
}
- return AUDIO_DEVICE_NONE;
+ return mSupportedDevices.contains(device);
}
- audio_devices_t getSupportedDevicesType() const { return mSupportedDevices.types(); }
-
void clearSupportedDevices() { mSupportedDevices.clear(); }
void addSupportedDevice(const sp<DeviceDescriptor> &device)
{
mSupportedDevices.add(device);
}
-
+ void removeSupportedDevice(const sp<DeviceDescriptor> &device)
+ {
+ mSupportedDevices.remove(device);
+ }
void setSupportedDevices(const DeviceVector &devices)
{
mSupportedDevices = devices;
}
- sp<DeviceDescriptor> getSupportedDeviceByAddress(audio_devices_t type, String8 address) const
- {
- return mSupportedDevices.getDevice(type, address);
- }
-
const DeviceVector &getSupportedDevices() const { return mSupportedDevices; }
bool canOpenNewIo() {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 0bc88a5..55d4db4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -21,7 +21,6 @@
#include <policy.h>
#include <AudioPolicyInterface.h>
#include "AudioInputDescriptor.h"
-#include "IOProfile.h"
#include "AudioGain.h"
#include "HwModule.h"
@@ -55,30 +54,7 @@
audio_source_t AudioInputDescriptor::source() const
{
- audio_source_t source = AUDIO_SOURCE_DEFAULT;
-
- for (bool activeOnly : { true, false }) {
- int32_t topPriority = -1;
- app_state_t topState = APP_STATE_IDLE;
- for (const auto &client : getClientIterable()) {
- if (activeOnly && !client->active()) {
- continue;
- }
- app_state_t curState = client->appState();
- if (curState >= topState) {
- int32_t curPriority = source_priority(client->source());
- if (curPriority > topPriority) {
- source = client->source();
- topPriority = curPriority;
- }
- topState = curState;
- }
- }
- if (source != AUDIO_SOURCE_DEFAULT) {
- break;
- }
- }
- return source;
+ return getHighestPriorityAttributes().source;
}
void AudioInputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -148,6 +124,34 @@
return false;
}
+audio_attributes_t AudioInputDescriptor::getHighestPriorityAttributes() const
+{
+ audio_attributes_t attributes = { .source = AUDIO_SOURCE_DEFAULT };
+
+ for (bool activeOnly : { true, false }) {
+ int32_t topPriority = -1;
+ app_state_t topState = APP_STATE_IDLE;
+ for (const auto &client : getClientIterable()) {
+ if (activeOnly && !client->active()) {
+ continue;
+ }
+ app_state_t curState = client->appState();
+ if (curState >= topState) {
+ int32_t curPriority = source_priority(client->source());
+ if (curPriority > topPriority) {
+ attributes = client->attributes();
+ topPriority = curPriority;
+ }
+ topState = curState;
+ }
+ }
+ if (attributes.source != AUDIO_SOURCE_DEFAULT) {
+ break;
+ }
+ }
+ return attributes;
+}
+
bool AudioInputDescriptor::isSoundTrigger() const {
// sound trigger and non sound trigger clients are not mixed on a given input
// so check only first client
@@ -180,8 +184,7 @@
}
status_t AudioInputDescriptor::open(const audio_config_t *config,
- audio_devices_t device,
- const String8& address,
+ const sp<DeviceDescriptor> &device,
audio_source_t source,
audio_input_flags_t flags,
audio_io_handle_t *input)
@@ -198,24 +201,26 @@
mDevice = device;
- ALOGV("opening input for device %08x address %s profile %p name %s",
- mDevice, address.string(), mProfile.get(), mProfile->getName().string());
+ ALOGV("opening input for device %s profile %p name %s",
+ mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string());
+
+ audio_devices_t deviceType = mDevice->type();
status_t status = mClientInterface->openInput(mProfile->getModuleHandle(),
input,
&lConfig,
- &mDevice,
- address,
+ &deviceType,
+ mDevice->address(),
source,
flags);
- LOG_ALWAYS_FATAL_IF(mDevice != device,
+ LOG_ALWAYS_FATAL_IF(mDevice->type() != deviceType,
"%s openInput returned device %08x when given device %08x",
- __FUNCTION__, mDevice, device);
+ __FUNCTION__, mDevice->type(), deviceType);
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*input == AUDIO_IO_HANDLE_NONE,
- "%s openInput returned input handle %d for device %08x",
- __FUNCTION__, *input, device);
+ "%s openInput returned input handle %d for device %s",
+ __FUNCTION__, *input, mDevice->toString().c_str());
mSamplingRate = lConfig.sample_rate;
mChannelMask = lConfig.channel_mask;
mFormat = lConfig.format;
@@ -423,7 +428,7 @@
dst->appendFormat(" Sampling rate: %d\n", mSamplingRate);
dst->appendFormat(" Format: %d\n", mFormat);
dst->appendFormat(" Channels: %08x\n", mChannelMask);
- dst->appendFormat(" Devices %08x\n", mDevice);
+ dst->appendFormat(" Devices %s\n", mDevice->toString().c_str());
getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
dst->append(" AudioRecord Clients:\n");
ClientMapHandler<RecordClientDescriptor>::dump(dst);
@@ -452,14 +457,13 @@
return NULL;
}
-uint32_t AudioInputCollection::activeInputsCountOnDevices(audio_devices_t devices) const
+uint32_t AudioInputCollection::activeInputsCountOnDevices(const DeviceVector &devices) const
{
uint32_t count = 0;
for (size_t i = 0; i < size(); i++) {
const sp<AudioInputDescriptor> inputDescriptor = valueAt(i);
if (inputDescriptor->isActive() &&
- ((devices == AUDIO_DEVICE_IN_DEFAULT) ||
- ((inputDescriptor->mDevice & devices & ~AUDIO_DEVICE_BIT_IN) != 0))) {
+ (devices.isEmpty() || devices.contains(inputDescriptor->getDevice()))) {
count++;
}
}
@@ -479,13 +483,6 @@
return activeInputs;
}
-audio_devices_t AudioInputCollection::getSupportedDevices(audio_io_handle_t handle) const
-{
- sp<AudioInputDescriptor> inputDesc = valueFor(handle);
- audio_devices_t devices = inputDesc->mProfile->getSupportedDevicesType();
- return devices;
-}
-
sp<AudioInputDescriptor> AudioInputCollection::getInputForClient(audio_port_handle_t portId)
{
for (size_t i = 0; i < size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 97504ab..643cbd1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -82,25 +82,10 @@
return mId;
}
-audio_devices_t AudioOutputDescriptor::device() const
-{
- return mDevice;
-}
-
-audio_devices_t AudioOutputDescriptor::supportedDevices()
-{
- return mDevice;
-}
-
bool AudioOutputDescriptor::sharesHwModuleWith(
const sp<AudioOutputDescriptor>& outputDesc)
{
- if (outputDesc->isDuplicated()) {
- return sharesHwModuleWith(outputDesc->subOutput1()) ||
- sharesHwModuleWith(outputDesc->subOutput2());
- } else {
- return hasSameHwModuleAs(outputDesc);
- }
+ return hasSameHwModuleAs(outputDesc);
}
void AudioOutputDescriptor::changeStreamActiveCount(const sp<TrackClientDescriptor>& client,
@@ -282,7 +267,7 @@
dst->appendFormat(" Sampling rate: %d\n", mSamplingRate);
dst->appendFormat(" Format: %08x\n", mFormat);
dst->appendFormat(" Channels: %08x\n", mChannelMask);
- dst->appendFormat(" Devices: %08x\n", device());
+ dst->appendFormat(" Devices: %s\n", devices().toString().c_str());
dst->appendFormat(" Global active count: %u\n", mGlobalActiveCount);
dst->append(" Stream volume activeCount muteCount\n");
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
@@ -330,17 +315,18 @@
AudioOutputDescriptor::dump(dst);
}
-audio_devices_t SwAudioOutputDescriptor::device() const
+DeviceVector SwAudioOutputDescriptor::devices() const
{
if (isDuplicated()) {
- return (audio_devices_t)(mOutput1->mDevice | mOutput2->mDevice);
- } else {
- return mDevice;
+ DeviceVector devices = mOutput1->devices();
+ devices.merge(mOutput2->devices());
+ return devices;
}
+ return mDevices;
}
bool SwAudioOutputDescriptor::sharesHwModuleWith(
- const sp<AudioOutputDescriptor>& outputDesc)
+ const sp<SwAudioOutputDescriptor>& outputDesc)
{
if (isDuplicated()) {
return mOutput1->sharesHwModuleWith(outputDesc) || mOutput2->sharesHwModuleWith(outputDesc);
@@ -352,13 +338,30 @@
}
}
-audio_devices_t SwAudioOutputDescriptor::supportedDevices()
+DeviceVector SwAudioOutputDescriptor::supportedDevices() const
{
if (isDuplicated()) {
- return (audio_devices_t)(mOutput1->supportedDevices() | mOutput2->supportedDevices());
- } else {
- return mProfile->getSupportedDevicesType();
+ DeviceVector supportedDevices = mOutput1->supportedDevices();
+ supportedDevices.merge(mOutput2->supportedDevices());
+ return supportedDevices;
}
+ return mProfile->getSupportedDevices();
+}
+
+bool SwAudioOutputDescriptor::supportsDevice(const sp<DeviceDescriptor> &device) const
+{
+ return supportedDevices().contains(device);
+}
+
+bool SwAudioOutputDescriptor::supportsAllDevices(const DeviceVector &devices) const
+{
+ return supportedDevices().containsAllDevices(devices);
+}
+
+DeviceVector SwAudioOutputDescriptor::filterSupportedDevices(const DeviceVector &devices) const
+{
+ DeviceVector filteredDevices = supportedDevices();
+ return filteredDevices.filter(devices);
}
uint32_t SwAudioOutputDescriptor::latency()
@@ -443,12 +446,15 @@
}
status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
- audio_devices_t device,
- const String8& address,
+ const DeviceVector &devices,
audio_stream_type_t stream,
audio_output_flags_t flags,
audio_io_handle_t *output)
{
+ mDevices = devices;
+ const String8& address = devices.getFirstValidAddress();
+ audio_devices_t device = devices.types();
+
audio_config_t lConfig;
if (config == nullptr) {
lConfig = AUDIO_CONFIG_INITIALIZER;
@@ -459,7 +465,6 @@
lConfig = *config;
}
- mDevice = device;
// if the selected profile is offloaded and no offload info was specified,
// create a default one
if ((mProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
@@ -477,19 +482,19 @@
mFlags = (audio_output_flags_t)(mFlags | flags);
- ALOGV("opening output for device %08x address %s profile %p name %s",
- mDevice, address.string(), mProfile.get(), mProfile->getName().string());
+ ALOGV("opening output for device %s profile %p name %s",
+ mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string());
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
&lConfig,
- &mDevice,
+ &device,
address,
&mLatency,
mFlags);
- LOG_ALWAYS_FATAL_IF(mDevice != device,
+ LOG_ALWAYS_FATAL_IF(mDevices.types() != device,
"%s openOutput returned device %08x when given device %08x",
- __FUNCTION__, mDevice, device);
+ __FUNCTION__, mDevices.types(), device);
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
@@ -605,11 +610,6 @@
mSource->dump(dst, 0, 0);
}
-audio_devices_t HwAudioOutputDescriptor::supportedDevices()
-{
- return mDevice;
-}
-
void HwAudioOutputDescriptor::toAudioPortConfig(
struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
@@ -657,7 +657,7 @@
for (size_t i = 0; i < this->size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isStreamActive(stream, inPastMs, sysTime)
- && ((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
+ && ((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) == 0)) {
return true;
}
}
@@ -670,7 +670,7 @@
nsecs_t sysTime = systemTime();
for (size_t i = 0; i < size(); i++) {
const sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- if (((outputDesc->device() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
+ if (((outputDesc->devices().types() & APM_AUDIO_OUT_DEVICE_REMOTE_ALL) != 0) &&
outputDesc->isStreamActive(stream, inPastMs, sysTime)) {
// do not consider re routing (when the output is going to a dynamic policy)
// as "remote playback"
@@ -686,7 +686,8 @@
{
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ if (!outputDesc->isDuplicated() &&
+ outputDesc->devices().types() & AUDIO_DEVICE_OUT_ALL_A2DP) {
return this->keyAt(i);
}
}
@@ -700,10 +701,9 @@
if ((primaryOutput != NULL) && (primaryOutput->mProfile != NULL)
&& (primaryOutput->mProfile->getModule() != NULL)) {
sp<HwModule> primaryHwModule = primaryOutput->mProfile->getModule();
- Vector <sp<IOProfile>> primaryHwModuleOutputProfiles =
- primaryHwModule->getOutputProfiles();
- for (size_t i = 0; i < primaryHwModuleOutputProfiles.size(); i++) {
- if (primaryHwModuleOutputProfiles[i]->supportDevice(AUDIO_DEVICE_OUT_ALL_A2DP)) {
+
+ for (const auto &outputProfile : primaryHwModule->getOutputProfiles()) {
+ if (outputProfile->supportsDeviceTypes(AUDIO_DEVICE_OUT_ALL_A2DP)) {
return true;
}
}
@@ -754,13 +754,6 @@
return false;
}
-audio_devices_t SwAudioOutputCollection::getSupportedDevices(audio_io_handle_t handle) const
-{
- sp<SwAudioOutputDescriptor> outputDesc = valueFor(handle);
- audio_devices_t devices = outputDesc->mProfile->getSupportedDevicesType();
- return devices;
-}
-
sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getOutputForClient(audio_port_handle_t portId)
{
for (size_t i = 0; i < size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3cf8014..d18091c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -280,13 +280,11 @@
return BAD_VALUE;
}
-audio_devices_t AudioPolicyMixCollection::getDeviceAndMixForInputSource(audio_source_t inputSource,
- audio_devices_t availDevices,
- AudioMix **policyMix)
+sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
+ audio_source_t inputSource, const DeviceVector &availDevices, AudioMix **policyMix)
{
for (size_t i = 0; i < size(); i++) {
AudioMix *mix = valueAt(i)->getMix();
-
if (mix->mMixType != MIX_TYPE_RECORDERS) {
continue;
}
@@ -295,17 +293,21 @@
mix->mCriteria[j].mValue.mSource == inputSource) ||
(RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
mix->mCriteria[j].mValue.mSource != inputSource)) {
- if (availDevices & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ // assuming PolicyMix only for remote submix for input
+ // so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+ audio_devices_t device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ auto mixDevice = availDevices.getDevice(device, mix->mDeviceAddress);
+ if (mixDevice != nullptr) {
if (policyMix != NULL) {
*policyMix = mix;
}
- return AUDIO_DEVICE_IN_REMOTE_SUBMIX;
+ return mixDevice;
}
break;
}
}
}
- return AUDIO_DEVICE_NONE;
+ return nullptr;
}
status_t AudioPolicyMixCollection::getInputMixForAttr(audio_attributes_t attr, AudioMix **policyMix)
@@ -340,6 +342,89 @@
return NO_ERROR;
}
+status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ // remove existing rules for this uid
+ removeUidDeviceAffinities(uid);
+
+ // for each player mix: add a rule to match or exclude the uid based on the device
+ for (size_t i = 0; i < size(); i++) {
+ const AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ // check if this mix goes to a device in the list of devices
+ bool deviceMatch = false;
+ for (size_t j = 0; j < devices.size(); j++) {
+ if (devices[j].mType == mix->mDeviceType
+ && devices[j].mAddress == mix->mDeviceAddress) {
+ deviceMatch = true;
+ break;
+ }
+ }
+ if (deviceMatch) {
+ mix->setMatchUid(uid);
+ } else {
+ // this mix doesn't go to one of the listed devices for the given uid,
+ // modify its rules to exclude the uid
+ mix->setExcludeUid(uid);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
+ // for each player mix: remove existing rules that match or exclude this uid
+ for (size_t i = 0; i < size(); i++) {
+ bool foundUidRule = false;
+ AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ std::vector<size_t> criteriaToRemove;
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ // is this rule affecting the uid?
+ if ((rule == RULE_EXCLUDE_UID || rule == RULE_MATCH_UID)
+ && uid == mix->mCriteria[j].mValue.mUid) {
+ foundUidRule = true;
+ criteriaToRemove.push_back(j);
+ }
+ }
+ if (foundUidRule) {
+ for (size_t j = criteriaToRemove.size() - 1; j >= 0; j--) {
+ mix->mCriteria.removeAt(criteriaToRemove[j]);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyMixCollection::getDevicesForUid(uid_t uid,
+ Vector<AudioDeviceTypeAddr>& devices) const {
+ // for each player mix: find rules that don't exclude this uid, and add the device to the list
+ for (size_t i = 0; i < size(); i++) {
+ bool ruleAllowsUid = true;
+ AudioMix *mix = valueAt(i)->getMix();
+ if (mix->mMixType != MIX_TYPE_PLAYERS) {
+ continue;
+ }
+ for (size_t j = 0; j < mix->mCriteria.size(); j++) {
+ const uint32_t rule = mix->mCriteria[j].mRule;
+ if (rule == RULE_EXCLUDE_UID
+ && uid == mix->mCriteria[j].mValue.mUid) {
+ ruleAllowsUid = false;
+ break;
+ }
+ }
+ if (ruleAllowsUid) {
+ devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
+ }
+ }
+ return NO_ERROR;
+}
+
void AudioPolicyMixCollection::dump(String8 *dst) const
{
dst->append("\nAudio Policy Mix:\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 19dde6a..9fcf5e7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -31,9 +31,15 @@
// --- AudioPort class implementation
void AudioPort::attach(const sp<HwModule>& module)
{
+ ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string());
mModule = module;
}
+void AudioPort::detach()
+{
+ mModule = nullptr;
+}
+
// Note that is a different namespace than AudioFlinger unique IDs
audio_port_handle_t AudioPort::getNextUniqueId()
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 04cbcd1..01111c5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -58,6 +58,12 @@
mId = getNextUniqueId();
}
+void DeviceDescriptor::detach()
+{
+ mId = AUDIO_PORT_HANDLE_NONE;
+ AudioPort::detach();
+}
+
bool DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
{
// Devices are considered equal if they:
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 80af88d..7d2d094 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -52,6 +52,9 @@
sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->setAddress(address);
+ addDynamicDevice(devDesc);
+ // Reciprocally attach the device to the module
+ devDesc->attach(this);
profile->addSupportedDevice(devDesc);
return addOutputProfile(profile);
@@ -97,6 +100,9 @@
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
if (mOutputProfiles[i]->getName() == name) {
+ for (const auto &device : mOutputProfiles[i]->getSupportedDevices()) {
+ removeDynamicDevice(device);
+ }
mOutputProfiles.removeAt(i);
break;
}
@@ -114,6 +120,9 @@
sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
devDesc->setAddress(address);
+ addDynamicDevice(devDesc);
+ // Reciprocally attach the device to the module
+ devDesc->attach(this);
profile->addSupportedDevice(devDesc);
ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
@@ -126,6 +135,9 @@
{
for (size_t i = 0; i < mInputProfiles.size(); i++) {
if (mInputProfiles[i]->getName() == name) {
+ for (const auto &device : mInputProfiles[i]->getSupportedDevices()) {
+ removeDynamicDevice(device);
+ }
mInputProfiles.removeAt(i);
break;
}
@@ -247,6 +259,7 @@
}
}
mDeclaredDevices.dump(dst, String8("Declared"), 2, true);
+ mDynamicDevices.dump(dst, String8("Dynamic"), 2, true);
mRoutes.dump(dst, 2);
}
@@ -260,13 +273,13 @@
return nullptr;
}
-sp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
+sp <HwModule> HwModuleCollection::getModuleForDeviceTypes(audio_devices_t device) const
{
for (const auto& module : *this) {
const auto& profiles = audio_is_output_device(device) ?
module->getOutputProfiles() : module->getInputProfiles();
for (const auto& profile : profiles) {
- if (profile->supportDevice(device)) {
+ if (profile->supportsDeviceTypes(device)) {
return module;
}
}
@@ -274,30 +287,127 @@
return nullptr;
}
-sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
- const char *device_address,
- const char *device_name,
+sp <HwModule> HwModuleCollection::getModuleForDevice(const sp<DeviceDescriptor> &device) const
+{
+ for (const auto& module : *this) {
+ const auto& profiles = audio_is_output_device(device->type()) ?
+ module->getOutputProfiles() : module->getInputProfiles();
+ for (const auto& profile : profiles) {
+ if (profile->supportsDevice(device)) {
+ return module;
+ }
+ }
+ }
+ return nullptr;
+}
+
+DeviceVector HwModuleCollection::getAvailableDevicesFromModuleName(
+ const char *name, const DeviceVector &availableDevices) const
+{
+ sp<HwModule> module = getModuleFromName(name);
+ if (module == nullptr) {
+ return DeviceVector();
+ }
+ return availableDevices.getDevicesFromHwModule(module->getHandle());
+}
+
+sp<DeviceDescriptor> HwModuleCollection::getDeviceDescriptor(const audio_devices_t deviceType,
+ const char *address,
+ const char *name,
+ bool allowToCreate,
bool matchAddress) const
{
- String8 address = (device_address == nullptr || !matchAddress) ?
- String8("") : String8(device_address);
+ String8 devAddress = (address == nullptr || !matchAddress) ? String8("") : String8(address);
// handle legacy remote submix case where the address was not always specified
- if (device_distinguishes_on_address(device) && (address.length() == 0)) {
- address = String8("0");
+ if (device_distinguishes_on_address(deviceType) && (devAddress.length() == 0)) {
+ devAddress = String8("0");
}
for (const auto& hwModule : *this) {
- DeviceVector declaredDevices = hwModule->getDeclaredDevices();
- sp<DeviceDescriptor> deviceDesc = declaredDevices.getDevice(device, address);
- if (deviceDesc) {
- return deviceDesc;
+ DeviceVector moduleDevices = hwModule->getAllDevices();
+ auto moduleDevice = moduleDevices.getDevice(deviceType, devAddress);
+ if (moduleDevice) {
+ if (allowToCreate) {
+ moduleDevice->attach(hwModule);
+ }
+ return moduleDevice;
}
}
+ if (!allowToCreate) {
+ ALOGE("%s: could not find HW module for device %s %04x address %s", __FUNCTION__,
+ name, deviceType, address);
+ return nullptr;
+ }
+ return createDevice(deviceType, address, name);
+}
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
- devDesc->setName(String8(device_name));
- devDesc->setAddress(address);
- return devDesc;
+sp<DeviceDescriptor> HwModuleCollection::createDevice(const audio_devices_t type,
+ const char *address,
+ const char *name) const
+{
+ sp<HwModule> hwModule = getModuleForDeviceTypes(type);
+ if (hwModule == 0) {
+ ALOGE("%s: could not find HW module for device %04x address %s", __FUNCTION__, type,
+ address);
+ return nullptr;
+ }
+ sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name));
+ device->setName(String8(name));
+ device->setAddress(String8(address));
+
+ // Add the device to the list of dynamic devices
+ hwModule->addDynamicDevice(device);
+ // Reciprocally attach the device to the module
+ device->attach(hwModule);
+ ALOGD("%s: adding dynamic device %s to module %s", __FUNCTION__,
+ device->toString().c_str(), hwModule->getName());
+
+ const auto &profiles = (audio_is_output_device(type) ? hwModule->getOutputProfiles() :
+ hwModule->getInputProfiles());
+ for (const auto &profile : profiles) {
+ // Add the device as supported to all profile supporting "weakly" or not the device
+ // according to its type
+ if (profile->supportsDevice(device, false /*matchAdress*/)) {
+
+ // @todo quid of audio profile? import the profile from device of the same type?
+ const auto &isoTypeDeviceForProfile = profile->getSupportedDevices().getDevice(type);
+ device->importAudioPort(isoTypeDeviceForProfile, true /* force */);
+
+ ALOGV("%s: adding device %s to profile %s", __FUNCTION__,
+ device->toString().c_str(), profile->getTagName().c_str());
+ profile->addSupportedDevice(device);
+ }
+ }
+ return device;
+}
+
+void HwModuleCollection::cleanUpForDevice(const sp<DeviceDescriptor> &device)
+{
+ for (const auto& hwModule : *this) {
+ DeviceVector moduleDevices = hwModule->getAllDevices();
+ if (!moduleDevices.contains(device)) {
+ continue;
+ }
+ device->detach();
+ // Only remove from dynamic list, not from declared list!!!
+ if (!hwModule->getDynamicDevices().contains(device)) {
+ return;
+ }
+ hwModule->removeDynamicDevice(device);
+ ALOGV("%s: removed dynamic device %s from module %s", __FUNCTION__,
+ device->toString().c_str(), hwModule->getName());
+
+ const IOProfileCollection &profiles = audio_is_output_device(device->type()) ?
+ hwModule->getOutputProfiles() : hwModule->getInputProfiles();
+ for (const auto &profile : profiles) {
+ // For cleanup, strong match is required
+ if (profile->supportsDevice(device, true /*matchAdress*/)) {
+ ALOGV("%s: removing device %s from profile %s", __FUNCTION__,
+ device->toString().c_str(), profile->getTagName().c_str());
+ profile->removeSupportedDevice(device);
+ }
+ }
+ }
}
void HwModuleCollection::dump(String8 *dst) const
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 3788244..fe2eaee 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -25,11 +25,7 @@
namespace android {
-// checks if the IO profile is compatible with specified parameters.
-// Sampling rate, format and channel mask must be specified in order to
-// get a valid a match
-bool IOProfile::isCompatibleProfile(audio_devices_t device,
- const String8& address,
+bool IOProfile::isCompatibleProfile(const DeviceVector &devices,
uint32_t samplingRate,
uint32_t *updatedSamplingRate,
audio_format_t format,
@@ -46,14 +42,8 @@
getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
ALOG_ASSERT(isPlaybackThread != isRecordThread);
-
- if (device != AUDIO_DEVICE_NONE) {
- // just check types if multiple devices are selected
- if (popcount(device & ~AUDIO_DEVICE_BIT_IN) > 1) {
- if ((mSupportedDevices.types() & device) != device) {
- return false;
- }
- } else if (mSupportedDevices.getDevice(device, address) == 0) {
+ if (!devices.isEmpty()) {
+ if (!mSupportedDevices.containsAllDevices(devices)) {
return false;
}
}
diff --git a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
index a597e87..efc69da 100644
--- a/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
+++ b/services/audiopolicy/engineconfigurable/include/AudioPolicyEngineInstance.h
@@ -19,10 +19,8 @@
class AudioPolicyManagerInterface;
class AudioPolicyPluginInterface;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
class Engine;
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
index baaefd2..7631976 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Android.mk
@@ -7,15 +7,19 @@
#
################################################################################################
-ifeq (1, 0)
-
LOCAL_PATH := $(call my-dir)
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
PFW_CORE := external/parameter-framework
-BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
+#@TODO: upstream new domain generator
+#BUILD_PFW_SETTINGS := $(PFW_CORE)/support/android/build_pfw_settings.mk
PFW_DEFAULT_SCHEMAS_DIR := $(PFW_CORE)/upstream/schemas
PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+BUILD_PFW_SETTINGS := $(TOOLS)/build_audio_pfw_settings.mk
+
##################################################################
# CONFIGURATION FILES
##################################################################
@@ -25,7 +29,8 @@
LOCAL_MODULE := ParameterFrameworkConfigurationPolicy.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework
LOCAL_SRC_FILES := $(LOCAL_MODULE).in
AUDIO_PATTERN = @TUNING_ALLOWED@
@@ -46,7 +51,8 @@
LOCAL_MODULE := PolicyClass.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -54,12 +60,12 @@
LOCAL_MODULE := PolicySubsystem.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_REQUIRED_MODULES := \
PolicySubsystem-CommonTypes.xml \
- PolicySubsystem-Volume.xml \
- libpolicy-subsystem \
+ libpolicy-subsystem
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -67,7 +73,8 @@
LOCAL_MODULE := PolicySubsystem-CommonTypes.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/parameter-framework/Structure/Policy
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/Structure/Policy
LOCAL_SRC_FILES := Structure/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
@@ -76,15 +83,16 @@
LOCAL_MODULE := parameter-framework.policy
LOCAL_MODULE_STEM := PolicyConfigurableDomains.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
ifeq ($(pfw_rebuild_settings),true)
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -100,6 +108,17 @@
$(LOCAL_PATH)/Settings/device_for_input_source.pfw \
$(LOCAL_PATH)/Settings/volumes.pfw
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(PFW_EDD_FILES)
+
+
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
+
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
+
include $(BUILD_PFW_SETTINGS)
else
# Use the existing file
@@ -107,19 +126,27 @@
include $(BUILD_PREBUILT)
endif # pfw_rebuild_settings
+endif # ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 0)
+
######### Policy PFW Settings - No Output #########
+ifeq (0, 1)
+
include $(CLEAR_VARS)
LOCAL_MODULE := parameter-framework.policy.no-output
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoOutputDevice.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/SettingsNoOutput/device_for_strategies.pfw \
$(LOCAL_PATH)/Settings/strategy_for_stream.pfw \
@@ -128,20 +155,26 @@
$(LOCAL_PATH)/Settings/volumes.pfw
include $(BUILD_PFW_SETTINGS)
-
+endif # ifeq (0, 1)
######### Policy PFW Settings - No Input #########
+ifeq (0, 1)
+
include $(CLEAR_VARS)
LOCAL_MODULE := parameter-framework.policy.no-input
LOCAL_MODULE_STEM := PolicyConfigurableDomains-NoInputDevice.xml
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_RELATIVE_PATH := parameter-framework/Settings/Policy
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- PolicyClass.xml \
- PolicySubsystem.xml \
- ParameterFrameworkConfigurationPolicy.xml
+LOCAL_REQUIRED_MODULES := \
+ policy_criteria.xml \
+ policy_criterion_types.xml \
+ PolicySubsystem.xml \
+ PolicyClass.xml \
+ ParameterFrameworkConfigurationPolicy.xml
-PFW_TOPLEVEL_FILE := $(TARGET_OUT_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
-PFW_CRITERIA_FILE := $(LOCAL_PATH)/policy_criteria.txt
+PFW_TOPLEVEL_FILE := $(TARGET_OUT_VENDOR_ETC)/parameter-framework/ParameterFrameworkConfigurationPolicy.xml
+PFW_CRITERION_TYPES_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criterion_types.xml
+PFW_CRITERIA_FILE := $(TARGET_OUT_VENDOR_ETC)/policy_criteria.xml
PFW_EDD_FILES := \
$(LOCAL_PATH)/Settings/device_for_strategy_media.pfw \
$(LOCAL_PATH)/Settings/device_for_strategy_phone.pfw \
@@ -160,3 +193,9 @@
include $(BUILD_PFW_SETTINGS)
endif # ifeq (1, 0)
+
+#######################################################################
+# Recursive call sub-folder Android.mk
+#######################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
index f5615cd..f80a07f 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/ParameterFrameworkConfigurationPolicy.xml.in
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- SystemClassName="Policy" ServerPort="5019" TuningAllowed="@TUNING_ALLOWED@">
+ SystemClassName="Policy" ServerPort="/dev/socket/audioserver/policy_debug"
+ TuningAllowed="@TUNING_ALLOWED@">
<SubsystemPlugins>
<Location Folder="">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
index b43f83b..0710441 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/PolicyConfigurableDomains.xml
@@ -8472,7 +8472,7 @@
<Configurations>
<Configuration Name="Sonification">
<CompoundRule Type="All">
- <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="RingTone"/>
+ <SelectionCriterionRule SelectionCriterion="TelephonyMode" MatchesWhen="Is" Value="Ringtone"/>
</CompoundRule>
</Configuration>
<Configuration Name="Phone">
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
index b3115e7..fbea9e2 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Settings/strategy_for_usage.pfw
@@ -24,7 +24,7 @@
# In case of Ring or Alarm stream type active, switching to sonification
# @todo: handle this dynamic case. As a WA, using Ringtone mode...
#
- TelephonyMode Is RingTone
+ TelephonyMode Is Ringtone
/Policy/policy/usages/assistance_accessibility/applicable_strategy/strategy = sonification
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
index 917d4a7..f923610 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/device_for_strategies.pfw
@@ -9,7 +9,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -37,7 +37,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -65,7 +65,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -93,7 +93,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -121,7 +121,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -149,7 +149,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -177,7 +177,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -205,7 +205,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
@@ -233,7 +233,7 @@
bluetooth_sco = 0
bluetooth_sco_headset = 0
bluetooth_sco_carkit = 0
- bluetooth_a2dp = 0>
+ bluetooth_a2dp = 0
bluetooth_a2dp_headphones = 0
bluetooth_a2dp_speaker = 0
hdmi = 0
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
index 461e44a..daa7f68 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem-CommonTypes.xml
@@ -37,6 +37,10 @@
<BitParameter Name="speaker_safe" Size="1" Pos="22"/>
<BitParameter Name="ip" Size="1" Pos="23"/>
<BitParameter Name="bus" Size="1" Pos="24"/>
+ <BitParameter Name="proxy" Size="1" Pos="25"/>
+ <BitParameter Name="usb_headset" Size="1" Pos="26"/>
+ <BitParameter Name="hearing_aid" Size="1" Pos="27"/>
+ <BitParameter Name="echo_canceller" Size="1" Pos="28"/>
<BitParameter Name="stub" Size="1" Pos="30"/>
</BitParameterBlock>
</ComponentType>
@@ -67,6 +71,9 @@
<BitParameter Name="loopback" Size="1" Pos="18"/>
<BitParameter Name="ip" Size="1" Pos="19"/>
<BitParameter Name="bus" Size="1" Pos="20"/>
+ <BitParameter Name="proxy" Size="1" Pos="21"/>
+ <BitParameter Name="usb_headset" Size="1" Pos="22"/>
+ <BitParameter Name="bluetooth_ble" Size="1" Pos="23"/>
<BitParameter Name="stub" Size="1" Pos="30"/>
</BitParameterBlock>
</ComponentType>
@@ -144,7 +151,7 @@
<!--#################### STRATEGY COMMON TYPES BEGIN ####################-->
- <ComponentType Name="StrategyConfig" Mapping="Strategy:'%1'">
+ <ComponentType Name="StrategyConfig" Mapping="Strategy">
<Component Name="selected_output_devices" Type="OutputDevicesMask"/>
</ComponentType>
@@ -170,7 +177,7 @@
</EnumParameter>
</ComponentType>
- <ComponentType Name="Stream">
+ <ComponentType Name="Stream" Mapping="Stream">
<Component Name="applicable_strategy" Type="Strategy"/>
<Component Name="applicable_volume_profile" Type="VolumeProfileType"
Description="Volume profile followed by a given stream type."/>
@@ -181,7 +188,7 @@
<!--#################### USAGE COMMON TYPES BEGIN ####################-->
<ComponentType Name="Usage">
- <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage:'%1'"/>
+ <Component Name="applicable_strategy" Type="Strategy" Mapping="Usage"/>
</ComponentType>
<!--#################### USAGE COMMON TYPES END ####################-->
@@ -190,7 +197,7 @@
<ComponentType Name="InputSource">
<Component Name="applicable_input_device" Type="InputDevicesMask"
- Mapping="InputSource:'%1'" Description="Selected Input device"/>
+ Mapping="InputSource" Description="Selected Input device"/>
</ComponentType>
<!--#################### INPUT SOURCE COMMON TYPES END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
index ad9c356..45d1e8a 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Structure/PolicySubsystem.xml
@@ -13,54 +13,40 @@
<!--#################### STRATEGY BEGIN ####################-->
- <ComponentType Name="Strategies" Description="Identifier must match the enum value to make
- the link between the PolicyManager and PFW">
- <Component Name="media" Type="StrategyConfig" Mapping="Amend1:Media,Identifier:0"/>
- <Component Name="phone" Type="StrategyConfig" Mapping="Amend1:Phone,Identifier:1"/>
- <Component Name="sonification" Type="StrategyConfig"
- Mapping="Amend1:Sonification,Identifier:2"/>
- <Component Name="sonification_respectful" Type="StrategyConfig"
- Mapping="Amend1:SonificationRespectful,Identifier:3"/>
- <Component Name="dtmf" Type="StrategyConfig" Mapping="Amend1:Dtmf,Identifier:4"/>
- <Component Name="enforced_audible" Type="StrategyConfig"
- Mapping="Amend1:EnforcedAudible,Identifier:5"/>
- <Component Name="transmitted_through_speaker" Type="StrategyConfig"
- Mapping="Amend1:TransmittedThroughSpeaker,Identifier:6"/>
- <Component Name="accessibility" Type="StrategyConfig"
- Mapping="Amend1:Accessibility,Identifier:7"/>
- <Component Name="rerouting" Type="StrategyConfig"
- Mapping="Amend1:Rerouting,Identifier:8"/>
+ <ComponentType Name="Strategies">
+ <Component Name="media" Type="StrategyConfig" Mapping="Name:STRATEGY_MEDIA"/>
+ <Component Name="phone" Type="StrategyConfig" Mapping="Name:STRATEGY_PHONE"/>
+ <Component Name="sonification" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION"/>
+ <Component Name="sonification_respectful" Type="StrategyConfig" Mapping="Name:STRATEGY_SONIFICATION_RESPECTFUL"/>
+ <Component Name="dtmf" Type="StrategyConfig" Mapping="Name:STRATEGY_DTMF"/>
+ <Component Name="enforced_audible" Type="StrategyConfig" Mapping="Name:STRATEGY_ENFORCED_AUDIBLE"/>
+ <Component Name="transmitted_through_speaker" Type="StrategyConfig" Mapping="Name:STRATEGY_TRANSMITTED_THROUGH_SPEAKER"/>
+ <Component Name="accessibility" Type="StrategyConfig" Mapping="Name:STRATEGY_ACCESSIBILITY"/>
+ <Component Name="rerouting" Type="StrategyConfig" Mapping=",Name:STRATEGY_REROUTING"/>
</ComponentType>
<!--#################### STRATEGY END ####################-->
<!--#################### STREAM BEGIN ####################-->
- <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition,
- identifier mapping must match the value of the enum">
- <Component Name="voice_call" Type="Stream" Mapping="Stream:VoiceCall,Identifier:0"/>
- <Component Name="system" Type="Stream" Mapping="Stream:System,Identifier:1"/>
- <Component Name="ring" Type="Stream" Mapping="Stream:Ring,Identifier:2"/>
- <Component Name="music" Type="Stream" Mapping="Stream:Music,Identifier:3"/>
- <Component Name="alarm" Type="Stream" Mapping="Stream:Alarm,Identifier:4"/>
- <Component Name="notification" Type="Stream"
- Mapping="Stream:Notification,Identifier:5"/>
- <Component Name="bluetooth_sco" Type="Stream"
- Mapping="Stream:BluetoothSco,Identifier:6"/>
- <Component Name="enforced_audible" Type="Stream"
- Mapping="Stream:EnforceAudible,Identifier:7"
- Description="Sounds that cannot be muted by user and must
- be routed to speaker"/>
- <Component Name="dtmf" Type="Stream" Mapping="Stream:Dtmf,Identifier:8"/>
- <Component Name="tts" Type="Stream" Mapping="Stream:Tts,Identifier:9"
- Description="Transmitted Through Speaker.
- Plays over speaker only, silent on other devices"/>
- <Component Name="accessibility" Type="Stream"
- Mapping="Stream:Accessibility,Identifier:10"
+ <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+ <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+ <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+ <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+ <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+ <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+ <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+ <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+ <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+ Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+ <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+ <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+ Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+ <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
Description="For accessibility talk back prompts"/>
- <Component Name="rerouting" Type="Stream" Mapping="Stream:Rerouting,Identifier:11"
+ <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
Description="For dynamic policy output mixes"/>
- <Component Name="patch" Type="Stream" Mapping="Stream:Patch,Identifier:12"
+ <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
Description="For internal audio flinger tracks. Fixed volume"/>
</ComponentType>
@@ -68,36 +54,34 @@
<!--#################### USAGE BEGIN ####################-->
- <ComponentType Name="Usages" Description="associated to audio_usage_t definition,
- identifier mapping must match the value of the enum">
- <Component Name="unknown" Type="Usage" Mapping="Amend1:Unknown,Identifier:0"/>
- <Component Name="media" Type="Usage" Mapping="Amend1:Media,Identifier:1"/>
+ <ComponentType Name="Usages" Description="associated to audio_usage_t definition">
+ <Component Name="unknown" Type="Usage" Mapping="Name:AUDIO_USAGE_UNKNOWN"/>
+ <Component Name="media" Type="Usage" Mapping="Name:AUDIO_USAGE_MEDIA"/>
<Component Name="voice_communication" Type="Usage"
- Mapping="Amend1:VoiceCommunication,Identifier:2"/>
+ Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION"/>
<Component Name="voice_communication_signalling" Type="Usage"
- Mapping="Amend1:VoiceCommunicationSignalling,Identifier:3"/>
- <Component Name="alarm" Type="Usage" Mapping="Amend1:Alarm,Identifier:4"/>
- <Component Name="notification" Type="Usage" Mapping="Amend1:Notification,Identifier:5"/>
+ Mapping="Name:AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/>
+ <Component Name="alarm" Type="Usage" Mapping="Name:AUDIO_USAGE_ALARM"/>
+ <Component Name="notification" Type="Usage" Mapping="Name:AUDIO_USAGE_NOTIFICATION"/>
<Component Name="notification_telephony_ringtone" Type="Usage"
- Mapping="Amend1:NotificationTelephonyRingtone,Identifier:6"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/>
<Component Name="notification_communication_request" Type="Usage"
- Mapping="Amend1:NotificationCommunicationRequest,Identifier:7"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST"/>
<Component Name="notification_communication_instant" Type="Usage"
- Mapping="Amend1:NotificationCommunicationInstant,Identifier:8"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT"/>
<Component Name="notification_communication_delayed" Type="Usage"
- Mapping="Amend1:NotificationCommunicationDelated,Identifier:9"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED"/>
<Component Name="notification_event" Type="Usage"
- Mapping="Amend1:NotificationEvent,Identifier:10"/>
+ Mapping="Name:AUDIO_USAGE_NOTIFICATION_EVENT"/>
<Component Name="assistance_accessibility" Type="Usage"
- Mapping="Amend1:AssistanceAccessibility,Identifier:11"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/>
<Component Name="assistance_navigation_guidance" Type="Usage"
- Mapping="Amend1:AssistanceNavigationGuidance,Identifier:12"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/>
<Component Name="assistance_sonification" Type="Usage"
- Mapping="Amend1:AssistanceSonification,Identifier:13"/>
- <Component Name="game" Type="Usage" Mapping="Amend1:BluetoothSco,Identifier:14"/>
- <Component Name="virtual_source" Type="Usage"
- Mapping="Amend1:VirtualSource,Identifier:15"/>
- <Component Name="assistant" Type="Usage" Mapping="Amend1:Assistant,Identifier:16"/>
+ Mapping="Name:AUDIO_USAGE_ASSISTANCE_SONIFICATION"/>
+ <Component Name="game" Type="Usage" Mapping="Name:AUDIO_USAGE_GAME"/>
+ <Component Name="virtual_source" Type="Usage" Mapping="Name:AUDIO_USAGE_VIRTUAL_SOURCE"/>
+ <Component Name="assistant" Type="Usage" Mapping="Name:AUDIO_USAGE_ASSISTANT"/>
</ComponentType>
<!--#################### USAGE END ####################-->
@@ -106,25 +90,25 @@
<ComponentType Name="InputSources" Description="associated to audio_source_t definition,
identifier mapping must match the value of the enum">
- <Component Name="default" Type="InputSource" Mapping="Amend1:Default,Identifier:0"/>
- <Component Name="mic" Type="InputSource" Mapping="Amend1:Mic,Identifier:1"/>
+ <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+ <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
<Component Name="voice_uplink" Type="InputSource"
- Mapping="Amend1:VoiceUplink,Identifier:2"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
<Component Name="voice_downlink" Type="InputSource"
- Mapping="Amend1:VoiceDownlink,Identifier:3"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
<Component Name="voice_call" Type="InputSource"
- Mapping="Amend1:VoiceCall,Identifier:4"/>
- <Component Name="camcorder" Type="InputSource" Mapping="Amend1:Camcorder,Identifier:5"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+ <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
<Component Name="voice_recognition" Type="InputSource"
- Mapping="Amend1:VoiceRecognition,Identifier:6"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
<Component Name="voice_communication" Type="InputSource"
- Mapping="Amend1:VoiceCommunication,Identifier:7"/>
+ Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
<Component Name="remote_submix" Type="InputSource"
- Mapping="Amend1:RemoteSubmix,Identifier:8"/>
+ Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
<Component Name="unprocessed" Type="InputSource"
- Mapping="Amend1:Unprocessed,Identifier:9"/>
- <Component Name="fm_tuner" Type="InputSource" Mapping="Amend1:FmTuner,Identifier:1998"/>
- <Component Name="hotword" Type="InputSource" Mapping="Amend1:Hotword,Identifier:1999"/>
+ Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+ <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+ <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
</ComponentType>
<!--#################### INPUT SOURCE END ####################-->
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt b/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
deleted file mode 100644
index 480cbe1..0000000
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/policy_criteria.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-ExclusiveCriterion TelephonyMode : Normal RingTone InCall InCommunication
-InclusiveCriterion AvailableInputDevices : Communication Ambient BuiltinMic BluetoothScoHeadset WiredHeadset Hdmi TelephonyRx BackMic RemoteSubmix AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice FmTuner TvTuner Line Spdif BluetoothA2dp Loopback Ip Bus Stub
-InclusiveCriterion AvailableOutputDevices : Earpiece Speaker WiredSpeaker WiredHeadset WiredHeadphone BluetoothSco BluetoothScoHeadset BluetoothScoCarkit BluetoothA2dp BluetoothA2dpHeadphones BluetoothA2dpSpeaker Hdmi AnlgDockHeadset DgtlDockHeadset UsbAccessory UsbDevice RemoteSubmix TelephonyTx Line HdmiArc Spdif Fm AuxLine SpeakerSafe Ip Bus Stub
-ExclusiveCriterion ForceUseForCommunication : ForceNone ForceSpeaker ForceBtSco
-ExclusiveCriterion ForceUseForMedia : ForceNone ForceSpeaker ForceHeadphones ForceBtA2dp ForceWiredAccessory ForceAnalogDock ForceDigitalDock ForceNoBtA2dp ForceSystemEnforced
-ExclusiveCriterion ForceUseForRecord : ForceNone ForceBtSco ForceWiredAccessory
-ExclusiveCriterion ForceUseForDock : ForceNone ForceWiredAccessory ForceBtCarDock ForceBtDeskDock ForceAnalogDock ForceDigitalDock
-ExclusiveCriterion ForceUseForSystem : ForceNone ForceSystemEnforced
-ExclusiveCriterion ForceUseForHdmiSystemAudio : ForceNone ForceHdmiSystemEnforced
-ExclusiveCriterion ForceUseForEncodedSurround : ForceNone ForceEncodedSurroundNever ForceEncodedSurroundAlways
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index 3559cf1..db1f038 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -28,6 +28,7 @@
LOCAL_SHARED_LIBRARIES := \
libaudiopolicyengineconfigurable \
libparameter \
+ libmedia_helper \
liblog \
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
index eac4efe..f91f8d7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/InputSource.cpp
@@ -17,6 +17,7 @@
#include "InputSource.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
@@ -33,9 +34,13 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_source_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+
+ if(not android::SourceTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Input Source name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addInputSource(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addInputSource(name, mId);
}
bool InputSource::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 98d10a9..7374fc3 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -65,22 +65,22 @@
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Stream>(
mStreamComponentName,
- (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Strategy>(
mStrategyComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ 0)
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<Usage>(
mUsageComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
addSubsystemObjectFactory(
new TSubsystemObjectFactory<InputSource>(
mInputSourceComponentName,
- (1 << MappingKeyAmend1) | (1 << MappingKeyIdentifier))
+ (1 << MappingKeyName))
);
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
index 746c3a8..876bcb0 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Strategy.cpp
@@ -17,10 +17,38 @@
#include "Strategy.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <RoutingStrategy.h>
using std::string;
using android::routing_strategy;
+namespace detail {
+
+constexpr std::pair<routing_strategy, const char*> routingStrategyMap[] = {
+ {android::STRATEGY_MEDIA, "STRATEGY_MEDIA"},
+ {android::STRATEGY_PHONE, "STRATEGY_PHONE"},
+ {android::STRATEGY_SONIFICATION, "STRATEGY_SONIFICATION"},
+ {android::STRATEGY_SONIFICATION_RESPECTFUL, "STRATEGY_SONIFICATION_RESPECTFUL"},
+ {android::STRATEGY_DTMF, "STRATEGY_DTMF"},
+ {android::STRATEGY_ENFORCED_AUDIBLE, "STRATEGY_ENFORCED_AUDIBLE"},
+ {android::STRATEGY_TRANSMITTED_THROUGH_SPEAKER, "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"},
+ {android::STRATEGY_ACCESSIBILITY, "STRATEGY_ACCESSIBILITY"},
+ {android::STRATEGY_REROUTING, "STRATEGY_REROUTING"},
+};
+
+bool fromString(const char *literalName, routing_strategy &type)
+{
+ for (auto& pair : routingStrategyMap) {
+ if (strcmp(pair.second, literalName) == 0) {
+ type = pair.first;
+ return true;
+ }
+ }
+ return false;
+}
+
+}
+
Strategy::Strategy(const string &mappingValue,
CInstanceConfigurableElement *instanceConfigurableElement,
const CMappingContext &context,
@@ -35,10 +63,12 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<routing_strategy>(context.getItemAsInteger(MappingKeyIdentifier));
-
+ std::string name(context.getItem(MappingKeyName));
+ if (not detail::fromString(name.c_str(), mId)) {
+ LOG_ALWAYS_FATAL("Invalid Strategy %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addStrategy(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addStrategy(instanceConfigurableElement->getName(), mId);
}
bool Strategy::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
index c642a23..46c9e1c 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Stream.cpp
@@ -17,6 +17,7 @@
#include "Stream.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
using android::routing_strategy;
@@ -29,10 +30,14 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_stream_type_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+
+ if (not android::StreamTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Stream type name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addStream(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addStream(name, mId);
}
bool Stream::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
index 78199f8..925d631 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Usage.cpp
@@ -17,6 +17,7 @@
#include "Usage.h"
#include "PolicyMappingKeys.h"
#include "PolicySubsystem.h"
+#include <media/TypeConverter.h>
using std::string;
using android::routing_strategy;
@@ -34,10 +35,13 @@
instanceConfigurableElement->getBelongingSubsystem())),
mPolicyPluginInterface(mPolicySubsystem->getPolicyPluginInterface())
{
- mId = static_cast<audio_usage_t>(context.getItemAsInteger(MappingKeyIdentifier));
+ std::string name(context.getItem(MappingKeyName));
+ if (not android::UsageTypeConverter::fromString(name, mId)) {
+ LOG_ALWAYS_FATAL("Invalid Usage name: %s, invalid XML structure file", name.c_str());
+ }
// Declares the strategy to audio policy engine
- mPolicyPluginInterface->addUsage(getFormattedMappingValue(), mId);
+ mPolicyPluginInterface->addUsage(name, mId);
}
bool Usage::sendToHW(string & /*error*/)
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
new file mode 100644
index 0000000..4d41d42
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/audioserver.te
@@ -0,0 +1,4 @@
+userdebug_or_eng(`
+ allow audioserver audioserver_socket:dir rw_dir_perms;
+ allow audioserver audioserver_socket:sock_file create_file_perms;
+')
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file.te b/services/audiopolicy/engineconfigurable/sepolicy/file.te
new file mode 100644
index 0000000..7db1937
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file.te
@@ -0,0 +1,2 @@
+# Policy Engine remote connection for runtime debug of parameter framework
+type audioserver_socket, file_type, coredomain_socket;
diff --git a/services/audiopolicy/engineconfigurable/sepolicy/file_contexts b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
new file mode 100644
index 0000000..950fcce
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/sepolicy/file_contexts
@@ -0,0 +1 @@
+/dev/socket/audioserver(/.*)? u:object_r:audioserver_socket:s0
diff --git a/services/audiopolicy/engineconfigurable/src/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index b72ded8..1f8ed8d 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -28,10 +28,8 @@
#include <stdint.h>
#include <string>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* Collection of policy element as a map indexed with a their UID type.
diff --git a/services/audiopolicy/engineconfigurable/src/Element.h b/services/audiopolicy/engineconfigurable/src/Element.h
index 52e77e5..1b55c8c 100644
--- a/services/audiopolicy/engineconfigurable/src/Element.h
+++ b/services/audiopolicy/engineconfigurable/src/Element.h
@@ -22,10 +22,8 @@
#include <system/audio.h>
#include <utils/Log.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
template <typename Key>
class Element
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 0d18ffa..009cf90 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -35,10 +35,9 @@
using std::string;
using std::map;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
template <>
StrategyCollection &Engine::getCollection<routing_strategy>()
{
@@ -220,8 +219,10 @@
}
status_t Engine::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t /*state*/)
+ audio_policy_dev_state_t state)
{
+ mPolicyParameterMgr->setDeviceConnectionState(devDesc, state);
+
if (audio_is_output_device(devDesc->type())) {
return mPolicyParameterMgr->setAvailableOutputDevices(
mApmObserver->getAvailableOutputDevices().types());
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 328d23d..ba4f889 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -21,12 +21,10 @@
#include <AudioPolicyPluginInterface.h>
#include "Collection.h"
-namespace android
-{
+namespace android {
class AudioPolicyManagerObserver;
-namespace audio_policy
-{
+namespace audio_policy {
class ParameterManagerWrapper;
class VolumeProfile;
diff --git a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
index 9aa89b2..2442590 100644
--- a/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
+++ b/services/audiopolicy/engineconfigurable/src/EngineInstance.cpp
@@ -21,10 +21,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
EngineInstance::EngineInstance()
{
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index ae39fef..d252d3f 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -20,13 +20,13 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier)
{
- if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD) {
+ if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD
+ && identifier != AUDIO_SOURCE_FM_TUNER && identifier != AUDIO_SOURCE_ECHO_REFERENCE) {
return BAD_VALUE;
}
mIdentifier = identifier;
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.h b/services/audiopolicy/engineconfigurable/src/InputSource.h
index 6c498dc..64b390e 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.h
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.h
@@ -18,10 +18,8 @@
#include "Element.h"
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* Specialization of policy base class element for audio_source_t
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.cpp b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
index a539914..310b35e 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.cpp
@@ -20,10 +20,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<routing_strategy>::setIdentifier(routing_strategy identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Strategy.h b/services/audiopolicy/engineconfigurable/src/Strategy.h
index 1157d55..f2487fd 100644
--- a/services/audiopolicy/engineconfigurable/src/Strategy.h
+++ b/services/audiopolicy/engineconfigurable/src/Strategy.h
@@ -19,10 +19,8 @@
#include "Element.h"
#include <RoutingStrategy.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* @tparam audio_devices_t: Applicable output device(s) for this strategy.
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index 0ed364f..73fb94d 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -21,10 +21,8 @@
using std::string;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.h b/services/audiopolicy/engineconfigurable/src/Stream.h
index 6902003..2bf70b3 100644
--- a/services/audiopolicy/engineconfigurable/src/Stream.h
+++ b/services/audiopolicy/engineconfigurable/src/Stream.h
@@ -21,10 +21,9 @@
#include <RoutingStrategy.h>
#include <map>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
+
/**
* @tparam routing_strategy: Applicable strategy for this stream.
*/
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.cpp b/services/audiopolicy/engineconfigurable/src/Usage.cpp
index 5d20828..8c0dfba 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Usage.cpp
@@ -18,10 +18,8 @@
#include "Usage.h"
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
status_t Element<audio_usage_t>::setIdentifier(audio_usage_t identifier)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Usage.h b/services/audiopolicy/engineconfigurable/src/Usage.h
index d69e0e0..72a452f 100644
--- a/services/audiopolicy/engineconfigurable/src/Usage.h
+++ b/services/audiopolicy/engineconfigurable/src/Usage.h
@@ -19,10 +19,8 @@
#include "Element.h"
#include <RoutingStrategy.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
/**
* @tparam routing_strategy: Applicable strategy for this usage.
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
new file mode 100644
index 0000000..d8f29dc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -0,0 +1,31 @@
+// 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.
+
+python_binary_host {
+ name: "buildPolicyCriterionTypes.py",
+ owner: "renault",
+ main: "buildPolicyCriterionTypes.py",
+ srcs: [
+ "buildPolicyCriterionTypes.py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+}
+
diff --git a/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
new file mode 100755
index 0000000..0fb70a6
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/buildPolicyCriterionTypes.py
@@ -0,0 +1,243 @@
+#!/usr/bin/python
+
+#
+# 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.
+#
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+# --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+# --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+# --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+# --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ audio criterion type file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--androidaudiobaseheader',
+ help="Android Audio Base C header file, Mandatory.",
+ metavar="ANDROID_AUDIO_BASE_HEADER",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--audiopolicyconfigurationfile',
+ help="Android Audio Policy Configuration file, Mandatory.",
+ metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML base file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--outputfile',
+ help="Criterion types outputfile file. Mandatory.",
+ metavar="CRITERION_TYPE_OUTPUT_FILE",
+ type=argparse.FileType('w'),
+ required=True)
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+ criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+ criterion_types_root = criterion_types_in_tree.getroot()
+
+ for criterion_name, values_dict in criterionTypes.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ values_node = ET.SubElement(criterion_type, "values")
+ ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+ for key, value in ordered_values.items():
+ value_node = ET.SubElement(values_node, "value")
+ value_node.set('numerical', str(value))
+ value_node.set('literal', key)
+
+ if addressCriteria:
+ for criterion_name, values_list in addressCriteria.items():
+ for criterion_type in criterion_types_root.findall('criterion_type'):
+ if criterion_type.get('name') == criterion_name:
+ values_node = ET.SubElement(criterion_type, "values")
+ index = 0
+ for value in values_list:
+ value_node = ET.SubElement(values_node, "value", literal=value)
+ value_node.set('numerical', str(1 << index))
+ index += 1
+
+ xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+ reparsed = MINIDOM.parseString(xmlstr)
+ prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+ prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+ outputFile.write(prettyXmlStr.encode('utf-8'))
+
+def capitalizeLine(line):
+ return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+ logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+ #
+ # extract all devices addresses from audio policy configuration file
+ #
+ address_criteria_mapping_table = {
+ 'sink' : "OutputDevicesAddressesType",
+ 'source' : "InputDevicesAddressesType" }
+
+ address_criteria = {
+ 'OutputDevicesAddressesType' : [],
+ 'InputDevicesAddressesType' : [] }
+
+ oldWorkingDir = os.getcwd()
+ print "Current working directory %s" % oldWorkingDir
+
+ newDir = os.path.join(oldWorkingDir , audiopolicyconfigurationfile.name)
+
+ policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+ os.chdir(os.path.dirname(os.path.normpath(newDir)))
+
+ print "new working directory %s" % os.getcwd()
+
+ policy_root = policy_in_tree.getroot()
+ EI.include(policy_root)
+
+ os.chdir(oldWorkingDir)
+
+ for device in policy_root.iter('devicePort'):
+ for key in address_criteria_mapping_table.keys():
+ if device.get('role') == key and device.get('address') :
+ logging.info("{}: <{}>".format(key, device.get('address')))
+ address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+ for criteria in address_criteria:
+ values = ','.join(address_criteria[criteria])
+ logging.info("{}: <{}>".format(criteria, values))
+
+ return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+# -Android Mode
+# -Output devices type
+# -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile):
+ #
+ # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+ #
+ criterion_mapping_table = {
+ 'AUDIO_MODE' : "AndroidModeType",
+ 'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+ 'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+ all_criteria = {
+ 'AndroidModeType' : {},
+ 'OutputDevicesMaskType' : {},
+ 'InputDevicesMaskType' : {} }
+
+ #
+ # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+ #
+ ignored_values = [ 'CNT', 'MAX', 'ALL', 'NONE' ]
+
+ criteria_pattern = re.compile(
+ r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))\_" \
+ r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+ r"(?P<values>(?:0[xX])?[0-9a-fA-F]+)")
+
+ logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+ for line_number, line in enumerate(androidaudiobaseheaderFile):
+ match = criteria_pattern.match(line)
+ if match:
+ logging.debug("The following line is VALID: {}:{}\n{}".format(
+ androidaudiobaseheaderFile.name, line_number, line))
+
+ criterion_name = criterion_mapping_table[match.groupdict()['type']]
+ literal = ''.join((w.capitalize() for w in match.groupdict()['literal'].split('_')))
+ numerical_value = match.groupdict()['values']
+
+ # for AUDIO_DEVICE_IN: need to remove sign bit
+ if criterion_name == "InputDevicesMaskType":
+ numerical_value = str(int(numerical_value, 0) & ~2147483648)
+
+ # Remove duplicated numerical values
+ if int(numerical_value, 0) in all_criteria[criterion_name].values():
+ logging.info("criterion {} duplicated values:".format(criterion_name))
+ logging.info("{}:{}".format(numerical_value, literal))
+ logging.info("KEEPING LATEST")
+ for key in all_criteria[criterion_name].keys():
+ if all_criteria[criterion_name][key] == int(numerical_value, 0):
+ del all_criteria[criterion_name][key]
+
+ all_criteria[criterion_name][literal] = int(numerical_value, 0)
+
+ logging.debug("type:{},".format(criterion_name))
+ logging.debug("iteral:{},".format(literal))
+ logging.debug("values:{}.".format(numerical_value))
+
+ return all_criteria
+
+
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader)
+
+ address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+ criterion_types = args.criteriontypes
+
+ generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
new file mode 100644
index 0000000..2b86469
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/build_audio_pfw_settings.mk
@@ -0,0 +1,35 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_TOOL := domainGeneratorPolicy.py
+$(LOCAL_BUILT_MODULE): MY_TOPLEVEL_FILE := $(PFW_TOPLEVEL_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERIA_FILE := $(PFW_CRITERIA_FILE)
+$(LOCAL_BUILT_MODULE): MY_TUNING_FILE := $(PFW_TUNING_FILE)
+$(LOCAL_BUILT_MODULE): MY_EDD_FILES := $(PFW_EDD_FILES)
+$(LOCAL_BUILT_MODULE): MY_DOMAIN_FILES := $(PFW_DOMAIN_FILES)
+$(LOCAL_BUILT_MODULE): MY_SCHEMAS_DIR := $(PFW_SCHEMAS_DIR)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(PFW_CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) domainGeneratorPolicy.py
+
+ "$(MY_TOOL)" --validate \
+ --toplevel-config "$(MY_TOPLEVEL_FILE)" \
+ --criteria "$(MY_CRITERIA_FILE)" \
+ --criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+ --initial-settings $(MY_TUNING_FILE) \
+ --add-edds $(MY_EDD_FILES) \
+ --add-domains $(MY_DOMAIN_FILES) \
+ --schemas-dir $(MY_SCHEMAS_DIR) > "$@"
+
+
+# Clear variables for further use
+PFW_TOPLEVEL_FILE :=
+PFW_STRUCTURE_FILES :=
+PFW_CRITERIA_FILE :=
+PFW_CRITERION_TYPES_FILE :=
+PFW_TUNING_FILE :=
+PFW_EDD_FILES :=
+PFW_DOMAIN_FILES :=
+PFW_SCHEMAS_DIR := $(PFW_DEFAULT_SCHEMAS_DIR)
diff --git a/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
new file mode 100755
index 0000000..7929402
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/domainGeneratorPolicy.py
@@ -0,0 +1,268 @@
+#!/usr/bin/python
+
+#
+# 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.
+#
+
+import EddParser
+from PFWScriptGenerator import PfwScriptTranslator
+import hostConfig
+
+import argparse
+import re
+import sys
+import tempfile
+import os
+import logging
+import subprocess
+import xml.etree.ElementTree as ET
+
+#
+# In order to build the XML Settings file at build time, an instance of the parameter-framework
+# shall be started and fed with all the criterion types/criteria that will be used by
+# the engineconfigurable.
+# This scripts allows generates the settings from the same audio_criterion_types.xml /
+# audio_criteria.xml files used at run time by the engineconfigurable
+#
+
+def parseArgs():
+ argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+ Settings file generator.\n\
+ Exit with the number of (recoverable or not) error that occured.")
+ argparser.add_argument('--toplevel-config',
+ help="Top-level parameter-framework configuration file. Mandatory.",
+ metavar="TOPLEVEL_CONFIG_FILE",
+ required=True)
+ argparser.add_argument('--criteria',
+ help="Criteria file, in XML format: \
+ in '<criteria> \
+ <criterion name="" type=""/> \
+ </criteria>' \
+ format. Mandatory.",
+ metavar="CRITERIA_FILE",
+ type=argparse.FileType('r'),
+ required=True)
+ argparser.add_argument('--criteriontypes',
+ help="Criterion types XML file, in \
+ '<criterion_types> \
+ <criterion_type name="" type=<inclusive|exclusive> values=<value1,value2,...>/> \
+ </criterion_types>' \
+ format. Mandatory.",
+ metavar="CRITERION_TYPE_FILE",
+ type=argparse.FileType('r'),
+ required=False)
+ argparser.add_argument('--initial-settings',
+ help="Initial XML settings file (containing a \
+ <ConfigurableDomains> tag",
+ nargs='?',
+ default=None,
+ metavar="XML_SETTINGS_FILE")
+ argparser.add_argument('--add-domains',
+ help="List of single domain files (each containing a single \
+ <ConfigurableDomain> tag",
+ metavar="XML_DOMAIN_FILE",
+ nargs='*',
+ dest='xml_domain_files',
+ default=[])
+ argparser.add_argument('--add-edds',
+ help="List of files in EDD syntax (aka \".pfw\" files)",
+ metavar="EDD_FILE",
+ type=argparse.FileType('r'),
+ nargs='*',
+ default=[],
+ dest='edd_files')
+ argparser.add_argument('--schemas-dir',
+ help="Directory of parameter-framework XML Schemas for generation \
+ validation",
+ default=None)
+ argparser.add_argument('--target-schemas-dir',
+ help="Ignored. Kept for retro-compatibility")
+ argparser.add_argument('--validate',
+ help="Validate the settings against XML schemas",
+ action='store_true')
+ argparser.add_argument('--verbose',
+ action='store_true')
+
+ return argparser.parse_args()
+
+#
+# Parses audio_criterion_types.xml / audio_criteria.xml files used at run time by the
+# engineconfigurable and outputs a dictionnary of criteria.
+# For each criteria, the name, type (aka inclusive (bitfield) or exclusive (enum), the values
+# are provided.
+#
+def parseCriteriaAndCriterionTypes(criteriaFile, criterionTypesFile):
+ # Parse criteria and criterion types XML files
+ #
+ criteria_tree = ET.parse(criteriaFile)
+ logging.info("Importing criteriaFile {}".format(criteriaFile))
+ criterion_types_tree = ET.parse(criterionTypesFile)
+ logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+
+ criteria_root = criteria_tree.getroot()
+ criterion_types_root = criterion_types_tree.getroot()
+
+ all_criteria = []
+ for criterion in criteria_root.findall('criterion'):
+ criterion_name = criterion.get('name')
+ type_name = criterion.get('type')
+ logging.info("Importing criterion_name {}".format(criterion_name))
+ logging.info("Importing type_name {}".format(type_name))
+
+ for criterion_types in criterion_types_tree.findall('criterion_type'):
+ criterion_type_name = criterion_types.get('name')
+ if criterion_type_name == type_name:
+ criterion_inclusiveness = criterion_types.get('type')
+
+ criterion_values = []
+
+ values_node = criterion_types.find('values')
+ if values_node:
+ for value in values_node.findall('value'):
+ criterion_values.append(value.get('literal'))
+
+ if len(criterion_values) == 0:
+ criterion_values.append('')
+
+ logging.info("Importing criterion_type_name {}".format(criterion_type_name))
+ logging.info("Importing criterion_inclusiveness {}".format(criterion_inclusiveness))
+ logging.info("Importing criterion_values {}".format(criterion_values))
+
+ all_criteria.append({
+ "name" : criterion_name,
+ "inclusive" : criterion_inclusiveness,
+ "values" : criterion_values})
+ break
+
+ return all_criteria
+
+#
+# Parses the Edd files (aka .pfw extension file), which is a simplified language to write the
+# parameter framework settings.
+#
+def parseEdd(EDDFiles):
+ parsed_edds = []
+
+ for edd_file in EDDFiles:
+ try:
+ root = EddParser.Parser().parse(edd_file)
+ except EddParser.MySyntaxError as ex:
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(2)
+
+ try:
+ root.propagate()
+ except EddParser.MyPropagationError, ex :
+ logging.critical(str(ex))
+ logging.info("EXIT ON FAILURE")
+ exit(1)
+
+ parsed_edds.append((edd_file.name, root))
+ return parsed_edds
+
+#
+# Generates all the required commands to be sent to the instance of parameter-framework launched
+# at runtime to generate the XML Settings file.
+# It takes as input the collection of criteria, the domains and the simplified settings read from
+# pfw.
+#
+def generateDomainCommands(logging, all_criteria, initial_settings, xml_domain_files, parsed_edds):
+ # create and inject all the criteria
+ logging.info("Creating all criteria")
+ for criterion in all_criteria:
+ yield ["createSelectionCriterion", criterion['inclusive'],
+ criterion['name']] + criterion['values']
+
+ yield ["start"]
+
+ # Import initial settings file
+ if initial_settings:
+ logging.info("Importing initial settings file {}".format(initial_settings))
+ yield ["importDomainsWithSettingsXML", initial_settings]
+
+ # Import each standalone domain files
+ for domain_file in xml_domain_files:
+ logging.info("Importing single domain file {}".format(domain_file))
+ yield ["importDomainWithSettingsXML", domain_file]
+
+ # Generate the script for each EDD file
+ for filename, parsed_edd in parsed_edds:
+ logging.info("Translating and injecting EDD file {}".format(filename))
+ translator = PfwScriptTranslator()
+ parsed_edd.translate(translator)
+ for command in translator.getScript():
+ yield command
+
+#
+# Entry point of the domain generator.
+# -Parses Criterion types and criteria files
+# -Parses settings written in simplified pfw language.
+# -Launches a parameter-framework
+# -Translates the settings into command that can be interpreted by parameter-framework.
+# -Use the exports command and output them in XML Settings file.
+#
+def main():
+ logging.root.setLevel(logging.INFO)
+ args = parseArgs()
+
+ all_criteria = parseCriteriaAndCriterionTypes(args.criteria, args.criteriontypes)
+
+ #
+ # EDD files (aka ".pfw" files)
+ #
+ parsed_edds = parseEdd(args.edd_files)
+
+ # We need to modify the toplevel configuration file to account for differences
+ # between development setup and target (installation) setup, in particular, the
+ # TuningMwith ode must be enforced, regardless of what will be allowed on the target
+ fake_toplevel_config = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix=".xml",
+ prefix="TMPdomainGeneratorPFConfig_")
+
+ install_path = os.path.dirname(os.path.realpath(args.toplevel_config))
+ hostConfig.configure(
+ infile=args.toplevel_config,
+ outfile=fake_toplevel_config,
+ structPath=install_path)
+ fake_toplevel_config.close()
+
+ # Create the connector. Pipe its input to us in order to write commands;
+ # connect its output to stdout in order to have it dump the domains
+ # there; connect its error output to stderr.
+ connector = subprocess.Popen(["domainGeneratorConnector",
+ fake_toplevel_config.name,
+ 'verbose' if args.verbose else 'no-verbose',
+ 'validate' if args.validate else 'no-validate',
+ args.schemas_dir],
+ stdout=sys.stdout, stdin=subprocess.PIPE, stderr=sys.stderr)
+
+ initial_settings = None
+ if args.initial_settings:
+ initial_settings = os.path.realpath(args.initial_settings)
+
+ for command in generateDomainCommands(logging, all_criteria, initial_settings,
+ args.xml_domain_files, parsed_edds):
+ connector.stdin.write('\0'.join(command))
+ connector.stdin.write("\n")
+
+ # Closing the connector's input triggers the domain generation
+ connector.stdin.close()
+ connector.wait()
+ os.remove(fake_toplevel_config.name)
+ return connector.returncode
+
+# If this file is directly executed
+if __name__ == "__main__":
+ exit(main())
diff --git a/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
new file mode 100644
index 0000000..4814376
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/provision_criterion_types_from_android_headers.mk
@@ -0,0 +1,24 @@
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TYPES_FILE := $(CRITERION_TYPES_FILE)
+$(LOCAL_BUILT_MODULE): MY_ANDROID_AUDIO_BASE_HEADER_FILE := $(ANDROID_AUDIO_BASE_HEADER_FILE)
+$(LOCAL_BUILT_MODULE): MY_AUDIO_POLICY_CONFIGURATION_FILE := $(AUDIO_POLICY_CONFIGURATION_FILE)
+$(LOCAL_BUILT_MODULE): MY_CRITERION_TOOL := $(HOST_OUT)/bin/buildPolicyCriterionTypes.py
+$(LOCAL_BUILT_MODULE): $(LOCAL_REQUIRED_MODULES) $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+ buildPolicyCriterionTypes.py \
+ $(CRITERION_TYPES_FILE) \
+ $(ANDROID_AUDIO_BASE_HEADER_FILE)
+
+ "$(MY_CRITERION_TOOL)" \
+ --androidaudiobaseheader "$(MY_ANDROID_AUDIO_BASE_HEADER_FILE)" \
+ --audiopolicyconfigurationfile "$(MY_AUDIO_POLICY_CONFIGURATION_FILE)" \
+ --criteriontypes "$(MY_CRITERION_TYPES_FILE)" \
+ --outputfile "$(@)"
+
+# Clear variables for further use
+CRITERION_TYPES_FILE :=
+ANDROID_AUDIO_BASE_HEADER_FILE :=
+AUDIO_POLICY_CONFIGURATION_FILE :=
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.mk b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
index b128a38..d19a364 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.mk
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.mk
@@ -1,5 +1,8 @@
LOCAL_PATH:= $(call my-dir)
+TOOLS := frameworks/av/services/audiopolicy/engineconfigurable/tools
+PROVISION_CRITERION_TYPES := $(TOOLS)/provision_criterion_types_from_android_headers.mk
+
##################################################################
# WRAPPER LIBRARY
##################################################################
@@ -10,12 +13,22 @@
$(LOCAL_PATH)/include \
frameworks/av/services/audiopolicy/engineconfigurable/include \
frameworks/av/services/audiopolicy/engineconfigurable/interface \
+ frameworks/av/services/audiopolicy/common/include \
+ external/libxml2/include \
+ external/icu/icu4c/source/common
-LOCAL_SRC_FILES:= ParameterManagerWrapper.cpp
+LOCAL_SRC_FILES:= \
+ ParameterManagerWrapper.cpp \
+ ParameterManagerWrapperConfig.cpp
LOCAL_SHARED_LIBRARIES := \
libparameter \
- libmedia_helper
+ libmedia_helper \
+ libicuuc \
+ libxml2
+
+LOCAL_STATIC_LIBRARIES := \
+ libaudiopolicycomponents
LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
@@ -31,11 +44,35 @@
# CONFIGURATION FILE
##################################################################
-# specific management of audio_policy_criteria.conf
+ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
+
include $(CLEAR_VARS)
-LOCAL_MODULE := audio_policy_criteria.conf
+LOCAL_MODULE := policy_wrapper_configuration.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_VENDOR_MODULE := true
LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criteria.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_SRC_FILES := config/$(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := policy_criterion_types.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+
+AUDIO_POLICY_CONFIGURATION_FILE := $(TARGET_OUT_VENDOR_ETC)/audio_policy_configuration.xml
+ANDROID_AUDIO_BASE_HEADER_FILE := system/media/audio/include/system/audio-base.h
+CRITERION_TYPES_FILE := $(LOCAL_PATH)/config/policy_criterion_types.xml.in
+
+include $(PROVISION_CRITERION_TYPES)
+
+endif #ifeq ($(BUILD_AUDIO_POLICY_EXAMPLE_CONFIGURATION), 1)
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 9b0442e..1934fa4 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include "ParameterManagerWrapper.h"
-#include "audio_policy_criteria_conf.h"
+#include "ParameterManagerWrapperConfig.h"
#include <ParameterMgrPlatformConnector.h>
#include <SelectionCriterionTypeInterface.h>
#include <SelectionCriterionInterface.h>
@@ -38,6 +38,7 @@
using std::string;
using std::map;
using std::vector;
+using CriterionTypes = std::map<std::string, ISelectionCriterionTypeInterface *>;
/// PFW related definitions
// Logger
@@ -56,16 +57,36 @@
}
};
-namespace android
-{
+namespace android {
using utilities::convertTo;
-namespace audio_policy
-{
+namespace audio_policy {
+
const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
"/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+ * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
+ */
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+ [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
+ [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
+ [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
+ [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
+ [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
+ [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
+ [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
+ [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
+};
+
template <>
struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
template <>
@@ -80,15 +101,64 @@
// Logger
mPfwConnector->setLogger(mPfwConnectorLogger);
- // Load criteria file
- if ((loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaVendorConfFilePath) != NO_ERROR) &&
- (loadAudioPolicyCriteriaConfig(gAudioPolicyCriteriaConfFilePath) != NO_ERROR)) {
- ALOGE("%s: Neither vendor conf file (%s) nor system conf file (%s) could be found",
- __FUNCTION__, gAudioPolicyCriteriaVendorConfFilePath,
- gAudioPolicyCriteriaConfFilePath);
+ status_t loadResult = loadConfig();
+ if (loadResult < 0) {
+ ALOGE("Policy Wrapper configuration is partially invalid.");
}
}
+status_t ParameterManagerWrapper::loadConfig()
+{
+ auto result = wrapper_config::parse();
+ if (result.parsedConfig == nullptr) {
+ return -ENOENT;
+ }
+ ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+
+ CriterionTypes criterionTypes;
+ for (auto criterionType : result.parsedConfig->criterionTypes) {
+ ALOG_ASSERT(criterionTypes.find(criterionType.name) == criterionTypes.end(),
+ "CriterionType %s already added", criterionType.name.c_str());
+ ALOGV("%s: Adding new criterionType %s", __FUNCTION__, criterionType.name.c_str());
+
+ auto criterionTypePfw =
+ mPfwConnector->createSelectionCriterionType(criterionType.isInclusive);
+
+ for (auto pair : criterionType.valuePairs) {
+ std::string error;
+ ALOGV("%s: Adding pair %d,%s for criterionType %s", __FUNCTION__, pair.first,
+ pair.second.c_str(), criterionType.name.c_str());
+ criterionTypePfw->addValuePair(pair.first, pair.second, error);
+ }
+ criterionTypes[criterionType.name] = criterionTypePfw;
+ }
+
+ for (auto criterion : result.parsedConfig->criteria) {
+ ALOG_ASSERT(mPolicyCriteria.find(criterion.name) == mPolicyCriteria.end(),
+ "%s: Criterion %s already added", __FUNCTION__, criterion.name.c_str());
+
+ auto criterionType =
+ getElement<ISelectionCriterionTypeInterface>(criterion.typeName, criterionTypes);
+ ALOG_ASSERT(criterionType != nullptr, "No %s Criterion type found for criterion %s",
+ criterion.typeName.c_str(), criterion.name.c_str());
+
+ auto criterionPfw = mPfwConnector->createSelectionCriterion(criterion.name, criterionType);
+ mPolicyCriteria[criterion.name] = criterionPfw;
+
+ if (not criterion.defaultLiteralValue.empty()) {
+ int numericalValue = 0;
+ if (not criterionType->getNumericalValue(criterion.defaultLiteralValue.c_str(),
+ numericalValue)) {
+ ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
+ criterion.defaultLiteralValue.c_str());
+ continue;
+ }
+ criterionPfw->setCriterionState(numericalValue);
+ }
+ }
+ return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
ParameterManagerWrapper::~ParameterManagerWrapper()
{
// Unset logger
@@ -112,112 +182,6 @@
return NO_ERROR;
}
-
-void ParameterManagerWrapper::addCriterionType(const string &typeName, bool isInclusive)
-{
- ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) == mPolicyCriterionTypes.end(),
- "CriterionType %s already added", typeName.c_str());
- ALOGD("%s: Adding new criterionType %s", __FUNCTION__, typeName.c_str());
-
- mPolicyCriterionTypes[typeName] = mPfwConnector->createSelectionCriterionType(isInclusive);
-}
-
-void ParameterManagerWrapper::addCriterionTypeValuePair(
- const string &typeName,
- uint32_t numericValue,
- const string &literalValue)
-{
- ALOG_ASSERT(mPolicyCriterionTypes.find(typeName) != mPolicyCriterionTypes.end(),
- "CriterionType %s not found", typeName.c_str());
- ALOGV("%s: Adding new value pair (%d,%s) for criterionType %s", __FUNCTION__,
- numericValue, literalValue.c_str(), typeName.c_str());
- ISelectionCriterionTypeInterface *criterionType = mPolicyCriterionTypes[typeName];
- std::string error;
- criterionType->addValuePair(numericValue, literalValue, error);
-}
-
-void ParameterManagerWrapper::loadCriterionType(cnode *root, bool isInclusive)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node;
- for (node = root->first_child; node != NULL; node = node->next) {
-
- ALOG_ASSERT(node != NULL, "error in parsing file");
- const char *typeName = node->name;
- char *valueNames = strndup(node->value, strlen(node->value));
-
- addCriterionType(typeName, isInclusive);
-
- uint32_t index = 0;
- char *ctx;
- char *valueName = strtok_r(valueNames, ",", &ctx);
- while (valueName != NULL) {
- if (strlen(valueName) != 0) {
-
- // Conf file may use or not pair, if no pair, use incremental index, else
- // use provided index.
- if (strchr(valueName, ':') != NULL) {
-
- char *first = strtok(valueName, ":");
- char *second = strtok(NULL, ":");
- ALOG_ASSERT((first != NULL) && (strlen(first) != 0) &&
- (second != NULL) && (strlen(second) != 0),
- "invalid value pair");
-
- if (!convertTo<string, uint32_t>(first, index)) {
- ALOGE("%s: Invalid index(%s) found", __FUNCTION__, first);
- }
- addCriterionTypeValuePair(typeName, index, second);
- } else {
-
- uint32_t pfwIndex = isInclusive ? 1 << index : index;
- addCriterionTypeValuePair(typeName, pfwIndex, valueName);
- index += 1;
- }
- }
- valueName = strtok_r(NULL, ",", &ctx);
- }
- free(valueNames);
- }
-}
-
-void ParameterManagerWrapper::loadInclusiveCriterionType(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gInclusiveCriterionTypeTag.c_str());
- if (node == NULL) {
- return;
- }
- loadCriterionType(node, true);
-}
-
-void ParameterManagerWrapper::loadExclusiveCriterionType(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gExclusiveCriterionTypeTag.c_str());
- if (node == NULL) {
- return;
- }
- loadCriterionType(node, false);
-}
-
-void ParameterManagerWrapper::parseChildren(cnode *root, string &defaultValue, string &type)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node;
- for (node = root->first_child; node != NULL; node = node->next) {
- ALOG_ASSERT(node != NULL, "error in parsing file");
-
- if (string(node->name) == gDefaultTag) {
- defaultValue = node->value;
- } else if (string(node->name) == gTypeTag) {
- type = node->value;
- } else {
- ALOGE("%s: Unrecognized %s %s node", __FUNCTION__, node->name, node->value);
- }
- }
-}
-
template <typename T>
T *ParameterManagerWrapper::getElement(const string &name, std::map<string, T *> &elementsMap)
{
@@ -236,97 +200,6 @@
return it != elementsMap.end() ? it->second : NULL;
}
-void ParameterManagerWrapper::loadCriteria(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gCriterionTag.c_str());
-
- if (node == NULL) {
- ALOGW("%s: no inclusive criteria found", __FUNCTION__);
- return;
- }
- for (node = node->first_child; node != NULL; node = node->next) {
- loadCriterion(node);
- }
-}
-
-void ParameterManagerWrapper::addCriterion(const string &name, const string &typeName,
- const string &defaultLiteralValue)
-{
- ALOG_ASSERT(mPolicyCriteria.find(name) == mPolicyCriteria.end(),
- "Route Criterion %s already added", name.c_str());
-
- ISelectionCriterionTypeInterface *criterionType =
- getElement<ISelectionCriterionTypeInterface>(typeName, mPolicyCriterionTypes);
-
- ISelectionCriterionInterface *criterion =
- mPfwConnector->createSelectionCriterion(name, criterionType);
-
- mPolicyCriteria[name] = criterion;
- int numericalValue = 0;
- if (!criterionType->getNumericalValue(defaultLiteralValue.c_str(), numericalValue)) {
- ALOGE("%s; trying to apply invalid default literal value (%s)", __FUNCTION__,
- defaultLiteralValue.c_str());
- }
- criterion->setCriterionState(numericalValue);
-}
-
-void ParameterManagerWrapper::loadCriterion(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- const char *criterionName = root->name;
-
- ALOG_ASSERT(mPolicyCriteria.find(criterionName) == mPolicyCriteria.end(),
- "Criterion %s already added", criterionName);
-
- string paramKeyName = "";
- string path = "";
- string typeName = "";
- string defaultValue = "";
-
- parseChildren(root, defaultValue, typeName);
-
- addCriterion(criterionName, typeName, defaultValue);
-}
-
-void ParameterManagerWrapper::loadConfig(cnode *root)
-{
- ALOG_ASSERT(root != NULL, "error in parsing file");
- cnode *node = config_find(root, gPolicyConfTag.c_str());
- if (node == NULL) {
- ALOGW("%s: Could not find node for pfw", __FUNCTION__);
- return;
- }
- ALOGD("%s: Loading conf for pfw", __FUNCTION__);
- loadInclusiveCriterionType(node);
- loadExclusiveCriterionType(node);
- loadCriteria(node);
-}
-
-
-status_t ParameterManagerWrapper::loadAudioPolicyCriteriaConfig(const char *path)
-{
- ALOG_ASSERT(path != NULL, "error in parsing file: empty path");
- cnode *root;
- char *data;
- ALOGD("%s", __FUNCTION__);
- data = (char *)load_file(path, NULL);
- if (data == NULL) {
- return -ENODEV;
- }
- root = config_node("", "");
- ALOG_ASSERT(root != NULL, "Unable to allocate a configuration node");
- config_load(root, data);
-
- loadConfig(root);
-
- config_free(root);
- free(root);
- free(data);
- ALOGD("%s: loaded", __FUNCTION__);
- return NO_ERROR;
-}
-
bool ParameterManagerWrapper::isStarted()
{
return mPfwConnector && mPfwConnector->isStarted();
@@ -335,9 +208,9 @@
status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -351,9 +224,9 @@
audio_mode_t ParameterManagerWrapper::getPhoneState() const
{
const ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gPhoneStateCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
return AUDIO_MODE_NORMAL;
}
return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -370,7 +243,7 @@
ISelectionCriterionInterface *criterion =
getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
return BAD_VALUE;
}
if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -390,7 +263,7 @@
const ISelectionCriterionInterface *criterion =
getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage].c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
return AUDIO_POLICY_FORCE_NONE;
}
return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -404,12 +277,45 @@
return interface->getLiteralValue(valueToCheck, literalValue);
}
+status_t ParameterManagerWrapper::setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state)
+{
+ std::string criterionName = audio_is_output_device(devDesc->type()) ?
+ gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
+
+ ALOGV("%s: device with address %s %s", __FUNCTION__, devDesc->mAddress.string(),
+ state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
+ ISelectionCriterionInterface *criterion =
+ getElement<ISelectionCriterionInterface>(criterionName, mPolicyCriteria);
+
+ if (criterion == NULL) {
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, criterionName.c_str());
+ return DEAD_OBJECT;
+ }
+
+ auto criterionType = criterion->getCriterionType();
+ int deviceAddressId;
+ if (not criterionType->getNumericalValue(devDesc->address().string(), deviceAddressId)) {
+ ALOGW("%s: unknown device address reported (%s)", __FUNCTION__, devDesc->address().c_str());
+ return BAD_TYPE;
+ }
+ int currentValueMask = criterion->getCriterionState();
+ if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ currentValueMask |= deviceAddressId;
+ }
+ else {
+ currentValueMask &= ~deviceAddressId;
+ }
+ criterion->setCriterionState(currentValueMask);
+ return NO_ERROR;
+}
+
status_t ParameterManagerWrapper::setAvailableInputDevices(audio_devices_t inputDevices)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gInputDeviceCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gInputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(inputDevices & ~AUDIO_DEVICE_BIT_IN);
@@ -420,9 +326,9 @@
status_t ParameterManagerWrapper::setAvailableOutputDevices(audio_devices_t outputDevices)
{
ISelectionCriterionInterface *criterion =
- getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionTag, mPolicyCriteria);
+ getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
if (criterion == NULL) {
- ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionTag.c_str());
+ ALOGE("%s: no criterion found for %s", __FUNCTION__, gOutputDeviceCriterionName);
return DEAD_OBJECT;
}
criterion->setCriterionState(outputDevices);
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
new file mode 100644
index 0000000..bc6d046
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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 "APM::AudioPolicyEngine/PFWWrapperConfig"
+#define LOG_NDEBUG 0
+
+#include "ParameterManagerWrapperConfig.h"
+
+#include <media/convert.h>
+#include <utils/Log.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <istream>
+
+
+namespace android {
+
+using utilities::convertTo;
+
+namespace audio_policy {
+namespace wrapper_config {
+namespace detail {
+
+std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
+{
+ xmlChar *xmlValue = xmlGetProp(cur, (const xmlChar *)attribute);
+ if (xmlValue == NULL) {
+ return "";
+ }
+ std::string value((const char *)xmlValue);
+ xmlFree(xmlValue);
+ return value;
+}
+
+template <class Trait>
+static status_t deserializeCollection(_xmlDoc *doc, const _xmlNode *cur,
+ typename Trait::Collection &collection,
+ size_t &nbSkippedElement)
+{
+ const xmlNode *root = cur->xmlChildrenNode;
+ while (root != NULL) {
+ if (xmlStrcmp(root->name, (const xmlChar *)Trait::collectionTag) &&
+ xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ root = root->next;
+ continue;
+ }
+ const xmlNode *child = root;
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::collectionTag)) {
+ child = child->xmlChildrenNode;
+ }
+ while (child != NULL) {
+ if (!xmlStrcmp(child->name, (const xmlChar *)Trait::tag)) {
+ status_t status = Trait::deserialize(doc, child, collection);
+ if (status == NO_ERROR) {
+ nbSkippedElement += 1;
+ }
+ }
+ child = child->next;
+ }
+ if (!xmlStrcmp(root->name, (const xmlChar *)Trait::tag)) {
+ return NO_ERROR;
+ }
+ root = root->next;
+ }
+ return NO_ERROR;
+}
+
+const char *const ValueTraits::tag = "value";
+const char *const ValueTraits::collectionTag = "values";
+
+const char ValueTraits::Attributes::literal[] = "literal";
+const char ValueTraits::Attributes::numerical[] = "numerical";
+
+status_t ValueTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &values)
+{
+ std::string literal = getXmlAttribute(child, Attributes::literal);
+ if (literal.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+ return BAD_VALUE;
+ }
+ uint32_t numerical = 0;
+ std::string numericalTag = getXmlAttribute(child, Attributes::numerical);
+ if (numericalTag.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::literal);
+ return BAD_VALUE;
+ }
+ if (!convertTo(numericalTag, numerical)) {
+ ALOGE("%s: : Invalid value(%s)", __FUNCTION__, numericalTag.c_str());
+ return BAD_VALUE;
+ }
+ values.push_back({numerical, literal});
+ return NO_ERROR;
+}
+
+const char *const CriterionTypeTraits::tag = "criterion_type";
+const char *const CriterionTypeTraits::collectionTag = "criterion_types";
+
+const char CriterionTypeTraits::Attributes::name[] = "name";
+const char CriterionTypeTraits::Attributes::type[] = "type";
+
+status_t CriterionTypeTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
+ Collection &criterionTypes)
+{
+ std::string name = getXmlAttribute(child, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::name, name.c_str());
+
+ std::string type = getXmlAttribute(child, Attributes::type);
+ if (type.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::type);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s %s = %s", __FUNCTION__, tag, Attributes::type, type.c_str());
+ bool isInclusive(type == "inclusive");
+
+ ValuePairs pairs;
+ size_t nbSkippedElements = 0;
+ detail::deserializeCollection<detail::ValueTraits>(doc, child, pairs, nbSkippedElements);
+
+ criterionTypes.push_back({name, isInclusive, pairs});
+ return NO_ERROR;
+}
+
+const char *const CriterionTraits::tag = "criterion";
+const char *const CriterionTraits::collectionTag = "criteria";
+
+const char CriterionTraits::Attributes::name[] = "name";
+const char CriterionTraits::Attributes::type[] = "type";
+const char CriterionTraits::Attributes::defaultVal[] = "default";
+
+status_t CriterionTraits::deserialize(_xmlDoc */*doc*/, const _xmlNode *child, Collection &criteria)
+{
+ std::string name = getXmlAttribute(child, Attributes::name);
+ if (name.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
+
+ std::string defaultValue = getXmlAttribute(child, Attributes::defaultVal);
+ if (defaultValue.empty()) {
+ // Not mandatory to provide a default value for a criterion, even it is recommanded...
+ ALOGV("%s: No attribute %s found", __FUNCTION__, Attributes::defaultVal);
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::defaultVal, defaultValue.c_str());
+
+ std::string typeName = getXmlAttribute(child, Attributes::type);
+ if (typeName.empty()) {
+ ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::name);
+ return BAD_VALUE;
+ }
+ ALOGV("%s: %s = %s", __FUNCTION__, Attributes::type, typeName.c_str());
+
+ criteria.push_back({name, typeName, defaultValue});
+ return NO_ERROR;
+}
+} // namespace detail
+
+ParsingResult parse(const char* path) {
+ xmlDocPtr doc;
+ doc = xmlParseFile(path);
+ if (doc == NULL) {
+ ALOGE("%s: Could not parse document %s", __FUNCTION__, path);
+ return {nullptr, 0};
+ }
+ xmlNodePtr cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
+ xmlFreeDoc(doc);
+ return {nullptr, 0};
+ }
+ if (xmlXIncludeProcess(doc) < 0) {
+ ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
+ return {nullptr, 0};
+ }
+ size_t nbSkippedElements = 0;
+ auto config = std::make_unique<Config>();
+
+ detail::deserializeCollection<detail::CriterionTraits>(
+ doc, cur, config->criteria, nbSkippedElements);
+ detail::deserializeCollection<detail::CriterionTypeTraits>(
+ doc, cur, config->criterionTypes, nbSkippedElements);
+
+ return {std::move(config), nbSkippedElements};
+}
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
new file mode 100644
index 0000000..467d0e1
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapperConfig.h
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <utils/Errors.h>
+
+struct _xmlNode;
+struct _xmlDoc;
+
+namespace android {
+namespace audio_policy {
+namespace wrapper_config {
+
+/** Default path of audio policy usages configuration file. */
+constexpr char DEFAULT_PATH[] = "/vendor/etc/policy_wrapper_configuration.xml";
+
+/** Directories where the effect libraries will be search for. */
+constexpr const char* POLICY_USAGE_LIBRARY_PATH[] = {"/odm/etc/", "/vendor/etc/", "/system/etc/"};
+
+using ValuePair = std::pair<uint32_t, std::string>;
+using ValuePairs = std::vector<ValuePair>;
+
+struct CriterionType
+{
+ std::string name;
+ bool isInclusive;
+ ValuePairs valuePairs;
+};
+
+using CriterionTypes = std::vector<CriterionType>;
+
+struct Criterion
+{
+ std::string name;
+ std::string typeName;
+ std::string defaultLiteralValue;
+};
+
+using Criteria = std::vector<Criterion>;
+
+struct Config {
+ float version;
+ Criteria criteria;
+ CriterionTypes criterionTypes;
+};
+
+namespace detail
+{
+struct ValueTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char literal[];
+ static const char numerical[];
+ };
+
+ typedef ValuePair Element;
+ typedef ValuePair *PtrElement;
+ typedef ValuePairs Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+
+struct CriterionTypeTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char type[];
+ };
+
+ typedef CriterionType Element;
+ typedef CriterionType *PtrElement;
+ typedef CriterionTypes Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+
+struct CriterionTraits
+{
+ static const char *const tag;
+ static const char *const collectionTag;
+
+ struct Attributes
+ {
+ static const char name[];
+ static const char type[];
+ static const char defaultVal[];
+ };
+
+ typedef Criterion Element;
+ typedef Criterion *PtrElement;
+ typedef Criteria Collection;
+
+ static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root,
+ Collection &collection);
+};
+} // namespace detail
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+ /** Parsed config, nullptr if the xml lib could not load the file */
+ std::unique_ptr<Config> parsedConfig;
+ size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Parses the provided audio policy usage configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult parse(const char* path = DEFAULT_PATH);
+
+} // namespace wrapper_config
+} // namespace audio_policy
+} // android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h b/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
deleted file mode 100644
index e4fd176..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/audio_policy_criteria_conf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2015 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 <string>
-#include <system/audio_policy.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-// Definitions for audio policy criteria configuration file (audio_policy_criteria.conf) //
-// //
-// @TODO: scripted from audio.h & audio_policy,h //
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-static const char *const gAudioPolicyCriteriaConfFilePath =
- "/system/etc/audio_policy_criteria.conf";
-static const char *const gAudioPolicyCriteriaVendorConfFilePath =
- "/vendor/etc/audio_policy_criteria.conf";
-
-/**
- * PFW instances tags
- */
-static const std::string &gPolicyConfTag = "Policy";
-static const std::string &gDefaultTag = "Default";
-static const std::string &gTypeTag = "Type";
-
-/**
- * PFW elements tags
- */
-static const std::string &gInclusiveCriterionTypeTag = "InclusiveCriterionType";
-static const std::string &gExclusiveCriterionTypeTag = "ExclusiveCriterionType";
-static const std::string &gCriterionTag = "Criterion";
-
-/**
- * PFW known criterion tags
- */
-static const std::string &gInputDeviceCriterionTag = "AvailableInputDevices";
-static const std::string &gOutputDeviceCriterionTag = "AvailableOutputDevices";
-static const std::string &gPhoneStateCriterionTag = "TelephonyMode";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const std::string gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
- [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] = "ForceUseForCommunication",
- [AUDIO_POLICY_FORCE_FOR_MEDIA] = "ForceUseForMedia",
- [AUDIO_POLICY_FORCE_FOR_RECORD] = "ForceUseForRecord",
- [AUDIO_POLICY_FORCE_FOR_DOCK] = "ForceUseForDock",
- [AUDIO_POLICY_FORCE_FOR_SYSTEM] = "ForceUseForSystem",
- [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] = "ForceUseForHdmiSystemAudio",
- [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] = "ForceUseForEncodedSurround",
- [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] = "ForceUseForVibrateRinging"
-};
-
-
-
-
-
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf b/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
deleted file mode 100644
index 043d5a6..0000000
--- a/services/audiopolicy/engineconfigurable/wrapper/config/audio_policy_criteria.conf
+++ /dev/null
@@ -1,146 +0,0 @@
-################################################################################################
-#
-# @NOTE:
-# Audio Policy Criteria file example for generic device build
-#
-# Any vendor shall have its own configuration within the corresponding device folder
-#
-################################################################################################
-
-#########################################################
-# Criterion type Example:
-# For each criterion, a couple of numerical, literal values must be provided to the PFW.
-# The numerical part is not mandatory. If not filled by the user, a default numerical value will be
-# automatically provided by audio HAL using the following logic:
-# - Exclusive criterion:
-# * 0 -> first literal value,
-# * 1 -> second literal value,
-# ...
-# * N -> (N+1)th literal value.
-# - Inclusive criterion:
-# * 1 << 0 -> first literal value,
-# * 1 << 1 -> second literal value,
-# ...
-# * 1 << N -> (N+1)th literal value,
-#
-#########################################################
-# Policy {
-# InclusiveCriterionType|ExclusiveCriterionType {
-# <Criterion Name> [numerical value 1:]<literal value 1>,[numerical value 2:]<literal value 2>,<literal value 3>,...
-# }
-# }
-
-#########################################################
-# Criterion:
-#########################################################
-# Policy {
-# Criterion {
-# <Criterion Name> {
-# Type <Criterion type name>
-# Default <default value of the criterion>
-# }
-# }
-# }
-
-Policy {
- InclusiveCriterionType {
- #
- # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
- # AUDIO_DEVICE_OUT_* within <system/audio.h> file of android.
- #
- OutputDevicesMaskType Earpiece,Speaker,WiredHeadset,WiredHeadphone,BluetoothSco,BluetoothScoHeadset,BluetoothScoCarkit,BluetoothA2dp,BluetoothA2dpHeadphones,BluetoothA2dpSpeaker,Hdmi,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,RemoteSubmix,TelephonyTx,Line,HdmiArc,Spdif,Fm,AuxLine,SpeakerSafe
- #
- # DO NOT CHANGE ORDER. This definition must be aligned with the definition of
- # AUDIO_DEVICE_IN_* within <system/audio.h> file of android.
- # Note also that direction bit will be decimated by AudioHAL in order to allow using a mask
- # with the cardinality of 1 between a bit and an input device.
- #
- InputDevicesMaskType Communication,Ambient,BuiltinMic,BluetoothScoHeadset,WiredHeadset,Hdmi,TelephonyRx,BackMic,RemoteSubmix,AnlgDockHeadset,DgtlDockHeadset,UsbAccessory,UsbDevice,FmTuner,TvTune,Line,Spdif,BluetoothA2dp,Loopback
- }
- ExclusiveCriterionType {
- #
- # The values of the mode MUST be aligned with the definition of the audio_mode_t
- # from system/audio.h
- #
- AndroidModeType 0:Normal,1:RingTone,2:InCall,3:InCommunication
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForCommunicationType 0:ForceNone,1:ForceSpeaker,3:ForceBtSco
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForMediaType 0:ForceNone,1:ForceSpeaker,2:ForceHeadphones,4:ForceBtA2dp,5:ForceWiredAccessory,8:ForceAnalogDock,9:ForceDigitalDock,10:ForceNoBtA2dp
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForRecordType 0:ForceNone,3:ForceBtSco,5:ForceWiredAccessory
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForDockType 0:ForceNone,5:ForceWiredAccessory,6:ForceBtCarDock,7:ForceBtDeskDock,8:ForceAnalogDock,9:ForceDigitalDock
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForSystemType 0:ForceNone,11:ForceSystemEnforced
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio.h
- #
- ForceUseForHdmiSystemAudioType 0:ForceNone,12:ForceHdmiSystemEnforced
- #
- # The values of the mode MUST be aligned with the definition of the
- # audio_policy_forced_config_t from system/audio_policy.h
- #
- ForceUseForEncodedSurroundType 0:ForceNone,13:ForceEncodedSurroundNever,14:ForceEncodedSurroundAlways
- }
-
- Criterion {
- AvailableInputDevices {
- Type InputDevicesMaskType
- Default none
- }
- AvailableOutputDevices {
- Type OutputDevicesMaskType
- Default none
- }
- TelephonyMode {
- Type AndroidModeType
- Default Normal
- }
- ForceUseForCommunication {
- Type ForceUseForCommunicationType
- Default ForceNone
- }
- ForceUseForMedia {
- Type ForceUseForMediaType
- Default ForceNone
- }
- ForceUseForRecord {
- Type ForceUseForRecordType
- Default ForceNone
- }
- ForceUseForDock {
- Type ForceUseForDockType
- Default ForceNone
- }
- ForceUseForSystem {
- Type ForceUseForSystemType
- Default ForceNone
- }
- ForceUseForHdmiSystemAudio {
- Type ForceUseForHdmiSystemAudioType
- Default ForceNone
- }
- ForceUseForEncodedSurround {
- Type ForceUseForEncodedSurroundType
- Default ForceNone
- }
- }
-}
-
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
new file mode 100644
index 0000000..ec82b2e
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criteria.xml
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- 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.
+-->
+<criteria>
+ <criterion name="AvailableInputDevices" type="InputDevicesMaskType" default="none"/>
+ <criterion name="AvailableOutputDevices" type="OutputDevicesMaskType" default="none"/>
+ <criterion name="AvailableOutputDevicesAddresses" type="OutputDevicesAddressesType" default="none"/>
+ <criterion name="AvailableInputDevicesAddresses" type="InputDevicesAddressesType" default="none"/>
+ <criterion name="TelephonyMode" type="AndroidModeType" default="Normal"/>
+ <criterion name="ForceUseForCommunication" type="ForceUseForCommunicationType" default="ForceNone"/>
+ <criterion name="ForceUseForMedia" type="ForceUseForMediaType" default="ForceNone"/>
+ <criterion name="ForceUseForRecord" type="ForceUseForRecordType" default="ForceNone"/>
+ <criterion name="ForceUseForDock" type="ForceUseForDockType" default="ForceNone"/>
+ <criterion name="ForceUseForSystem" type="ForceUseForSystemType" default="ForceNone"/>
+ <criterion name="ForceUseForHdmiSystemAudio" type="ForceUseForHdmiSystemAudioType" default="ForceNone"/>
+ <criterion name="ForceUseForEncodedSurround" type="ForceUseForEncodedSurroundType" default="ForceNone"/>
+ <criterion name="ForceUseForVibrateRinging" type="ForceUseForVibrateRingingType" default="ForceNone"/>
+</criteria>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
new file mode 100644
index 0000000..6cb799f
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_criterion_types.xml.in
@@ -0,0 +1,91 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- 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.
+-->
+<criterion_types>
+ <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+ <criterion_type name="OutputDevicesAddressesType" type="inclusive"/>
+ <criterion_type name="InputDevicesAddressesType" type="inclusive"/>
+ <criterion_type name="AndroidModeType" type="exclusive"/>
+ <criterion_type name="BooleanType" type="exclusive">
+ <values>
+ <value literal="False" numerical="0"/>
+ <value literal="True" numerical="1"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSpeaker" numerical="1"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForMediaType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSpeaker" numerical="1"/>
+ <value literal="ForceHeadphones" numerical="2"/>
+ <value literal="ForceBtA2dp" numerical="4"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ <value literal="ForceAnalogDock" numerical="8"/>
+ <value literal="ForceDigitalDock" numerical="9"/>
+ <value literal="ForceNoBtA2dp" numerical="10"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForRecordType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForDockType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceWiredAccessory" numerical="5"/>
+ <value literal="ForceBtCarDock" numerical="6"/>
+ <value literal="ForceBtDeskDock" numerical="7"/>
+ <value literal="ForceAnalogDock" numerical="8"/>
+ <value literal="ForceDigitalDock" numerical="9"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForSystemType" type="exclusive" >
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceSystemEnforced" numerical="11"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceHdmiSystemEnforced" numerical="12"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceEncodedSurroundNever" numerical="13"/>
+ <value literal="ForceEncodedSurroundAlways" numerical="14"/>
+ </values>
+ </criterion_type>
+ <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+ <values>
+ <value literal="ForceNone" numerical="0"/>
+ <value literal="ForceBtSco" numerical="3"/>
+ </values>
+ </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
new file mode 100644
index 0000000..5d9193b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/wrapper/config/policy_wrapper_configuration.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+-->
+<!--
+ These are the minimum required criteria to be used by Audio HAL to ensure a basic
+ user experience on an Android device
+-->
+<configuration name="audio_policy_wrapper_configuration" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+ <xi:include href="policy_criterion_types.xml"/>
+ <xi:include href="policy_criteria.xml"/>
+
+</configuration>
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index 4c1acfe..1a634a1 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,10 +16,15 @@
#pragma once
+#include <AudioGain.h>
+#include <AudioPort.h>
+#include <HwModule.h>
+#include <DeviceDescriptor.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <utils/Errors.h>
#include <utils/RWLock.h>
+#include <utils/RefBase.h>
#include <list>
#include <map>
#include <string>
@@ -27,27 +32,17 @@
class CParameterMgrPlatformConnector;
class ISelectionCriterionInterface;
-class ISelectionCriterionTypeInterface;
struct cnode;
class ParameterMgrPlatformConnectorLogger;
-namespace android
-{
-namespace audio_policy
-{
+namespace android {
+namespace audio_policy {
class ParameterManagerWrapper
{
private:
- typedef std::pair<int, const char *> CriterionTypeValuePair;
-
- typedef std::map<std::string, ISelectionCriterionInterface *> CriterionCollection;
- typedef std::map<std::string, ISelectionCriterionTypeInterface *> CriterionTypeCollection;
- typedef CriterionCollection::iterator CriterionMapIterator;
- typedef CriterionCollection::const_iterator CriterionMapConstIterator;
- typedef CriterionTypeCollection::iterator CriterionTypeMapIterator;
- typedef CriterionTypeCollection::const_iterator CriteriaTypeMapConstIterator;
+ using Criteria = std::map<std::string, ISelectionCriterionInterface *>;
public:
ParameterManagerWrapper();
@@ -120,6 +115,9 @@
*/
status_t setAvailableOutputDevices(audio_devices_t outputDevices);
+ status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state);
+
private:
/**
* Apply the configuration of the platform on the policy parameter manager.
@@ -136,93 +134,11 @@
/**
* Load the criterion configuration file.
*
- * @param[in] path Criterion conf file path.
- *
* @return NO_ERROR is parsing successful, error code otherwise.
*/
- status_t loadAudioPolicyCriteriaConfig(const char *path);
+ status_t loadConfig();
- /**
- * Add a criterion type to AudioPolicyPfw.
- *
- * @param[in] typeName of the PFW criterion type.
- * @param[in] isInclusive attribute of the criterion type.
- */
- void addCriterionType(const std::string &typeName, bool isInclusive);
-
- /**
- * Add a criterion type value pair to AudioPolicyPfw.
- *
- * @param[in] typeName criterion type name to which this value pair is added to.
- * @param[in] numeric part of the value pair.
- * @param[in] literal part of the value pair.
- */
- void addCriterionTypeValuePair(const std::string &typeName, uint32_t numeric,
- const std::string &literal);
-
- /**
- * Add a criterion to AudioPolicyPfw.
- *
- * @param[in] name of the PFW criterion.
- * @param[in] typeName criterion type name to which this criterion is associated to.
- * @param[in] defaultLiteralValue of the PFW criterion.
- */
- void addCriterion(const std::string &name,
- const std::string &typeName,
- const std::string &defaultLiteralValue);
- /**
- * Parse and load the inclusive criterion type from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadInclusiveCriterionType(cnode *root);
-
- /**
- * Parse and load the exclusive criterion type from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadExclusiveCriterionType(cnode *root);
-
- /**
- * Parse and load the criteria from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadCriteria(cnode *root);
-
- /**
- * Parse and load a criterion from configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadCriterion(cnode *root);
-
- /**
- * Parse and load the criterion types from configuration file.
- *
- * @param[in] root node of the configuration file
- * @param[in] isInclusive true if inclusive, false is exclusive.
- */
- void loadCriterionType(cnode *root, bool isInclusive);
-
- /**
- * Load the configuration file.
- *
- * @param[in] root node of the configuration file.
- */
- void loadConfig(cnode *root);
-
- /**
- * Parse and load the chidren node from a given root node.
- *
- * @param[in] root node of the configuration file
- * @param[out] defaultValue of the parameter manager element to retrieve.
- * @param[out] type of the parameter manager element to retrieve.
- */
- void parseChildren(cnode *root, std::string &defaultValue, std::string &type);
-
- /**
+ /**
* Retrieve an element from a map by its name.
*
* @tparam T type of element to search.
@@ -266,8 +182,7 @@
bool isValueValidForCriterion(ISelectionCriterionInterface *criterion, int valueToCheck);
- CriterionTypeCollection mPolicyCriterionTypes; /**< Policy Criterion Type map. */
- CriterionCollection mPolicyCriteria; /**< Policy Criterion Map. */
+ Criteria mPolicyCriteria; /**< Policy Criterion Map. */
CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 69395f3..3d68cd8 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -322,7 +322,7 @@
// a primary device
// FIXME: this is not the right way of solving this problem
audio_devices_t availPrimaryOutputDevices =
- (primaryOutput->supportedDevices() | AUDIO_DEVICE_OUT_HEARING_AID) &
+ (primaryOutput->supportedDevices().types() | AUDIO_DEVICE_OUT_HEARING_AID) &
availableOutputDevices.types();
if (((availableInputDevices.types() &
@@ -475,7 +475,7 @@
// compressed format as they would likely not be mixed and dropped.
for (size_t i = 0; i < outputs.size(); i++) {
sp<AudioOutputDescriptor> desc = outputs.valueAt(i);
- audio_devices_t devices = desc->device() &
+ audio_devices_t devices = desc->devices().types() &
(AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF | AUDIO_DEVICE_OUT_HDMI_ARC);
if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat) &&
devices != AUDIO_DEVICE_NONE) {
@@ -631,6 +631,7 @@
case AUDIO_SOURCE_UNPROCESSED:
case AUDIO_SOURCE_HOTWORD:
case AUDIO_SOURCE_CAMCORDER:
+ case AUDIO_SOURCE_VOICE_PERFORMANCE:
inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
break;
default:
@@ -737,16 +738,32 @@
device = AUDIO_DEVICE_IN_VOICE_CALL;
}
break;
+ case AUDIO_SOURCE_VOICE_PERFORMANCE:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET) {
+ device = AUDIO_DEVICE_IN_WIRED_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_HEADSET) {
+ device = AUDIO_DEVICE_IN_USB_HEADSET;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
+ device = AUDIO_DEVICE_IN_USB_DEVICE;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ device = AUDIO_DEVICE_IN_BUILTIN_MIC;
+ }
+ break;
case AUDIO_SOURCE_REMOTE_SUBMIX:
if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
}
break;
- case AUDIO_SOURCE_FM_TUNER:
+ case AUDIO_SOURCE_FM_TUNER:
if (availableDeviceTypes & AUDIO_DEVICE_IN_FM_TUNER) {
device = AUDIO_DEVICE_IN_FM_TUNER;
}
break;
+ case AUDIO_SOURCE_ECHO_REFERENCE:
+ if (availableDeviceTypes & AUDIO_DEVICE_IN_ECHO_REFERENCE) {
+ device = AUDIO_DEVICE_IN_ECHO_REFERENCE;
+ }
+ break;
default:
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index aa205f0..5c8a799 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -88,36 +88,39 @@
return status;
}
-void AudioPolicyManager::broadcastDeviceConnectionState(audio_devices_t device,
- audio_policy_dev_state_t state,
- const String8 &device_address)
+void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
+ audio_policy_dev_state_t state)
{
- AudioParameter param(device_address);
+ AudioParameter param(device->address());
const String8 key(state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE ?
AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect);
- param.addInt(key, device);
+ param.addInt(key, device->type());
mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
}
-status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
+status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
- device, state, device_address, device_name);
+ deviceType, state, device_address, device_name);
// connect/disconnect only 1 device at a time
- if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
+ if (!audio_is_output_device(deviceType) && !audio_is_input_device(deviceType)) return BAD_VALUE;
- sp<DeviceDescriptor> devDesc =
- mHwModules.getDeviceDescriptor(device, device_address, device_name);
+ sp<DeviceDescriptor> device =
+ mHwModules.getDeviceDescriptor(deviceType, device_address, device_name,
+ state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+ if (device == 0) {
+ return INVALID_OPERATION;
+ }
// handle output devices
- if (audio_is_output_device(device)) {
+ if (audio_is_output_device(deviceType)) {
SortedVector <audio_io_handle_t> outputs;
- ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
+ ssize_t index = mAvailableOutputDevices.indexOf(device);
// save a copy of the opened output descriptors before any output is opened or closed
// by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
@@ -127,70 +130,60 @@
// handle output device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
- ALOGW("setDeviceConnectionState() device already connected: %x", device);
+ ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- ALOGV("setDeviceConnectionState() connecting device %x", device);
+ ALOGV("%s() connecting device %s", __func__, device->toString().c_str());
// register new device as available
- index = mAvailableOutputDevices.add(devDesc);
- if (index >= 0) {
- sp<HwModule> module = mHwModules.getModuleForDevice(device);
- if (module == 0) {
- ALOGD("setDeviceConnectionState() could not find HW module for device %08x",
- device);
- mAvailableOutputDevices.remove(devDesc);
- return INVALID_OPERATION;
- }
- mAvailableOutputDevices[index]->attach(module);
- } else {
+ if (mAvailableOutputDevices.add(device) < 0) {
return NO_MEMORY;
}
// Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
// parameters on newly connected devices (instead of opening the outputs...)
- broadcastDeviceConnectionState(device, state, devDesc->address());
+ broadcastDeviceConnectionState(device, state);
- if (checkOutputsForDevice(devDesc, state, outputs, devDesc->address()) != NO_ERROR) {
- mAvailableOutputDevices.remove(devDesc);
+ if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
+ mAvailableOutputDevices.remove(device);
- broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- devDesc->address());
+ mHwModules.cleanUpForDevice(device);
+
+ broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
return INVALID_OPERATION;
}
// Propagate device availability to Engine
- mEngine->setDeviceConnectionState(devDesc, state);
+ mEngine->setDeviceConnectionState(device, state);
// outputs should never be empty here
ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
"checkOutputsForDevice() returned no outputs but status OK");
- ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs",
- outputs.size());
+ ALOGV("%s() checkOutputsForDevice() returned %zu outputs", __func__, outputs.size());
} break;
// handle output device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
if (index < 0) {
- ALOGW("setDeviceConnectionState() device not connected: %x", device);
+ ALOGW("%s() device not connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
+ ALOGV("%s() disconnecting output device %s", __func__, device->toString().c_str());
// Send Disconnect to HALs
- broadcastDeviceConnectionState(device, state, devDesc->address());
+ broadcastDeviceConnectionState(device, state);
// remove device from available output devices
- mAvailableOutputDevices.remove(devDesc);
+ mAvailableOutputDevices.remove(device);
- checkOutputsForDevice(devDesc, state, outputs, devDesc->address());
+ checkOutputsForDevice(device, state, outputs);
// Propagate device availability to Engine
- mEngine->setDeviceConnectionState(devDesc, state);
+ mEngine->setDeviceConnectionState(device, state);
} break;
default:
- ALOGE("setDeviceConnectionState() invalid state: %x", state);
+ ALOGE("%s() invalid state: %x", __func__, state);
return BAD_VALUE;
}
@@ -199,8 +192,8 @@
if (!outputs.isEmpty()) {
for (audio_io_handle_t output : outputs) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
- // close unused outputs after device disconnection or direct outputs that have been
- // opened by checkOutputsForDevice() to query dynamic parameters
+ // close unused outputs after device disconnection or direct outputs that have
+ // been opened by checkOutputsForDevice() to query dynamic parameters
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
(((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
(desc->mDirectOpenCount == 0))) {
@@ -214,29 +207,28 @@
});
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
- updateCallRouting(newDevice);
+ DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
+ updateCallRouting(newDevices);
}
- const audio_devices_t msdOutDevice = getModuleDeviceTypes(
- mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);
+ const DeviceVector msdOutDevices = getMsdAudioOutDevices();
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
- audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/);
+ DeviceVector newDevices = getNewOutputDevices(desc, true /*fromCache*/);
// do not force device change on duplicated output because if device is 0, it will
// also force a device 0 for the two outputs it is duplicated to which may override
// a valid device selection on those outputs.
- bool force = (msdOutDevice == AUDIO_DEVICE_NONE || msdOutDevice != desc->device())
+ bool force = (msdOutDevices.isEmpty() || msdOutDevices != desc->devices())
&& !desc->isDuplicated()
- && (!device_distinguishes_on_address(device)
+ && (!device_distinguishes_on_address(deviceType)
// always force when disconnecting (a non-duplicated device)
|| (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
- setOutputDevice(desc, newDevice, force, 0);
+ setOutputDevices(desc, newDevices, force, 0);
}
}
if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
- cleanUpForDevice(devDesc);
+ cleanUpForDevice(device);
}
mpClientInterface->onAudioPortListUpdate();
@@ -244,67 +236,59 @@
} // end if is output device
// handle input devices
- if (audio_is_input_device(device)) {
+ if (audio_is_input_device(deviceType)) {
SortedVector <audio_io_handle_t> inputs;
- ssize_t index = mAvailableInputDevices.indexOf(devDesc);
+ ssize_t index = mAvailableInputDevices.indexOf(device);
switch (state)
{
// handle input device connection
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
if (index >= 0) {
- ALOGW("setDeviceConnectionState() device already connected: %d", device);
+ ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- sp<HwModule> module = mHwModules.getModuleForDevice(device);
- if (module == NULL) {
- ALOGW("setDeviceConnectionState(): could not find HW module for device %08x",
- device);
- return INVALID_OPERATION;
- }
-
// Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
// parameters on newly connected devices (instead of opening the inputs...)
- broadcastDeviceConnectionState(device, state, devDesc->address());
+ broadcastDeviceConnectionState(device, state);
- if (checkInputsForDevice(devDesc, state, inputs, devDesc->address()) != NO_ERROR) {
- broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- devDesc->address());
+ if (checkInputsForDevice(device, state, inputs) != NO_ERROR) {
+ broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+
+ mHwModules.cleanUpForDevice(device);
+
return INVALID_OPERATION;
}
- index = mAvailableInputDevices.add(devDesc);
- if (index >= 0) {
- mAvailableInputDevices[index]->attach(module);
- } else {
+ if (mAvailableInputDevices.add(device) < 0) {
return NO_MEMORY;
}
// Propagate device availability to Engine
- mEngine->setDeviceConnectionState(devDesc, state);
+ mEngine->setDeviceConnectionState(device, state);
} break;
// handle input device disconnection
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
if (index < 0) {
- ALOGW("setDeviceConnectionState() device not connected: %d", device);
+ ALOGW("%s() device not connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
+ ALOGV("%s() disconnecting input device %s", __func__, device->toString().c_str());
// Set Disconnect to HALs
- broadcastDeviceConnectionState(device, state, devDesc->address());
+ broadcastDeviceConnectionState(device, state);
- checkInputsForDevice(devDesc, state, inputs, devDesc->address());
- mAvailableInputDevices.remove(devDesc);
+ checkInputsForDevice(device, state, inputs);
+ mAvailableInputDevices.remove(device);
// Propagate device availability to Engine
- mEngine->setDeviceConnectionState(devDesc, state);
+ mEngine->setDeviceConnectionState(device, state);
} break;
default:
- ALOGE("setDeviceConnectionState() invalid state: %x", state);
+ ALOGE("%s() invalid state: %x", __func__, state);
return BAD_VALUE;
}
@@ -314,19 +298,19 @@
updateDevicesAndOutputs();
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
- updateCallRouting(newDevice);
+ DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
+ updateCallRouting(newDevices);
}
if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
- cleanUpForDevice(devDesc);
+ cleanUpForDevice(device);
}
mpClientInterface->onAudioPortListUpdate();
return NO_ERROR;
} // end if is input device
- ALOGW("setDeviceConnectionState() invalid device: %x", device);
+ ALOGW("%s() invalid device: %s", __func__, device->toString().c_str());
return BAD_VALUE;
}
@@ -334,7 +318,7 @@
const char *device_address)
{
sp<DeviceDescriptor> devDesc =
- mHwModules.getDeviceDescriptor(device, device_address, "",
+ mHwModules.getDeviceDescriptor(device, device_address, "", false /* allowToCreate */,
(strlen(device_address) != 0)/*matchAddress*/);
if (devDesc == 0) {
@@ -350,7 +334,7 @@
} else if (audio_is_input_device(device)) {
deviceVector = &mAvailableInputDevices;
} else {
- ALOGW("getDeviceConnectionState() invalid device type %08x", device);
+ ALOGW("%s() invalid device type %08x", __func__, device);
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
@@ -376,8 +360,7 @@
// Check if the device is currently connected
sp<DeviceDescriptor> devDesc =
mHwModules.getDeviceDescriptor(device, device_address, device_name);
- ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
- if (index < 0) {
+ if (devDesc == 0 || mAvailableOutputDevices.indexOf(devDesc) < 0) {
// Nothing to do: device is not connected
return NO_ERROR;
}
@@ -425,16 +408,20 @@
return NO_ERROR;
}
-uint32_t AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs)
+uint32_t AudioPolicyManager::updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs)
{
bool createTxPatch = false;
uint32_t muteWaitMs = 0;
- if(!hasPrimaryOutput() || mPrimaryOutput->device() == AUDIO_DEVICE_OUT_STUB) {
+ if(!hasPrimaryOutput() || mPrimaryOutput->devices().types() == AUDIO_DEVICE_OUT_STUB) {
return muteWaitMs;
}
- audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
- ALOGV("updateCallRouting device rxDevice %08x txDevice %08x", rxDevice, txDevice);
+ ALOG_ASSERT(!rxDevices.isEmpty(), "updateCallRouting() no selected output device");
+
+ audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
+ auto txDevice = getDeviceAndMixForAttributes(attr);
+ ALOGV("updateCallRouting device rxDevice %s txDevice %s",
+ rxDevices.toString().c_str(), txDevice->toString().c_str());
// release existing RX patch if any
if (mCallRxPatch != 0) {
@@ -450,16 +437,15 @@
// If the RX device is on the primary HW module, then use legacy routing method for voice calls
// via setOutputDevice() on primary output.
// Otherwise, create two audio patches for TX and RX path.
- if (availablePrimaryOutputDevices() & rxDevice) {
- muteWaitMs = setOutputDevice(mPrimaryOutput, rxDevice, true, delayMs);
+ if (availablePrimaryOutputDevices().contains(rxDevices.itemAt(0))) {
+ muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
// If the TX device is also on the primary HW module, setOutputDevice() will take care
// of it due to legacy implementation. If not, create a patch.
- if ((availablePrimaryInputDevices() & txDevice & ~AUDIO_DEVICE_BIT_IN)
- == AUDIO_DEVICE_NONE) {
+ if (!availablePrimaryModuleInputDevices().contains(txDevice)) {
createTxPatch = true;
}
} else { // create RX path audio patch
- mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevice, delayMs);
+ mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);
createTxPatch = true;
}
if (createTxPatch) { // create TX path audio patch
@@ -470,26 +456,31 @@
}
sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
- bool isRx, audio_devices_t device, uint32_t delayMs) {
+ bool isRx, const sp<DeviceDescriptor> &device, uint32_t delayMs) {
PatchBuilder patchBuilder;
- sp<DeviceDescriptor> txSourceDeviceDesc;
+ if (device == nullptr) {
+ return nullptr;
+ }
if (isRx) {
- patchBuilder.addSink(findDevice(mAvailableOutputDevices, device)).
- addSource(findDevice(mAvailableInputDevices, AUDIO_DEVICE_IN_TELEPHONY_RX));
+ patchBuilder.addSink(device).
+ addSource(mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX));
} else {
- patchBuilder.addSource(txSourceDeviceDesc = findDevice(mAvailableInputDevices, device)).
- addSink(findDevice(mAvailableOutputDevices, AUDIO_DEVICE_OUT_TELEPHONY_TX));
+ patchBuilder.addSource(device).
+ addSink(mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX));
}
- audio_devices_t outputDevice = isRx ? device : AUDIO_DEVICE_OUT_TELEPHONY_TX;
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(outputDevice, mOutputs);
- audio_io_handle_t output = selectOutput(outputs);
+ // @TODO: still ignoring the address, or not dealing platform with mutliple telephonydevices
+ const sp<DeviceDescriptor> outputDevice = isRx ?
+ device : mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX);
+ SortedVector<audio_io_handle_t> outputs =
+ getOutputsForDevices(DeviceVector(outputDevice), mOutputs);
+ audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
// request to reuse existing output stream if one is already opened to reach the target device
if (output != AUDIO_IO_HANDLE_NONE) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
- ALOG_ASSERT(!outputDesc->isDuplicated(),
- "%s() %#x device output %d is duplicated", __func__, outputDevice, output);
+ ALOG_ASSERT(!outputDesc->isDuplicated(), "%s() %s device output %d is duplicated", __func__,
+ outputDevice->toString().c_str(), output);
patchBuilder.addSource(outputDesc, { .stream = AUDIO_STREAM_PATCH });
}
@@ -499,7 +490,7 @@
// call TX device but this information is not in the audio patch and logic here must be
// symmetric to the one in startInput()
for (const auto& activeDesc : mInputs.getActiveInputs()) {
- if (activeDesc->hasSameHwModuleAs(txSourceDeviceDesc)) {
+ if (activeDesc->hasSameHwModuleAs(device)) {
closeActiveClients(activeDesc);
}
}
@@ -599,17 +590,17 @@
}
if (hasPrimaryOutput()) {
- // Note that despite the fact that getNewOutputDevice() is called on the primary output,
+ // Note that despite the fact that getNewOutputDevices() is called on the primary output,
// the device returned is not necessarily reachable via this output
- audio_devices_t rxDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
+ DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
// force routing command to audio hardware when ending call
// even if no device change is needed
- if (isStateInCall(oldState) && rxDevice == AUDIO_DEVICE_NONE) {
- rxDevice = mPrimaryOutput->device();
+ if (isStateInCall(oldState) && rxDevices.isEmpty()) {
+ rxDevices = mPrimaryOutput->devices();
}
if (state == AUDIO_MODE_IN_CALL) {
- updateCallRouting(rxDevice, delayMs);
+ updateCallRouting(rxDevices, delayMs);
} else if (oldState == AUDIO_MODE_IN_CALL) {
if (mCallRxPatch != 0) {
mpClientInterface->releaseAudioPatch(mCallRxPatch->mAfPatchHandle, 0);
@@ -619,18 +610,18 @@
mpClientInterface->releaseAudioPatch(mCallTxPatch->mAfPatchHandle, 0);
mCallTxPatch.clear();
}
- setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
+ setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
} else {
- setOutputDevice(mPrimaryOutput, rxDevice, force, 0);
+ setOutputDevices(mPrimaryOutput, rxDevices, force, 0);
}
}
// reevaluate routing on all outputs in case tracks have been started during the call
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- audio_devices_t newDevice = getNewOutputDevice(desc, true /*fromCache*/);
+ DeviceVector newDevices = getNewOutputDevices(desc, true /*fromCache*/);
if (state != AUDIO_MODE_IN_CALL || desc != mPrimaryOutput) {
- setOutputDevice(desc, newDevice, (newDevice != AUDIO_DEVICE_NONE), 0 /*delayMs*/);
+ setOutputDevices(desc, newDevices, !newDevices.isEmpty(), 0 /*delayMs*/);
}
}
@@ -654,7 +645,7 @@
}
void AudioPolicyManager::setForceUse(audio_policy_force_use_t usage,
- audio_policy_forced_cfg_t config)
+ audio_policy_forced_cfg_t config)
{
ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
if (config == mEngine->getForceUse(usage)) {
@@ -680,26 +671,24 @@
delayMs = TOUCH_SOUND_FIXED_DELAY_MS;
}
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
- audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
- waitMs = updateCallRouting(newDevice, delayMs);
+ DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, true /*fromCache*/);
+ waitMs = updateCallRouting(newDevices, delayMs);
}
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- audio_devices_t newDevice = getNewOutputDevice(outputDesc, true /*fromCache*/);
+ DeviceVector newDevices = getNewOutputDevices(outputDesc, true /*fromCache*/);
if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (outputDesc != mPrimaryOutput)) {
- waitMs = setOutputDevice(outputDesc, newDevice, (newDevice != AUDIO_DEVICE_NONE),
- delayMs);
+ waitMs = setOutputDevices(outputDesc, newDevices, !newDevices.isEmpty(), delayMs);
}
- if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
- applyStreamVolumes(outputDesc, newDevice, waitMs, true);
+ if (forceVolumeReeval && !newDevices.isEmpty()) {
+ applyStreamVolumes(outputDesc, newDevices.types(), waitMs, true);
}
}
for (const auto& activeDesc : mInputs.getActiveInputs()) {
- audio_devices_t newDevice = getNewInputDevice(activeDesc);
+ auto newDevice = getNewInputDevice(activeDesc);
// Force new input selection if the new device can not be reached via current input
- if (activeDesc->mProfile->getSupportedDevices().types() &
- (newDevice & ~AUDIO_DEVICE_BIT_IN)) {
+ if (activeDesc->mProfile->getSupportedDevices().contains(newDevice)) {
setInputDevice(activeDesc->mIoHandle, newDevice);
} else {
closeInput(activeDesc->mIoHandle);
@@ -715,7 +704,7 @@
// Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict
// search to profiles for direct outputs.
sp<IOProfile> AudioPolicyManager::getProfileForOutput(
- audio_devices_t device,
+ const DeviceVector& devices,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@@ -736,7 +725,7 @@
for (const auto& hwModule : mHwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
- if (!curProfile->isCompatibleProfile(device, String8(""),
+ if (!curProfile->isCompatibleProfile(devices,
samplingRate, NULL /*updatedSamplingRate*/,
format, NULL /*updatedFormat*/,
channelMask, NULL /*updatedChannelMask*/,
@@ -744,7 +733,7 @@
continue;
}
// reject profiles not corresponding to a device currently available
- if ((mAvailableOutputDevices.types() & curProfile->getSupportedDevicesType()) == 0) {
+ if (!mAvailableOutputDevices.containsAtLeastOne(curProfile->getSupportedDevices())) {
continue;
}
if (!directOnly) return curProfile;
@@ -765,7 +754,7 @@
audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream)
{
routing_strategy strategy = getStrategy(stream);
- audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
+ DeviceVector devices = getDevicesForStrategy(strategy, false /*fromCache*/);
// Note that related method getOutputForAttr() uses getOutputForDevice() not selectOutput().
// We use selectOutput() here since we don't have the desired AudioTrack sample rate,
@@ -773,10 +762,11 @@
// getOutput() solely on audio_stream_type such as AudioSystem::getOutputFrameCount()
// and AudioSystem::getOutputSamplingRate().
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
- audio_io_handle_t output = selectOutput(outputs);
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
+ audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
- ALOGV("getOutput() stream %d selected device %08x, output %d", stream, device, output);
+ ALOGV("getOutput() stream %d selected devices %s, output %d", stream,
+ devices.toString().c_str(), output);
return output;
}
@@ -813,12 +803,11 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId)
{
- DeviceVector outputDevices;
+ DeviceVector devices;
routing_strategy strategy;
- audio_devices_t device;
- const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
- audio_devices_t msdDevice =
- getModuleDeviceTypes(mAvailableOutputDevices, AUDIO_HARDWARE_MODULE_ID_MSD);
+ audio_devices_t deviceType = AUDIO_DEVICE_NONE;
+ const audio_port_handle_t requestedPortId = *selectedDeviceId;
+ DeviceVector msdDevices = getMsdAudioOutDevices();
status_t status = getAudioAttributes(resultAttr, attr, *stream);
if (status != NO_ERROR) {
@@ -829,17 +818,16 @@
" session %d selectedDeviceId %d",
__func__,
resultAttr->usage, resultAttr->content_type, resultAttr->tags, resultAttr->flags,
- session, requestedDeviceId);
+ session, requestedPortId);
*stream = streamTypefromAttributesInt(resultAttr);
strategy = getStrategyForAttr(resultAttr);
// First check for explicit routing (eg. setPreferredDevice)
- if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
- sp<DeviceDescriptor> deviceDesc =
- mAvailableOutputDevices.getDeviceFromId(requestedDeviceId);
- device = deviceDesc->type();
+ sp<DeviceDescriptor> requestedDevice = mAvailableOutputDevices.getDeviceFromId(requestedPortId);
+ if (requestedDevice != nullptr) {
+ deviceType = requestedDevice->type();
} else {
// If no explict route, is there a matching dynamic policy that applies?
sp<SwAudioOutputDescriptor> desc;
@@ -863,7 +851,7 @@
ALOGW("%s no policy mix found for usage AUDIO_USAGE_VIRTUAL_SOURCE", __func__);
return BAD_VALUE;
}
- device = getDeviceForStrategy(strategy, false /*fromCache*/);
+ deviceType = getDeviceForStrategy(strategy, false /*fromCache*/);
}
if ((resultAttr->flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
@@ -875,42 +863,44 @@
// FIXME: provide a more generic approach which is not device specific and move this back
// to getOutputForDevice.
// TODO: Remove check of AUDIO_STREAM_MUSIC once migration is completed on the app side.
- if (device == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
+ if (deviceType == AUDIO_DEVICE_OUT_TELEPHONY_TX &&
(*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
audio_is_linear_pcm(config->format) &&
isInCall()) {
- if (requestedDeviceId != AUDIO_PORT_HANDLE_NONE) {
+ if (requestedPortId != AUDIO_PORT_HANDLE_NONE) {
*flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
} else {
// Get the devce type directly from the engine to bypass preferred route logic
- device = mEngine->getDeviceForStrategy(strategy);
+ deviceType = mEngine->getDeviceForStrategy(strategy);
}
}
ALOGV("%s device 0x%x, sampling rate %d, format %#x, channel mask %#x, "
"flags %#x",
- __func__, device, config->sample_rate, config->format, config->channel_mask, *flags);
+ __func__,
+ deviceType, config->sample_rate, config->format, config->channel_mask, *flags);
*output = AUDIO_IO_HANDLE_NONE;
- if (msdDevice != AUDIO_DEVICE_NONE) {
- *output = getOutputForDevice(msdDevice, session, *stream, config, flags);
- if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(device) == NO_ERROR) {
- ALOGV("%s() Using MSD device 0x%x instead of device 0x%x",
- __func__, msdDevice, device);
- device = msdDevice;
+ if (!msdDevices.isEmpty()) {
+ *output = getOutputForDevices(msdDevices, session, *stream, config, flags);
+ sp<DeviceDescriptor> deviceDesc = mAvailableOutputDevices.getDevice(deviceType);
+ if (*output != AUDIO_IO_HANDLE_NONE && setMsdPatch(deviceDesc) == NO_ERROR) {
+ ALOGV("%s() Using MSD devices %s instead of device %s",
+ __func__, msdDevices.toString().c_str(), deviceDesc->toString().c_str());
+ deviceType = msdDevices.types();
} else {
*output = AUDIO_IO_HANDLE_NONE;
}
}
+ devices = mAvailableOutputDevices.getDevicesFromTypeMask(deviceType);
if (*output == AUDIO_IO_HANDLE_NONE) {
- *output = getOutputForDevice(device, session, *stream, config, flags);
+ *output = getOutputForDevices(devices, session, *stream, config, flags);
}
if (*output == AUDIO_IO_HANDLE_NONE) {
return INVALID_OPERATION;
}
- outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
- *selectedDeviceId = getFirstDeviceId(outputDevices);
+ *selectedDeviceId = getFirstDeviceId(devices);
ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
@@ -931,7 +921,7 @@
if (*portId != AUDIO_PORT_HANDLE_NONE) {
return INVALID_OPERATION;
}
- const audio_port_handle_t requestedDeviceId = *selectedDeviceId;
+ const audio_port_handle_t requestedPortId = *selectedDeviceId;
audio_attributes_t resultAttr;
status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
config, flags, selectedDeviceId);
@@ -946,20 +936,20 @@
sp<TrackClientDescriptor> clientDesc =
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
- requestedDeviceId, *stream,
+ requestedPortId, *stream,
getStrategyForAttr(&resultAttr),
*flags);
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
outputDesc->addClient(clientDesc);
ALOGV("%s returns output %d selectedDeviceId %d for port ID %d",
- __func__, *output, requestedDeviceId, *portId);
+ __func__, *output, requestedPortId, *portId);
return NO_ERROR;
}
-audio_io_handle_t AudioPolicyManager::getOutputForDevice(
- audio_devices_t device,
+audio_io_handle_t AudioPolicyManager::getOutputForDevices(
+ const DeviceVector &devices,
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
@@ -1017,7 +1007,7 @@
if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) ||
!(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) {
- profile = getProfileForOutput(device,
+ profile = getProfileForOutput(devices,
config->sample_rate,
config->format,
config->channel_mask,
@@ -1037,7 +1027,7 @@
(config->channel_mask == desc->mChannelMask) &&
(session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++;
- ALOGI("getOutputForDevice() reusing direct output %d for session %d",
+ ALOGI("%s reusing direct output %d for session %d", __func__,
mOutputs.keyAt(i), session);
return mOutputs.keyAt(i);
}
@@ -1051,8 +1041,7 @@
sp<SwAudioOutputDescriptor> outputDesc =
new SwAudioOutputDescriptor(profile, mpClientInterface);
- DeviceVector outputDevices = mAvailableOutputDevices.getDevicesFromTypeMask(device);
- String8 address = getFirstDeviceAddress(outputDevices);
+ String8 address = getFirstDeviceAddress(devices);
// MSD patch may be using the only output stream that can service this request. Release
// MSD patch to prioritize this request over any active output on MSD.
@@ -1062,7 +1051,7 @@
for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
const struct audio_port_config *sink = &patch->mPatch.sinks[j];
if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
- (sink->ext.device.type & device) != AUDIO_DEVICE_NONE &&
+ (sink->ext.device.type & devices.types()) != AUDIO_DEVICE_NONE &&
(address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
releaseAudioPatch(patch->mHandle, mUidCached);
@@ -1071,15 +1060,15 @@
}
}
- status = outputDesc->open(config, device, address, stream, *flags, &output);
+ status = outputDesc->open(config, devices, stream, *flags, &output);
// only accept an output with the requested parameters
if (status != NO_ERROR ||
(config->sample_rate != 0 && config->sample_rate != outputDesc->mSamplingRate) ||
(config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->mFormat) ||
(config->channel_mask != 0 && config->channel_mask != outputDesc->mChannelMask)) {
- ALOGV("getOutputForDevice() failed opening direct output: output %d sample rate %d %d,"
- "format %d %d, channel mask %04x %04x", output, config->sample_rate,
+ ALOGV("%s failed opening direct output: output %d sample rate %d %d,"
+ "format %d %d, channel mask %04x %04x", __func__, output, config->sample_rate,
outputDesc->mSamplingRate, config->format, outputDesc->mFormat,
config->channel_mask, outputDesc->mChannelMask);
if (output != AUDIO_IO_HANDLE_NONE) {
@@ -1097,7 +1086,7 @@
addOutput(output, outputDesc);
mPreviousOutputs = mOutputs;
- ALOGV("getOutputForDevice() returns new direct output %d", output);
+ ALOGV("%s returns new direct output %d", __func__, output);
mpClientInterface->onAudioPortListUpdate();
return output;
}
@@ -1118,14 +1107,14 @@
if (audio_is_linear_pcm(config->format)) {
// get which output is suitable for the specified stream. The actual
// routing change will happen when startOutput() will be called
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
// at this stage we should ignore the DIRECT flag as no direct output could be found earlier
*flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
output = selectOutput(outputs, *flags, config->format,
config->channel_mask, config->sample_rate);
}
- ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
+ ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
stream, config->sample_rate, config->format, config->channel_mask, *flags);
@@ -1133,13 +1122,14 @@
}
sp<DeviceDescriptor> AudioPolicyManager::getMsdAudioInDevice() const {
- sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
- if (msdModule != 0) {
- DeviceVector msdInputDevices = mAvailableInputDevices.getDevicesFromHwModule(
- msdModule->getHandle());
- if (!msdInputDevices.isEmpty()) return msdInputDevices.itemAt(0);
- }
- return 0;
+ auto msdInDevices = mHwModules.getAvailableDevicesFromModuleName(AUDIO_HARDWARE_MODULE_ID_MSD,
+ mAvailableInputDevices);
+ return msdInDevices.isEmpty()? nullptr : msdInDevices.itemAt(0);
+}
+
+DeviceVector AudioPolicyManager::getMsdAudioOutDevices() const {
+ return mHwModules.getAvailableDevicesFromModuleName(AUDIO_HARDWARE_MODULE_ID_MSD,
+ mAvailableOutputDevices);
}
const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
@@ -1160,7 +1150,7 @@
return msdPatches;
}
-status_t AudioPolicyManager::getBestMsdAudioProfileFor(audio_devices_t outputDevice,
+status_t AudioPolicyManager::getBestMsdAudioProfileFor(const sp<DeviceDescriptor> &outputDevice,
bool hwAvSync, audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
{
sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
@@ -1170,7 +1160,7 @@
}
sp<HwModule> deviceModule = mHwModules.getModuleForDevice(outputDevice);
if (deviceModule == nullptr) {
- ALOGE("%s() unable to get module for %#x", __func__, outputDevice);
+ ALOGE("%s() unable to get module for %s", __func__, outputDevice->toString().c_str());
return NO_INIT;
}
const InputProfileCollection &inputProfiles = msdModule->getInputProfiles();
@@ -1180,7 +1170,7 @@
}
const OutputProfileCollection &outputProfiles = deviceModule->getOutputProfiles();
if (outputProfiles.isEmpty()) {
- ALOGE("%s() no output profiles for device %#x", __func__, outputDevice);
+ ALOGE("%s() no output profiles for device %s", __func__, outputDevice->toString().c_str());
return NO_INIT;
}
AudioProfileVector msdProfiles;
@@ -1201,8 +1191,8 @@
compressedFormatsOrder, surroundChannelMasksOrder, true /*preferHigherSamplingRates*/,
&bestSinkConfig);
if (result != NO_ERROR) {
- ALOGD("%s() no matching profiles found for device: %#x, hwAvSync: %d",
- __func__, outputDevice, hwAvSync);
+ ALOGD("%s() no matching profiles found for device: %s, hwAvSync: %d",
+ __func__, outputDevice->toString().c_str(), hwAvSync);
return result;
}
sinkConfig->sample_rate = bestSinkConfig.sample_rate;
@@ -1231,11 +1221,10 @@
return NO_ERROR;
}
-PatchBuilder AudioPolicyManager::buildMsdPatch(audio_devices_t outputDevice) const
+PatchBuilder AudioPolicyManager::buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const
{
PatchBuilder patchBuilder;
- patchBuilder.addSource(getMsdAudioInDevice()).
- addSink(findDevice(mAvailableOutputDevices, outputDevice));
+ patchBuilder.addSource(getMsdAudioInDevice()).addSink(outputDevice);
audio_port_config sourceConfig = patchBuilder.patch()->sources[0];
audio_port_config sinkConfig = patchBuilder.patch()->sinks[0];
// TODO: Figure out whether MSD module has HW_AV_SYNC flag set in the AP config file.
@@ -1253,15 +1242,18 @@
return patchBuilder;
}
-status_t AudioPolicyManager::setMsdPatch(audio_devices_t outputDevice) {
- ALOGV("%s() for outputDevice %#x", __func__, outputDevice);
- if (outputDevice == AUDIO_DEVICE_NONE) {
+status_t AudioPolicyManager::setMsdPatch(const sp<DeviceDescriptor> &outputDevice) {
+ sp<DeviceDescriptor> device = outputDevice;
+ if (device == nullptr) {
// Use media strategy for unspecified output device. This should only
// occur on checkForDeviceAndOutputChanges(). Device connection events may
// therefore invalidate explicit routing requests.
- outputDevice = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
+ DeviceVector devices = getDevicesForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
+ LOG_ALWAYS_FATAL_IF(devices.isEmpty(), "no outpudevice to set Msd Patch");
+ device = devices.itemAt(0);
}
- PatchBuilder patchBuilder = buildMsdPatch(outputDevice);
+ ALOGV("%s() for device %s", __func__, device->toString().c_str());
+ PatchBuilder patchBuilder = buildMsdPatch(device);
const struct audio_patch* patch = patchBuilder.patch();
const AudioPatchCollection msdPatches = getMsdPatches();
if (!msdPatches.isEmpty()) {
@@ -1277,8 +1269,9 @@
patch, 0 /*delayMs*/, mUidCached, nullptr /*patchDescPtr*/);
ALOGE_IF(status != NO_ERROR, "%s() error %d creating MSD audio patch", __func__, status);
ALOGI_IF(status == NO_ERROR, "%s() Patch created from MSD_IN to "
- "device:%#x (format:%#x channels:%#x samplerate:%d)", __func__, outputDevice,
- patch->sources[0].format, patch->sources[0].channel_mask, patch->sources[0].sample_rate);
+ "device:%s (format:%#x channels:%#x samplerate:%d)", __func__,
+ device->toString().c_str(), patch->sources[0].format,
+ patch->sources[0].channel_mask, patch->sources[0].sample_rate);
return status;
}
@@ -1289,7 +1282,7 @@
uint32_t samplingRate)
{
// select one output among several that provide a path to a particular device or set of
- // devices (the list was previously build by getOutputsForDevice()).
+ // devices (the list was previously build by getOutputsForDevices()).
// The priority is as follows:
// 1: the output supporting haptic playback when requesting haptic playback
// 2: the output with the highest number of requested policy flags
@@ -1451,17 +1444,19 @@
bool force = !outputDesc->isActive() &&
(outputDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE);
- audio_devices_t device = AUDIO_DEVICE_NONE;
+ DeviceVector devices;
AudioMix *policyMix = NULL;
const char *address = NULL;
if (outputDesc->mPolicyMix != NULL) {
policyMix = outputDesc->mPolicyMix;
+ audio_devices_t newDeviceType;
address = policyMix->mDeviceAddress.string();
if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
- device = policyMix->mDeviceType;
+ newDeviceType = policyMix->mDeviceType;
} else {
- device = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+ newDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
+ devices.add(mAvailableOutputDevices.getDevice(newDeviceType, String8(address)));
}
// requiresMuteCheck is false when we can bypass mute strategy.
@@ -1476,8 +1471,8 @@
outputDesc->setClientActive(client, true);
if (client->hasPreferredDevice(true)) {
- device = getNewOutputDevice(outputDesc, false /*fromCache*/);
- if (device != outputDesc->device()) {
+ devices = getNewOutputDevices(outputDesc, false /*fromCache*/);
+ if (devices != outputDesc->devices()) {
checkStrategyRoute(getStrategy(stream), outputDesc->mIoHandle);
}
}
@@ -1486,10 +1481,10 @@
selectOutputForMusicEffects();
}
- if (outputDesc->streamActiveCount(stream) == 1 || device != AUDIO_DEVICE_NONE) {
+ if (outputDesc->streamActiveCount(stream) == 1 || !devices.isEmpty()) {
// starting an output being rerouted?
- if (device == AUDIO_DEVICE_NONE) {
- device = getNewOutputDevice(outputDesc, false /*fromCache*/);
+ if (devices.isEmpty()) {
+ devices = getNewOutputDevices(outputDesc, false /*fromCache*/);
}
routing_strategy strategy = getStrategy(stream);
@@ -1498,13 +1493,13 @@
(beaconMuteLatency > 0);
uint32_t waitMs = beaconMuteLatency;
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (desc != outputDesc) {
// An output has a shared device if
// - managed by the same hw module
// - supports the currently selected device
const bool sharedDevice = outputDesc->sharesHwModuleWith(desc)
- && (desc->supportedDevices() & device) != AUDIO_DEVICE_NONE;
+ && (!desc->filterSupportedDevices(devices).isEmpty());
// force a device change if any other output is:
// - managed by the same hw module
@@ -1514,7 +1509,7 @@
// In this case, the audio HAL must receive the new device selection so that it can
// change the device currently selected by the other output.
if (sharedDevice &&
- desc->device() != device &&
+ desc->devices() != devices &&
desc->getPatchHandle() != AUDIO_PATCH_HANDLE_NONE) {
force = true;
}
@@ -1537,13 +1532,13 @@
}
const uint32_t muteWaitMs =
- setOutputDevice(outputDesc, device, force, 0, NULL, address, requiresMuteCheck);
+ setOutputDevices(outputDesc, devices, force, 0, NULL, requiresMuteCheck);
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
- mVolumeCurves->getVolumeIndex(stream, outputDesc->device()),
+ mVolumeCurves->getVolumeIndex(stream, outputDesc->devices().types()),
outputDesc,
- outputDesc->device());
+ outputDesc->devices().types());
// update the outputs if starting an output with a stream that can affect notification
// routing
@@ -1574,7 +1569,7 @@
// Automatically enable the remote submix input when output is started on a re routing mix
// of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(device) && policyMix != NULL &&
+ if (audio_is_remote_submix_device(devices.types()) && policyMix != NULL &&
policyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
@@ -1619,7 +1614,7 @@
if (outputDesc->streamActiveCount(stream) == 1) {
// Automatically disable the remote submix input when output is stopped on a
// re routing mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(outputDesc->mDevice) &&
+ if (audio_is_remote_submix_device(outputDesc->devices().types()) &&
outputDesc->mPolicyMix != NULL &&
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
@@ -1640,33 +1635,31 @@
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->streamActiveCount(stream) == 0 || forceDeviceUpdate) {
outputDesc->mStopTime[stream] = systemTime();
- audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
+ DeviceVector newDevices = getNewOutputDevices(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
// the track stop() command is received and at that time the audio track buffer can
// still contain data that needs to be drained. The latency only covers the audio HAL
// and kernel buffers. Also the latency does not always include additional delay in the
// audio path (audio DSP, CODEC ...)
- setOutputDevice(outputDesc, newDevice, false, outputDesc->latency()*2);
+ setOutputDevices(outputDesc, newDevices, false, outputDesc->latency()*2);
// force restoring the device selection on other active outputs if it differs from the
// one being selected for this output
uint32_t delayMs = outputDesc->latency()*2;
for (size_t i = 0; i < mOutputs.size(); i++) {
- sp<AudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (desc != outputDesc &&
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
- (newDevice != desc->device())) {
- audio_devices_t newDevice2 = getNewOutputDevice(desc, false /*fromCache*/);
- bool force = desc->device() != newDevice2;
+ (newDevices != desc->devices())) {
+ DeviceVector newDevices2 = getNewOutputDevices(desc, false /*fromCache*/);
+ bool force = desc->devices() != newDevices2;
- setOutputDevice(desc,
- newDevice2,
- force,
- delayMs);
+ setOutputDevices(desc, newDevices2, force, delayMs);
+
// re-apply device specific volume if not done by setOutputDevice()
if (!force) {
- applyStreamVolumes(desc, newDevice2, delayMs);
+ applyStreamVolumes(desc, newDevices2.types(), delayMs);
}
}
}
@@ -1739,29 +1732,27 @@
attr->source, config->sample_rate, config->format, config->channel_mask, session, flags);
status_t status = NO_ERROR;
- // handle legacy remote submix case where the address was not always specified
- String8 address = String8("");
audio_source_t halInputSource;
- audio_source_t inputSource = attr->source;
+ audio_attributes_t attributes = *attr;
AudioMix *policyMix = NULL;
- DeviceVector inputDevices;
+ sp<DeviceDescriptor> device;
sp<AudioInputDescriptor> inputDesc;
sp<RecordClientDescriptor> clientDesc;
audio_port_handle_t requestedDeviceId = *selectedDeviceId;
bool isSoundTrigger;
- audio_devices_t device;
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
return INVALID_OPERATION;
}
- if (inputSource == AUDIO_SOURCE_DEFAULT) {
- inputSource = AUDIO_SOURCE_MIC;
+ if (attr->source == AUDIO_SOURCE_DEFAULT) {
+ attributes.source = AUDIO_SOURCE_MIC;
}
// Explicit routing?
- sp<DeviceDescriptor> deviceDesc = mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
+ sp<DeviceDescriptor> explicitRoutingDevice =
+ mAvailableInputDevices.getDeviceFromId(*selectedDeviceId);
// special case for mmap capture: if an input IO handle is specified, we reuse this input if
// possible
@@ -1802,7 +1793,7 @@
}
}
*inputType = API_INPUT_LEGACY;
- device = inputDesc->mDevice;
+ device = inputDesc->getDevice();
ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
goto exit;
@@ -1811,44 +1802,38 @@
*input = AUDIO_IO_HANDLE_NONE;
*inputType = API_INPUT_INVALID;
- halInputSource = inputSource;
+ halInputSource = attributes.source;
- if (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX &&
- strncmp(attr->tags, "addr=", strlen("addr=")) == 0) {
- status = mPolicyMixes.getInputMixForAttr(*attr, &policyMix);
+ if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
+ strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
+ status = mPolicyMixes.getInputMixForAttr(attributes, &policyMix);
if (status != NO_ERROR) {
goto error;
}
*inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
- device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
- address = String8(attr->tags + strlen("addr="));
+ device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ String8(attr->tags + strlen("addr=")));
} else {
- if (deviceDesc != 0) {
- device = deviceDesc->type();
+ if (explicitRoutingDevice != nullptr) {
+ device = explicitRoutingDevice;
} else {
- device = getDeviceAndMixForInputSource(inputSource, &policyMix);
+ device = getDeviceAndMixForAttributes(attributes, &policyMix);
}
- if (device == AUDIO_DEVICE_NONE) {
- ALOGW("getInputForAttr() could not find device for source %d", inputSource);
+ if (device == nullptr) {
+ ALOGW("getInputForAttr() could not find device for source %d", attributes.source);
status = BAD_VALUE;
goto error;
}
- if (policyMix != NULL) {
- address = policyMix->mDeviceAddress;
- if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
- // there is an external policy, but this input is attached to a mix of recorders,
- // meaning it receives audio injected into the framework, so the recorder doesn't
- // know about it and is therefore considered "legacy"
- *inputType = API_INPUT_LEGACY;
- } else {
- // recording a mix of players defined by an external policy, we're rerouting for
- // an external policy
- *inputType = API_INPUT_MIX_EXT_POLICY_REROUTE;
- }
- } else if (audio_is_remote_submix_device(device)) {
- address = String8("0");
+ if (policyMix != nullptr) {
+ ALOG_ASSERT(policyMix->mMixType == MIX_TYPE_RECORDERS, "Invalid Mix Type");
+ // there is an external policy, but this input is attached to a mix of recorders,
+ // meaning it receives audio injected into the framework, so the recorder doesn't
+ // know about it and is therefore considered "legacy"
+ *inputType = API_INPUT_LEGACY;
+ } else if (audio_is_remote_submix_device(device->type())) {
+ device = mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX, String8("0"));
*inputType = API_INPUT_MIX_CAPTURE;
- } else if (device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
+ } else if (device->type() == AUDIO_DEVICE_IN_TELEPHONY_RX) {
*inputType = API_INPUT_TELEPHONY_RX;
} else {
*inputType = API_INPUT_LEGACY;
@@ -1856,7 +1841,7 @@
}
- *input = getInputForDevice(device, address, session, inputSource,
+ *input = getInputForDevice(device, session, attributes.source,
config, flags,
policyMix);
if (*input == AUDIO_IO_HANDLE_NONE) {
@@ -1866,16 +1851,16 @@
exit:
- inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
- *selectedDeviceId = getFirstDeviceId(inputDevices);
+ *selectedDeviceId = mAvailableInputDevices.contains(device) ?
+ device->getId() : AUDIO_PORT_HANDLE_NONE;
- isSoundTrigger = inputSource == AUDIO_SOURCE_HOTWORD &&
+ isSoundTrigger = attributes.source == AUDIO_SOURCE_HOTWORD &&
mSoundTriggerSessions.indexOfKey(session) > 0;
*portId = AudioPort::getNextUniqueId();
- clientDesc = new RecordClientDescriptor(*portId, uid, session,
- *attr, *config, requestedDeviceId,
- inputSource,flags, isSoundTrigger);
+ clientDesc = new RecordClientDescriptor(*portId, uid, session, *attr, *config,
+ requestedDeviceId, attributes.source, flags,
+ isSoundTrigger);
inputDesc = mInputs.valueFor(*input);
inputDesc->addClient(clientDesc);
@@ -1889,8 +1874,7 @@
}
-audio_io_handle_t AudioPolicyManager::getInputForDevice(audio_devices_t device,
- String8 address,
+audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor> &device,
audio_session_t session,
audio_source_t inputSource,
const audio_config_base_t *config,
@@ -1926,8 +1910,7 @@
audio_input_flags_t profileFlags = flags;
for (;;) {
profileFormat = config->format; // reset each time through loop, in case it is updated
- profile = getInputProfile(device, address,
- profileSamplingRate, profileFormat, profileChannelMask,
+ profile = getInputProfile(device, profileSamplingRate, profileFormat, profileChannelMask,
profileFlags);
if (profile != 0) {
break; // success
@@ -1936,9 +1919,9 @@
} else if (profileFlags != AUDIO_INPUT_FLAG_NONE) {
profileFlags = AUDIO_INPUT_FLAG_NONE; // retry
} else { // fail
- ALOGW("getInputForDevice() could not find profile for device 0x%X, "
- "sampling rate %u, format %#x, channel mask 0x%X, flags %#x",
- device, config->sample_rate, config->format, config->channel_mask, flags);
+ ALOGW("%s could not find profile for device %s, sampling rate %u, format %#x, "
+ "channel mask 0x%X, flags %#x", __func__, device->toString().c_str(),
+ config->sample_rate, config->format, config->channel_mask, flags);
return input;
}
}
@@ -1995,14 +1978,7 @@
lConfig.channel_mask = profileChannelMask;
lConfig.format = profileFormat;
- if (address == "") {
- DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(device);
- // the inputs vector must be of size >= 1, but we don't want to crash here
- address = getFirstDeviceAddress(inputDevices);
- }
-
- status_t status = inputDesc->open(&lConfig, device, address,
- halInputSource, profileFlags, &input);
+ status_t status = inputDesc->open(&lConfig, device, halInputSource, profileFlags, &input);
// only accept input with the exact requested set of parameters
if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE ||
@@ -2059,7 +2035,7 @@
// indicate active capture to sound trigger service if starting capture from a mic on
// primary HW module
- audio_devices_t device = getNewInputDevice(inputDesc);
+ sp<DeviceDescriptor> device = getNewInputDevice(inputDesc);
setInputDevice(input, device, true /* force */);
if (inputDesc->activeCount() == 1) {
@@ -2070,8 +2046,8 @@
MIX_STATE_MIXING);
}
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
+ if (primaryInputDevices.contains(device) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 1) {
SoundTrigger::setCaptureState(true);
}
@@ -2079,7 +2055,7 @@
// automatically enable the remote submix output when input is started if not
// used by a policy mix of type MIX_TYPE_RECORDERS
// For remote submix (a virtual device), we open only one input per capture request.
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
String8 address = String8("");
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
@@ -2130,7 +2106,7 @@
// automatically disable the remote submix output when input is stopped if not
// used by a policy mix of type MIX_TYPE_RECORDERS
- if (audio_is_remote_submix_device(inputDesc->mDevice)) {
+ if (audio_is_remote_submix_device(inputDesc->getDeviceType())) {
String8 address = String8("");
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
@@ -2143,14 +2119,12 @@
address, "remote-submix");
}
}
-
- audio_devices_t device = inputDesc->mDevice;
resetInputDevice(input);
// indicate inactive capture to sound trigger service if stopping capture from a mic on
// primary HW module
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
+ if (primaryInputDevices.contains(inputDesc->getDevice()) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
SoundTrigger::setCaptureState(false);
}
@@ -2280,7 +2254,7 @@
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- audio_devices_t curDevice = desc->device();
+ audio_devices_t curDevice = desc->devices().types();
for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
if (!(streamsMatchForvolume(stream, (audio_stream_type_t)curStream))) {
continue;
@@ -2356,8 +2330,8 @@
// 4: the first output in the list
routing_strategy strategy = getStrategy(AUDIO_STREAM_MUSIC);
- audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
+ DeviceVector devices = getDevicesForStrategy(strategy, false /*fromCache*/);
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
if (outputs.size() == 0) {
return AUDIO_IO_HANDLE_NONE;
@@ -2674,6 +2648,57 @@
}
}
+status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size());
+ // uid/device affinity is only for output devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ if (!audio_is_output_device(devices[i].mType)) {
+ ALOGE("setUidDeviceAffinities() device=%08x is NOT an output device",
+ devices[i].mType);
+ return BAD_VALUE;
+ }
+ }
+ status_t res = mPolicyMixes.setUidDeviceAffinities(uid, devices);
+ if (res == NO_ERROR) {
+ // reevaluate outputs for all given devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+ devices[i].mType, devices[i].mAddress, String8());
+ SortedVector<audio_io_handle_t> outputs;
+ if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ outputs) != NO_ERROR) {
+ ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
+ " addr=%s", devices[i].mType, devices[i].mAddress.string());
+ return INVALID_OPERATION;
+ }
+ }
+ }
+ return res;
+}
+
+status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
+ ALOGV("%s() uid=%d", __FUNCTION__, uid);
+ Vector<AudioDeviceTypeAddr> devices;
+ status_t res = mPolicyMixes.getDevicesForUid(uid, devices);
+ if (res == NO_ERROR) {
+ // reevaluate outputs for all found devices
+ for (size_t i = 0; i < devices.size(); i++) {
+ sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
+ devices[i].mType, devices[i].mAddress, String8());
+ SortedVector<audio_io_handle_t> outputs;
+ if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ outputs) != NO_ERROR) {
+ ALOGE("%s() error in checkOutputsForDevice for device=%08x addr=%s",
+ __FUNCTION__, devices[i].mType, devices[i].mAddress.string());
+ return INVALID_OPERATION;
+ }
+ }
+ }
+
+ return res;
+}
+
void AudioPolicyManager::dump(String8 *dst) const
{
dst->appendFormat("\nAudioPolicyManager Dump: %p\n", this);
@@ -2783,7 +2808,7 @@
// See if there is a profile to support this.
// AUDIO_DEVICE_NONE
- sp<IOProfile> profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */,
+ sp<IOProfile> profile = getProfileForOutput(DeviceVector() /*ignore device */,
offloadInfo.sample_rate,
offloadInfo.format,
offloadInfo.channel_mask,
@@ -2797,7 +2822,7 @@
const audio_attributes_t& attributes) {
audio_output_flags_t output_flags = AUDIO_OUTPUT_FLAG_NONE;
audio_attributes_flags_to_audio_output_flags(attributes.flags, output_flags);
- sp<IOProfile> profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */,
+ sp<IOProfile> profile = getProfileForOutput(DeviceVector() /*ignore device */,
config.sample_rate,
config.format,
config.channel_mask,
@@ -2991,8 +3016,7 @@
return BAD_VALUE;
}
- if (!outputDesc->mProfile->isCompatibleProfile(devDesc->type(),
- devDesc->address(),
+ if (!outputDesc->mProfile->isCompatibleProfile(DeviceVector(devDesc),
patch->sources[0].sample_rate,
NULL, // updatedSamplingRate
patch->sources[0].format,
@@ -3013,7 +3037,7 @@
// TODO: reconfigure output format and channels here
ALOGV("createAudioPatch() setting device %08x on output %d",
devices.types(), outputDesc->mIoHandle);
- setOutputDevice(outputDesc, devices.types(), true, 0, handle);
+ setOutputDevices(outputDesc, devices, true, 0, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -3042,14 +3066,13 @@
return BAD_VALUE;
}
}
- sp<DeviceDescriptor> devDesc =
+ sp<DeviceDescriptor> device =
mAvailableInputDevices.getDeviceFromId(patch->sources[0].id);
- if (devDesc == 0) {
+ if (device == 0) {
return BAD_VALUE;
}
- if (!inputDesc->mProfile->isCompatibleProfile(devDesc->type(),
- devDesc->address(),
+ if (!inputDesc->mProfile->isCompatibleProfile(DeviceVector(device),
patch->sinks[0].sample_rate,
NULL, /*updatedSampleRate*/
patch->sinks[0].format,
@@ -3063,9 +3086,9 @@
return INVALID_OPERATION;
}
// TODO: reconfigure output format and channels here
- ALOGV("createAudioPatch() setting device %08x on output %d",
- devDesc->type(), inputDesc->mIoHandle);
- setInputDevice(inputDesc->mIoHandle, devDesc->type(), true, handle);
+ ALOGV("%s() setting device %s on output %d", __func__,
+ device->toString().c_str(), inputDesc->mIoHandle);
+ setInputDevice(inputDesc->mIoHandle, device, true, handle);
index = mAudioPatches.indexOfKey(*handle);
if (index >= 0) {
if (patchDesc != 0 && patchDesc != mAudioPatches.valueAt(index)) {
@@ -3085,16 +3108,16 @@
return BAD_VALUE;
}
}
- sp<DeviceDescriptor> srcDeviceDesc =
+ sp<DeviceDescriptor> srcDevice =
mAvailableInputDevices.getDeviceFromId(patch->sources[0].id);
- if (srcDeviceDesc == 0) {
+ if (srcDevice == 0) {
return BAD_VALUE;
}
//update source and sink with our own data as the data passed in the patch may
// be incomplete.
struct audio_patch newPatch = *patch;
- srcDeviceDesc->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]);
+ srcDevice->toAudioPortConfig(&newPatch.sources[0], &patch->sources[0]);
for (size_t i = 0; i < patch->num_sinks; i++) {
if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
@@ -3102,26 +3125,26 @@
return INVALID_OPERATION;
}
- sp<DeviceDescriptor> sinkDeviceDesc =
+ sp<DeviceDescriptor> sinkDevice =
mAvailableOutputDevices.getDeviceFromId(patch->sinks[i].id);
- if (sinkDeviceDesc == 0) {
+ if (sinkDevice == 0) {
return BAD_VALUE;
}
- sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);
+ sinkDevice->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
// - audio HAL version is >= 3.0 but no route has been declared between devices
- if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
- (srcDeviceDesc->getModuleVersionMajor() < 3) ||
- !srcDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc)) {
+ if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
+ (srcDevice->getModuleVersionMajor() < 3) ||
+ !srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice)) {
// support only one sink device for now to simplify output selection logic
if (patch->num_sinks > 1) {
return INVALID_OPERATION;
}
SortedVector<audio_io_handle_t> outputs =
- getOutputsForDevice(sinkDeviceDesc->type(), mOutputs);
+ getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
// if the sink device is reachable via an opened output stream, request to go via
// this output stream by adding a second source to the patch description
audio_io_handle_t output = selectOutput(outputs);
@@ -3179,11 +3202,11 @@
return BAD_VALUE;
}
- setOutputDevice(outputDesc,
- getNewOutputDevice(outputDesc, true /*fromCache*/),
- true,
- 0,
- NULL);
+ setOutputDevices(outputDesc,
+ getNewOutputDevices(outputDesc, true /*fromCache*/),
+ true,
+ 0,
+ NULL);
} else if (patch->sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(patch->sinks[0].id);
@@ -3306,8 +3329,8 @@
void AudioPolicyManager::checkStrategyRoute(routing_strategy strategy,
audio_io_handle_t ouptutToSkip)
{
- audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
+ DeviceVector devices = getDevicesForStrategy(strategy, false /*fromCache*/);
+ SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
for (size_t j = 0; j < mOutputs.size(); j++) {
if (mOutputs.keyAt(j) == ouptutToSkip) {
continue;
@@ -3326,8 +3349,8 @@
}
}
} else {
- audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
- setOutputDevice(outputDesc, newDevice, false);
+ setOutputDevices(
+ outputDesc, getNewOutputDevices(outputDesc, false /*fromCache*/), false);
}
}
}
@@ -3390,7 +3413,8 @@
{
*session = (audio_session_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
*ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
- *device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD);
+ audio_attributes_t attr = { .source = AUDIO_SOURCE_HOTWORD };
+ *device = getDeviceAndMixForAttributes(attr)->type();
return mSoundTriggerSessions.acquireSession(*session, *ioHandle);
}
@@ -3416,10 +3440,10 @@
return INVALID_OPERATION;
}
- sp<DeviceDescriptor> srcDeviceDesc =
+ sp<DeviceDescriptor> srcDevice =
mAvailableInputDevices.getDevice(source->ext.device.type,
- String8(source->ext.device.address));
- if (srcDeviceDesc == 0) {
+ String8(source->ext.device.address));
+ if (srcDevice == 0) {
ALOGW("%s source->ext.device.type %08x not found", __FUNCTION__, source->ext.device.type);
return BAD_VALUE;
}
@@ -3430,7 +3454,7 @@
sp<AudioPatch> patchDesc = new AudioPatch(&dummyPatch, uid);
sp<SourceClientDescriptor> sourceDesc =
- new SourceClientDescriptor(*portId, uid, *attributes, patchDesc, srcDeviceDesc,
+ new SourceClientDescriptor(*portId, uid, *attributes, patchDesc, srcDevice,
streamTypefromAttributesInt(attributes),
getStrategyForAttr(attributes));
@@ -3451,18 +3475,20 @@
audio_attributes_t attributes = sourceDesc->attributes();
routing_strategy strategy = getStrategyForAttr(&attributes);
audio_stream_type_t stream = sourceDesc->stream();
- sp<DeviceDescriptor> srcDeviceDesc = sourceDesc->srcDevice();
+ sp<DeviceDescriptor> srcDevice = sourceDesc->srcDevice();
- audio_devices_t sinkDevice = getDeviceForStrategy(strategy, true);
- sp<DeviceDescriptor> sinkDeviceDesc =
- mAvailableOutputDevices.getDevice(sinkDevice, String8(""));
+ DeviceVector sinkDevices = getDevicesForStrategy(strategy, true);
+ ALOG_ASSERT(!sinkDevices.isEmpty(), "connectAudioSource(): no device found for strategy");
+ sp<DeviceDescriptor> sinkDevice = sinkDevices.itemAt(0);
+ ALOG_ASSERT(mAvailableOutputDevices.contains(sinkDevice), "%s: Device %s not available",
+ __FUNCTION__, sinkDevice->toString().c_str());
audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
- if (srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) &&
- srcDeviceDesc->getModuleVersionMajor() >= 3 &&
- sinkDeviceDesc->getModule()->supportsPatch(srcDeviceDesc, sinkDeviceDesc) &&
- srcDeviceDesc->getAudioPort()->mGains.size() > 0) {
+ if (srcDevice->hasSameHwModuleAs(sinkDevice) &&
+ srcDevice->getModuleVersionMajor() >= 3 &&
+ sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) &&
+ srcDevice->getAudioPort()->mGains.size() > 0) {
ALOGV("%s Device to Device route supported by >=3.0 HAL", __FUNCTION__);
// TODO: may explicitly specify whether we should use HW or SW patch
// create patch between src device and output device
@@ -3479,12 +3505,12 @@
getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
&attributes, &stream, sourceDesc->uid(), &config, &flags, &selectedDeviceId);
if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice);
+ ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevices.types());
return INVALID_OPERATION;
}
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isDuplicated()) {
- ALOGV("%s output for device %08x is duplicated", __FUNCTION__, sinkDevice);
+ ALOGV("%s output for device %08x is duplicated", __FUNCTION__, sinkDevices.types());
return INVALID_OPERATION;
}
status_t status = outputDesc->start();
@@ -3498,7 +3524,7 @@
// - the sink is defined by whatever output device is currently selected for the output
// though which this patch is routed.
PatchBuilder patchBuilder;
- patchBuilder.addSource(srcDeviceDesc).addSource(outputDesc, { .stream = stream });
+ patchBuilder.addSource(srcDevice).addSource(outputDesc, { .stream = stream });
status = mpClientInterface->createAudioPatch(patchBuilder.patch(),
&afPatchHandle,
0);
@@ -3925,8 +3951,6 @@
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// open all output streams needed to access attached devices
- audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
- audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
for (const auto& hwModule : mHwModulesAll) {
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
@@ -3955,51 +3979,49 @@
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
}
- audio_devices_t profileType = outProfile->getSupportedDevicesType();
- if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
- profileType = mDefaultOutputDevice->type();
+ const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
+ DeviceVector availProfileDevices = supportedDevices.filter(mAvailableOutputDevices);
+ sp<DeviceDescriptor> supportedDevice = 0;
+ if (supportedDevices.contains(mDefaultOutputDevice)) {
+ supportedDevice = mDefaultOutputDevice;
} else {
- // chose first device present in profile's SupportedDevices also part of
- // outputDeviceTypes
- profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
+ // choose first device present in profile's SupportedDevices also part of
+ // mAvailableOutputDevices.
+ if (availProfileDevices.isEmpty()) {
+ continue;
+ }
+ supportedDevice = availProfileDevices.itemAt(0);
}
- if ((profileType & outputDeviceTypes) == 0) {
+ if (!mAvailableOutputDevices.contains(supportedDevice)) {
continue;
}
sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
- const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
- const DeviceVector &devicesForType = supportedDevices.getDevicesFromTypeMask(
- profileType);
- String8 address = getFirstDeviceAddress(devicesForType);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = outputDesc->open(nullptr, profileType, address,
- AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
-
+ status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
+ AUDIO_STREAM_DEFAULT,
+ AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
- ALOGW("Cannot open output stream for device %08x on hw module %s",
- outputDesc->mDevice,
- hwModule->getName());
- } else {
- for (const auto& dev : supportedDevices) {
- ssize_t index = mAvailableOutputDevices.indexOf(dev);
- // give a valid ID to an attached device once confirmed it is reachable
- if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
- mAvailableOutputDevices[index]->attach(hwModule);
- }
- }
- if (mPrimaryOutput == 0 &&
- outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
- mPrimaryOutput = outputDesc;
- }
- addOutput(output, outputDesc);
- setOutputDevice(outputDesc,
- profileType,
- true,
- 0,
- NULL,
- address);
+ ALOGW("Cannot open output stream for devices %s on hw module %s",
+ supportedDevice->toString().c_str(), hwModule->getName());
+ continue;
}
+ for (const auto &device : availProfileDevices) {
+ // give a valid ID to an attached device once confirmed it is reachable
+ if (!device->isAttached()) {
+ device->attach(hwModule);
+ }
+ }
+ if (mPrimaryOutput == 0 &&
+ outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
+ mPrimaryOutput = outputDesc;
+ }
+ addOutput(output, outputDesc);
+ setOutputDevices(outputDesc,
+ DeviceVector(supportedDevice),
+ true,
+ 0,
+ NULL);
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
@@ -4014,84 +4036,68 @@
continue;
}
// chose first device present in profile's SupportedDevices also part of
- // inputDeviceTypes
- audio_devices_t profileType = inProfile->getSupportedDeviceForType(inputDeviceTypes);
-
- if ((profileType & inputDeviceTypes) == 0) {
+ // available input devices
+ const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
+ DeviceVector availProfileDevices = supportedDevices.filter(mAvailableInputDevices);
+ if (availProfileDevices.isEmpty()) {
+ ALOGE("%s: Input device list is empty!", __FUNCTION__);
continue;
}
sp<AudioInputDescriptor> inputDesc =
new AudioInputDescriptor(inProfile, mpClientInterface);
- DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromTypeMask(profileType);
- // the inputs vector must be of size >= 1, but we don't want to crash here
- String8 address = getFirstDeviceAddress(inputDevices);
- ALOGV(" for input device 0x%x using address %s", profileType, address.string());
- ALOGE_IF(inputDevices.size() == 0, "Input device list is empty!");
-
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
status_t status = inputDesc->open(nullptr,
- profileType,
- address,
+ availProfileDevices.itemAt(0),
AUDIO_SOURCE_MIC,
AUDIO_INPUT_FLAG_NONE,
&input);
-
- if (status == NO_ERROR) {
- for (const auto& dev : inProfile->getSupportedDevices()) {
- ssize_t index = mAvailableInputDevices.indexOf(dev);
- // give a valid ID to an attached device once confirmed it is reachable
- if (index >= 0) {
- sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
- if (!devDesc->isAttached()) {
- devDesc->attach(hwModule);
- devDesc->importAudioPort(inProfile, true);
- }
- }
- }
- inputDesc->close();
- } else {
- ALOGW("Cannot open input stream for device %08x on hw module %s",
- profileType,
+ if (status != NO_ERROR) {
+ ALOGW("Cannot open input stream for device %s on hw module %s",
+ availProfileDevices.toString().c_str(),
hwModule->getName());
+ continue;
}
+ for (const auto &device : availProfileDevices) {
+ // give a valid ID to an attached device once confirmed it is reachable
+ if (!device->isAttached()) {
+ device->attach(hwModule);
+ device->importAudioPort(inProfile, true);
+ }
+ }
+ inputDesc->close();
}
}
// make sure all attached devices have been allocated a unique ID
- for (size_t i = 0; i < mAvailableOutputDevices.size();) {
- if (!mAvailableOutputDevices[i]->isAttached()) {
- ALOGW("Output device %08x unreachable", mAvailableOutputDevices[i]->type());
- mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
- continue;
+ auto checkAndSetAvailable = [this](auto& devices) {
+ for (size_t i = 0; i < devices.size();) {
+ const auto &device = devices[i];
+ if (!device->isAttached()) {
+ ALOGW("device %s is unreachable", device->toString().c_str());
+ devices.remove(device);
+ continue;
+ }
+ // Device is now validated and can be appended to the available devices of the engine
+ mEngine->setDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+ i++;
}
- // The device is now validated and can be appended to the available devices of the engine
- mEngine->setDeviceConnectionState(mAvailableOutputDevices[i],
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
- i++;
- }
- for (size_t i = 0; i < mAvailableInputDevices.size();) {
- if (!mAvailableInputDevices[i]->isAttached()) {
- ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->type());
- mAvailableInputDevices.remove(mAvailableInputDevices[i]);
- continue;
- }
- // The device is now validated and can be appended to the available devices of the engine
- mEngine->setDeviceConnectionState(mAvailableInputDevices[i],
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
- i++;
- }
+ };
+ checkAndSetAvailable(mAvailableOutputDevices);
+ checkAndSetAvailable(mAvailableInputDevices);
+
// make sure default device is reachable
- if (mDefaultOutputDevice == 0 || mAvailableOutputDevices.indexOf(mDefaultOutputDevice) < 0) {
- ALOGE("Default device %08x is unreachable", mDefaultOutputDevice->type());
+ if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
+ ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
+ mDefaultOutputDevice->toString().c_str());
status = NO_INIT;
}
// If microphones address is empty, set it according to device type
for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
if (mAvailableInputDevices[i]->address().isEmpty()) {
if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
- mAvailableInputDevices[i]->address() = String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ mAvailableInputDevices[i]->setAddress(String8(AUDIO_BOTTOM_MICROPHONE_ADDRESS));
} else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
- mAvailableInputDevices[i]->address() = String8(AUDIO_BACK_MICROPHONE_ADDRESS);
+ mAvailableInputDevices[i]->setAddress(String8(AUDIO_BACK_MICROPHONE_ADDRESS));
}
}
}
@@ -4155,44 +4161,27 @@
nextAudioPortGeneration();
}
-void AudioPolicyManager::findIoHandlesByAddress(const sp<SwAudioOutputDescriptor>& desc /*in*/,
- const audio_devices_t device /*in*/,
- const String8& address /*in*/,
- SortedVector<audio_io_handle_t>& outputs /*out*/) {
- sp<DeviceDescriptor> devDesc =
- desc->mProfile->getSupportedDeviceByAddress(device, address);
- if (devDesc != 0) {
- ALOGV("findIoHandlesByAddress(): adding opened output %d on same address %s",
- desc->mIoHandle, address.string());
- outputs.add(desc->mIoHandle);
- }
-}
-
-status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& devDesc,
+status_t AudioPolicyManager::checkOutputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& outputs,
- const String8& address)
+ SortedVector<audio_io_handle_t>& outputs)
{
- audio_devices_t device = devDesc->type();
+ audio_devices_t deviceType = device->type();
+ const String8 &address = device->address();
sp<SwAudioOutputDescriptor> desc;
- if (audio_device_is_digital(device)) {
+ if (audio_device_is_digital(deviceType)) {
// erase all current sample rates, formats and channel masks
- devDesc->clearAudioProfiles();
+ device->clearAudioProfiles();
}
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
// first list already open outputs that can be routed to this device
for (size_t i = 0; i < mOutputs.size(); i++) {
desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && (desc->supportedDevices() & device)) {
- if (!device_distinguishes_on_address(device)) {
- ALOGV("checkOutputsForDevice(): adding opened output %d", mOutputs.keyAt(i));
- outputs.add(mOutputs.keyAt(i));
- } else {
- ALOGV(" checking address match due to device 0x%x", device);
- findIoHandlesByAddress(desc, device, address, outputs);
- }
+ if (!desc->isDuplicated() && desc->supportsDevice(device)) {
+ ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
+ mOutputs.keyAt(i), device->toString().c_str());
+ outputs.add(mOutputs.keyAt(i));
}
}
// then look for output profiles that can be routed to this device
@@ -4200,13 +4189,10 @@
for (const auto& hwModule : mHwModules) {
for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
sp<IOProfile> profile = hwModule->getOutputProfiles()[j];
- if (profile->supportDevice(device)) {
- if (!device_distinguishes_on_address(device) ||
- profile->supportDeviceAddress(address)) {
- profiles.add(profile);
- ALOGV("checkOutputsForDevice(): adding profile %zu from module %s",
- j, hwModule->getName());
- }
+ if (profile->supportsDevice(device)) {
+ profiles.add(profile);
+ ALOGV("checkOutputsForDevice(): adding profile %zu from module %s",
+ j, hwModule->getName());
}
}
}
@@ -4214,7 +4200,7 @@
ALOGV(" found %zu profiles, %zu outputs", profiles.size(), outputs.size());
if (profiles.isEmpty() && outputs.isEmpty()) {
- ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
+ ALOGW("checkOutputsForDevice(): No output available for device %04x", deviceType);
return BAD_VALUE;
}
@@ -4230,8 +4216,8 @@
if (!desc->isDuplicated() && desc->mProfile == profile) {
// matching profile: save the sample rates, format and channel masks supported
// by the profile in our device descriptor
- if (audio_device_is_digital(device)) {
- devDesc->importAudioPort(profile);
+ if (audio_device_is_digital(deviceType)) {
+ device->importAudioPort(profile);
}
break;
}
@@ -4247,20 +4233,20 @@
}
ALOGV("opening output for device %08x with params %s profile %p name %s",
- device, address.string(), profile.get(), profile->getName().string());
+ deviceType, address.string(), profile.get(), profile->getName().string());
desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr, device, address,
+ status_t status = desc->open(nullptr, DeviceVector(device),
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status == NO_ERROR) {
// Here is where the out_set_parameters() for card & device gets called
if (!address.isEmpty()) {
- char *param = audio_device_address_to_parameter(device, address);
+ char *param = audio_device_address_to_parameter(deviceType, address);
mpClientInterface->setParameters(output, String8(param));
free(param);
}
- updateAudioProfiles(devDesc, output, profile->getAudioProfiles());
+ updateAudioProfiles(device, output, profile->getAudioProfiles());
if (!profile->hasValidAudioProfile()) {
ALOGW("checkOutputsForDevice() missing param");
desc->close();
@@ -4275,7 +4261,8 @@
config.offload_info.channel_mask = config.channel_mask;
config.offload_info.format = config.format;
- status_t status = desc->open(&config, device, address, AUDIO_STREAM_DEFAULT,
+ status_t status = desc->open(&config, DeviceVector(device),
+ AUDIO_STREAM_DEFAULT,
AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
output = AUDIO_IO_HANDLE_NONE;
@@ -4284,14 +4271,15 @@
if (output != AUDIO_IO_HANDLE_NONE) {
addOutput(output, desc);
- if (device_distinguishes_on_address(device) && address != "0") {
+ if (device_distinguishes_on_address(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
- if (mPolicyMixes.getAudioPolicyMix(address, policyMix) != NO_ERROR) {
- ALOGE("checkOutputsForDevice() cannot find policy for address %s",
+ if (mPolicyMixes.getAudioPolicyMix(address, policyMix) == NO_ERROR) {
+ policyMix->setOutput(desc);
+ desc->mPolicyMix = policyMix->getMix();
+ } else {
+ ALOGW("checkOutputsForDevice() cannot find policy for address %s",
address.string());
}
- policyMix->setOutput(desc);
- desc->mPolicyMix = policyMix->getMix();
} else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
hasPrimaryOutput()) {
@@ -4323,28 +4311,28 @@
output = AUDIO_IO_HANDLE_NONE;
}
if (output == AUDIO_IO_HANDLE_NONE) {
- ALOGW("checkOutputsForDevice() could not open output for device %x", device);
+ ALOGW("checkOutputsForDevice() could not open output for device %x", deviceType);
profiles.removeAt(profile_index);
profile_index--;
} else {
outputs.add(output);
// Load digital format info only for digital devices
- if (audio_device_is_digital(device)) {
- devDesc->importAudioPort(profile);
+ if (audio_device_is_digital(deviceType)) {
+ device->importAudioPort(profile);
}
- if (device_distinguishes_on_address(device)) {
- ALOGV("checkOutputsForDevice(): setOutputDevice(dev=0x%x, addr=%s)",
- device, address.string());
- setOutputDevice(desc, device, true/*force*/, 0/*delay*/,
- NULL/*patch handle*/, address.string());
+ if (device_distinguishes_on_address(deviceType)) {
+ ALOGV("checkOutputsForDevice(): setOutputDevices %s",
+ device->toString().c_str());
+ setOutputDevices(desc, DeviceVector(device), true/*force*/, 0/*delay*/,
+ NULL/*patch handle*/);
}
ALOGV("checkOutputsForDevice(): adding output %d", output);
}
}
if (profiles.isEmpty()) {
- ALOGW("checkOutputsForDevice(): No output available for device %04x", device);
+ ALOGW("checkOutputsForDevice(): No output available for device %04x", deviceType);
return BAD_VALUE;
}
} else { // Disconnect
@@ -4353,10 +4341,9 @@
desc = mOutputs.valueAt(i);
if (!desc->isDuplicated()) {
// exact match on device
- if (device_distinguishes_on_address(device) &&
- (desc->supportedDevices() == device)) {
- findIoHandlesByAddress(desc, device, address, outputs);
- } else if (!(desc->supportedDevices() & mAvailableOutputDevices.types())) {
+ if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)) {
+ outputs.add(mOutputs.keyAt(i));
+ } else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
mOutputs.keyAt(i));
outputs.add(mOutputs.keyAt(i));
@@ -4367,7 +4354,7 @@
for (const auto& hwModule : mHwModules) {
for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
sp<IOProfile> profile = hwModule->getOutputProfiles()[j];
- if (profile->supportDevice(device)) {
+ if (profile->supportsDevice(device)) {
ALOGV("checkOutputsForDevice(): "
"clearing direct output profile %zu on module %s",
j, hwModule->getName());
@@ -4379,24 +4366,22 @@
return NO_ERROR;
}
-status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& devDesc,
+status_t AudioPolicyManager::checkInputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& inputs,
- const String8& address)
+ SortedVector<audio_io_handle_t>& inputs)
{
- audio_devices_t device = devDesc->type();
sp<AudioInputDescriptor> desc;
- if (audio_device_is_digital(device)) {
+ if (audio_device_is_digital(device->type())) {
// erase all current sample rates, formats and channel masks
- devDesc->clearAudioProfiles();
+ device->clearAudioProfiles();
}
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
// first list already open inputs that can be routed to this device
for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
desc = mInputs.valueAt(input_index);
- if (desc->mProfile->supportDevice(device)) {
+ if (desc->mProfile->supportsDeviceTypes(device->type())) {
ALOGV("checkInputsForDevice(): adding opened input %d", mInputs.keyAt(input_index));
inputs.add(mInputs.keyAt(input_index));
}
@@ -4410,19 +4395,16 @@
profile_index++) {
sp<IOProfile> profile = hwModule->getInputProfiles()[profile_index];
- if (profile->supportDevice(device)) {
- if (!device_distinguishes_on_address(device) ||
- profile->supportDeviceAddress(address)) {
- profiles.add(profile);
- ALOGV("checkInputsForDevice(): adding profile %zu from module %s",
- profile_index, hwModule->getName());
- }
+ if (profile->supportsDevice(device)) {
+ profiles.add(profile);
+ ALOGV("checkInputsForDevice(): adding profile %zu from module %s",
+ profile_index, hwModule->getName());
}
}
}
if (profiles.isEmpty() && inputs.isEmpty()) {
- ALOGW("checkInputsForDevice(): No input available for device 0x%X", device);
+ ALOGW("%s: No input available for device %s", __func__, device->toString().c_str());
return BAD_VALUE;
}
@@ -4437,8 +4419,8 @@
for (input_index = 0; input_index < mInputs.size(); input_index++) {
desc = mInputs.valueAt(input_index);
if (desc->mProfile == profile) {
- if (audio_device_is_digital(device)) {
- devDesc->importAudioPort(profile);
+ if (audio_device_is_digital(device->type())) {
+ device->importAudioPort(profile);
}
break;
}
@@ -4457,18 +4439,18 @@
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
status_t status = desc->open(nullptr,
device,
- address,
AUDIO_SOURCE_MIC,
AUDIO_INPUT_FLAG_NONE,
&input);
if (status == NO_ERROR) {
+ const String8& address = device->address();
if (!address.isEmpty()) {
- char *param = audio_device_address_to_parameter(device, address);
+ char *param = audio_device_address_to_parameter(device->type(), address);
mpClientInterface->setParameters(input, String8(param));
free(param);
}
- updateAudioProfiles(devDesc, input, profile->getAudioProfiles());
+ updateAudioProfiles(device, input, profile->getAudioProfiles());
if (!profile->hasValidAudioProfile()) {
ALOGW("checkInputsForDevice() direct input missing param");
desc->close();
@@ -4481,20 +4463,21 @@
} // endif input != 0
if (input == AUDIO_IO_HANDLE_NONE) {
- ALOGW("checkInputsForDevice() could not open input for device 0x%X", device);
+ ALOGW("%s could not open input for device %s", __func__,
+ device->toString().c_str());
profiles.removeAt(profile_index);
profile_index--;
} else {
inputs.add(input);
- if (audio_device_is_digital(device)) {
- devDesc->importAudioPort(profile);
+ if (audio_device_is_digital(device->type())) {
+ device->importAudioPort(profile);
}
ALOGV("checkInputsForDevice(): adding input %d", input);
}
} // end scan profiles
if (profiles.isEmpty()) {
- ALOGW("checkInputsForDevice(): No input available for device 0x%X", device);
+ ALOGW("%s: No input available for device %s", __func__, device->toString().c_str());
return BAD_VALUE;
}
} else {
@@ -4502,7 +4485,7 @@
// check if one opened input is not needed any more after disconnecting one device
for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
desc = mInputs.valueAt(input_index);
- if (!(desc->mProfile->supportDevice(mAvailableInputDevices.types()))) {
+ if (!mAvailableInputDevices.containsAtLeastOne(desc->supportedDevices())) {
ALOGV("checkInputsForDevice(): disconnecting adding input %d",
mInputs.keyAt(input_index));
inputs.add(mInputs.keyAt(input_index));
@@ -4514,7 +4497,7 @@
profile_index < hwModule->getInputProfiles().size();
profile_index++) {
sp<IOProfile> profile = hwModule->getInputProfiles()[profile_index];
- if (profile->supportDevice(device)) {
+ if (profile->supportsDevice(device)) {
ALOGV("checkInputsForDevice(): clearing direct input profile %zu on module %s",
profile_index, hwModule->getName());
profile->clearAudioProfiles();
@@ -4588,7 +4571,7 @@
// MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if
// no direct outputs are open.
- if (mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD) != 0) {
+ if (!getMsdAudioOutDevices().isEmpty()) {
bool directOutputOpen = false;
for (size_t i = 0; i < mOutputs.size(); i++) {
if (mOutputs[i]->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
@@ -4615,7 +4598,7 @@
nextAudioPortGeneration();
- audio_devices_t device = inputDesc->mDevice;
+ sp<DeviceDescriptor> device = inputDesc->getDevice();
ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
@@ -4627,26 +4610,26 @@
inputDesc->close();
mInputs.removeItem(input);
- audio_devices_t primaryInputDevices = availablePrimaryInputDevices();
- if (((device & primaryInputDevices & ~AUDIO_DEVICE_BIT_IN) != 0) &&
+ DeviceVector primaryInputDevices = availablePrimaryModuleInputDevices();
+ if (primaryInputDevices.contains(device) &&
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
SoundTrigger::setCaptureState(false);
}
}
-SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(
- audio_devices_t device,
- const SwAudioOutputCollection& openOutputs)
+SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
+ const DeviceVector &devices,
+ const SwAudioOutputCollection& openOutputs)
{
SortedVector<audio_io_handle_t> outputs;
- ALOGVV("getOutputsForDevice() device %04x", device);
+ ALOGVV("%s() devices %s", __func__, devices.toString().c_str());
for (size_t i = 0; i < openOutputs.size(); i++) {
- ALOGVV("output %zu isDuplicated=%d device=%04x",
+ ALOGVV("output %zu isDuplicated=%d device=%s",
i, openOutputs.valueAt(i)->isDuplicated(),
- openOutputs.valueAt(i)->supportedDevices());
- if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
- ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i));
+ openOutputs.valueAt(i)->supportedDevices().toString().c_str());
+ if (openOutputs.valueAt(i)->supportsAllDevices(devices)) {
+ ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
outputs.add(openOutputs.keyAt(i));
}
}
@@ -4668,10 +4651,10 @@
void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
{
- audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);
- audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/);
- SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs);
- SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
+ DeviceVector oldDevices = getDevicesForStrategy(strategy, true /*fromCache*/);
+ DeviceVector newDevices = getDevicesForStrategy(strategy, false /*fromCache*/);
+ SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
+ SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);
// also take into account external policy-related changes: add all outputs which are
// associated with policies in the "before" and "after" output vectors
@@ -4691,7 +4674,7 @@
}
}
- if (srcOutputs != dstOutputs) {
+ if (!dstOutputs.isEmpty() && srcOutputs != dstOutputs) {
// get maximum latency of all source outputs to determine the minimum mute time guaranteeing
// audio from invalidated tracks will be rendered when unmuting
uint32_t maxLatency = 0;
@@ -4701,14 +4684,16 @@
maxLatency = desc->latency();
}
}
- ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d",
- strategy, srcOutputs[0], dstOutputs[0]);
+ ALOGV("%s: strategy %d, moving from output %s to output %s", __func__, strategy,
+ (srcOutputs.isEmpty()? "none" : std::to_string(srcOutputs[0]).c_str()),
+ (dstOutputs.isEmpty()? "none" : std::to_string(dstOutputs[0]).c_str()));
// mute strategy while moving tracks from one output to another
for (audio_io_handle_t srcOut : srcOutputs) {
sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
if (desc != 0 && isStrategyActive(desc, strategy)) {
setStrategyMute(strategy, true, desc);
- setStrategyMute(strategy, false, desc, maxLatency * LATENCY_MUTE_FACTOR, newDevice);
+ setStrategyMute(strategy, false, desc, maxLatency * LATENCY_MUTE_FACTOR,
+ newDevices.types());
}
sp<SourceClientDescriptor> source =
getSourceForStrategyOnOutput(srcOut, strategy);
@@ -4827,26 +4812,28 @@
return device;
}
-audio_devices_t AudioPolicyManager::getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
- bool fromCache)
+DeviceVector AudioPolicyManager::getNewOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
+ bool fromCache)
{
+ DeviceVector devices;
+
ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
- ALOGV("getNewOutputDevice() device %08x forced by patch %d",
- outputDesc->device(), outputDesc->getPatchHandle());
- return outputDesc->device();
+ ALOGV("%s device %s forced by patch %d", __func__,
+ outputDesc->devices().toString().c_str(), outputDesc->getPatchHandle());
+ return outputDesc->devices();
}
}
// Honor explicit routing requests only if no client using default routing is active on this
// input: a specific app can not force routing for other apps by setting a preferred device.
bool active; // unused
- sp<DeviceDescriptor> deviceDesc =
+ sp<DeviceDescriptor> device =
findPreferredDevice(outputDesc, STRATEGY_NONE, active, mAvailableOutputDevices);
- if (deviceDesc != nullptr) {
- return deviceDesc->type();
+ if (device != nullptr) {
+ return DeviceVector(device);
}
// check the following by order of priority to request a routing change if necessary:
@@ -4872,66 +4859,65 @@
// FIXME: extend use of isStrategyActiveOnSameModule() to all strategies
// with a refined rule considering mutually exclusive devices (using same backend)
// as opposed to all streams on the same audio HAL module.
- audio_devices_t device = AUDIO_DEVICE_NONE;
if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE) &&
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM) == AUDIO_POLICY_FORCE_SYSTEM_ENFORCED) {
- device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (isInCall() ||
isStrategyActiveOnSameModule(outputDesc, STRATEGY_PHONE)) {
- device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_PHONE, fromCache);
} else if (isStrategyActiveOnSameModule(outputDesc, STRATEGY_SONIFICATION)) {
- device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_SONIFICATION, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_ENFORCED_AUDIBLE)) {
- device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_ACCESSIBILITY)) {
- device = getDeviceForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_ACCESSIBILITY, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_SONIFICATION_RESPECTFUL)) {
- device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_MEDIA)) {
- device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_MEDIA, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_DTMF)) {
- device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_DTMF, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_TRANSMITTED_THROUGH_SPEAKER)) {
- device = getDeviceForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_TRANSMITTED_THROUGH_SPEAKER, fromCache);
} else if (isStrategyActive(outputDesc, STRATEGY_REROUTING)) {
- device = getDeviceForStrategy(STRATEGY_REROUTING, fromCache);
+ devices = getDevicesForStrategy(STRATEGY_REROUTING, fromCache);
}
- ALOGV("getNewOutputDevice() selected device %x", device);
- return device;
+ ALOGV("getNewOutputDevice() selected devices %s", devices.toString().c_str());
+ return devices;
}
-audio_devices_t AudioPolicyManager::getNewInputDevice(const sp<AudioInputDescriptor>& inputDesc)
+sp<DeviceDescriptor> AudioPolicyManager::getNewInputDevice(
+ const sp<AudioInputDescriptor>& inputDesc)
{
- audio_devices_t device = AUDIO_DEVICE_NONE;
+ sp<DeviceDescriptor> device;
ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
- ALOGV("getNewInputDevice() device %08x forced by patch %d",
- inputDesc->mDevice, inputDesc->getPatchHandle());
- return inputDesc->mDevice;
+ ALOGV("getNewInputDevice() device %s forced by patch %d",
+ inputDesc->getDevice()->toString().c_str(), inputDesc->getPatchHandle());
+ return inputDesc->getDevice();
}
}
// Honor explicit routing requests only if no client using default routing is active on this
// input: a specific app can not force routing for other apps by setting a preferred device.
bool active;
- sp<DeviceDescriptor> deviceDesc =
- findPreferredDevice(inputDesc, AUDIO_SOURCE_DEFAULT, active, mAvailableInputDevices);
- if (deviceDesc != nullptr) {
- return deviceDesc->type();
+ device = findPreferredDevice(inputDesc, AUDIO_SOURCE_DEFAULT, active, mAvailableInputDevices);
+ if (device != nullptr) {
+ return device;
}
// If we are not in call and no client is active on this input, this methods returns
// AUDIO_DEVICE_NONE, causing the patch on the input stream to be released.
- audio_source_t source = inputDesc->source();
- if (source == AUDIO_SOURCE_DEFAULT && isInCall()) {
- source = AUDIO_SOURCE_VOICE_COMMUNICATION;
+ audio_attributes_t attributes = inputDesc->getHighestPriorityAttributes();
+ if (attributes.source == AUDIO_SOURCE_DEFAULT && isInCall()) {
+ attributes.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
}
- if (source != AUDIO_SOURCE_DEFAULT) {
- device = getDeviceAndMixForInputSource(source);
+ if (attributes.source != AUDIO_SOURCE_DEFAULT) {
+ device = getDeviceAndMixForAttributes(attributes);
}
return device;
@@ -4953,36 +4939,37 @@
if (stream < (audio_stream_type_t) 0 || stream >= AUDIO_STREAM_PUBLIC_CNT) {
return AUDIO_DEVICE_NONE;
}
- audio_devices_t activeDevices = AUDIO_DEVICE_NONE;
- audio_devices_t devices = AUDIO_DEVICE_NONE;
+ DeviceVector activeDevices;
+ DeviceVector devices;
for (int curStream = 0; curStream < AUDIO_STREAM_FOR_POLICY_CNT; curStream++) {
if (!streamsMatchForvolume(stream, (audio_stream_type_t)curStream)) {
continue;
}
routing_strategy curStrategy = getStrategy((audio_stream_type_t)curStream);
- audio_devices_t curDevices =
- getDeviceForStrategy((routing_strategy)curStrategy, false /*fromCache*/);
- devices |= curDevices;
- for (audio_io_handle_t output : getOutputsForDevice(curDevices, mOutputs)) {
+ DeviceVector curDevices =
+ getDevicesForStrategy((routing_strategy)curStrategy, false /*fromCache*/);
+ devices.merge(curDevices);
+ for (audio_io_handle_t output : getOutputsForDevices(curDevices, mOutputs)) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isStreamActive((audio_stream_type_t)curStream)) {
- activeDevices |= outputDesc->device();
+ activeDevices.merge(outputDesc->devices());
}
}
}
// Favor devices selected on active streams if any to report correct device in case of
// explicit device selection
- if (activeDevices != AUDIO_DEVICE_NONE) {
+ if (!activeDevices.isEmpty()) {
devices = activeDevices;
}
/*Filter SPEAKER_SAFE out of results, as AudioService doesn't know about it
and doesn't really need to.*/
- if (devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
- devices |= AUDIO_DEVICE_OUT_SPEAKER;
- devices &= ~AUDIO_DEVICE_OUT_SPEAKER_SAFE;
+ DeviceVector speakerSafeDevices = devices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER_SAFE);
+ if (!speakerSafeDevices.isEmpty()) {
+ devices.merge(mAvailableOutputDevices.getDevicesFromTypeMask(AUDIO_DEVICE_OUT_SPEAKER));
+ devices.remove(speakerSafeDevices);
}
- return devices;
+ return devices.types();
}
routing_strategy AudioPolicyManager::getStrategy(audio_stream_type_t stream) const
@@ -5073,34 +5060,33 @@
return 0;
}
-audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
- bool fromCache)
+DeviceVector AudioPolicyManager::getDevicesForStrategy(routing_strategy strategy, bool fromCache)
{
// Honor explicit routing requests only if all active clients have a preferred route in which
// case the last active client route is used
- sp<DeviceDescriptor> deviceDesc = findPreferredDevice(mOutputs, strategy, mAvailableOutputDevices);
- if (deviceDesc != nullptr) {
- return deviceDesc->type();
+ sp<DeviceDescriptor> device = findPreferredDevice(mOutputs, strategy, mAvailableOutputDevices);
+ if (device != nullptr) {
+ return DeviceVector(device);
}
if (fromCache) {
- ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
- strategy, mDeviceForStrategy[strategy]);
- return mDeviceForStrategy[strategy];
+ ALOGVV("%s from cache strategy %d, device %s", __func__, strategy,
+ mDevicesForStrategy[strategy].toString().c_str());
+ return mDevicesForStrategy[strategy];
}
- return mEngine->getDeviceForStrategy(strategy);
+ return mAvailableOutputDevices.getDevicesFromTypeMask(mEngine->getDeviceForStrategy(strategy));
}
void AudioPolicyManager::updateDevicesAndOutputs()
{
for (int i = 0; i < NUM_STRATEGIES; i++) {
- mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
+ mDevicesForStrategy[i] = getDevicesForStrategy((routing_strategy)i, false /*fromCache*/);
}
mPreviousOutputs = mOutputs;
}
uint32_t AudioPolicyManager::checkDeviceMuteStrategies(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t prevDevice,
+ audio_devices_t prevDeviceType,
uint32_t delayMs)
{
// mute/unmute strategies using an incompatible device combination
@@ -5111,13 +5097,14 @@
}
uint32_t muteWaitMs = 0;
- audio_devices_t device = outputDesc->device();
- bool shouldMute = outputDesc->isActive() && (popcount(device) >= 2);
+ audio_devices_t deviceType = outputDesc->devices().types();
+ bool shouldMute = outputDesc->isActive() && (popcount(deviceType) >= 2);
for (size_t i = 0; i < NUM_STRATEGIES; i++) {
- audio_devices_t curDevice = getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
- curDevice = curDevice & outputDesc->supportedDevices();
- bool mute = shouldMute && (curDevice & device) && (curDevice != device);
+ audio_devices_t curDeviceType =
+ getDeviceForStrategy((routing_strategy)i, false /*fromCache*/);
+ curDeviceType = curDeviceType & outputDesc->supportedDevices().types();
+ bool mute = shouldMute && (curDeviceType & deviceType) && (curDeviceType != deviceType);
bool doMute = false;
if (mute && !outputDesc->mStrategyMutedByDevice[i]) {
@@ -5131,12 +5118,11 @@
for (size_t j = 0; j < mOutputs.size(); j++) {
sp<AudioOutputDescriptor> desc = mOutputs.valueAt(j);
// skip output if it does not share any device with current output
- if ((desc->supportedDevices() & outputDesc->supportedDevices())
- == AUDIO_DEVICE_NONE) {
+ if (!desc->supportedDevices().containsAtLeastOne(outputDesc->supportedDevices())) {
continue;
}
ALOGVV("checkDeviceMuteStrategies() %s strategy %zu (curDevice %04x)",
- mute ? "muting" : "unmuting", i, curDevice);
+ mute ? "muting" : "unmuting", i, curDeviceType);
setStrategyMute((routing_strategy)i, mute, desc, mute ? 0 : delayMs);
if (isStrategyActive(desc, (routing_strategy)i)) {
if (mute) {
@@ -5156,7 +5142,7 @@
// temporary mute output if device selection changes to avoid volume bursts due to
// different per device volumes
- if (outputDesc->isActive() && (device != prevDevice)) {
+ if (outputDesc->isActive() && (deviceType != prevDeviceType)) {
uint32_t tempMuteWaitMs = outputDesc->latency() * 2;
// temporary mute duration is conservatively set to 4 times the reported latency
uint32_t tempMuteDurationMs = outputDesc->latency() * 4;
@@ -5170,7 +5156,7 @@
// delayed device change
setStrategyMute((routing_strategy)i, true, outputDesc, delayMs);
setStrategyMute((routing_strategy)i, false, outputDesc,
- delayMs + tempMuteDurationMs, device);
+ delayMs + tempMuteDurationMs, deviceType);
}
}
}
@@ -5184,46 +5170,45 @@
return 0;
}
-uint32_t AudioPolicyManager::setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- bool force,
- int delayMs,
- audio_patch_handle_t *patchHandle,
- const char *address,
- bool requiresMuteCheck)
+uint32_t AudioPolicyManager::setOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const DeviceVector &devices,
+ bool force,
+ int delayMs,
+ audio_patch_handle_t *patchHandle,
+ bool requiresMuteCheck)
{
- ALOGV("setOutputDevice() device %04x delayMs %d", device, delayMs);
- AudioParameter param;
+ ALOGV("%s device %s delayMs %d", __func__, devices.toString().c_str(), delayMs);
uint32_t muteWaitMs;
if (outputDesc->isDuplicated()) {
- muteWaitMs = setOutputDevice(outputDesc->subOutput1(), device, force, delayMs,
- nullptr /* patchHandle */, nullptr /* address */, requiresMuteCheck);
- muteWaitMs += setOutputDevice(outputDesc->subOutput2(), device, force, delayMs,
- nullptr /* patchHandle */, nullptr /* address */, requiresMuteCheck);
+ muteWaitMs = setOutputDevices(outputDesc->subOutput1(), devices, force, delayMs,
+ nullptr /* patchHandle */, requiresMuteCheck);
+ muteWaitMs += setOutputDevices(outputDesc->subOutput2(), devices, force, delayMs,
+ nullptr /* patchHandle */, requiresMuteCheck);
return muteWaitMs;
}
- // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
- // output profile
- if ((device != AUDIO_DEVICE_NONE) &&
- ((device & outputDesc->supportedDevices()) == AUDIO_DEVICE_NONE)) {
- return 0;
- }
// filter devices according to output selected
- device = (audio_devices_t)(device & outputDesc->supportedDevices());
+ DeviceVector filteredDevices = outputDesc->filterSupportedDevices(devices);
- audio_devices_t prevDevice = outputDesc->mDevice;
+ // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current
+ // output profile
+ if (!devices.isEmpty() && filteredDevices.isEmpty()) {
+ ALOGV("%s: unsupported device %s for output", __func__, devices.toString().c_str());
+ return 0;
+ }
- ALOGV("setOutputDevice() prevDevice 0x%04x", prevDevice);
+ DeviceVector prevDevices = outputDesc->devices();
- if (device != AUDIO_DEVICE_NONE) {
- outputDesc->mDevice = device;
+ ALOGV("setOutputDevices() prevDevice %s", prevDevices.toString().c_str());
+
+ if (!filteredDevices.isEmpty()) {
+ outputDesc->setDevices(filteredDevices);
}
// if the outputs are not materially active, there is no need to mute.
if (requiresMuteCheck) {
- muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs);
+ muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevices.types(), delayMs);
} else {
ALOGV("%s: suppressing checkDeviceMuteStrategies", __func__);
muteWaitMs = 0;
@@ -5234,42 +5219,32 @@
// OR the requested device is the same as current device
// AND force is not specified
// AND the output is connected by a valid audio patch.
- // Doing this check here allows the caller to call setOutputDevice() without conditions
- if ((device == AUDIO_DEVICE_NONE || device == prevDevice) &&
- !force &&
- outputDesc->getPatchHandle() != 0) {
- ALOGV("setOutputDevice() setting same device 0x%04x or null device", device);
+ // Doing this check here allows the caller to call setOutputDevices() without conditions
+ if ((!filteredDevices.isEmpty() || filteredDevices == prevDevices) &&
+ !force && outputDesc->getPatchHandle() != 0) {
+ ALOGV("%s setting same device %s or null device, force=%d, patch handle=%d", __func__,
+ filteredDevices.toString().c_str(), force, outputDesc->getPatchHandle());
return muteWaitMs;
}
- ALOGV("setOutputDevice() changing device");
+ ALOGV("%s changing device to %s", __func__, filteredDevices.toString().c_str());
// do the routing
- if (device == AUDIO_DEVICE_NONE) {
+ if (filteredDevices.isEmpty()) {
resetOutputDevice(outputDesc, delayMs, NULL);
} else {
- DeviceVector deviceList;
- if ((address == NULL) || (strlen(address) == 0)) {
- deviceList = mAvailableOutputDevices.getDevicesFromTypeMask(device);
- } else {
- sp<DeviceDescriptor> deviceDesc = mAvailableOutputDevices.getDevice(
- device, String8(address));
- if (deviceDesc) deviceList.add(deviceDesc);
+ PatchBuilder patchBuilder;
+ patchBuilder.addSource(outputDesc);
+ ALOG_ASSERT(filteredDevices.size() <= AUDIO_PATCH_PORTS_MAX, "Too many sink ports");
+ for (const auto &filteredDevice : filteredDevices) {
+ patchBuilder.addSink(filteredDevice);
}
- if (!deviceList.isEmpty()) {
- PatchBuilder patchBuilder;
- patchBuilder.addSource(outputDesc);
- ALOG_ASSERT(deviceList.size() <= AUDIO_PATCH_PORTS_MAX, "Too many sink ports");
- for (const auto &device : deviceList) {
- patchBuilder.addSink(device);
- }
- installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
- }
+ installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), delayMs);
}
// update stream volumes according to new device
- applyStreamVolumes(outputDesc, device, delayMs);
+ applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs);
return muteWaitMs;
}
@@ -5298,18 +5273,17 @@
}
status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input,
- audio_devices_t device,
+ const sp<DeviceDescriptor> &device,
bool force,
audio_patch_handle_t *patchHandle)
{
status_t status = NO_ERROR;
sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input);
- if ((device != AUDIO_DEVICE_NONE) && ((device != inputDesc->mDevice) || force)) {
- inputDesc->mDevice = device;
+ if ((device != nullptr) && ((device != inputDesc->getDevice()) || force)) {
+ inputDesc->setDevice(device);
- DeviceVector deviceList = mAvailableInputDevices.getDevicesFromTypeMask(device);
- if (!deviceList.isEmpty()) {
+ if (mAvailableInputDevices.contains(device)) {
PatchBuilder patchBuilder;
patchBuilder.addSink(inputDesc,
// AUDIO_SOURCE_HOTWORD is for internal use only:
@@ -5321,7 +5295,7 @@
}
return result; }).
//only one input device for now
- addSource(deviceList.itemAt(0));
+ addSource(device);
status = installPatch(__func__, patchHandle, inputDesc.get(), patchBuilder.patch(), 0);
}
}
@@ -5351,8 +5325,7 @@
return status;
}
-sp<IOProfile> AudioPolicyManager::getInputProfile(audio_devices_t device,
- const String8& address,
+sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &device,
uint32_t& samplingRate,
audio_format_t& format,
audio_channel_mask_t& channelMask,
@@ -5372,7 +5345,7 @@
for (const auto& profile : hwModule->getInputProfiles()) {
// profile->log();
//updatedFormat = format;
- if (profile->isCompatibleProfile(device, address, samplingRate,
+ if (profile->isCompatibleProfile(DeviceVector(device), samplingRate,
&samplingRate /*updatedSamplingRate*/,
format,
&format, /*updatedFormat*/
@@ -5383,7 +5356,7 @@
true /*exactMatchRequiredForInputFlags*/)) {
return profile;
}
- if (firstInexact == nullptr && profile->isCompatibleProfile(device, address,
+ if (firstInexact == nullptr && profile->isCompatibleProfile(DeviceVector(device),
samplingRate,
&updatedSamplingRate,
format,
@@ -5407,32 +5380,33 @@
return NULL;
}
-
-audio_devices_t AudioPolicyManager::getDeviceAndMixForInputSource(audio_source_t inputSource,
- AudioMix **policyMix)
+sp<DeviceDescriptor> AudioPolicyManager::getDeviceAndMixForAttributes(
+ const audio_attributes_t &attributes, AudioMix **policyMix)
{
// Honor explicit routing requests only if all active clients have a preferred route in which
// case the last active client route is used
- sp<DeviceDescriptor> deviceDesc =
- findPreferredDevice(mInputs, inputSource, mAvailableInputDevices);
- if (deviceDesc != nullptr) {
- return deviceDesc->type();
+ sp<DeviceDescriptor> device =
+ findPreferredDevice(mInputs, attributes.source, mAvailableInputDevices);
+ if (device != nullptr) {
+ return device;
}
-
- audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
- audio_devices_t selectedDeviceFromMix =
- mPolicyMixes.getDeviceAndMixForInputSource(inputSource, availableDeviceTypes, policyMix);
-
- if (selectedDeviceFromMix != AUDIO_DEVICE_NONE) {
- return selectedDeviceFromMix;
- }
- return getDeviceForInputSource(inputSource);
+ sp<DeviceDescriptor> selectedDeviceFromMix =
+ mPolicyMixes.getDeviceAndMixForInputSource(attributes.source, mAvailableInputDevices,
+ policyMix);
+ return (selectedDeviceFromMix != nullptr) ?
+ selectedDeviceFromMix : getDeviceForAttributes(attributes);
}
-audio_devices_t AudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
+sp<DeviceDescriptor> AudioPolicyManager::getDeviceForAttributes(const audio_attributes_t &attributes)
{
- return mEngine->getDeviceForInputSource(inputSource);
+ audio_devices_t device = mEngine->getDeviceForInputSource(attributes.source);
+ if (attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX &&
+ strncmp(attributes.tags, "addr=", strlen("addr=")) == 0) {
+ return mAvailableInputDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ String8(attributes.tags + strlen("addr=")));
+ }
+ return mAvailableInputDevices.getDevice(device);
}
float AudioPolicyManager::computeVolume(audio_stream_type_t stream,
@@ -5577,7 +5551,7 @@
}
if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->device();
+ device = outputDesc->devices().types();
}
float volumeDb = computeVolume(stream, index, device);
@@ -5648,7 +5622,7 @@
audio_devices_t device)
{
if (device == AUDIO_DEVICE_NONE) {
- device = outputDesc->device();
+ device = outputDesc->devices().types();
}
ALOGVV("setStreamMute() stream %d, mute %d, mMuteCount %d device %04x",
@@ -5745,9 +5719,9 @@
return false;
}
-bool AudioPolicyManager::isStrategyActiveOnSameModule(const sp<AudioOutputDescriptor>& outputDesc,
- routing_strategy strategy, uint32_t inPastMs,
- nsecs_t sysTime) const
+bool AudioPolicyManager::isStrategyActiveOnSameModule(const sp<SwAudioOutputDescriptor>& outputDesc,
+ routing_strategy strategy, uint32_t inPastMs,
+ nsecs_t sysTime) const
{
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
@@ -5806,6 +5780,8 @@
releaseAudioPatch(patchDesc->mHandle, patchDesc->mUid);
}
}
+
+ mHwModules.cleanUpForDevice(deviceDesc);
}
void AudioPolicyManager::modifySurroundFormats(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 35dd87c..e99de16 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -218,6 +218,9 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+ virtual status_t setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices);
+ virtual status_t removeUidDeviceAffinities(uid_t uid);
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
@@ -310,36 +313,40 @@
// where conditions are changing (setDeviceConnectionState(), setPhoneState()...) AND
// before updateDevicesAndOutputs() is called.
virtual audio_devices_t getDeviceForStrategy(routing_strategy strategy,
- bool fromCache);
+ bool fromCache)
+ {
+ return getDevicesForStrategy(strategy, fromCache).types();
+ }
+
+ DeviceVector getDevicesForStrategy(routing_strategy strategy, bool fromCache);
bool isStrategyActive(const sp<AudioOutputDescriptor>& outputDesc, routing_strategy strategy,
uint32_t inPastMs = 0, nsecs_t sysTime = 0) const;
- bool isStrategyActiveOnSameModule(const sp<AudioOutputDescriptor>& outputDesc,
- routing_strategy strategy, uint32_t inPastMs = 0,
- nsecs_t sysTime = 0) const;
+ bool isStrategyActiveOnSameModule(const sp<SwAudioOutputDescriptor>& outputDesc,
+ routing_strategy strategy, uint32_t inPastMs = 0,
+ nsecs_t sysTime = 0) const;
// change the route of the specified output. Returns the number of ms we have slept to
// allow new routing to take effect in certain cases.
- virtual uint32_t setOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t device,
- bool force = false,
- int delayMs = 0,
- audio_patch_handle_t *patchHandle = NULL,
- const char *address = nullptr,
- bool requiresMuteCheck = true);
+ uint32_t setOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
+ const DeviceVector &device,
+ bool force = false,
+ int delayMs = 0,
+ audio_patch_handle_t *patchHandle = NULL,
+ bool requiresMuteCheck = true);
status_t resetOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
int delayMs = 0,
audio_patch_handle_t *patchHandle = NULL);
status_t setInputDevice(audio_io_handle_t input,
- audio_devices_t device,
+ const sp<DeviceDescriptor> &device,
bool force = false,
audio_patch_handle_t *patchHandle = NULL);
status_t resetInputDevice(audio_io_handle_t input,
audio_patch_handle_t *patchHandle = NULL);
// select input device corresponding to requested audio source
- virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
+ sp<DeviceDescriptor> getDeviceForAttributes(const audio_attributes_t &attributes);
// compute the actual volume for a given stream according to the requested index and a particular
// device
@@ -388,15 +395,13 @@
// when a device is disconnected, checks if an output is not used any more and
// returns its handle if any.
// transfers the audio tracks and effects from one output thread to another accordingly.
- status_t checkOutputsForDevice(const sp<DeviceDescriptor>& devDesc,
+ status_t checkOutputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& outputs,
- const String8& address);
+ SortedVector<audio_io_handle_t>& outputs);
- status_t checkInputsForDevice(const sp<DeviceDescriptor>& devDesc,
+ status_t checkInputsForDevice(const sp<DeviceDescriptor>& device,
audio_policy_dev_state_t state,
- SortedVector<audio_io_handle_t>& inputs,
- const String8& address);
+ SortedVector<audio_io_handle_t>& inputs);
// close an output and its companion duplicating output.
void closeOutput(audio_io_handle_t output);
@@ -434,8 +439,8 @@
// must be called every time a condition that affects the device choice for a given output is
// changed: connected device, phone state, force use, output start, output stop..
// see getDeviceForStrategy() for the use of fromCache parameter
- audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
- bool fromCache);
+ DeviceVector getNewOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
+ bool fromCache);
// updates cache of device used by all strategies (mDeviceForStrategy[])
// must be called every time a condition that affects the device choice for a given strategy is
@@ -445,7 +450,7 @@
void updateDevicesAndOutputs();
// selects the most appropriate device on input for current state
- audio_devices_t getNewInputDevice(const sp<AudioInputDescriptor>& inputDesc);
+ sp<DeviceDescriptor> getNewInputDevice(const sp<AudioInputDescriptor>& inputDesc);
virtual uint32_t getMaxEffectsCpuLoad()
{
@@ -457,16 +462,16 @@
return mEffects.getMaxEffectsMemory();
}
- SortedVector<audio_io_handle_t> getOutputsForDevice(audio_devices_t device,
- const SwAudioOutputCollection& openOutputs);
+ SortedVector<audio_io_handle_t> getOutputsForDevices(
+ const DeviceVector &devices, const SwAudioOutputCollection& openOutputs);
// mute/unmute strategies using an incompatible device combination
// if muting, wait for the audio in pcm buffer to be drained before proceeding
// if unmuting, unmute only after the specified delay
// Returns the number of ms waited
virtual uint32_t checkDeviceMuteStrategies(const sp<AudioOutputDescriptor>& outputDesc,
- audio_devices_t prevDevice,
- uint32_t delayMs);
+ audio_devices_t prevDeviceType,
+ uint32_t delayMs);
audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
@@ -474,13 +479,22 @@
audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE,
uint32_t samplingRate = 0);
// samplingRate, format, channelMask are in/out and so may be modified
- sp<IOProfile> getInputProfile(audio_devices_t device,
- const String8& address,
+ sp<IOProfile> getInputProfile(const sp<DeviceDescriptor> & device,
uint32_t& samplingRate,
audio_format_t& format,
audio_channel_mask_t& channelMask,
audio_input_flags_t flags);
- sp<IOProfile> getProfileForOutput(audio_devices_t device,
+ /**
+ * @brief getProfileForOutput
+ * @param devices vector of descriptors, may be empty if ignoring the device is required
+ * @param samplingRate
+ * @param format
+ * @param channelMask
+ * @param flags
+ * @param directOnly
+ * @return IOProfile to be used if found, nullptr otherwise
+ */
+ sp<IOProfile> getProfileForOutput(const DeviceVector &devices,
uint32_t samplingRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@@ -498,19 +512,19 @@
return mAudioPatches.removeAudioPatch(handle);
}
- audio_devices_t availablePrimaryOutputDevices() const
+ DeviceVector availablePrimaryOutputDevices() const
{
if (!hasPrimaryOutput()) {
- return AUDIO_DEVICE_NONE;
+ return DeviceVector();
}
- return mPrimaryOutput->supportedDevices() & mAvailableOutputDevices.types();
+ return mAvailableOutputDevices.filter(mPrimaryOutput->supportedDevices());
}
- audio_devices_t availablePrimaryInputDevices() const
+ DeviceVector availablePrimaryModuleInputDevices() const
{
if (!hasPrimaryOutput()) {
- return AUDIO_DEVICE_NONE;
+ return DeviceVector();
}
- return mAvailableInputDevices.getDeviceTypesFromHwModule(
+ return mAvailableInputDevices.getDevicesFromHwModule(
mPrimaryOutput->getModuleHandle());
}
/**
@@ -527,8 +541,9 @@
return (devices.size() > 0) ? devices.itemAt(0)->address() : String8("");
}
- uint32_t updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs = 0);
- sp<AudioPatch> createTelephonyPatch(bool isRx, audio_devices_t device, uint32_t delayMs);
+ uint32_t updateCallRouting(const DeviceVector &rxDevices, uint32_t delayMs = 0);
+ sp<AudioPatch> createTelephonyPatch(bool isRx, const sp<DeviceDescriptor> &device,
+ uint32_t delayMs);
sp<DeviceDescriptor> findDevice(
const DeviceVector& devices, audio_devices_t device) const;
audio_devices_t getModuleDeviceTypes(
@@ -578,7 +593,16 @@
DeviceVector mAvailableInputDevices; // all available input devices
bool mLimitRingtoneVolume; // limit ringtone volume to music volume if headset connected
- audio_devices_t mDeviceForStrategy[NUM_STRATEGIES];
+
+ /**
+ * @brief mDevicesForStrategy vector of devices that are assigned for a given strategy.
+ * Note: in case of removal of device (@see setDeviceConnectionState), the device descriptor
+ * will be removed from the @see mAvailableOutputDevices or @see mAvailableInputDevices
+ * but the devices for strategies will be reevaluated within the
+ * @see setDeviceConnectionState function.
+ */
+ DeviceVector mDevicesForStrategy[NUM_STRATEGIES];
+
float mLastVoiceVolume; // last voice volume value sent to audio HAL
bool mA2dpSuspended; // true if A2DP output is suspended
@@ -634,13 +658,14 @@
// Support for Multi-Stream Decoder (MSD) module
sp<DeviceDescriptor> getMsdAudioInDevice() const;
+ DeviceVector getMsdAudioOutDevices() const;
const AudioPatchCollection getMsdPatches() const;
- status_t getBestMsdAudioProfileFor(audio_devices_t outputDevice,
+ status_t getBestMsdAudioProfileFor(const sp<DeviceDescriptor> &outputDevice,
bool hwAvSync,
audio_port_config *sourceConfig,
audio_port_config *sinkConfig) const;
- PatchBuilder buildMsdPatch(audio_devices_t outputDevice) const;
- status_t setMsdPatch(audio_devices_t outputDevice = AUDIO_DEVICE_NONE);
+ PatchBuilder buildMsdPatch(const sp<DeviceDescriptor> &outputDevice) const;
+ status_t setMsdPatch(const sp<DeviceDescriptor> &outputDevice = nullptr);
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
@@ -651,22 +676,12 @@
// It can give a chance to HAL implementer to retrieve dynamic capabilities associated
// to this device for example.
// TODO avoid opening stream to retrieve capabilities of a profile.
- void broadcastDeviceConnectionState(audio_devices_t device,
- audio_policy_dev_state_t state,
- const String8 &device_address);
+ void broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
+ audio_policy_dev_state_t state);
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
- // find the outputs on a given output descriptor that have the given address.
- // to be called on an AudioOutputDescriptor whose supported devices (as defined
- // in mProfile->mSupportedDevices) matches the device whose address is to be matched.
- // see deviceDistinguishesOnAddress(audio_devices_t) for whether the device type is one
- // where addresses are used to distinguish between one connected device and another.
- void findIoHandlesByAddress(const sp<SwAudioOutputDescriptor>& desc /*in*/,
- const audio_devices_t device /*in*/,
- const String8& address /*in*/,
- SortedVector<audio_io_handle_t>& outputs /*out*/);
uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
// internal method, get audio_attributes_t from either a source audio_attributes_t
// or audio_stream_type_t, respectively.
@@ -684,15 +699,14 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId);
// internal method to return the output handle for the given device and format
- audio_io_handle_t getOutputForDevice(
- audio_devices_t device,
+ audio_io_handle_t getOutputForDevices(
+ const DeviceVector &devices,
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
audio_output_flags_t *flags);
// internal method to return the input handle for the given device and format
- audio_io_handle_t getInputForDevice(audio_devices_t device,
- String8 address,
+ audio_io_handle_t getInputForDevice(const sp<DeviceDescriptor> &device,
audio_session_t session,
audio_source_t inputSource,
const audio_config_base_t *config,
@@ -710,14 +724,14 @@
// select input device corresponding to requested audio source and return associated policy
// mix if any. Calls getDeviceForInputSource().
- audio_devices_t getDeviceAndMixForInputSource(audio_source_t inputSource,
- AudioMix **policyMix = NULL);
+ sp<DeviceDescriptor> getDeviceAndMixForAttributes(const audio_attributes_t &attributes,
+ AudioMix **policyMix = NULL);
// Called by setDeviceConnectionState().
- status_t setDeviceConnectionStateInt(audio_devices_t device,
- audio_policy_dev_state_t state,
- const char *device_address,
- const char *device_name);
+ status_t setDeviceConnectionStateInt(audio_devices_t deviceType,
+ audio_policy_dev_state_t state,
+ const char *device_address,
+ const char *device_name);
void updateMono(audio_io_handle_t output) {
AudioParameter param;
param.addInt(String8(AudioParameter::keyMonoOutput), (int)mMasterMono);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 29b0561..919a90d 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -330,11 +330,12 @@
return BAD_VALUE;
}
- // HOTWORD and FM_TUNER are two special case sources > MAX.
+ // HOTWORD, FM_TUNER and ECHO_REFERENCE are special case sources > MAX.
if (source < AUDIO_SOURCE_DEFAULT ||
(source > AUDIO_SOURCE_MAX &&
source != AUDIO_SOURCE_HOTWORD &&
- source != AUDIO_SOURCE_FM_TUNER)) {
+ source != AUDIO_SOURCE_FM_TUNER &&
+ source != AUDIO_SOURCE_ECHO_REFERENCE)) {
ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
return BAD_VALUE;
}
@@ -534,7 +535,8 @@
CAMCORDER_SRC_TAG,
VOICE_REC_SRC_TAG,
VOICE_COMM_SRC_TAG,
- UNPROCESSED_SRC_TAG
+ UNPROCESSED_SRC_TAG,
+ VOICE_PERFORMANCE_SRC_TAG
};
// returns the audio_source_t enum corresponding to the input source name or
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 439764b..2c904d9 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -336,8 +336,11 @@
}
// already checked by client, but double-check in case the client wrapper is bypassed
- if (attr->source < AUDIO_SOURCE_DEFAULT && attr->source >= AUDIO_SOURCE_CNT &&
- attr->source != AUDIO_SOURCE_HOTWORD && attr->source != AUDIO_SOURCE_FM_TUNER) {
+ if ((attr->source < AUDIO_SOURCE_DEFAULT)
+ || (attr->source >= AUDIO_SOURCE_CNT
+ && attr->source != AUDIO_SOURCE_HOTWORD
+ && attr->source != AUDIO_SOURCE_FM_TUNER
+ && attr->source != AUDIO_SOURCE_ECHO_REFERENCE)) {
return BAD_VALUE;
}
@@ -367,7 +370,8 @@
if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
- attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+ attr->source == AUDIO_SOURCE_VOICE_CALL ||
+ attr->source == AUDIO_SOURCE_ECHO_REFERENCE) &&
!captureAudioOutputAllowed(pid, uid)) {
return PERMISSION_DENIED;
}
@@ -1037,6 +1041,31 @@
}
}
+status_t AudioPolicyService::setUidDeviceAffinities(uid_t uid,
+ const Vector<AudioDeviceTypeAddr>& devices) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->setUidDeviceAffinities(uid, devices);
+}
+
+status_t AudioPolicyService::removeUidDeviceAffinities(uid_t uid) {
+ Mutex::Autolock _l(mLock);
+ if(!modifyAudioRoutingAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ AutoCallerClear acc;
+ return mAudioPolicyManager->removeUidDeviceAffinities(uid);
+}
+
status_t AudioPolicyService::startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId)
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c44d816..959e757 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -199,6 +199,10 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
+
+ virtual status_t removeUidDeviceAffinities(uid_t uid);
+
virtual status_t startAudioSource(const struct audio_port_config *source,
const audio_attributes_t *attributes,
audio_port_handle_t *portId);
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 56af152..24326bb 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -112,10 +112,34 @@
std::set<audio_patch_handle_t> mActivePatches;
};
+class PatchCountCheck {
+ public:
+ explicit PatchCountCheck(AudioPolicyManagerTestClient *client)
+ : mClient{client},
+ mInitialCount{mClient->getActivePatchesCount()} {}
+ void assertDelta(int delta) const {
+ ASSERT_EQ(mInitialCount + delta, mClient->getActivePatchesCount()); }
+ void assertNoChange() const { assertDelta(0); }
+ private:
+ const AudioPolicyManagerTestClient *mClient;
+ const size_t mInitialCount;
+};
+
class AudioPolicyManagerTest : public testing::Test {
protected:
- virtual void SetUp();
- virtual void TearDown();
+ void SetUp() override;
+ void TearDown() override;
+ virtual void SetUpConfig(AudioPolicyConfig *config) { (void)config; }
+
+ void dumpToLog();
+ void getOutputForAttr(
+ audio_port_handle_t *selectedDeviceId,
+ audio_format_t format,
+ int channelMask,
+ int sampleRate,
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+ audio_port_handle_t *portId = nullptr);
+ PatchCountCheck snapPatchCount() { return PatchCountCheck(mClient.get()); }
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
@@ -125,6 +149,7 @@
mClient.reset(new AudioPolicyManagerTestClient);
mManager.reset(new AudioPolicyTestManager(mClient.get()));
mManager->getConfig().setDefault();
+ SetUpConfig(&mManager->getConfig()); // Subclasses may want to customize the config.
ASSERT_EQ(NO_ERROR, mManager->initialize());
ASSERT_EQ(NO_ERROR, mManager->initCheck());
}
@@ -134,11 +159,7 @@
mClient.reset();
}
-TEST_F(AudioPolicyManagerTest, InitSuccess) {
- // SetUp must finish with no assertions.
-}
-
-TEST_F(AudioPolicyManagerTest, Dump) {
+void AudioPolicyManagerTest::dumpToLog() {
int pipefd[2];
ASSERT_NE(-1, pipe(pipefd));
pid_t cpid = fork();
@@ -168,10 +189,43 @@
}
}
+void AudioPolicyManagerTest::getOutputForAttr(
+ audio_port_handle_t *selectedDeviceId,
+ audio_format_t format,
+ int channelMask,
+ int sampleRate,
+ audio_output_flags_t flags,
+ audio_port_handle_t *portId) {
+ audio_attributes_t attr = {};
+ audio_io_handle_t output = AUDIO_PORT_HANDLE_NONE;
+ audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.sample_rate = sampleRate;
+ config.channel_mask = channelMask;
+ config.format = format;
+ *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t localPortId;
+ if (!portId) portId = &localPortId;
+ *portId = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_EQ(OK, mManager->getOutputForAttr(
+ &attr, &output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
+ selectedDeviceId, portId));
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+}
+
+
+TEST_F(AudioPolicyManagerTest, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTest, Dump) {
+ dumpToLog();
+}
+
TEST_F(AudioPolicyManagerTest, CreateAudioPatchFailure) {
audio_patch patch{};
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
- const size_t patchCountBefore = mClient->getActivePatchesCount();
+ const PatchCountCheck patchCount = snapPatchCount();
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
@@ -198,20 +252,182 @@
ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
// Verify that the handle is left unchanged.
ASSERT_EQ(AUDIO_PATCH_HANDLE_NONE, handle);
- ASSERT_EQ(patchCountBefore, mClient->getActivePatchesCount());
+ patchCount.assertNoChange();
}
TEST_F(AudioPolicyManagerTest, CreateAudioPatchFromMix) {
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
uid_t uid = 42;
- const size_t patchCountBefore = mClient->getActivePatchesCount();
+ const PatchCountCheck patchCount = snapPatchCount();
ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
PatchBuilder patchBuilder;
patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
addSink(mManager->getConfig().getDefaultOutputDevice());
ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
- ASSERT_EQ(patchCountBefore + 1, mClient->getActivePatchesCount());
+ patchCount.assertDelta(1);
}
// TODO: Add patch creation tests that involve already existing patch
+
+class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
+ protected:
+ void SetUpConfig(AudioPolicyConfig *config) override;
+ void TearDown() override;
+
+ sp<DeviceDescriptor> mMsdOutputDevice;
+ sp<DeviceDescriptor> mMsdInputDevice;
+};
+
+void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
+ // TODO: Consider using Serializer to load part of the config from a string.
+ mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
+ sp<AudioProfile> pcmOutputProfile = new AudioProfile(
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ sp<AudioProfile> ac3OutputProfile = new AudioProfile(
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+ mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
+ mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
+ mMsdInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUS);
+ // Match output profile from AudioPolicyConfig::setDefault.
+ sp<AudioProfile> pcmInputProfile = new AudioProfile(
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
+ mMsdInputDevice->addAudioProfile(pcmInputProfile);
+ config->addAvailableDevice(mMsdOutputDevice);
+ config->addAvailableDevice(mMsdInputDevice);
+
+ sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
+ HwModuleCollection modules = config->getHwModules();
+ modules.add(msdModule);
+ config->setHwModules(modules);
+ mMsdOutputDevice->attach(msdModule);
+ mMsdInputDevice->attach(msdModule);
+
+ sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input"));
+ msdOutputProfile->addAudioProfile(pcmOutputProfile);
+ msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
+ msdModule->addOutputProfile(msdOutputProfile);
+ sp<OutputProfile> msdCompressedOutputProfile =
+ new OutputProfile(String8("msd compressed input"));
+ msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
+ msdCompressedOutputProfile->setFlags(
+ AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+ AUDIO_OUTPUT_FLAG_NON_BLOCKING);
+ msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
+ msdModule->addOutputProfile(msdCompressedOutputProfile);
+
+ sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output"));
+ msdInputProfile->addAudioProfile(pcmInputProfile);
+ msdInputProfile->addSupportedDevice(mMsdInputDevice);
+ msdModule->addInputProfile(msdInputProfile);
+
+ // Add a profile with another encoding to the default device to test routing
+ // of streams that are not supported by MSD.
+ sp<AudioProfile> dtsOutputProfile = new AudioProfile(
+ AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000);
+ config->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+ sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile(String8("encoded"));
+ primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
+ primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
+ primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());
+ config->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ addOutputProfile(primaryEncodedOutputProfile);
+}
+
+void AudioPolicyManagerTestMsd::TearDown() {
+ mMsdOutputDevice.clear();
+ mMsdInputDevice.clear();
+ AudioPolicyManagerTest::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, InitSuccess) {
+ ASSERT_TRUE(mMsdOutputDevice);
+ ASSERT_TRUE(mMsdInputDevice);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, Dump) {
+ dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, PatchCreationOnSetForceUse) {
+ const PatchCountCheck patchCount = snapPatchCount();
+ mManager->setForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
+ AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS);
+ patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(1);
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(1);
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertNoChange();
+}
+
+TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrFormatSwitching) {
+ // Switch between formats that are supported and not supported by MSD.
+ {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId, portId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
+ &portId);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(1);
+ mManager->releaseOutput(portId);
+ patchCount.assertDelta(1); // compared to the state at the block entry
+ // TODO: make PatchCountCheck asserts more obvious. It's easy to
+ // miss the fact that it is immutable.
+ }
+ {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId, portId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
+ &portId);
+ ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertDelta(-1);
+ mManager->releaseOutput(portId);
+ patchCount.assertNoChange();
+ }
+ {
+ const PatchCountCheck patchCount = snapPatchCount();
+ audio_port_handle_t selectedDeviceId;
+ getOutputForAttr(&selectedDeviceId,
+ AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
+ ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
+ patchCount.assertNoChange();
+ }
+}
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 025f0b2..851dd69 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -83,6 +83,7 @@
"libhidltransport",
"libjpeg",
"libmemunreachable",
+ "libsensorprivacy",
"libstagefright_foundation",
"android.frameworks.cameraservice.common@2.0",
"android.frameworks.cameraservice.service@2.0",
@@ -100,6 +101,7 @@
"libbinder",
"libcamera_client",
"libfmq",
+ "libsensorprivacy",
],
include_dirs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6003607..c3113bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -54,6 +54,7 @@
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
#include <mediautils/BatteryNotifier.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -145,6 +146,8 @@
mUidPolicy = new UidPolicy(this);
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
+ mSensorPrivacyPolicy->registerSelf();
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -230,6 +233,7 @@
CameraService::~CameraService() {
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
mUidPolicy->unregisterSelf();
+ mSensorPrivacyPolicy->unregisterSelf();
}
void CameraService::onNewProviderRegistered() {
@@ -951,6 +955,14 @@
clientName8.string(), clientUid, clientPid, cameraId.string());
}
+ // If sensor privacy is enabled then prevent access to the camera
+ if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+ ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
+ return STATUS_ERROR_FMT(ERROR_DISABLED,
+ "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
+ "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string());
+ }
+
// Only use passed in clientPid to check permission. Use calling PID as the client PID that's
// connected to camera service directly.
originalClientPid = clientPid;
@@ -1603,9 +1615,10 @@
switch(eventId) {
case ICameraService::EVENT_USER_SWITCHED: {
- // Try to register for UID policy updates, in case we're recovering
+ // Try to register for UID and sensor privacy policy updates, in case we're recovering
// from a system server crash
mUidPolicy->registerSelf();
+ mSensorPrivacyPolicy->registerSelf();
doUserSwitch(/*newUserIds*/ args);
break;
}
@@ -2577,6 +2590,59 @@
}
// ----------------------------------------------------------------------------
+// SensorPrivacyPolicy
+// ----------------------------------------------------------------------------
+void CameraService::SensorPrivacyPolicy::registerSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ if (mRegistered) {
+ return;
+ }
+ SensorPrivacyManager spm;
+ spm.addSensorPrivacyListener(this);
+ mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
+ status_t res = spm.linkToDeath(this);
+ if (res == OK) {
+ mRegistered = true;
+ ALOGV("SensorPrivacyPolicy: Registered with SensorPrivacyManager");
+ }
+}
+
+void CameraService::SensorPrivacyPolicy::unregisterSelf() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ SensorPrivacyManager spm;
+ spm.removeSensorPrivacyListener(this);
+ spm.unlinkToDeath(this);
+ mRegistered = false;
+ ALOGV("SensorPrivacyPolicy: Unregistered with SensorPrivacyManager");
+}
+
+bool CameraService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ return mSensorPrivacyEnabled;
+}
+
+binder::Status CameraService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
+ {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ mSensorPrivacyEnabled = enabled;
+ }
+ // if sensor privacy is enabled then block all clients from accessing the camera
+ if (enabled) {
+ sp<CameraService> service = mService.promote();
+ if (service != nullptr) {
+ service->blockAllClients();
+ }
+ }
+ return binder::Status::ok();
+}
+
+void CameraService::SensorPrivacyPolicy::binderDied(const wp<IBinder>& /*who*/) {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+ ALOGV("SensorPrivacyPolicy: SensorPrivacyManager has died");
+ mRegistered = false;
+}
+
+// ----------------------------------------------------------------------------
// CameraState
// ----------------------------------------------------------------------------
@@ -3062,6 +3128,18 @@
}
}
+void CameraService::blockAllClients() {
+ const auto clients = mActiveClientManager.getAll();
+ for (auto& current : clients) {
+ if (current != nullptr) {
+ const auto basicClient = current->getValue();
+ if (basicClient.get() != nullptr) {
+ basicClient->block();
+ }
+ }
+ }
+}
+
// NOTE: This is a remote API - make sure all args are validated
status_t CameraService::shellCommand(int in, int out, int err, const Vector<String16>& args) {
if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d332f6e..a296198 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -18,6 +18,7 @@
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#include <android/hardware/BnCameraService.h>
+#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
#include <android/hardware/ICameraServiceProxy.h>
@@ -554,8 +555,35 @@
std::unordered_map<uid_t, bool> mOverrideUids;
}; // class UidPolicy
+ // If sensor privacy is enabled then all apps, including those that are active, should be
+ // prevented from accessing the camera.
+ class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener,
+ public virtual IBinder::DeathRecipient {
+ public:
+ explicit SensorPrivacyPolicy(wp<CameraService> service)
+ : mService(service), mSensorPrivacyEnabled(false), mRegistered(false) {}
+
+ void registerSelf();
+ void unregisterSelf();
+
+ bool isSensorPrivacyEnabled();
+
+ binder::Status onSensorPrivacyChanged(bool enabled);
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder> &who);
+
+ private:
+ wp<CameraService> mService;
+ Mutex mSensorPrivacyLock;
+ bool mSensorPrivacyEnabled;
+ bool mRegistered;
+ };
+
sp<UidPolicy> mUidPolicy;
+ sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
+
// Delay-load the Camera HAL module
virtual void onFirstRef();
@@ -825,6 +853,9 @@
// Blocks all clients from the UID
void blockClientsForUid(uid_t uid);
+ // Blocks all active clients.
+ void blockAllClients();
+
// Overrides the UID state as if it is idle
status_t handleSetUidState(const Vector<String16>& args, int err);
diff --git a/services/mediacodec/MediaCodecUpdateService.cpp b/services/mediacodec/MediaCodecUpdateService.cpp
index aee890d..0e6892d 100644
--- a/services/mediacodec/MediaCodecUpdateService.cpp
+++ b/services/mediacodec/MediaCodecUpdateService.cpp
@@ -18,14 +18,10 @@
//#define LOG_NDEBUG 0
#include <android/dlext.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <dirent.h>
#include <dlfcn.h>
#include <media/CodecServiceRegistrant.h>
#include <utils/Log.h>
-#include <ziparchive/zip_archive.h>
-#include <cutils/properties.h>
+#include <utils/String8.h>
#include "MediaCodecUpdateService.h"
@@ -47,90 +43,53 @@
}
namespace android {
-namespace media {
-binder::Status MediaCodecUpdateService::loadPlugins(const ::std::string& apkPath) {
- ALOGV("loadPlugins %s", apkPath.c_str());
+void loadFromApex(const char *libDirPath) {
+ ALOGV("loadFromApex: path=%s", libDirPath);
- ZipArchiveHandle zipHandle;
- void *registrantLib = NULL;
- int32_t ret = OpenArchive(apkPath.c_str(), &zipHandle);
+ String8 libPath = String8(libDirPath) + "/libmedia_codecserviceregistrant.so";
- if (ret == 0) {
- char abilist32[PROPERTY_VALUE_MAX];
- property_get("ro.product.cpu.abilist32", abilist32, "armeabi-v7a");
+ android_namespace_t *codecNs = android_create_namespace("codecs",
+ nullptr, // ld_library_path
+ libDirPath,
+ ANDROID_NAMESPACE_TYPE_ISOLATED,
+ nullptr, // permitted_when_isolated_path
+ nullptr); // parent
- auto abis = base::Split(abilist32, ",");
- if (abis.empty()) {
- ALOGW("abilist is empty, trying armeabi-v7a ...");
- abis.push_back("armeabi-v7a");
- }
-
- // TODO: Only try the first entry in abilist32 for now.
- // We probably should try the next if it fails.
- String8 libPathInApk = String8("lib/") + String8(abis[0].c_str());
- String8 defaultLibPath = String8(apkPath.c_str()) + "!/" + libPathInApk;
- String8 libPath = defaultLibPath + "/libmedia_codecserviceregistrant.so";
- String8 zipEntryPath = libPathInApk + "/libmedia_codecserviceregistrant.so";
-
- ZipEntry entry;
- ret = FindEntry(zipHandle, ZipString(zipEntryPath), &entry);
-
- if (ret == 0) {
- android_namespace_t *codecNs = android_create_namespace("codecs",
- nullptr, // ld_library_path
- defaultLibPath.c_str(),
- ANDROID_NAMESPACE_TYPE_ISOLATED,
- nullptr, // permitted_when_isolated_path
- nullptr); // parent
-
- if (codecNs != nullptr) {
- String8 linked_libraries(LINKED_LIBRARIES);
- if (android_link_namespaces(
- codecNs, nullptr, linked_libraries.c_str())) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = codecNs,
- };
-
- registrantLib = android_dlopen_ext(
- libPath.string(),
- RTLD_NOW | RTLD_LOCAL, &dlextinfo);
-
- if (registrantLib == NULL) {
- ALOGE("Failed to load lib from archive: %s", dlerror());
- }
- } else {
- ALOGE("Failed to link namespace");
- }
- } else {
- ALOGE("Failed to create codec namespace");
- }
- } else {
- ALOGE("Failed to find entry (ret=%d)", ret);
- }
-
- CloseArchive(zipHandle);
- } else {
- ALOGE("Failed to open archive (ret=%d)", ret);
+ if (codecNs == nullptr) {
+ ALOGE("Failed to create codec namespace");
+ return;
}
- if (registrantLib) {
- RegisterCodecServicesFunc registerCodecServices =
- reinterpret_cast<RegisterCodecServicesFunc>(
- dlsym(registrantLib, "RegisterCodecServices"));
- if (registerCodecServices) {
- registerCodecServices();
- } else {
- LOG(WARNING) << "Cannot register codec services "
- "-- corrupted library.";
- }
- } else {
- LOG(ERROR) << "Cannot find codec service registrant.";
+ String8 linked_libraries(LINKED_LIBRARIES);
+ if (!android_link_namespaces(codecNs, nullptr, linked_libraries.c_str())) {
+ ALOGE("Failed to link namespace");
+ return;
}
- return binder::Status::ok();
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = codecNs,
+ };
+
+ void *registrantLib = android_dlopen_ext(
+ libPath.string(),
+ RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+
+ if (registrantLib == nullptr) {
+ ALOGE("Failed to load lib from archive: %s", dlerror());
+ }
+
+ RegisterCodecServicesFunc registerCodecServices =
+ reinterpret_cast<RegisterCodecServicesFunc>(
+ dlsym(registrantLib, "RegisterCodecServices"));
+
+ if (registerCodecServices == nullptr) {
+ ALOGE("Cannot register codec services -- corrupted library.");
+ return;
+ }
+
+ registerCodecServices();
}
-} // namespace media
} // namespace android
diff --git a/services/mediacodec/MediaCodecUpdateService.h b/services/mediacodec/MediaCodecUpdateService.h
index 7b7cee9..09d6dbe 100644
--- a/services/mediacodec/MediaCodecUpdateService.h
+++ b/services/mediacodec/MediaCodecUpdateService.h
@@ -17,24 +17,10 @@
#ifndef ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
#define ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
-#include <binder/BinderService.h>
-#include <android/media/BnMediaUpdateService.h>
-
namespace android {
-namespace media {
-class MediaCodecUpdateService
- : public BinderService<MediaCodecUpdateService>, public BnMediaUpdateService
-{
- friend class BinderService<MediaCodecUpdateService>;
-public:
- MediaCodecUpdateService() : BnMediaUpdateService() { }
- virtual ~MediaCodecUpdateService() { }
- static const char* getServiceName() { return "media.codec.update"; }
- binder::Status loadPlugins(const ::std::string& apkPath);
-};
+void loadFromApex(const char *libDirPath);
-} // namespace media
} // namespace android
#endif // ANDROID_MEDIA_CODEC_UPDATE_SERVICE_H
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index 79fea25..1168825 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -20,11 +20,7 @@
// from LOCAL_C_INCLUDES
#include "minijail.h"
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <dlfcn.h>
#include <hidl/HidlTransportSupport.h>
-#include <media/CodecServiceRegistrant.h>
#include "MediaCodecUpdateService.h"
@@ -49,32 +45,10 @@
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
- std::string value = base::GetProperty("ro.build.type", "unknown");
- if (value == "userdebug" || value == "eng") {
- media::MediaCodecUpdateService::instantiate();
- }
-
- android::ProcessState::self()->startThreadPool();
-
::android::hardware::configureRpcThreadpool(64, false);
- // Registration of customized codec services
- void *registrantLib = dlopen(
- "libmedia_codecserviceregistrant.so",
- RTLD_NOW | RTLD_LOCAL);
- if (registrantLib) {
- RegisterCodecServicesFunc registerCodecServices =
- reinterpret_cast<RegisterCodecServicesFunc>(
- dlsym(registrantLib, "RegisterCodecServices"));
- if (registerCodecServices) {
- registerCodecServices();
- } else {
- LOG(WARNING) << "Cannot register codec services "
- "-- corrupted library.";
- }
- } else {
- LOG(ERROR) << "Cannot find codec service registrant.";
- }
+ // codec libs are currently 32-bit only
+ loadFromApex("/apex/com.android.media.swcodec/lib");
::android::hardware::joinRpcThreadpool();
}
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index 653317b..8c40ad1 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -1,5 +1,6 @@
cc_library_shared {
name: "libmedia_codecserviceregistrant",
+ vendor_available: true,
srcs: [
"CodecServiceRegistrant.cpp",
],
@@ -39,6 +40,7 @@
"libcodec2_soft_opusdec",
"libcodec2_soft_vp8dec",
"libcodec2_soft_vp9dec",
+ "libcodec2_soft_av1dec",
"libcodec2_soft_vp8enc",
"libcodec2_soft_vp9enc",
"libcodec2_soft_rawdec",
diff --git a/services/mediadrm/tests/Android.mk b/services/mediadrm/tests/Android.mk
deleted file mode 100644
index e2f7399..0000000
--- a/services/mediadrm/tests/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := DrmSessionManager_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- DrmSessionManager_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libmediaplayerservice \
- libutils \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/include \
- frameworks/av/media/libmediaplayerservice \
-
-LOCAL_CFLAGS += -Werror -Wall
-
-LOCAL_32_BIT_ONLY := true
-
-include $(BUILD_NATIVE_TEST)
-
diff --git a/services/mediadrm/tests/DrmSessionManager_test.cpp b/services/mediadrm/tests/DrmSessionManager_test.cpp
deleted file mode 100644
index de350a1..0000000
--- a/services/mediadrm/tests/DrmSessionManager_test.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2015 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 "DrmSessionManager_test"
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-#include "Drm.h"
-#include "DrmSessionClientInterface.h"
-#include "DrmSessionManager.h"
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/ProcessInfoInterface.h>
-
-namespace android {
-
-struct FakeProcessInfo : public ProcessInfoInterface {
- FakeProcessInfo() {}
- virtual ~FakeProcessInfo() {}
-
- virtual bool getPriority(int pid, int* priority) {
- // For testing, use pid as priority.
- // Lower the value higher the priority.
- *priority = pid;
- return true;
- }
-
-private:
- DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
-};
-
-struct FakeDrm : public DrmSessionClientInterface {
- FakeDrm() {}
- virtual ~FakeDrm() {}
-
- virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
- mReclaimedSessions.push_back(sessionId);
- return true;
- }
-
- const Vector<Vector<uint8_t> >& reclaimedSessions() const {
- return mReclaimedSessions;
- }
-
-private:
- Vector<Vector<uint8_t> > mReclaimedSessions;
-
- DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
-};
-
-static const int kTestPid1 = 30;
-static const int kTestPid2 = 20;
-static const uint8_t kTestSessionId1[] = {1, 2, 3};
-static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8};
-static const uint8_t kTestSessionId3[] = {9, 0};
-
-class DrmSessionManagerTest : public ::testing::Test {
-public:
- DrmSessionManagerTest()
- : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())),
- mTestDrm1(new FakeDrm()),
- mTestDrm2(new FakeDrm()) {
- GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1);
- GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2);
- GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3);
- }
-
-protected:
- static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) {
- for (size_t i = 0; i < num; ++i) {
- sessionId->push_back(ids[i]);
- }
- }
-
- static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm,
- const Vector<uint8_t>& sessionId, int64_t timeStamp) {
- EXPECT_EQ(drm, info.drm);
- EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId));
- EXPECT_EQ(timeStamp, info.timeStamp);
- }
-
- void addSession() {
- mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3);
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- ssize_t index1 = map.indexOfKey(kTestPid1);
- ASSERT_GE(index1, 0);
- const SessionInfos& infos1 = map[index1];
- EXPECT_EQ(1u, infos1.size());
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0);
-
- ssize_t index2 = map.indexOfKey(kTestPid2);
- ASSERT_GE(index2, 0);
- const SessionInfos& infos2 = map[index2];
- EXPECT_EQ(2u, infos2.size());
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2);
- }
-
- const PidSessionInfosMap& sessionMap() {
- return mDrmSessionManager->mSessionMap;
- }
-
- void testGetLowestPriority() {
- int pid;
- int priority;
- EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- addSession();
- EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority));
-
- EXPECT_EQ(kTestPid1, pid);
- FakeProcessInfo processInfo;
- int priority1;
- processInfo.getPriority(kTestPid1, &priority1);
- EXPECT_EQ(priority1, priority);
- }
-
- void testGetLeastUsedSession() {
- sp<DrmSessionClientInterface> drm;
- Vector<uint8_t> sessionId;
- EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
-
- addSession();
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId));
- EXPECT_EQ(mTestDrm1, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId));
-
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId));
-
- // mSessionId2 is no longer the least used session.
- mDrmSessionManager->useSession(mSessionId2);
- EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId));
- EXPECT_EQ(mTestDrm2, drm);
- EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId));
- }
-
- sp<DrmSessionManager> mDrmSessionManager;
- sp<FakeDrm> mTestDrm1;
- sp<FakeDrm> mTestDrm2;
- Vector<uint8_t> mSessionId1;
- Vector<uint8_t> mSessionId2;
- Vector<uint8_t> mSessionId3;
-};
-
-TEST_F(DrmSessionManagerTest, addSession) {
- addSession();
-}
-
-TEST_F(DrmSessionManagerTest, useSession) {
- addSession();
-
- mDrmSessionManager->useSession(mSessionId1);
- mDrmSessionManager->useSession(mSessionId3);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3);
- ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4);
-}
-
-TEST_F(DrmSessionManagerTest, removeSession) {
- addSession();
-
- mDrmSessionManager->removeSession(mSessionId2);
-
- const PidSessionInfosMap& map = sessionMap();
- EXPECT_EQ(2u, map.size());
- const SessionInfos& infos1 = map.valueFor(kTestPid1);
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos1.size());
- EXPECT_EQ(1u, infos2.size());
- // mSessionId2 has been removed.
- ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2);
-}
-
-TEST_F(DrmSessionManagerTest, removeDrm) {
- addSession();
-
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {123};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(kTestPid2, drm, sessionId);
-
- mDrmSessionManager->removeDrm(mTestDrm2);
-
- const PidSessionInfosMap& map = sessionMap();
- const SessionInfos& infos2 = map.valueFor(kTestPid2);
- EXPECT_EQ(1u, infos2.size());
- // mTestDrm2 has been removed.
- ExpectEqSessionInfo(infos2[0], drm, sessionId, 3);
-}
-
-TEST_F(DrmSessionManagerTest, reclaimSession) {
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
- addSession();
-
- // calling pid priority is too low
- EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
- EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size());
- EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0]));
-
- mDrmSessionManager->removeSession(mSessionId1);
-
- // add a session from a higher priority process.
- sp<FakeDrm> drm = new FakeDrm;
- const uint8_t ids[] = {1, 3, 5};
- Vector<uint8_t> sessionId;
- GetSessionId(ids, ARRAY_SIZE(ids), &sessionId);
- mDrmSessionManager->addSession(15, drm, sessionId);
-
- EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
- EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size());
- // mSessionId2 is reclaimed.
- EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0]));
-}
-
-TEST_F(DrmSessionManagerTest, getLowestPriority) {
- testGetLowestPriority();
-}
-
-TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) {
- testGetLeastUsedSession();
-}
-
-} // namespace android
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index e31eadc..dd64881 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -40,12 +40,13 @@
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
- liblog libbase libicuuc libavservices_minijail
+ liblog libbase libandroidicu libavservices_minijail
LOCAL_STATIC_LIBRARIES := libicuandroid_utils
LOCAL_MODULE:= mediaextractor
LOCAL_INIT_RC := mediaextractor.rc
LOCAL_C_INCLUDES := frameworks/av/media/libmedia
LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SANITIZE := scudo
include $(BUILD_EXECUTABLE)
# service seccomp filter
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 8b26178..0665930 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -59,6 +59,10 @@
return CreateIDataSourceFromDataSource(source);
}
+std::unordered_set<std::string> MediaExtractorService::getSupportedTypes() {
+ return MediaExtractorFactory::getSupportedTypes();
+}
+
status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
}
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 6007004..c9cebcf 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -37,6 +37,8 @@
virtual sp<IDataSource> makeIDataSource(int fd, int64_t offset, int64_t length);
+ virtual std::unordered_set<std::string> getSupportedTypes();
+
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
diff --git a/services/mediaextractor/main_extractorservice.cpp b/services/mediaextractor/main_extractorservice.cpp
index 8d3359a..5f42711 100644
--- a/services/mediaextractor/main_extractorservice.cpp
+++ b/services/mediaextractor/main_extractorservice.cpp
@@ -42,6 +42,12 @@
static const char kVendorSeccompPolicyPath[] =
"/vendor/etc/seccomp_policy/mediaextractor.policy";
+// Disable Scudo's mismatch allocation check, as it is being triggered
+// by some third party code.
+extern "C" const char *__scudo_default_options() {
+ return "DeallocationTypeMismatch=false";
+}
+
int main(int argc __unused, char** argv)
{
limitProcessMemory(
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 6d9ed6f..607a03e 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -11,6 +11,7 @@
mmap: 1
madvise: 1
openat: 1
+open: 1
clock_gettime: 1
writev: 1
brk: 1
@@ -21,6 +22,7 @@
getuid: 1
setpriority: 1
sigaltstack: 1
+fstat: 1
fstatfs: 1
newfstatat: 1
restart_syscall: 1
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
index 1d37a8e..68d54c7 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ b/services/soundtrigger/SoundTriggerHalHidl.cpp
@@ -168,18 +168,23 @@
int ret;
SoundModelHandle halHandle;
sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
+ sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
- if (!soundtrigger_2_1) {
- ISoundTriggerHw::PhraseSoundModel halSoundModel;
- convertPhraseSoundModelToHal(&halSoundModel, sound_model);
- AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->loadPhraseSoundModel(
- halSoundModel,
- this, modelId, [&](int32_t retval, auto res) {
- ret = retval;
- halHandle = res;
- });
- } else {
+ if (soundtrigger_2_2) {
+ V2_2_ISoundTriggerHw::PhraseSoundModel halSoundModel;
+ auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
+ if (result.first) {
+ AutoMutex lock(mHalLock);
+ hidlReturn = soundtrigger_2_2->loadPhraseSoundModel_2_1(
+ halSoundModel,
+ this, modelId, [&](int32_t retval, auto res) {
+ ret = retval;
+ halHandle = res;
+ });
+ } else {
+ return NO_MEMORY;
+ }
+ } else if (soundtrigger_2_1) {
V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel;
auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
if (result.first) {
@@ -193,18 +198,32 @@
} else {
return NO_MEMORY;
}
- }
- } else {
- if (!soundtrigger_2_1) {
- ISoundTriggerHw::SoundModel halSoundModel;
- convertSoundModelToHal(&halSoundModel, sound_model);
+ } else {
+ ISoundTriggerHw::PhraseSoundModel halSoundModel;
+ convertPhraseSoundModelToHal(&halSoundModel, sound_model);
AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
+ hidlReturn = soundtrigger->loadPhraseSoundModel(
+ halSoundModel,
this, modelId, [&](int32_t retval, auto res) {
ret = retval;
halHandle = res;
});
- } else {
+ }
+ } else {
+ if (soundtrigger_2_2) {
+ V2_2_ISoundTriggerHw::SoundModel halSoundModel;
+ auto result = convertSoundModelToHal(&halSoundModel, sound_model);
+ if (result.first) {
+ AutoMutex lock(mHalLock);
+ hidlReturn = soundtrigger_2_2->loadSoundModel_2_1(halSoundModel,
+ this, modelId, [&](int32_t retval, auto res) {
+ ret = retval;
+ halHandle = res;
+ });
+ } else {
+ return NO_MEMORY;
+ }
+ } else if (soundtrigger_2_1) {
V2_1_ISoundTriggerHw::SoundModel halSoundModel;
auto result = convertSoundModelToHal(&halSoundModel, sound_model);
if (result.first) {
@@ -217,6 +236,15 @@
} else {
return NO_MEMORY;
}
+ } else {
+ ISoundTriggerHw::SoundModel halSoundModel;
+ convertSoundModelToHal(&halSoundModel, sound_model);
+ AutoMutex lock(mHalLock);
+ hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
+ this, modelId, [&](int32_t retval, auto res) {
+ ret = retval;
+ halHandle = res;
+ });
}
}
@@ -282,16 +310,20 @@
model->mRecognitionCookie = cookie;
sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
+ sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
Return<int32_t> hidlReturn(0);
- if (!soundtrigger_2_1) {
- ISoundTriggerHw::RecognitionConfig halConfig;
- convertRecognitionConfigToHal(&halConfig, config);
- {
+ if (soundtrigger_2_2) {
+ V2_2_ISoundTriggerHw::RecognitionConfig halConfig;
+ auto result = convertRecognitionConfigToHal(&halConfig, config);
+ if (result.first) {
AutoMutex lock(mHalLock);
- hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
+ hidlReturn = soundtrigger_2_2->startRecognition_2_1(
+ model->mHalHandle, halConfig, this, handle);
+ } else {
+ return NO_MEMORY;
}
- } else {
+ } else if (soundtrigger_2_1) {
V2_1_ISoundTriggerHw::RecognitionConfig halConfig;
auto result = convertRecognitionConfigToHal(&halConfig, config);
if (result.first) {
@@ -301,6 +333,13 @@
} else {
return NO_MEMORY;
}
+ } else {
+ ISoundTriggerHw::RecognitionConfig halConfig;
+ convertRecognitionConfigToHal(&halConfig, config);
+ {
+ AutoMutex lock(mHalLock);
+ hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
+ }
}
if (!hidlReturn.isOk()) {
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 944abcc..fe2ccf2 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -765,10 +765,7 @@
}
recognitionEvent->capture_session = model->mCaptureSession;
- // Don't reset the model state if this recognition event is a get-state response
- if (recognitionEvent->status != RECOGNITION_STATUS_GET_STATE_RESPONSE) {
- model->mState = Model::STATE_IDLE;
- }
+ model->mState = Model::STATE_IDLE;
clients.add(model->mModuleClient);
}
} break;