Merge "Camera2: Heic: Reduce FRAME_RATE in case no grid is used"
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index c6c35ef..84d1d93 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -347,6 +347,20 @@
return c->setPreviewCallbackTarget(callbackProducer);
}
+status_t Camera::setAudioRestriction(int32_t mode)
+{
+ sp <::android::hardware::ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->setAudioRestriction(mode);
+}
+
+int32_t Camera::getGlobalAudioRestriction()
+{
+ sp <::android::hardware::ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->getGlobalAudioRestriction();
+}
+
// callback from camera service
void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
{
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index f0945c7..b83edf7 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -56,6 +56,8 @@
SET_VIDEO_BUFFER_TARGET,
RELEASE_RECORDING_FRAME_HANDLE,
RELEASE_RECORDING_FRAME_HANDLE_BATCH,
+ SET_AUDIO_RESTRICTION,
+ GET_GLOBAL_AUDIO_RESTRICTION,
};
class BpCamera: public BpInterface<ICamera>
@@ -191,6 +193,21 @@
}
}
+ status_t setAudioRestriction(int32_t mode) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(mode);
+ remote()->transact(SET_AUDIO_RESTRICTION, data, &reply);
+ return reply.readInt32();
+ }
+
+ int32_t getGlobalAudioRestriction() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(GET_GLOBAL_AUDIO_RESTRICTION, data, &reply);
+ return reply.readInt32();
+ }
+
status_t setVideoBufferMode(int32_t videoBufferMode)
{
ALOGV("setVideoBufferMode: %d", videoBufferMode);
@@ -494,6 +511,17 @@
reply->writeInt32(setVideoTarget(st));
return NO_ERROR;
} break;
+ case SET_AUDIO_RESTRICTION: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ int32_t mode = data.readInt32();
+ reply->writeInt32(setAudioRestriction(mode));
+ return NO_ERROR;
+ } break;
+ case GET_GLOBAL_AUDIO_RESTRICTION: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(getGlobalAudioRestriction());
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 49dfde8..93549e0 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -155,4 +155,26 @@
void updateOutputConfiguration(int streamId, in OutputConfiguration outputConfiguration);
void finalizeOutputConfigurations(int streamId, in OutputConfiguration outputConfiguration);
+
+
+ // Keep in sync with public API in
+ // frameworks/base/core/java/android/hardware/camera2/CameraDevice.java
+ const int AUDIO_RESTRICTION_NONE = 0;
+ const int AUDIO_RESTRICTION_VIBRATION = 1;
+ const int AUDIO_RESTRICTION_VIBRATION_SOUND = 3;
+
+ /**
+ * Set audio restriction mode for this camera device.
+ *
+ * @param mode the audio restriction mode ID as above
+ *
+ */
+ void setCameraAudioRestriction(int mode);
+
+ /**
+ * Get global audio restriction mode for all camera clients.
+ *
+ * @return the currently applied system-wide audio restriction mode
+ */
+ int getGlobalAudioRestriction();
}
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index ecaba3a..334f879 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -25,7 +25,6 @@
"libgui",
"libbinder",
"libhidlbase",
- "libhidltransport",
"android.hardware.camera.common@1.0",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 430aa1c..2cdb617 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -167,6 +167,9 @@
sp<ICameraRecordingProxy> getRecordingProxy();
+ status_t setAudioRestriction(int32_t mode);
+ int32_t getGlobalAudioRestriction();
+
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
diff --git a/camera/include/camera/android/hardware/ICamera.h b/camera/include/camera/android/hardware/ICamera.h
index 80823d6..ec19e5d 100644
--- a/camera/include/camera/android/hardware/ICamera.h
+++ b/camera/include/camera/android/hardware/ICamera.h
@@ -140,6 +140,12 @@
// Set the video buffer producer for camera to use in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
virtual status_t setVideoTarget(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
+
+ // Set the audio restriction mode
+ virtual status_t setAudioRestriction(int32_t mode) = 0;
+
+ // Get the global audio restriction mode
+ virtual int32_t getGlobalAudioRestriction() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index a2ee65d..d8220eb 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -107,7 +107,6 @@
],
shared_libs: [
- "libhwbinder",
"libfmq",
"libhidlbase",
"libhardware",
@@ -143,7 +142,6 @@
vendor: true,
srcs: ["ndk_vendor/tests/AImageReaderVendorTest.cpp"],
shared_libs: [
- "libhwbinder",
"libcamera2ndk_vendor",
"libcamera_metadata",
"libmediandk",
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 488641d..68fe045 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3543,11 +3543,19 @@
* output capture result.</p>
* <p>This control is only effective if ACAMERA_CONTROL_AE_MODE or ACAMERA_CONTROL_MODE is set to
* OFF; otherwise the auto-exposure algorithm will override this value.</p>
+ * <p>Note that for devices supporting postRawSensitivityBoost, the total sensitivity applied
+ * to the final processed image is the combination of ACAMERA_SENSOR_SENSITIVITY and
+ * ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST. In case the application uses the sensor
+ * sensitivity from last capture result of an auto request for a manual request, in order
+ * to achieve the same brightness in the output image, the application should also
+ * set postRawSensitivityBoost.</p>
*
* @see ACAMERA_CONTROL_AE_MODE
* @see ACAMERA_CONTROL_MODE
+ * @see ACAMERA_CONTROL_POST_RAW_SENSITIVITY_BOOST
* @see ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE
* @see ACAMERA_SENSOR_MAX_ANALOG_SENSITIVITY
+ * @see ACAMERA_SENSOR_SENSITIVITY
*/
ACAMERA_SENSOR_SENSITIVITY = // int32
ACAMERA_SENSOR_START + 2,
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index c25a0a1..fd71837 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -25,6 +25,7 @@
shared_libs: [
"libmedia",
+ "libmediametrics",
"libutils",
"liblog",
"libbinder",
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index afbcb39..66610b3 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -19,7 +19,10 @@
#include "utils/Log.h"
#include <utils/String8.h>
+
+#include <binder/IPCThreadState.h>
#include <drm/DrmInfo.h>
+
#include <drm/DrmInfoEvent.h>
#include <drm/DrmRights.h>
#include <drm/DrmConstraints.h>
@@ -28,6 +31,7 @@
#include <drm/DrmInfoRequest.h>
#include <drm/DrmSupportInfo.h>
#include <drm/DrmConvertedStatus.h>
+#include <media/MediaAnalyticsItem.h>
#include <IDrmEngine.h>
#include "DrmManager.h"
@@ -50,6 +54,40 @@
}
+void DrmManager::reportEngineMetrics(
+ const char func[], const String8& plugInId, const String8& mimeType) {
+ IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId);
+
+ std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("drmmanager"));
+ item->generateSessionID();
+ item->setUid(IPCThreadState::self()->getCallingUid());
+ item->setCString("function_name", func);
+ item->setCString("plugin_id", plugInId.getPathLeaf().getBasePath().c_str());
+
+ std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
+ if (NULL != info) {
+ item->setCString("description", info->getDescription().c_str());
+ }
+
+ if (!mimeType.isEmpty()) {
+ item->setCString("mime_types", mimeType.c_str());
+ } else if (NULL != info) {
+ DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
+ String8 mimes;
+ while (mimeIter.hasNext()) {
+ mimes += mimeIter.next();
+ if (mimeIter.hasNext()) {
+ mimes += ",";
+ }
+ }
+ item->setCString("mime_types", mimes.c_str());
+ }
+
+ if (!item->selfrecord()) {
+ ALOGE("Failed to record metrics");
+ }
+}
+
int DrmManager::addUniqueId(bool isNative) {
Mutex::Autolock _l(mLock);
@@ -147,27 +185,36 @@
for (size_t index = 0; index < plugInIdList.size(); index++) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
rDrmEngine.terminate(uniqueId);
+ reportEngineMetrics(__func__, plugInIdList[index]);
}
}
DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
Mutex::Autolock _l(mLock);
+ DrmConstraints *constraints = NULL;
const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.getConstraints(uniqueId, path, action);
+ constraints = rDrmEngine.getConstraints(uniqueId, path, action);
}
- return NULL;
+ if (NULL != constraints) {
+ reportEngineMetrics(__func__, plugInId);
+ }
+ return constraints;
}
DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
Mutex::Autolock _l(mLock);
+ DrmMetadata *meta = NULL;
const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.getMetadata(uniqueId, path);
+ meta = rDrmEngine.getMetadata(uniqueId, path);
}
- return NULL;
+ if (NULL != meta) {
+ reportEngineMetrics(__func__, plugInId);
+ }
+ return meta;
}
bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
@@ -175,6 +222,10 @@
const String8 plugInId = getSupportedPlugInId(mimeType);
bool result = (EMPTY_STRING != plugInId) ? true : false;
+ if (result) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
+
if (0 < path.length()) {
if (result) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
@@ -191,12 +242,17 @@
DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
Mutex::Autolock _l(mLock);
- const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
+ DrmInfoStatus *infoStatus = NULL;
+ const String8 mimeType = drmInfo->getMimeType();
+ const String8 plugInId = getSupportedPlugInId(mimeType);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
+ infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
}
- return NULL;
+ if (NULL != infoStatus) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
+ return infoStatus;
}
bool DrmManager::canHandle(int uniqueId, const String8& path) {
@@ -208,6 +264,7 @@
result = rDrmEngine.canHandle(uniqueId, path);
if (result) {
+ reportEngineMetrics(__func__, plugInPathList[i]);
break;
}
}
@@ -216,54 +273,75 @@
DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
Mutex::Autolock _l(mLock);
- const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
+ DrmInfo *info = NULL;
+ const String8 mimeType = drmInfoRequest->getMimeType();
+ const String8 plugInId = getSupportedPlugInId(mimeType);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
+ info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
}
- return NULL;
+ if (NULL != info) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
+ return info;
}
status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
const String8& rightsPath, const String8& contentPath) {
Mutex::Autolock _l(mLock);
- const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
+ const String8 mimeType = drmRights.getMimeType();
+ const String8 plugInId = getSupportedPlugInId(mimeType);
status_t result = DRM_ERROR_UNKNOWN;
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
}
+ if (DRM_NO_ERROR == result) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
return result;
}
String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
Mutex::Autolock _l(mLock);
+ String8 mimeType(EMPTY_STRING);
const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
+ mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
}
- return EMPTY_STRING;
+ if (!mimeType.isEmpty()) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
+ return mimeType;
}
int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
Mutex::Autolock _l(mLock);
+ int type = DrmObjectType::UNKNOWN;
const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
+ type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
}
- return DrmObjectType::UNKNOWN;
+ if (DrmObjectType::UNKNOWN != type) {
+ reportEngineMetrics(__func__, plugInId, mimeType);
+ }
+ return type;
}
int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
Mutex::Autolock _l(mLock);
+ int rightsStatus = RightsStatus::RIGHTS_INVALID;
const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
if (EMPTY_STRING != plugInId) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
- return rDrmEngine.checkRightsStatus(uniqueId, path, action);
+ rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
}
- return RightsStatus::RIGHTS_INVALID;
+ if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
+ reportEngineMetrics(__func__, plugInId);
+ }
+ return rightsStatus;
}
status_t DrmManager::consumeRights(
@@ -307,6 +385,9 @@
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
result = rDrmEngine.removeRights(uniqueId, path);
}
+ if (DRM_NO_ERROR == result) {
+ reportEngineMetrics(__func__, plugInId);
+ }
return result;
}
@@ -319,6 +400,7 @@
if (DRM_NO_ERROR != result) {
break;
}
+ reportEngineMetrics(__func__, plugInIdList[index]);
}
return result;
}
@@ -335,6 +417,7 @@
++mConvertId;
convertId = mConvertId;
mConvertSessionMap.add(convertId, &rDrmEngine);
+ reportEngineMetrics(__func__, plugInId, mimeType);
}
}
return convertId;
@@ -415,6 +498,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ reportEngineMetrics(__func__, plugInId, String8(mime));
break;
}
}
@@ -443,6 +527,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ reportEngineMetrics(__func__, plugInId, String8(mime));
break;
}
}
@@ -472,6 +557,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ reportEngineMetrics(__func__, plugInId, mimeType);
break;
}
}
diff --git a/drm/drmserver/DrmManager.h b/drm/drmserver/DrmManager.h
index 26222bc..75fc1a8 100644
--- a/drm/drmserver/DrmManager.h
+++ b/drm/drmserver/DrmManager.h
@@ -143,6 +143,9 @@
bool canHandle(int uniqueId, const String8& path);
+ void reportEngineMetrics(const char func[],
+ const String8& plugInId, const String8& mimeType = String8(""));
+
private:
enum {
kMaxNumUniqueIds = 0x1000,
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index d6db1d4..6dce472 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -34,7 +34,6 @@
"android.hardware.drm@1.2",
"libhidlallocatorutils",
"libhidlbase",
- "libhidltransport",
],
cflags: [
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
index eaa3390..cb69f91 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyFetcher.cpp
@@ -89,7 +89,7 @@
// asset_id change. If it sends an EcmContainer with 2 Ecms with different
// asset_ids (old and new) then it might be best to prefetch the Emm.
if ((asset_.id() != 0) && (*asset_id != asset_.id())) {
- ALOGW("Asset_id change from %llu to %" PRIu64, asset_.id(), *asset_id);
+ ALOGW("Asset_id change from %" PRIu64 " to %" PRIu64, asset_.id(), *asset_id);
asset_.Clear();
}
diff --git a/drm/mediacas/plugins/clearkey/ecm.cpp b/drm/mediacas/plugins/clearkey/ecm.cpp
index 9fde13a..b3b5218 100644
--- a/drm/mediacas/plugins/clearkey/ecm.cpp
+++ b/drm/mediacas/plugins/clearkey/ecm.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ecm"
+#include <inttypes.h>
+
#include "ecm.h"
#include "ecm_generator.h"
#include "protos/license_protos.pb.h"
@@ -76,7 +78,7 @@
return status;
}
if (asset.id() != asset_from_emm.id()) {
- ALOGE("Asset_id from Emm (%llu) does not match asset_id from Ecm (%llu).",
+ ALOGE("Asset_id from Emm (%" PRIu64 ") does not match asset_id from Ecm (%" PRIu64 ").",
asset_from_emm.id(), asset.id());
return CLEARKEY_STATUS_INVALID_PARAMETER;
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index e91e918..a153ce2 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -48,7 +48,6 @@
"libcrypto",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libprotobuf-cpp-lite",
"libutils",
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 23a35e5..f164f28 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -62,10 +62,8 @@
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;
- }
+ bytesWritten = hBytesWritten;
+ detailedError = hDetailedError;
}
);
@@ -109,6 +107,10 @@
"destination decrypt buffer base not set");
return Void();
}
+ } else {
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
+ "destination type not supported");
+ return Void();
}
sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
@@ -126,38 +128,45 @@
(static_cast<void *>(sourceBase->getPointer()));
uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
void* destPtr = NULL;
- if (destination.type == BufferType::SHARED_MEMORY) {
- const SharedBuffer& destBuffer = destination.nonsecureMemory;
- sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
- if (destBase == nullptr) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
- return Void();
- }
-
- if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
- return Void();
- }
- destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
- } else if (destination.type == BufferType::NATIVE_HANDLE) {
- native_handle_t *handle = const_cast<native_handle_t *>(
- destination.secureMemory.getNativeHandle());
- destPtr = static_cast<void *>(handle);
+ // destination.type == BufferType::SHARED_MEMORY
+ const SharedBuffer& destBuffer = destination.nonsecureMemory;
+ sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
+ if (destBase == nullptr) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+ return Void();
}
+ if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
+ return Void();
+ }
+ destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+
+
// Calculate the output buffer size and determine if any subsamples are
// encrypted.
size_t destSize = 0;
bool haveEncryptedSubsamples = false;
for (size_t i = 0; i < subSamples.size(); i++) {
const SubSample &subSample = subSamples[i];
- destSize += subSample.numBytesOfClearData;
- destSize += subSample.numBytesOfEncryptedData;
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize)) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample clear size overflow");
+ return Void();
+ }
+ if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize)) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample encrypted size overflow");
+ return Void();
+ }
if (subSample.numBytesOfEncryptedData > 0) {
haveEncryptedSubsamples = true;
}
}
+ if (destSize > destBuffer.size) {
+ _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample sum too large");
+ return Void();
+ }
+
if (mode == Mode::UNENCRYPTED) {
if (haveEncryptedSubsamples) {
_hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
diff --git a/media/audioserver/Android.mk b/media/audioserver/Android.mk
index e11af12..6697cb5 100644
--- a/media/audioserver/Android.mk
+++ b/media/audioserver/Android.mk
@@ -14,8 +14,6 @@
libcutils \
liblog \
libhidlbase \
- libhidltransport \
- libhwbinder \
libmedia \
libmedialogservice \
libmediautils \
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index c7ea70f..f817c76 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -16,8 +16,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhwbinder",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.media.bufferpool@1.0",
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index c71ac17..97f114a 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -1,9 +1,5 @@
-cc_library {
- name: "libstagefright_bufferpool@2.0",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
+cc_defaults {
+ name: "libstagefright_bufferpool@2.0-default",
srcs: [
"Accessor.cpp",
"AccessorImpl.cpp",
@@ -20,8 +16,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhwbinder",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.media.bufferpool@2.0",
@@ -31,3 +25,23 @@
"android.hardware.media.bufferpool@2.0",
],
}
+
+cc_library {
+ name: "libstagefright_bufferpool@2.0.1",
+ defaults: ["libstagefright_bufferpool@2.0-default"],
+ vendor_available: true,
+ cflags: [
+ "-DBUFFERPOOL_CLONE_HANDLES",
+ ],
+}
+
+// Deprecated. Do not use. Use libstagefright_bufferpool@2.0.1 instead.
+cc_library {
+ name: "libstagefright_bufferpool@2.0",
+ defaults: ["libstagefright_bufferpool@2.0-default"],
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+}
+
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/bufferpool/2.0/ClientManager.cpp
index 48c2da4..87ee4e8 100644
--- a/media/bufferpool/2.0/ClientManager.cpp
+++ b/media/bufferpool/2.0/ClientManager.cpp
@@ -351,6 +351,7 @@
}
client = it->second;
}
+#ifdef BUFFERPOOL_CLONE_HANDLES
native_handle_t *origHandle;
ResultStatus res = client->allocate(params, &origHandle, buffer);
if (res != ResultStatus::OK) {
@@ -362,6 +363,9 @@
return ResultStatus::NO_MEMORY;
}
return ResultStatus::OK;
+#else
+ return client->allocate(params, handle, buffer);
+#endif
}
ResultStatus ClientManager::Impl::receive(
@@ -377,6 +381,7 @@
}
client = it->second;
}
+#ifdef BUFFERPOOL_CLONE_HANDLES
native_handle_t *origHandle;
ResultStatus res = client->receive(
transactionId, bufferId, timestampUs, &origHandle, buffer);
@@ -389,6 +394,9 @@
return ResultStatus::NO_MEMORY;
}
return ResultStatus::OK;
+#else
+ return client->receive(transactionId, bufferId, timestampUs, handle, buffer);
+#endif
}
ResultStatus ClientManager::Impl::postSend(
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 3f015b4..fa98178 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -33,7 +33,8 @@
namespace {
constexpr char COMPONENT_NAME[] = "c2.android.avc.decoder";
-
+constexpr uint32_t kDefaultOutputDelay = 8;
+constexpr uint32_t kMaxOutputDelay = 16;
} // namespace
class C2SoftAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -54,7 +55,9 @@
// TODO: Proper support for reorder depth.
addParameter(
DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
- .withConstValue(new C2PortActualDelayTuning::output(8u))
+ .withDefault(new C2PortActualDelayTuning::output(kDefaultOutputDelay))
+ .withFields({C2F(mActualOutputDelay, value).inRange(0, kMaxOutputDelay)})
+ .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
.build());
// TODO: output latency and reordering
@@ -196,7 +199,6 @@
0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
.build());
}
-
static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output> &oldMe,
C2P<C2StreamPictureSizeInfo::output> &me) {
(void)mayBlock;
@@ -333,6 +335,7 @@
mDecHandle(nullptr),
mOutBufferFlush(nullptr),
mIvColorFormat(IV_YUV_420P),
+ mOutputDelay(kDefaultOutputDelay),
mWidth(320),
mHeight(240),
mHeaderDecoded(false),
@@ -882,6 +885,26 @@
work->result = C2_CORRUPTED;
return;
}
+ if (s_decode_op.i4_reorder_depth >= 0 && mOutputDelay != s_decode_op.i4_reorder_depth) {
+ mOutputDelay = s_decode_op.i4_reorder_depth;
+ ALOGV("New Output delay %d ", mOutputDelay);
+
+ C2PortActualDelayTuning::output outputDelay(mOutputDelay);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err =
+ mIntf->config({&outputDelay}, C2_MAY_BLOCK, &failures);
+ if (err == OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(outputDelay));
+ } else {
+ ALOGE("Cannot set output delay");
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ continue;
+ }
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 72ee583..4414a26 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -157,7 +157,7 @@
size_t mNumCores;
IV_COLOR_FORMAT_T mIvColorFormat;
-
+ uint32_t mOutputDelay;
uint32_t mWidth;
uint32_t mHeight;
uint32_t mStride;
diff --git a/media/codec2/components/g711/C2SoftG711Dec.cpp b/media/codec2/components/g711/C2SoftG711Dec.cpp
index 43b843a..b6cc32e 100644
--- a/media/codec2/components/g711/C2SoftG711Dec.cpp
+++ b/media/codec2/components/g711/C2SoftG711Dec.cpp
@@ -73,7 +73,7 @@
addParameter(
DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
- .withDefault(new C2StreamChannelCountInfo::output(0u, 1))
+ .withDefault(new C2StreamChannelCountInfo::output(0u, 6))
.withFields({C2F(mChannelCount, value).equalTo(1)})
.withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
.build());
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 7232572..df677c2 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -33,7 +33,8 @@
namespace {
constexpr char COMPONENT_NAME[] = "c2.android.hevc.decoder";
-
+constexpr uint32_t kDefaultOutputDelay = 8;
+constexpr uint32_t kMaxOutputDelay = 16;
} // namespace
class C2SoftHevcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -54,7 +55,9 @@
// TODO: Proper support for reorder depth.
addParameter(
DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
- .withConstValue(new C2PortActualDelayTuning::output(8u))
+ .withDefault(new C2PortActualDelayTuning::output(kDefaultOutputDelay))
+ .withFields({C2F(mActualOutputDelay, value).inRange(0, kMaxOutputDelay)})
+ .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
.build());
addParameter(
@@ -327,6 +330,7 @@
mDecHandle(nullptr),
mOutBufferFlush(nullptr),
mIvColorformat(IV_YUV_420P),
+ mOutputDelay(kDefaultOutputDelay),
mWidth(320),
mHeight(240),
mHeaderDecoded(false),
@@ -877,6 +881,26 @@
work->result = C2_CORRUPTED;
return;
}
+ if (s_decode_op.i4_reorder_depth >= 0 && mOutputDelay != s_decode_op.i4_reorder_depth) {
+ mOutputDelay = s_decode_op.i4_reorder_depth;
+ ALOGV("New Output delay %d ", mOutputDelay);
+
+ C2PortActualDelayTuning::output outputDelay(mOutputDelay);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err =
+ mIntf->config({&outputDelay}, C2_MAY_BLOCK, &failures);
+ if (err == OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(outputDelay));
+ } else {
+ ALOGE("Cannot set output delay");
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ continue;
+ }
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
mHeaderDecoded = true;
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index b7664e6..ce63a6c 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -115,7 +115,7 @@
size_t mNumCores;
IV_COLOR_FORMAT_T mIvColorformat;
-
+ uint32_t mOutputDelay;
uint32_t mWidth;
uint32_t mHeight;
uint32_t mStride;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 36053f6..54c8c47 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -517,9 +517,11 @@
if (layout.planes[layout.PLANE_Y].colInc == 1
&& layout.planes[layout.PLANE_U].colInc == 1
&& layout.planes[layout.PLANE_V].colInc == 1
+ && yStride == align(width, 16)
&& uStride == vStride
&& yStride == 2 * vStride) {
- // I420 compatible - planes are already set up above
+ // I420 compatible with yStride being equal to aligned width
+ // planes are already set up above
break;
}
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 63fe36b..bdff29a 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -24,7 +24,7 @@
"libgui",
"libhidlbase",
"liblog",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libui",
"libutils",
],
@@ -37,7 +37,7 @@
"android.hardware.media.c2@1.0",
"libcodec2",
"libgui",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libui",
],
}
@@ -80,10 +80,8 @@
"libcodec2_vndk",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libstagefright_bufferqueue_helper",
"libui",
"libutils",
@@ -98,7 +96,7 @@
"libcodec2",
"libcodec2_vndk",
"libhidlbase",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libui",
],
}
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index 6038a40..89c1c4a 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -17,9 +17,8 @@
"libcutils",
"libgui",
"libhidlbase",
- "libhidltransport",
"liblog",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libui",
"libutils",
],
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 5ed54f1..c620bad 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -883,66 +883,72 @@
Codec2Client::CreateComponentByName(
const char* componentName,
const std::shared_ptr<Listener>& listener,
- std::shared_ptr<Codec2Client>* owner) {
- std::shared_ptr<Component> component;
- c2_status_t status = ForAllServices(
- componentName,
- [owner, &component, componentName, &listener](
- const std::shared_ptr<Codec2Client> &client)
- -> c2_status_t {
- c2_status_t status = client->createComponent(componentName,
- listener,
- &component);
- if (status == C2_OK) {
- if (owner) {
- *owner = client;
+ std::shared_ptr<Codec2Client>* owner,
+ size_t numberOfAttempts) {
+ while (true) {
+ std::shared_ptr<Component> component;
+ c2_status_t status = ForAllServices(
+ componentName,
+ [owner, &component, componentName, &listener](
+ const std::shared_ptr<Codec2Client> &client)
+ -> c2_status_t {
+ c2_status_t status = client->createComponent(componentName,
+ listener,
+ &component);
+ if (status == C2_OK) {
+ if (owner) {
+ *owner = client;
+ }
+ } else if (status != C2_NOT_FOUND) {
+ LOG(DEBUG) << "IComponentStore("
+ << client->getServiceName()
+ << ")::createComponent(\"" << componentName
+ << "\") returned status = "
+ << status << ".";
}
- } else if (status != C2_NOT_FOUND) {
- LOG(DEBUG) << "IComponentStore("
- << client->getServiceName()
- << ")::createComponent(\"" << componentName
- << "\") returned status = "
- << status << ".";
- }
- return status;
- });
- if (status != C2_OK) {
- LOG(DEBUG) << "Could not create component \"" << componentName << "\". "
- "Status = " << status << ".";
+ return status;
+ });
+ if (numberOfAttempts > 0 && status == C2_TRANSACTION_FAILED) {
+ --numberOfAttempts;
+ continue;
+ }
+ return component;
}
- return component;
}
std::shared_ptr<Codec2Client::Interface>
Codec2Client::CreateInterfaceByName(
const char* interfaceName,
- std::shared_ptr<Codec2Client>* owner) {
- std::shared_ptr<Interface> interface;
- c2_status_t status = ForAllServices(
- interfaceName,
- [owner, &interface, interfaceName](
- const std::shared_ptr<Codec2Client> &client)
- -> c2_status_t {
- c2_status_t status = client->createInterface(interfaceName,
- &interface);
- if (status == C2_OK) {
- if (owner) {
- *owner = client;
+ std::shared_ptr<Codec2Client>* owner,
+ size_t numberOfAttempts) {
+ while (true) {
+ std::shared_ptr<Interface> interface;
+ c2_status_t status = ForAllServices(
+ interfaceName,
+ [owner, &interface, interfaceName](
+ const std::shared_ptr<Codec2Client> &client)
+ -> c2_status_t {
+ c2_status_t status = client->createInterface(interfaceName,
+ &interface);
+ if (status == C2_OK) {
+ if (owner) {
+ *owner = client;
+ }
+ } else if (status != C2_NOT_FOUND) {
+ LOG(DEBUG) << "IComponentStore("
+ << client->getServiceName()
+ << ")::createInterface(\"" << interfaceName
+ << "\") returned status = "
+ << status << ".";
}
- } else if (status != C2_NOT_FOUND) {
- LOG(DEBUG) << "IComponentStore("
- << client->getServiceName()
- << ")::createInterface(\"" << interfaceName
- << "\") returned status = "
- << status << ".";
- }
- return status;
- });
- if (status != C2_OK) {
- LOG(DEBUG) << "Could not create interface \"" << interfaceName << "\". "
- "Status = " << status << ".";
+ return status;
+ });
+ if (numberOfAttempts > 0 && status == C2_TRANSACTION_FAILED) {
+ --numberOfAttempts;
+ continue;
+ }
+ return interface;
}
- return interface;
}
std::vector<C2Component::Traits> const& Codec2Client::ListComponents() {
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index b8a7fb5..848901d 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -179,17 +179,21 @@
static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();
// Try to create a component with a given name from all known
- // IComponentStore services.
+ // IComponentStore services. numberOfAttempts determines the number of times
+ // to retry the HIDL call if the transaction fails.
static std::shared_ptr<Component> CreateComponentByName(
char const* componentName,
std::shared_ptr<Listener> const& listener,
- std::shared_ptr<Codec2Client>* owner = nullptr);
+ std::shared_ptr<Codec2Client>* owner = nullptr,
+ size_t numberOfAttempts = 10);
// Try to create a component interface with a given name from all known
- // IComponentStore services.
+ // IComponentStore services. numberOfAttempts determines the number of times
+ // to retry the HIDL call if the transaction fails.
static std::shared_ptr<Interface> CreateInterfaceByName(
char const* interfaceName,
- std::shared_ptr<Codec2Client>* owner = nullptr);
+ std::shared_ptr<Codec2Client>* owner = nullptr,
+ size_t numberOfAttempts = 10);
// List traits from all known IComponentStore services.
static std::vector<C2Component::Traits> const& ListComponents();
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 216525e..0403a1f 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -17,8 +17,6 @@
"libcodec2_hidl@1.0",
"libcodec2_vndk",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libstagefright_omx",
"libstagefright_xmlparser",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 1883225..d61b751 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -225,7 +225,7 @@
mFirstValidFrameIndex(0u),
mMetaMode(MODE_NONE),
mInputMetEos(false) {
- mOutputSurface.lock()->maxDequeueBuffers = 2 * kSmoothnessFactor + kRenderingDepth;
+ mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + kRenderingDepth;
{
Mutexed<Input>::Locked input(mInput);
input->buffers.reset(new DummyInputBuffers(""));
@@ -949,8 +949,11 @@
uint32_t outputGeneration;
{
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = numOutputSlots + numInputSlots +
+ output->maxDequeueBuffers = numOutputSlots +
reorderDepth.value + kRenderingDepth;
+ if (!secure) {
+ output->maxDequeueBuffers += numInputSlots;
+ }
outputSurface = output->surface ?
output->surface->getIGraphicBufferProducer() : nullptr;
if (outputSurface) {
@@ -1330,14 +1333,18 @@
case C2PortReorderBufferDepthTuning::CORE_INDEX: {
C2PortReorderBufferDepthTuning::output reorderDepth;
if (reorderDepth.updateFrom(*param)) {
+ bool secure = mComponent->getName().find(".secure") != std::string::npos;
mReorderStash.lock()->setDepth(reorderDepth.value);
ALOGV("[%s] onWorkDone: updated reorder depth to %u",
mName, reorderDepth.value);
size_t numOutputSlots = mOutput.lock()->numSlots;
size_t numInputSlots = mInput.lock()->numSlots;
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = numOutputSlots + numInputSlots +
+ output->maxDequeueBuffers = numOutputSlots +
reorderDepth.value + kRenderingDepth;
+ if (!secure) {
+ output->maxDequeueBuffers += numInputSlots;
+ }
if (output->surface) {
output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
}
@@ -1381,6 +1388,7 @@
if (outputDelay.updateFrom(*param)) {
ALOGV("[%s] onWorkDone: updating output delay %u",
mName, outputDelay.value);
+ bool secure = mComponent->getName().find(".secure") != std::string::npos;
(void)mPipelineWatcher.lock()->outputDelay(outputDelay.value);
bool outputBuffersChanged = false;
@@ -1410,8 +1418,10 @@
uint32_t depth = mReorderStash.lock()->depth();
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = numOutputSlots + numInputSlots +
- depth + kRenderingDepth;
+ output->maxDequeueBuffers = numOutputSlots + depth + kRenderingDepth;
+ if (!secure) {
+ output->maxDequeueBuffers += numInputSlots;
+ }
if (output->surface) {
output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
}
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index b6ddfab..52cc7ad 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -66,7 +66,7 @@
"liblog",
"libnativewindow",
"libstagefright_foundation",
- "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
"libui",
"libutils",
],
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index efa0512..750fc21 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -340,11 +340,11 @@
return reply.readInt32();
}
- virtual void setRecordSilenced(uid_t uid, bool silenced)
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(uid);
+ data.writeInt32(portId);
data.writeInt32(silenced ? 1 : 0);
remote()->transact(SET_RECORD_SILENCED, data, &reply);
}
@@ -1156,11 +1156,9 @@
} break;
case SET_RECORD_SILENCED: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- uid_t uid = data.readInt32();
- audio_source_t source;
- data.read(&source, sizeof(audio_source_t));
+ audio_port_handle_t portId = data.readInt32();
bool silenced = data.readInt32() == 1;
- setRecordSilenced(uid, silenced);
+ setRecordSilenced(portId, silenced);
return NO_ERROR;
} break;
case SET_PARAMETERS: {
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8ec8931..db09ddf 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -384,7 +384,7 @@
// mic mute/state
virtual status_t setMicMute(bool state) = 0;
virtual bool getMicMute() const = 0;
- virtual void setRecordSilenced(uid_t uid, bool silenced) = 0;
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
virtual status_t setParameters(audio_io_handle_t ioHandle,
const String8& keyValuePairs) = 0;
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index 5045d87..c91b79e 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -10,17 +10,21 @@
srcs: [
"AudioGain.cpp",
+ "AudioPortBase.cpp",
+ "AudioProfile.cpp",
],
shared_libs: [
"libbase",
"libbinder",
"liblog",
+ "libmedia_helper",
"libutils",
],
header_libs: [
"libaudio_system_headers",
+ "libaudioclient_headers",
"libaudiofoundation_headers",
],
diff --git a/media/libaudiofoundation/AudioPortBase.cpp b/media/libaudiofoundation/AudioPortBase.cpp
new file mode 100644
index 0000000..922a82c
--- /dev/null
+++ b/media/libaudiofoundation/AudioPortBase.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+
+#include <android-base/stringprintf.h>
+#include <media/AudioPortBase.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void AudioPortFoundation::toAudioPort(struct audio_port *port) const {
+ // TODO: update this function once audio_port structure reflects the new profile definition.
+ // For compatibility reason: flatening the AudioProfile into audio_port structure.
+ FormatSet flatenedFormats;
+ SampleRateSet flatenedRates;
+ ChannelMaskSet flatenedChannels;
+ for (const auto& profile : *getAudioProfileVectorBase()) {
+ if (profile->isValid()) {
+ audio_format_t formatToExport = profile->getFormat();
+ const SampleRateSet &ratesToExport = profile->getSampleRates();
+ const ChannelMaskSet &channelsToExport = profile->getChannels();
+
+ flatenedFormats.insert(formatToExport);
+ flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
+ flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
+
+ if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
+ flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
+ flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
+ ALOGE("%s: bailing out: cannot export profiles to port config", __func__);
+ return;
+ }
+ }
+ }
+ port->role = mRole;
+ port->type = mType;
+ strlcpy(port->name, mName.c_str(), AUDIO_PORT_MAX_NAME_LEN);
+ port->num_sample_rates = flatenedRates.size();
+ port->num_channel_masks = flatenedChannels.size();
+ port->num_formats = flatenedFormats.size();
+ std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
+ std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
+ std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
+
+ ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
+
+ port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
+ for (size_t i = 0; i < port->num_gains; i++) {
+ port->gains[i] = mGains[i]->getGain();
+ }
+}
+
+void AudioPortFoundation::dump(std::string *dst, int spaces, bool verbose) const {
+ if (!mName.empty()) {
+ dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+ }
+ if (verbose) {
+ std::string profilesStr;
+ getAudioProfileVectorBase()->dump(&profilesStr, spaces);
+ dst->append(profilesStr);
+
+ if (mGains.size() != 0) {
+ dst->append(base::StringPrintf("%*s- gains:\n", spaces, ""));
+ for (size_t i = 0; i < mGains.size(); i++) {
+ std::string gainStr;
+ mGains[i]->dump(&gainStr, spaces + 2, i);
+ dst->append(gainStr);
+ }
+ }
+ }
+}
+
+}
\ No newline at end of file
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
new file mode 100644
index 0000000..aaaa7d1
--- /dev/null
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+#include <set>
+
+#define LOG_TAG "AudioProfile"
+//#define LOG_NDEBUG 0
+
+#include <android-base/stringprintf.h>
+#include <media/AudioContainers.h>
+#include <media/AudioProfile.h>
+#include <media/TypeConverter.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+bool operator == (const AudioProfile &left, const AudioProfile &right)
+{
+ return (left.getFormat() == right.getFormat()) &&
+ (left.getChannels() == right.getChannels()) &&
+ (left.getSampleRates() == right.getSampleRates());
+}
+
+// static
+sp<AudioProfile> AudioProfile::createFullDynamic(audio_format_t dynamicFormat)
+{
+ AudioProfile* dynamicProfile = new AudioProfile(dynamicFormat,
+ ChannelMaskSet(), SampleRateSet());
+ dynamicProfile->setDynamicFormat(true);
+ dynamicProfile->setDynamicChannels(true);
+ dynamicProfile->setDynamicRate(true);
+ return dynamicProfile;
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+ audio_channel_mask_t channelMasks,
+ uint32_t samplingRate) :
+ mName(""),
+ mFormat(format)
+{
+ mChannelMasks.insert(channelMasks);
+ mSamplingRates.insert(samplingRate);
+}
+
+AudioProfile::AudioProfile(audio_format_t format,
+ const ChannelMaskSet &channelMasks,
+ const SampleRateSet &samplingRateCollection) :
+ mName(""),
+ mFormat(format),
+ mChannelMasks(channelMasks),
+ mSamplingRates(samplingRateCollection) {}
+
+void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
+{
+ if (mIsDynamicChannels) {
+ mChannelMasks = channelMasks;
+ }
+}
+
+void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
+{
+ if (mIsDynamicRate) {
+ mSamplingRates = sampleRates;
+ }
+}
+
+void AudioProfile::clear()
+{
+ if (mIsDynamicChannels) {
+ mChannelMasks.clear();
+ }
+ if (mIsDynamicRate) {
+ mSamplingRates.clear();
+ }
+}
+
+void AudioProfile::dump(std::string *dst, int spaces) const
+{
+ dst->append(base::StringPrintf("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
+ mIsDynamicChannels ? "[dynamic channels]" : "",
+ mIsDynamicRate ? "[dynamic rates]" : ""));
+ if (mName.length() != 0) {
+ dst->append(base::StringPrintf("%*s- name: %s\n", spaces, "", mName.c_str()));
+ }
+ std::string formatLiteral;
+ if (FormatConverter::toString(mFormat, formatLiteral)) {
+ dst->append(base::StringPrintf("%*s- format: %s\n", spaces, "", formatLiteral.c_str()));
+ }
+ if (!mSamplingRates.empty()) {
+ dst->append(base::StringPrintf("%*s- sampling rates:", spaces, ""));
+ for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
+ dst->append(base::StringPrintf("%d", *it));
+ dst->append(++it == mSamplingRates.end() ? "" : ", ");
+ }
+ dst->append("\n");
+ }
+
+ if (!mChannelMasks.empty()) {
+ dst->append(base::StringPrintf("%*s- channel masks:", spaces, ""));
+ for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
+ dst->append(base::StringPrintf("0x%04x", *it));
+ dst->append(++it == mChannelMasks.end() ? "" : ", ");
+ }
+ dst->append("\n");
+ }
+}
+
+ssize_t AudioProfileVectorBase::add(const sp<AudioProfile> &profile)
+{
+ ssize_t index = size();
+ push_back(profile);
+ return index;
+}
+
+void AudioProfileVectorBase::clearProfiles()
+{
+ for (auto it = begin(); it != end();) {
+ if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
+ it = erase(it);
+ } else {
+ (*it)->clear();
+ ++it;
+ }
+ }
+}
+
+sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfile() const
+{
+ for (const auto &profile : *this) {
+ if (profile->isValid()) {
+ return profile;
+ }
+ }
+ return nullptr;
+}
+
+sp<AudioProfile> AudioProfileVectorBase::getFirstValidProfileFor(audio_format_t format) const
+{
+ for (const auto &profile : *this) {
+ if (profile->isValid() && profile->getFormat() == format) {
+ return profile;
+ }
+ }
+ return nullptr;
+}
+
+FormatVector AudioProfileVectorBase::getSupportedFormats() const
+{
+ FormatVector supportedFormats;
+ for (const auto &profile : *this) {
+ if (profile->hasValidFormat()) {
+ supportedFormats.push_back(profile->getFormat());
+ }
+ }
+ return supportedFormats;
+}
+
+bool AudioProfileVectorBase::hasDynamicChannelsFor(audio_format_t format) const
+{
+ for (const auto &profile : *this) {
+ if (profile->getFormat() == format && profile->isDynamicChannels()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicFormat() const
+{
+ for (const auto &profile : *this) {
+ if (profile->isDynamicFormat()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicProfile() const
+{
+ for (const auto &profile : *this) {
+ if (profile->isDynamic()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AudioProfileVectorBase::hasDynamicRateFor(audio_format_t format) const
+{
+ for (const auto &profile : *this) {
+ if (profile->getFormat() == format && profile->isDynamicRate()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void AudioProfileVectorBase::dump(std::string *dst, int spaces) const
+{
+ dst->append(base::StringPrintf("%*s- Profiles:\n", spaces, ""));
+ for (size_t i = 0; i < size(); i++) {
+ dst->append(base::StringPrintf("%*sProfile %zu:", spaces + 4, "", i));
+ std::string profileStr;
+ at(i)->dump(&profileStr, spaces + 8);
+ dst->append(profileStr);
+ }
+}
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioPortBase.h b/media/libaudiofoundation/include/media/AudioPortBase.h
new file mode 100644
index 0000000..5812c2c
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioPortBase.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <media/AudioGain.h>
+#include <media/AudioProfile.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <system/audio.h>
+#include <cutils/config_utils.h>
+
+namespace android {
+
+class AudioPortFoundation : public virtual RefBase
+{
+public:
+ AudioPortFoundation(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
+ mName(name), mType(type), mRole(role) {}
+
+ virtual ~AudioPortFoundation() = default;
+
+ void setName(const std::string &name) { mName = name; }
+ const std::string &getName() const { return mName; }
+
+ audio_port_type_t getType() const { return mType; }
+ audio_port_role_t getRole() const { return mRole; }
+
+ virtual const std::string getTagName() const = 0;
+
+ void setGains(const AudioGains &gains) { mGains = gains; }
+ const AudioGains &getGains() const { return mGains; }
+
+ virtual void toAudioPort(struct audio_port *port) const;
+
+ virtual AudioProfileVectorBase* getAudioProfileVectorBase() const = 0;
+ virtual void addAudioProfile(const sp<AudioProfile> &profile) {
+ getAudioProfileVectorBase()->add(profile);
+ }
+ virtual void clearAudioProfiles() {
+ getAudioProfileVectorBase()->clearProfiles();
+ }
+
+ bool hasValidAudioProfile() const { return getAudioProfileVectorBase()->hasValidProfile(); }
+
+ status_t checkGain(const struct audio_gain_config *gainConfig, int index) const {
+ if (index < 0 || (size_t)index >= mGains.size()) {
+ return BAD_VALUE;
+ }
+ return mGains[index]->checkConfig(gainConfig);
+ }
+
+ bool useInputChannelMask() const
+ {
+ return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
+ ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
+ }
+
+ void dump(std::string *dst, int spaces, bool verbose = true) const;
+
+ AudioGains mGains; // gain controllers
+protected:
+ std::string mName;
+ audio_port_type_t mType;
+ audio_port_role_t mRole;
+};
+
+template <typename ProfileVector,
+ typename = typename std::enable_if<std::is_base_of<
+ AudioProfileVectorBase, ProfileVector>::value>::type>
+class AudioPortBase : public AudioPortFoundation
+{
+public:
+ AudioPortBase(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
+ AudioPortFoundation(name, type, role) {}
+
+ virtual ~AudioPortBase() {}
+
+ AudioProfileVectorBase* getAudioProfileVectorBase() const override {
+ return static_cast<AudioProfileVectorBase*>(const_cast<ProfileVector*>(&mProfiles));
+ }
+
+ void addAudioProfile(const sp<AudioProfile> &profile) override { mProfiles.add(profile); }
+ void clearAudioProfiles() override { return mProfiles.clearProfiles(); }
+
+ void setAudioProfiles(const ProfileVector &profiles) { mProfiles = profiles; }
+ ProfileVector &getAudioProfiles() { return mProfiles; }
+
+protected:
+ ProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
+};
+
+
+class AudioPortConfigBase : public virtual RefBase
+{
+public:
+ virtual ~AudioPortConfigBase() = default;
+
+ virtual status_t applyAudioPortConfig(const struct audio_port_config *config,
+ struct audio_port_config *backupConfig = NULL) = 0;
+ virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
+ const struct audio_port_config *srcConfig = NULL) const = 0;
+
+ unsigned int getSamplingRate() const { return mSamplingRate; }
+ audio_format_t getFormat() const { return mFormat; }
+ audio_channel_mask_t getChannelMask() const { return mChannelMask; }
+
+protected:
+ unsigned int mSamplingRate = 0u;
+ audio_format_t mFormat = AUDIO_FORMAT_INVALID;
+ audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
+ struct audio_gain_config mGain = { .index = -1 };
+};
+
+} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
new file mode 100644
index 0000000..20f35eb
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -0,0 +1,106 @@
+/*
+ * 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 <vector>
+
+#include <media/AudioContainers.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class AudioProfile final : public RefBase
+{
+public:
+ static sp<AudioProfile> createFullDynamic(audio_format_t dynamicFormat = AUDIO_FORMAT_DEFAULT);
+
+ AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
+ AudioProfile(audio_format_t format,
+ const ChannelMaskSet &channelMasks,
+ const SampleRateSet &samplingRateCollection);
+
+ audio_format_t getFormat() const { return mFormat; }
+ const ChannelMaskSet &getChannels() const { return mChannelMasks; }
+ const SampleRateSet &getSampleRates() const { return mSamplingRates; }
+ void setChannels(const ChannelMaskSet &channelMasks);
+ void setSampleRates(const SampleRateSet &sampleRates);
+
+ void clear();
+ bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
+ bool supportsChannels(audio_channel_mask_t channels) const
+ {
+ return mChannelMasks.count(channels) != 0;
+ }
+ bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
+
+ bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
+ bool hasValidRates() const { return !mSamplingRates.empty(); }
+ bool hasValidChannels() const { return !mChannelMasks.empty(); }
+
+ void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
+ bool isDynamicChannels() const { return mIsDynamicChannels; }
+
+ void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
+ bool isDynamicRate() const { return mIsDynamicRate; }
+
+ void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
+ bool isDynamicFormat() const { return mIsDynamicFormat; }
+
+ bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
+
+ void dump(std::string *dst, int spaces) const;
+
+private:
+ std::string mName;
+ audio_format_t mFormat; // The format for an audio profile should only be set when initialized.
+ ChannelMaskSet mChannelMasks;
+ SampleRateSet mSamplingRates;
+
+ bool mIsDynamicFormat = false;
+ bool mIsDynamicChannels = false;
+ bool mIsDynamicRate = false;
+};
+
+class AudioProfileVectorBase : public std::vector<sp<AudioProfile> >
+{
+public:
+ virtual ~AudioProfileVectorBase() = default;
+
+ virtual ssize_t add(const sp<AudioProfile> &profile);
+
+ // If the profile is dynamic format and has valid format, it will be removed when doing
+ // clearProfiles(). Otherwise, AudioProfile::clear() will be called.
+ virtual void clearProfiles();
+
+ sp<AudioProfile> getFirstValidProfile() const;
+ sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
+ bool hasValidProfile() const { return getFirstValidProfile() != 0; }
+
+ FormatVector getSupportedFormats() const;
+ bool hasDynamicChannelsFor(audio_format_t format) const;
+ bool hasDynamicFormat() const;
+ bool hasDynamicProfile() const;
+ bool hasDynamicRateFor(audio_format_t format) const;
+
+ virtual void dump(std::string *dst, int spaces) const;
+};
+
+bool operator == (const AudioProfile &left, const AudioProfile &right);
+
+} // namespace android
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 88533da..d4a4f41 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -36,8 +36,6 @@
"libhardware",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libmedia_helper",
"libmediautils",
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index d141287..8b97fbe 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -93,7 +93,6 @@
"libbinder",
"libcutils",
"libhidlbase",
- "libhidltransport",
"liblog",
"libstagefright_foundation",
"libui",
@@ -154,7 +153,6 @@
"libcutils",
"libgui",
"libhidlbase",
- "libhidltransport",
"liblog",
"libmedia_omx",
"libstagefright_foundation",
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index 02c23b1..b7856a6 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -64,6 +64,16 @@
return item;
}
+MediaAnalyticsItem* MediaAnalyticsItem::convert(mediametrics_handle_t handle) {
+ MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ return item;
+}
+
+mediametrics_handle_t MediaAnalyticsItem::convert(MediaAnalyticsItem *item ) {
+ mediametrics_handle_t handle = (mediametrics_handle_t) item;
+ return handle;
+}
+
// access functions for the class
MediaAnalyticsItem::MediaAnalyticsItem()
: mPid(-1),
diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp
index 6109190..360ae0c 100644
--- a/media/libmediametrics/MediaMetrics.cpp
+++ b/media/libmediametrics/MediaMetrics.cpp
@@ -169,6 +169,11 @@
return item->selfrecord();
}
+mediametrics_handle_t mediametrics_dup(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return android::MediaAnalyticsItem::convert(item);
+ return android::MediaAnalyticsItem::convert(item->dup());
+}
const char *mediametrics_readable(mediametrics_handle_t handle) {
android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
index 4a36f6a..42a2f5b 100644
--- a/media/libmediametrics/include/MediaAnalyticsItem.h
+++ b/media/libmediametrics/include/MediaAnalyticsItem.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_MEDIA_MEDIAANALYTICSITEM_H
#define ANDROID_MEDIA_MEDIAANALYTICSITEM_H
+#include "MediaMetrics.h"
+
#include <string>
#include <sys/types.h>
@@ -94,6 +96,9 @@
static MediaAnalyticsItem* create(Key key);
static MediaAnalyticsItem* create();
+ static MediaAnalyticsItem* convert(mediametrics_handle_t);
+ static mediametrics_handle_t convert(MediaAnalyticsItem *);
+
// access functions for the class
~MediaAnalyticsItem();
diff --git a/media/libmediametrics/include/MediaMetrics.h b/media/libmediametrics/include/MediaMetrics.h
index a4e1ed2..29fb241 100644
--- a/media/libmediametrics/include/MediaMetrics.h
+++ b/media/libmediametrics/include/MediaMetrics.h
@@ -79,6 +79,7 @@
// # of attributes set within this record.
int32_t mediametrics_count(mediametrics_handle_t handle);
+mediametrics_handle_t mediametrics_dup(mediametrics_handle_t handle);
bool mediametrics_selfRecord(mediametrics_handle_t handle);
const char *mediametrics_readable(mediametrics_handle_t handle);
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index afdcd37..f21d2b3 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -130,29 +130,32 @@
} else if (n < 0) {
break;
} else {
- if (buffer[0] == 0x00) {
+ if (buffer[0] == 0x00) { // OK to access buffer[0] since n must be > 0 here
// XXX legacy
if (extra == NULL) {
extra = new AMessage;
}
- uint8_t type = buffer[1];
+ uint8_t type = 0;
+ if (n > 1) {
+ type = buffer[1];
- if (type & 2) {
- int64_t mediaTimeUs;
- memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
+ if ((type & 2) && (n >= 2 + sizeof(int64_t))) {
+ int64_t mediaTimeUs;
+ memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
- extra->setInt64(kATSParserKeyMediaTimeUs, mediaTimeUs);
+ extra->setInt64(kATSParserKeyMediaTimeUs, mediaTimeUs);
+ }
}
mTSParser->signalDiscontinuity(
((type & 1) == 0)
- ? ATSParser::DISCONTINUITY_TIME
- : ATSParser::DISCONTINUITY_FORMATCHANGE,
+ ? ATSParser::DISCONTINUITY_TIME
+ : ATSParser::DISCONTINUITY_FORMATCHANGE,
extra);
} else {
- status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
+ status_t err = mTSParser->feedTSPacket(buffer, n);
if (err != OK) {
ALOGE("TS Parser returned error %d", err);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index eceb84e..b1404de 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -527,7 +527,7 @@
mFlags(0),
mStickyError(OK),
mSoftRenderer(NULL),
- mAnalyticsItem(NULL),
+ mMetricsHandle(0),
mIsVideo(false),
mVideoWidth(0),
mVideoHeight(0),
@@ -548,19 +548,19 @@
mResourceManagerClient = new ResourceManagerClient(this);
mResourceManagerService = new ResourceManagerServiceProxy(pid, mUid);
- initAnalyticsItem();
+ initMediametrics();
}
MediaCodec::~MediaCodec() {
CHECK_EQ(mState, UNINITIALIZED);
mResourceManagerService->removeClient(getId(mResourceManagerClient));
- flushAnalyticsItem();
+ flushMediametrics();
}
-void MediaCodec::initAnalyticsItem() {
- if (mAnalyticsItem == NULL) {
- mAnalyticsItem = MediaAnalyticsItem::create(kCodecKeyName);
+void MediaCodec::initMediametrics() {
+ if (mMetricsHandle == 0) {
+ mMetricsHandle = mediametrics_create(kCodecKeyName);
}
mLatencyHist.setup(kLatencyHistBuckets, kLatencyHistWidth, kLatencyHistFloor);
@@ -574,38 +574,39 @@
}
}
-void MediaCodec::updateAnalyticsItem() {
- ALOGV("MediaCodec::updateAnalyticsItem");
- if (mAnalyticsItem == NULL) {
+void MediaCodec::updateMediametrics() {
+ ALOGV("MediaCodec::updateMediametrics");
+ if (mMetricsHandle == 0) {
return;
}
+
if (mLatencyHist.getCount() != 0 ) {
- mAnalyticsItem->setInt64(kCodecLatencyMax, mLatencyHist.getMax());
- mAnalyticsItem->setInt64(kCodecLatencyMin, mLatencyHist.getMin());
- mAnalyticsItem->setInt64(kCodecLatencyAvg, mLatencyHist.getAvg());
- mAnalyticsItem->setInt64(kCodecLatencyCount, mLatencyHist.getCount());
+ mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
+ mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
+ mediametrics_setInt64(mMetricsHandle, kCodecLatencyAvg, mLatencyHist.getAvg());
+ mediametrics_setInt64(mMetricsHandle, kCodecLatencyCount, mLatencyHist.getCount());
if (kEmitHistogram) {
// and the histogram itself
std::string hist = mLatencyHist.emit();
- mAnalyticsItem->setCString(kCodecLatencyHist, hist.c_str());
+ mediametrics_setCString(mMetricsHandle, kCodecLatencyHist, hist.c_str());
}
}
if (mLatencyUnknown > 0) {
- mAnalyticsItem->setInt64(kCodecLatencyUnknown, mLatencyUnknown);
+ mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown);
}
#if 0
// enable for short term, only while debugging
- updateEphemeralAnalytics(mAnalyticsItem);
+ updateEphemeralMediametrics(mMetricsHandle);
#endif
}
-void MediaCodec::updateEphemeralAnalytics(MediaAnalyticsItem *item) {
- ALOGD("MediaCodec::updateEphemeralAnalytics()");
+void MediaCodec::updateEphemeralMediametrics(mediametrics_handle_t item) {
+ ALOGD("MediaCodec::updateEphemeralMediametrics()");
- if (item == NULL) {
+ if (item == 0) {
return;
}
@@ -628,28 +629,27 @@
// spit the data (if any) into the supplied analytics record
if (recentHist.getCount()!= 0 ) {
- item->setInt64(kCodecRecentLatencyMax, recentHist.getMax());
- item->setInt64(kCodecRecentLatencyMin, recentHist.getMin());
- item->setInt64(kCodecRecentLatencyAvg, recentHist.getAvg());
- item->setInt64(kCodecRecentLatencyCount, recentHist.getCount());
+ mediametrics_setInt64(item, kCodecRecentLatencyMax, recentHist.getMax());
+ mediametrics_setInt64(item, kCodecRecentLatencyMin, recentHist.getMin());
+ mediametrics_setInt64(item, kCodecRecentLatencyAvg, recentHist.getAvg());
+ mediametrics_setInt64(item, kCodecRecentLatencyCount, recentHist.getCount());
if (kEmitHistogram) {
// and the histogram itself
std::string hist = recentHist.emit();
- item->setCString(kCodecRecentLatencyHist, hist.c_str());
+ mediametrics_setCString(item, kCodecRecentLatencyHist, hist.c_str());
}
}
}
-void MediaCodec::flushAnalyticsItem() {
- updateAnalyticsItem();
- if (mAnalyticsItem != NULL) {
- // don't log empty records
- if (mAnalyticsItem->count() > 0) {
- mAnalyticsItem->selfrecord();
+void MediaCodec::flushMediametrics() {
+ updateMediametrics();
+ if (mMetricsHandle != 0) {
+ if (mediametrics_count(mMetricsHandle) > 0) {
+ mediametrics_selfRecord(mMetricsHandle);
}
- delete mAnalyticsItem;
- mAnalyticsItem = NULL;
+ mediametrics_delete(mMetricsHandle);
+ mMetricsHandle = 0;
}
}
@@ -981,9 +981,10 @@
// ".secure"
msg->setString("name", name);
- if (mAnalyticsItem != NULL) {
- mAnalyticsItem->setCString(kCodecCodec, name.c_str());
- mAnalyticsItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio);
+ if (mMetricsHandle != 0) {
+ mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str());
+ mediametrics_setCString(mMetricsHandle, kCodecMode,
+ mIsVideo ? kCodecModeVideo : kCodecModeAudio);
}
if (mIsVideo) {
@@ -1044,16 +1045,17 @@
uint32_t flags) {
sp<AMessage> msg = new AMessage(kWhatConfigure, this);
- if (mAnalyticsItem != NULL) {
+ if (mMetricsHandle != 0) {
int32_t profile = 0;
if (format->findInt32("profile", &profile)) {
- mAnalyticsItem->setInt32(kCodecProfile, profile);
+ mediametrics_setInt32(mMetricsHandle, kCodecProfile, profile);
}
int32_t level = 0;
if (format->findInt32("level", &level)) {
- mAnalyticsItem->setInt32(kCodecLevel, level);
+ mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
}
- mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
+ mediametrics_setInt32(mMetricsHandle, kCodecEncoder,
+ (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
}
if (mIsVideo) {
@@ -1063,17 +1065,17 @@
mRotationDegrees = 0;
}
- if (mAnalyticsItem != NULL) {
- mAnalyticsItem->setInt32(kCodecWidth, mVideoWidth);
- mAnalyticsItem->setInt32(kCodecHeight, mVideoHeight);
- mAnalyticsItem->setInt32(kCodecRotation, mRotationDegrees);
+ if (mMetricsHandle != 0) {
+ mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth);
+ mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight);
+ mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees);
int32_t maxWidth = 0;
if (format->findInt32("max-width", &maxWidth)) {
- mAnalyticsItem->setInt32(kCodecMaxWidth, maxWidth);
+ mediametrics_setInt32(mMetricsHandle, kCodecMaxWidth, maxWidth);
}
int32_t maxHeight = 0;
if (format->findInt32("max-height", &maxHeight)) {
- mAnalyticsItem->setInt32(kCodecMaxHeight, maxHeight);
+ mediametrics_setInt32(mMetricsHandle, kCodecMaxHeight, maxHeight);
}
}
@@ -1095,8 +1097,8 @@
} else {
msg->setPointer("descrambler", descrambler.get());
}
- if (mAnalyticsItem != NULL) {
- mAnalyticsItem->setInt32(kCodecCrypto, 1);
+ if (mMetricsHandle != 0) {
+ mediametrics_setInt32(mMetricsHandle, kCodecCrypto, 1);
}
} else if (mFlags & kFlagIsSecure) {
ALOGW("Crypto or descrambler should be given for secure codec");
@@ -1561,22 +1563,22 @@
return OK;
}
-status_t MediaCodec::getMetrics(MediaAnalyticsItem * &reply) {
+status_t MediaCodec::getMetrics(mediametrics_handle_t &reply) {
- reply = NULL;
+ reply = 0;
// shouldn't happen, but be safe
- if (mAnalyticsItem == NULL) {
+ if (mMetricsHandle == 0) {
return UNKNOWN_ERROR;
}
// update any in-flight data that's not carried within the record
- updateAnalyticsItem();
+ updateMediametrics();
// send it back to the caller.
- reply = mAnalyticsItem->dup();
+ reply = mediametrics_dup(mMetricsHandle);
- updateEphemeralAnalytics(reply);
+ updateEphemeralMediametrics(reply);
return OK;
}
@@ -1890,10 +1892,11 @@
case CONFIGURING:
{
if (actionCode == ACTION_CODE_FATAL) {
- mAnalyticsItem->setInt32(kCodecError, err);
- mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
- flushAnalyticsItem();
- initAnalyticsItem();
+ mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+ mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+ stateString(mState).c_str());
+ flushMediametrics();
+ initMediametrics();
}
setState(actionCode == ACTION_CODE_FATAL ?
UNINITIALIZED : INITIALIZED);
@@ -1903,10 +1906,11 @@
case STARTING:
{
if (actionCode == ACTION_CODE_FATAL) {
- mAnalyticsItem->setInt32(kCodecError, err);
- mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
- flushAnalyticsItem();
- initAnalyticsItem();
+ mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+ mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+ stateString(mState).c_str());
+ flushMediametrics();
+ initMediametrics();
}
setState(actionCode == ACTION_CODE_FATAL ?
UNINITIALIZED : CONFIGURED);
@@ -1944,10 +1948,11 @@
case FLUSHING:
{
if (actionCode == ACTION_CODE_FATAL) {
- mAnalyticsItem->setInt32(kCodecError, err);
- mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
- flushAnalyticsItem();
- initAnalyticsItem();
+ mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+ mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+ stateString(mState).c_str());
+ flushMediametrics();
+ initMediametrics();
setState(UNINITIALIZED);
} else {
@@ -1977,10 +1982,11 @@
setState(INITIALIZED);
break;
default:
- mAnalyticsItem->setInt32(kCodecError, err);
- mAnalyticsItem->setCString(kCodecErrorState, stateString(mState).c_str());
- flushAnalyticsItem();
- initAnalyticsItem();
+ mediametrics_setInt32(mMetricsHandle, kCodecError, err);
+ mediametrics_setCString(mMetricsHandle, kCodecErrorState,
+ stateString(mState).c_str());
+ flushMediametrics();
+ initMediametrics();
setState(UNINITIALIZED);
break;
}
@@ -2037,7 +2043,8 @@
CHECK(msg->findString("componentName", &mComponentName));
if (mComponentName.c_str()) {
- mAnalyticsItem->setCString(kCodecCodec, mComponentName.c_str());
+ mediametrics_setCString(mMetricsHandle, kCodecCodec,
+ mComponentName.c_str());
}
const char *owner = mCodecInfo->getOwnerName();
@@ -2053,11 +2060,11 @@
if (mComponentName.endsWith(".secure")) {
mFlags |= kFlagIsSecure;
resourceType = MediaResource::kSecureCodec;
- mAnalyticsItem->setInt32(kCodecSecure, 1);
+ mediametrics_setInt32(mMetricsHandle, kCodecSecure, 1);
} else {
mFlags &= ~kFlagIsSecure;
resourceType = MediaResource::kNonSecureCodec;
- mAnalyticsItem->setInt32(kCodecSecure, 0);
+ mediametrics_setInt32(mMetricsHandle, kCodecSecure, 0);
}
if (mIsVideo) {
@@ -2105,14 +2112,15 @@
(new AMessage)->postReply(mReplyID);
// augment our media metrics info, now that we know more things
- if (mAnalyticsItem != NULL) {
+ if (mMetricsHandle != 0) {
sp<AMessage> format;
if (mConfigureMsg != NULL &&
mConfigureMsg->findMessage("format", &format)) {
// format includes: mime
AString mime;
if (format->findString("mime", &mime)) {
- mAnalyticsItem->setCString(kCodecMime, mime.c_str());
+ mediametrics_setCString(mMetricsHandle, kCodecMime,
+ mime.c_str());
}
}
}
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index db67034..6719bab 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -27,7 +27,6 @@
"libcutils",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libstagefright_foundation",
"libui",
@@ -39,7 +38,6 @@
"android.hidl.token@1.0-utils",
"libbase",
"libEGL",
- "libhwbinder",
"libnativewindow",
"libvndksupport",
],
diff --git a/media/libstagefright/data/media_codecs_google_c2_video.xml b/media/libstagefright/data/media_codecs_google_c2_video.xml
index a07eb8c..04041eb 100644
--- a/media/libstagefright/data/media_codecs_google_c2_video.xml
+++ b/media/libstagefright/data/media_codecs_google_c2_video.xml
@@ -77,7 +77,7 @@
<Limit name="bitrate" range="1-40000000" />
<Feature name="adaptive-playback" />
</MediaCodec>
- <MediaCodec name="c2.android.gav1.decoder" type="video/av01">
+ <MediaCodec name="c2.android.av1.decoder" type="video/av01">
<Limit name="size" min="96x96" max="1920x1080" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 9532ba6..67d3f1a 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -182,7 +182,7 @@
</Variant>
<Feature name="adaptive-playback" />
</MediaCodec>
- <MediaCodec name="c2.android.gav1.decoder" type="video/av01" variant="!slow-cpu">
+ <MediaCodec name="c2.android.av1.decoder" type="video/av01" variant="!slow-cpu">
<Limit name="size" min="2x2" max="1920x1080" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index cd30347..01d0325 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -25,7 +25,7 @@
#include <media/hardware/CryptoAPI.h>
#include <media/MediaCodecInfo.h>
#include <media/MediaResource.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/FrameRenderTracker.h>
#include <utils/Vector.h>
@@ -189,7 +189,7 @@
status_t getCodecInfo(sp<MediaCodecInfo> *codecInfo) const;
- status_t getMetrics(MediaAnalyticsItem * &reply);
+ status_t getMetrics(mediametrics_handle_t &reply);
status_t setParameters(const sp<AMessage> ¶ms);
@@ -328,11 +328,11 @@
sp<Surface> mSurface;
SoftwareRenderer *mSoftRenderer;
- MediaAnalyticsItem *mAnalyticsItem;
- void initAnalyticsItem();
- void updateAnalyticsItem();
- void flushAnalyticsItem();
- void updateEphemeralAnalytics(MediaAnalyticsItem *item);
+ mediametrics_handle_t mMetricsHandle;
+ void initMediametrics();
+ void updateMediametrics();
+ void flushMediametrics();
+ void updateEphemeralMediametrics(mediametrics_handle_t item);
sp<AMessage> mOutputFormat;
sp<AMessage> mInputFormat;
diff --git a/media/libstagefright/omx/Android.bp b/media/libstagefright/omx/Android.bp
index 7d03d98..7d612b4 100644
--- a/media/libstagefright/omx/Android.bp
+++ b/media/libstagefright/omx/Android.bp
@@ -45,7 +45,6 @@
"libdl",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"libvndksupport",
"android.hardware.media.omx@1.0",
"android.hardware.graphics.bufferqueue@1.0",
diff --git a/media/tests/benchmark/.clang-format b/media/tests/benchmark/.clang-format
new file mode 100644
index 0000000..bf1e355
--- /dev/null
+++ b/media/tests/benchmark/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+Standard: Cpp11
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IncludeBlocks: Preserve
+IndentWidth: 4
+ContinuationIndentWidth: 8
+PointerAlignment: Right
+TabWidth: 4
+UseTab: Never
diff --git a/media/tests/benchmark/Android.bp b/media/tests/benchmark/Android.bp
new file mode 100644
index 0000000..8a7a59f
--- /dev/null
+++ b/media/tests/benchmark/Android.bp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+subdirs = [
+ "src",
+ "tests",
+]
\ No newline at end of file
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
new file mode 100644
index 0000000..327f0e2
--- /dev/null
+++ b/media/tests/benchmark/README.md
@@ -0,0 +1,30 @@
+# Benchmark tests
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/tests/benchmark/
+```
+
+The binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+adb push $(OUT)/data/nativetest64/* /data/local/tmp/
+
+Eg. adb push $(OUT)/data/nativetest64/extractorTest/extractorTest /data/local/tmp/
+
+To run the binary, follow the commands mentioned below under each module.
+
+The resource files for the tests are taken from [here](https://drive.google.com/open?id=1ghMr17BBJ7n0pqbm7oREiTN_MNemJUqy)
+
+## Extractor
+
+The test extracts elementary stream and benchmarks the extractors available in NDK.
+
+Push the resource files to /sdcard/res on the device.
+
+You can use a different location, but you have to modify the rest of the instructions to replace /sdcard/res with wherever you chose to put the files.
+
+The path to these files on the device is required to be given for the test.
+
+```
+adb shell /data/local/tmp/extractorTest -P /sdcard/res/
+```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
new file mode 100644
index 0000000..e4f9ab6
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_library_static {
+ name: "libbenchmark_common",
+ defaults: [
+ "libbenchmark-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: [
+ "Timer.cpp",
+ ],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
+
+cc_defaults {
+ name: "libbenchmark_common-defaults",
+
+ defaults: [
+ "libbenchmark-defaults",
+ ],
+
+ static_libs: [
+ "libbenchmark_common",
+ ],
+}
+
+cc_defaults {
+ name: "libbenchmark-defaults",
+
+ header_libs: [
+ "media_ndk_headers",
+ ],
+
+ shared_libs: [
+ "libmediandk",
+ "liblog",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ]
+}
+
+// public dependency for native implementation
+// to be used by code under media/benchmark/* only
+cc_defaults {
+ name: "libbenchmark_soft_sanitize_all-defaults",
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ address: true,
+ }
+}
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
new file mode 100644
index 0000000..bad6346
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BENCHMARK_COMMON_H__
+#define __BENCHMARK_COMMON_H__
+
+#include <utils/Log.h>
+
+#include <media/NdkMediaCodec.h>
+#include <media/NdkMediaError.h>
+
+constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
+constexpr uint32_t kMaxCSDStrlen = 16;
+constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;
+
+#endif // __BENCHMARK_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/Timer.cpp b/media/tests/benchmark/src/native/common/Timer.cpp
new file mode 100644
index 0000000..0487123
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Timer.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Timer"
+
+#include <iostream>
+#include <stdint.h>
+#include <utils/Log.h>
+
+#include "Timer.h"
+
+/**
+ * Dumps the stats of the operation for a given input media.
+ *
+ * \param operation describes the operation performed on the input media
+ * (i.e. extract/mux/decode/encode)
+ * \param inputReference input media
+ * \param duarationUs is a duration of the input media in microseconds.
+ */
+void Timer::dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs) {
+ ALOGV("In %s", __func__);
+ if (!mOutputTimer.size()) {
+ ALOGE("No output produced");
+ return;
+ }
+ nsecs_t totalTimeTakenNs = getTotalTime();
+ nsecs_t timeTakenPerSec = (totalTimeTakenNs * 1000000) / duarationUs;
+ nsecs_t timeToFirstFrameNs = *mOutputTimer.begin() - mStartTimeNs;
+ // get min and max output intervals.
+ nsecs_t intervalNs;
+ nsecs_t minTimeTakenNs = INT64_MAX;
+ nsecs_t maxTimeTakenNs = 0;
+ nsecs_t prevIntervalNs = mStartTimeNs;
+ for (int32_t idx = 0; idx < mOutputTimer.size() - 1; idx++) {
+ intervalNs = mOutputTimer.at(idx) - prevIntervalNs;
+ prevIntervalNs = mOutputTimer.at(idx);
+ if (minTimeTakenNs > intervalNs) minTimeTakenNs = intervalNs;
+ else if (maxTimeTakenNs < intervalNs) maxTimeTakenNs = intervalNs;
+ }
+
+ // Print the Stats
+ std::cout << "Input Reference : " << inputReference << endl;
+ std::cout << "Setup Time in nano sec : " << mInitTimeNs << endl;
+ std::cout << "Average Time in nano sec : " << totalTimeTakenNs / mOutputTimer.size() << endl;
+ std::cout << "Time to first frame in nano sec : " << timeToFirstFrameNs << endl;
+ std::cout << "Time taken (in nano sec) to " << operation
+ << " 1 sec of content : " << timeTakenPerSec << endl;
+ std::cout << "Minimum Time in nano sec : " << minTimeTakenNs << endl;
+ std::cout << "Maximum Time in nano sec : " << maxTimeTakenNs << endl;
+ std::cout << "Destroy Time in nano sec : " << mDeInitTimeNs << endl;
+}
diff --git a/media/tests/benchmark/src/native/common/Timer.h b/media/tests/benchmark/src/native/common/Timer.h
new file mode 100644
index 0000000..92af86f
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/Timer.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIMER_H__
+#define __TIMER_H__
+
+#include <sys/time.h>
+#include <algorithm>
+#include <numeric>
+#include <vector>
+#include <utils/Timers.h>
+
+using namespace std;
+
+class Timer {
+ public:
+ Timer() {
+ mInitTimeNs = 0;
+ mDeInitTimeNs = 0;
+ }
+
+ ~Timer() {
+ if (!mInputTimer.empty()) mInputTimer.clear();
+ if (!mOutputTimer.empty()) mOutputTimer.clear();
+ }
+
+ private:
+ nsecs_t mInitTimeNs;
+ nsecs_t mDeInitTimeNs;
+ nsecs_t mStartTimeNs;
+ std::vector<nsecs_t> mInputTimer;
+ std::vector<nsecs_t> mOutputTimer;
+
+ public:
+ nsecs_t getCurTime() { return systemTime(CLOCK_MONOTONIC); }
+
+ void setInitTime(nsecs_t initTime) { mInitTimeNs = initTime; }
+
+ void setDeInitTime(nsecs_t deInitTime) { mDeInitTimeNs = deInitTime; }
+
+ void setStartTime() { mStartTimeNs = systemTime(CLOCK_MONOTONIC); }
+
+ void addInputTime() { mInputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+ void addOutputTime() { mOutputTimer.push_back(systemTime(CLOCK_MONOTONIC)); }
+
+ void resetTimers() {
+ if (!mInputTimer.empty()) mInputTimer.clear();
+ if (!mOutputTimer.empty()) mOutputTimer.clear();
+ }
+
+ std::vector<nsecs_t> getOutputTimer() { return mOutputTimer; }
+
+ nsecs_t getInitTime() { return mInitTimeNs; }
+
+ nsecs_t getDeInitTime() { return mDeInitTimeNs; }
+
+ nsecs_t getTimeDiff(nsecs_t sTime, nsecs_t eTime) { return (eTime - sTime); }
+
+ nsecs_t getTotalTime() {
+ if (mOutputTimer.empty()) return -1;
+ return (*(mOutputTimer.end() - 1) - mStartTimeNs);
+ }
+
+ void dumpStatistics(std::string operation, std::string inputReference, int64_t duarationUs);
+};
+
+#endif // __TIMER_H__
diff --git a/media/tests/benchmark/src/native/extractor/Android.bp b/media/tests/benchmark/src/native/extractor/Android.bp
new file mode 100644
index 0000000..2fbe4e8
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Android.bp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_library_static {
+ name: "libbenchmark_extractor",
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["Extractor.cpp"],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.cpp b/media/tests/benchmark/src/native/extractor/Extractor.cpp
new file mode 100644
index 0000000..0726ae3
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "extractor"
+
+#include <iostream>
+
+#include "Extractor.h"
+
+int32_t Extractor::initExtractor(int32_t fd, size_t fileSize) {
+ mTimer = new Timer();
+
+ mFrameBuf = (uint8_t *)calloc(kMaxBufferSize, sizeof(uint8_t));
+ if (!mFrameBuf) return -1;
+
+ int64_t sTime = mTimer->getCurTime();
+
+ mExtractor = AMediaExtractor_new();
+ if (!mExtractor) return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
+ media_status_t status = AMediaExtractor_setDataSourceFd(mExtractor, fd, 0, fileSize);
+ if (status != AMEDIA_OK) return status;
+
+ int64_t eTime = mTimer->getCurTime();
+ int64_t timeTaken = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setInitTime(timeTaken);
+
+ return AMediaExtractor_getTrackCount(mExtractor);
+}
+
+void *Extractor::getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex) {
+ char csdName[kMaxCSDStrlen];
+ void *csdBuffer = nullptr;
+ frameInfo.presentationTimeUs = 0;
+ frameInfo.flags = AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
+ snprintf(csdName, sizeof(csdName), "csd-%d", csdIndex);
+
+ size_t size;
+ bool csdFound = AMediaFormat_getBuffer(mFormat, csdName, &csdBuffer, &size);
+ if (!csdFound) return nullptr;
+ frameInfo.size = (int32_t)size;
+
+ return csdBuffer;
+}
+
+int32_t Extractor::getFrameSample(AMediaCodecBufferInfo &frameInfo) {
+ int32_t size = AMediaExtractor_readSampleData(mExtractor, mFrameBuf, kMaxBufferSize);
+ if (size < 0) return -1;
+
+ frameInfo.flags = AMediaExtractor_getSampleFlags(mExtractor);
+ frameInfo.size = size;
+ frameInfo.presentationTimeUs = AMediaExtractor_getSampleTime(mExtractor);
+ AMediaExtractor_advance(mExtractor);
+
+ return 0;
+}
+
+int32_t Extractor::setupTrackFormat(int32_t trackId) {
+ AMediaExtractor_selectTrack(mExtractor, trackId);
+ mFormat = AMediaExtractor_getTrackFormat(mExtractor, trackId);
+ if (!mFormat) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ bool durationFound = AMediaFormat_getInt64(mFormat, AMEDIAFORMAT_KEY_DURATION, &mDurationUs);
+ if (!durationFound) return AMEDIA_ERROR_INVALID_OBJECT;
+
+ return AMEDIA_OK;
+}
+
+int32_t Extractor::extract(int32_t trackId) {
+ int32_t status = setupTrackFormat(trackId);
+ if (status != AMEDIA_OK) return status;
+
+ int32_t idx = 0;
+ AMediaCodecBufferInfo frameInfo;
+ while (1) {
+ memset(&frameInfo, 0, sizeof(AMediaCodecBufferInfo));
+ void *csdBuffer = getCSDSample(frameInfo, idx);
+ if (!csdBuffer || !frameInfo.size) break;
+ idx++;
+ }
+
+ mTimer->setStartTime();
+ while (1) {
+ int32_t status = getFrameSample(frameInfo);
+ if (status || !frameInfo.size) break;
+ mTimer->addOutputTime();
+ }
+
+ if (mFormat) {
+ AMediaFormat_delete(mFormat);
+ mFormat = nullptr;
+ }
+
+ AMediaExtractor_unselectTrack(mExtractor, trackId);
+
+ return AMEDIA_OK;
+}
+
+void Extractor::dumpStatistics(string inputReference) {
+ string operation = "extract";
+ mTimer->dumpStatistics(operation, inputReference, mDurationUs);
+}
+
+void Extractor::deInitExtractor() {
+ if (mFrameBuf) {
+ free(mFrameBuf);
+ mFrameBuf = nullptr;
+ }
+
+ int64_t sTime = mTimer->getCurTime();
+ if (mExtractor) {
+ // TODO: (b/140128505) Multiple calls result in DoS.
+ // Uncomment call to AMediaExtractor_delete() once this is resolved
+ // AMediaExtractor_delete(mExtractor);
+ mExtractor = nullptr;
+ }
+ int64_t eTime = mTimer->getCurTime();
+ int64_t deInitTime = mTimer->getTimeDiff(sTime, eTime);
+ mTimer->setDeInitTime(deInitTime);
+}
diff --git a/media/tests/benchmark/src/native/extractor/Extractor.h b/media/tests/benchmark/src/native/extractor/Extractor.h
new file mode 100644
index 0000000..361bcd7
--- /dev/null
+++ b/media/tests/benchmark/src/native/extractor/Extractor.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EXTRACTOR_H__
+#define __EXTRACTOR_H__
+
+#include <media/NdkMediaExtractor.h>
+
+#include "BenchmarkCommon.h"
+#include "Timer.h"
+
+class Extractor {
+ public:
+ Extractor()
+ : mFormat(nullptr),
+ mExtractor(nullptr),
+ mTimer(nullptr),
+ mFrameBuf{nullptr},
+ mDurationUs{0} {}
+
+ ~Extractor() {
+ if (mTimer) delete mTimer;
+ }
+
+ int32_t initExtractor(int32_t fd, size_t fileSize);
+
+ int32_t setupTrackFormat(int32_t trackId);
+
+ void *getCSDSample(AMediaCodecBufferInfo &frameInfo, int32_t csdIndex);
+
+ int32_t getFrameSample(AMediaCodecBufferInfo &frameInfo);
+
+ int32_t extract(int32_t trackId);
+
+ void dumpStatistics(std::string inputReference);
+
+ void deInitExtractor();
+
+ AMediaFormat *getFormat() { return mFormat; }
+
+ uint8_t *getFrameBuf() { return mFrameBuf; }
+
+ int64_t getClipDuration() { return mDurationUs; }
+
+ private:
+ AMediaFormat *mFormat;
+ AMediaExtractor *mExtractor;
+ Timer *mTimer;
+ uint8_t *mFrameBuf;
+ int64_t mDurationUs;
+};
+
+#endif // __EXTRACTOR_H__
\ No newline at end of file
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
new file mode 100644
index 0000000..30d6e20
--- /dev/null
+++ b/media/tests/benchmark/tests/Android.bp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+ name: "extractorTest",
+ gtest: true,
+ defaults: [
+ "libbenchmark_common-defaults",
+ "libbenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["ExtractorTest.cpp"],
+
+ static_libs: ["libbenchmark_extractor"]
+}
diff --git a/media/tests/benchmark/tests/BenchmarkTestEnvironment.h b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
new file mode 100644
index 0000000..ae2eee1
--- /dev/null
+++ b/media/tests/benchmark/tests/BenchmarkTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BENCHMARK_TEST_ENVIRONMENT_H__
+#define __BENCHMARK_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class BenchmarkTestEnvironment : public ::testing::Environment {
+ public:
+ BenchmarkTestEnvironment() : res("/sdcard/media/") {}
+
+ // Parses the command line argument
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int BenchmarkTestEnvironment::initFromOptions(int argc, char **argv) {
+ static struct option options[] = {{"path", required_argument, 0, 'P'}, {0, 0, 0, 0}};
+
+ while (true) {
+ int index = 0;
+ int c = getopt_long(argc, argv, "P:", options, &index);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'P': {
+ setRes(optarg);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "unrecognized option: %s\n\n"
+ "usage: %s <gtest options> <test options>\n\n"
+ "test options are:\n\n"
+ "-P, --path: Resource files directory location\n",
+ argv[optind ?: 1], argv[0]);
+ return 2;
+ }
+ return 0;
+}
+
+#endif // __BENCHMARK_TEST_ENVIRONMENT_H__
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
new file mode 100644
index 0000000..dd0d711
--- /dev/null
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "extractorTest"
+
+#include <gtest/gtest.h>
+
+#include "Extractor.h"
+#include "BenchmarkTestEnvironment.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class ExtractorTest : public ::testing::TestWithParam<pair<string, int32_t>> {};
+
+TEST_P(ExtractorTest, Extract) {
+ Extractor *extractObj = new Extractor();
+
+ string inputFile = gEnv->getRes() + GetParam().first;
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file for reading \n";
+ return;
+ }
+
+ // Read file properties
+ size_t fileSize = 0;
+ fseek(inputFp, 0, SEEK_END);
+ fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ int32_t trackCount = extractObj->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+
+ int32_t trackID = GetParam().second;
+ int32_t status = extractObj->extract(trackID);
+ if (status != AMEDIA_OK) {
+ cout << "[ WARN ] Test Skipped. Extraction failed \n";
+ return;
+ }
+
+ extractObj->deInitExtractor();
+
+ extractObj->dumpStatistics(GetParam().first);
+
+ fclose(inputFp);
+ delete extractObj;
+}
+
+INSTANTIATE_TEST_SUITE_P(ExtractorTestAll, ExtractorTest,
+ ::testing::Values(make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", 0),
+ make_pair("crowd_1920x1080_25fps_6000kbps_h263.3gp", 0),
+ make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", 0),
+ make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", 0),
+ make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", 0),
+ make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", 0),
+ make_pair("bbb_44100hz_2ch_128kbps_aac_5mins.mp4", 0),
+ make_pair("bbb_44100hz_2ch_128kbps_mp3_5mins.mp3", 0),
+ make_pair("bbb_44100hz_2ch_600kbps_flac_5mins.flac", 0),
+ make_pair("bbb_8000hz_1ch_8kbps_amrnb_5mins.3gp", 0),
+ make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", 0),
+ make_pair("bbb_44100hz_2ch_80kbps_vorbis_5mins.mp4", 0),
+ make_pair("bbb_48000hz_2ch_100kbps_opus_5mins.webm", 0)));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGD(" Extractor Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b6da11e..aef0ade 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1132,16 +1132,16 @@
return mute;
}
-void AudioFlinger::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
- ALOGV("AudioFlinger::setRecordSilenced(uid:%d, silenced:%d)", uid, silenced);
+ ALOGV("AudioFlinger::setRecordSilenced(portId:%d, silenced:%d)", portId, silenced);
AutoMutex lock(mLock);
for (size_t i = 0; i < mRecordThreads.size(); i++) {
- mRecordThreads[i]->setRecordSilenced(uid, silenced);
+ mRecordThreads[i]->setRecordSilenced(portId, silenced);
}
for (size_t i = 0; i < mMmapThreads.size(); i++) {
- mMmapThreads[i]->setRecordSilenced(uid, silenced);
+ mMmapThreads[i]->setRecordSilenced(portId, silenced);
}
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 72e669a..5e4509f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -162,7 +162,7 @@
virtual status_t setMicMute(bool state);
virtual bool getMicMute() const;
- virtual void setRecordSilenced(uid_t uid, bool silenced);
+ virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced);
virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 868739f..6ca50a7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7934,12 +7934,12 @@
write(fd, result.string(), result.size());
}
-void AudioFlinger::RecordThread::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mTracks.size() ; i++) {
sp<RecordTrack> track = mTracks[i];
- if (track != 0 && track->uid() == uid) {
+ if (track != 0 && track->portId() == portId) {
track->setSilenced(silenced);
}
}
@@ -9477,11 +9477,11 @@
mInput->stream->updateSinkMetadata(metadata);
}
-void AudioFlinger::MmapCaptureThread::setRecordSilenced(uid_t uid, bool silenced)
+void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mActiveTracks.size() ; i++) {
- if (mActiveTracks[i]->uid() == uid) {
+ if (mActiveTracks[i]->portId() == portId) {
mActiveTracks[i]->setSilenced_l(silenced);
broadcast_l();
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 87bebf3..6a9c0e7 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1616,7 +1616,7 @@
void checkBtNrec();
// Sets the UID records silence
- void setRecordSilenced(uid_t uid, bool silenced);
+ void setRecordSilenced(audio_port_handle_t portId, bool silenced);
status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
@@ -1785,7 +1785,8 @@
virtual void invalidateTracks(audio_stream_type_t streamType __unused) {}
// Sets the UID records silence
- virtual void setRecordSilenced(uid_t uid __unused, bool silenced __unused) {}
+ virtual void setRecordSilenced(audio_port_handle_t portId __unused,
+ bool silenced __unused) {}
protected:
void dumpInternals_l(int fd, const Vector<String16>& args) override;
@@ -1872,7 +1873,8 @@
void updateMetadata_l() override;
void processVolume_l() override;
- void setRecordSilenced(uid_t uid, bool silenced) override;
+ void setRecordSilenced(audio_port_handle_t portId,
+ bool silenced) override;
virtual void toAudioPortConfig(struct audio_port_config *config);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 07f0538..fa35e5d 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -18,12 +18,14 @@
#define LOG_TAG "AudioFlinger"
//#define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_AUDIO
#include "Configuration.h"
#include <linux/futex.h>
#include <math.h>
#include <sys/syscall.h>
#include <utils/Log.h>
+#include <utils/Trace.h>
#include <private/media/AudioTrackShared.h>
@@ -1825,9 +1827,19 @@
ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
Proxy::Buffer buf;
buf.mFrameCount = buffer->frameCount;
+ if (ATRACE_ENABLED()) {
+ std::string traceName("PTnReq");
+ traceName += std::to_string(id());
+ ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+ }
status_t status = mPeerProxy->obtainBuffer(&buf, &mPeerTimeout);
ALOGV_IF(status != NO_ERROR, "%s(%d): getNextBuffer status %d", __func__, mId, status);
buffer->frameCount = buf.mFrameCount;
+ if (ATRACE_ENABLED()) {
+ std::string traceName("PTnObt");
+ traceName += std::to_string(id());
+ ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+ }
if (buf.mFrameCount == 0) {
return WOULD_BLOCK;
}
@@ -2400,6 +2412,11 @@
ALOGV_IF(status != NO_ERROR,
"%s(%d): mPeerProxy->obtainBuffer status %d", __func__, mId, status);
buffer->frameCount = buf.mFrameCount;
+ if (ATRACE_ENABLED()) {
+ std::string traceName("PRnObt");
+ traceName += std::to_string(id());
+ ATRACE_INT(traceName.c_str(), buf.mFrameCount);
+ }
if (buf.mFrameCount == 0) {
return WOULD_BLOCK;
}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 30f29d6..35126ad 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -258,7 +258,7 @@
virtual status_t getHwOffloadEncodingFormatsSupportedForA2DP(
std::vector<audio_format_t> *formats) = 0;
- virtual void setAppState(uid_t uid, app_state_t state) = 0;
+ virtual void setAppState(audio_port_handle_t portId, app_state_t state) = 0;
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index ebfba83..71d5789 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -8,7 +8,7 @@
"src/AudioPatch.cpp",
"src/AudioPolicyMix.cpp",
"src/AudioPort.cpp",
- "src/AudioProfile.cpp",
+ "src/AudioProfileVector.cpp",
"src/AudioRoute.cpp",
"src/ClientDescriptor.cpp",
"src/DeviceDescriptor.cpp",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
index a948ea9..646ef31 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioCollections.h
@@ -31,7 +31,7 @@
class AudioPortVector : public Vector<sp<AudioPort> >
{
public:
- sp<AudioPort> findByTagName(const String8 &tagName) const;
+ sp<AudioPort> findByTagName(const std::string &tagName) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 37f9d14..816498c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -97,7 +97,7 @@
RecordClientVector clientsList(bool activeOnly = false,
audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
- void setAppState(uid_t uid, app_state_t state);
+ void setAppState(audio_port_handle_t portId, app_state_t state);
// implementation of ClientMapHandler<RecordClientDescriptor>
void addClient(const sp<RecordClientDescriptor> &client) override;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 31c5041..c17f308 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -29,6 +29,7 @@
#include <AudioPolicyMix.h>
#include <EffectDescriptor.h>
#include <SoundTriggerSession.h>
+#include <media/AudioProfile.h>
namespace android {
@@ -118,9 +119,9 @@
mSource = "AudioPolicyConfig::setDefault";
mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
mDefaultOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
- mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+ mDefaultOutputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
- defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic());
+ defaultInputDevice->addAudioProfile(AudioProfile::createFullDynamic(gDynamicFormat));
sp<AudioProfile> micProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
defaultInputDevice->addAudioProfile(micProfile);
@@ -132,14 +133,14 @@
mDefaultOutputDevice->attach(module);
defaultInputDevice->attach(module);
- sp<OutputProfile> outProfile = new OutputProfile(String8("primary"));
+ sp<OutputProfile> outProfile = new OutputProfile("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 = new InputProfile(String8("primary"));
+ sp<InputProfile> inProfile = new InputProfile("primary");
inProfile->addAudioProfile(micProfile);
inProfile->addSupportedDevice(defaultInputDevice);
module->addInputProfile(inProfile);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 641cebf..c26bffc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -17,9 +17,10 @@
#pragma once
#include "AudioCollections.h"
-#include "AudioProfile.h"
+#include "AudioProfileVector.h"
#include "HandleGenerator.h"
#include <media/AudioGain.h>
+#include <media/AudioPortBase.h>
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/RefBase.h>
@@ -32,25 +33,15 @@
class HwModule;
class AudioRoute;
-class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
+class AudioPort : public virtual RefBase, public AudioPortBase<AudioProfileVector>,
+ private HandleGenerator<audio_port_handle_t>
{
public:
- AudioPort(const String8& name, audio_port_type_t type, audio_port_role_t role) :
- mName(name), mType(type), mRole(role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
+ AudioPort(const std::string& name, audio_port_type_t type, audio_port_role_t role) :
+ AudioPortBase(name, type, role), mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
virtual ~AudioPort() {}
- void setName(const String8 &name) { mName = name; }
- const String8 &getName() const { return mName; }
-
- audio_port_type_t getType() const { return mType; }
- audio_port_role_t getRole() const { return mRole; }
-
- virtual const String8 getTagName() const = 0;
-
- void setGains(const AudioGains &gains) { mGains = gains; }
- const AudioGains &getGains() const { return mGains; }
-
virtual void setFlags(uint32_t flags)
{
//force direct flag if offload flag is set: offloading implies a direct output stream
@@ -70,18 +61,9 @@
// Audio port IDs are in a different namespace than AudioFlinger unique IDs
static audio_port_handle_t getNextUniqueId();
- virtual void toAudioPort(struct audio_port *port) const;
-
virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
- void addAudioProfile(const sp<AudioProfile> &profile) { mProfiles.add(profile); }
-
- void setAudioProfiles(const AudioProfileVector &profiles) { mProfiles = profiles; }
- AudioProfileVector &getAudioProfiles() { return mProfiles; }
-
- bool hasValidAudioProfile() const { return mProfiles.hasValidProfile(); }
-
- bool hasDynamicAudioProfile() const { return mProfiles.hasDynamicProfile(); }
+ bool hasDynamicAudioProfile() const { return getAudioProfileVectorBase()->hasDynamicProfile(); }
// searches for an exact match
virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
@@ -95,10 +77,6 @@
return mProfiles.checkCompatibleProfile(samplingRate, channelMask, format, mType, mRole);
}
- void clearAudioProfiles() { return mProfiles.clearProfiles(); }
-
- status_t checkGain(const struct audio_gain_config *gainConfig, int index) const;
-
void pickAudioProfile(uint32_t &samplingRate,
audio_channel_mask_t &channelMask,
audio_format_t &format) const;
@@ -121,12 +99,6 @@
const char *getModuleName() const;
sp<HwModule> getModule() const { return mModule; }
- bool useInputChannelMask() const
- {
- return ((mType == AUDIO_PORT_TYPE_DEVICE) && (mRole == AUDIO_PORT_ROLE_SOURCE)) ||
- ((mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SINK));
- }
-
inline bool isDirectOutput() const
{
return (mType == AUDIO_PORT_TYPE_MIX) && (mRole == AUDIO_PORT_ROLE_SOURCE) &&
@@ -136,44 +108,36 @@
void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
const AudioRouteVector &getRoutes() const { return mRoutes; }
- void dump(String8 *dst, int spaces, bool verbose = true) const;
-
void log(const char* indent) const;
- AudioGains mGains; // gain controllers
-
private:
void pickChannelMask(audio_channel_mask_t &channelMask,
const ChannelMaskSet &channelMasks) const;
void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
- sp<HwModule> mModule; // audio HW module exposing this I/O stream
- String8 mName;
- audio_port_type_t mType;
- audio_port_role_t mRole;
uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
- AudioProfileVector mProfiles; // AudioProfiles supported by this port (format, Rates, Channels)
+ sp<HwModule> mModule; // audio HW module exposing this I/O stream
AudioRouteVector mRoutes; // Routes involving this port
};
-class AudioPortConfig : public virtual RefBase
+class AudioPortConfig : public AudioPortConfigBase
{
public:
status_t applyAudioPortConfig(const struct audio_port_config *config,
- struct audio_port_config *backupConfig = NULL);
+ struct audio_port_config *backupConfig = NULL) override;
+
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
- const struct audio_port_config *srcConfig = NULL) const = 0;
+ const struct audio_port_config *srcConfig = NULL) const override;
+
virtual sp<AudioPort> getAudioPort() const = 0;
+
virtual bool hasSameHwModuleAs(const sp<AudioPortConfig>& other) const {
return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
(other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
}
+
bool hasGainController(bool canUseForVolume = false) const;
- unsigned int mSamplingRate = 0u;
- audio_format_t mFormat = AUDIO_FORMAT_INVALID;
- audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
- struct audio_gain_config mGain = { .index = -1 };
union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
deleted file mode 100644
index ea56729..0000000
--- a/services/audiopolicy/common/managerdefinitions/include/AudioProfile.h
+++ /dev/null
@@ -1,141 +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 <media/AudioContainers.h>
-#include <system/audio.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-#include "policy.h"
-
-namespace android {
-
-class AudioProfile : public virtual RefBase
-{
-public:
- static sp<AudioProfile> createFullDynamic();
-
- AudioProfile(audio_format_t format, audio_channel_mask_t channelMasks, uint32_t samplingRate);
- AudioProfile(audio_format_t format,
- const ChannelMaskSet &channelMasks,
- const SampleRateSet &samplingRateCollection);
-
- audio_format_t getFormat() const { return mFormat; }
- const ChannelMaskSet &getChannels() const { return mChannelMasks; }
- const SampleRateSet &getSampleRates() const { return mSamplingRates; }
- void setChannels(const ChannelMaskSet &channelMasks);
- void setSampleRates(const SampleRateSet &sampleRates);
-
- void clear();
- bool isValid() const { return hasValidFormat() && hasValidRates() && hasValidChannels(); }
- bool supportsChannels(audio_channel_mask_t channels) const
- {
- return mChannelMasks.count(channels) != 0;
- }
- bool supportsRate(uint32_t rate) const { return mSamplingRates.count(rate) != 0; }
-
- status_t checkExact(uint32_t rate, audio_channel_mask_t channels, audio_format_t format) const;
- status_t checkCompatibleChannelMask(audio_channel_mask_t channelMask,
- audio_channel_mask_t &updatedChannelMask,
- audio_port_type_t portType,
- audio_port_role_t portRole) const;
- status_t checkCompatibleSamplingRate(uint32_t samplingRate,
- uint32_t &updatedSamplingRate) const;
-
- bool hasValidFormat() const { return mFormat != AUDIO_FORMAT_DEFAULT; }
- bool hasValidRates() const { return !mSamplingRates.empty(); }
- bool hasValidChannels() const { return !mChannelMasks.empty(); }
-
- void setDynamicChannels(bool dynamic) { mIsDynamicChannels = dynamic; }
- bool isDynamicChannels() const { return mIsDynamicChannels; }
-
- void setDynamicRate(bool dynamic) { mIsDynamicRate = dynamic; }
- bool isDynamicRate() const { return mIsDynamicRate; }
-
- void setDynamicFormat(bool dynamic) { mIsDynamicFormat = dynamic; }
- bool isDynamicFormat() const { return mIsDynamicFormat; }
-
- bool isDynamic() { return mIsDynamicFormat || mIsDynamicChannels || mIsDynamicRate; }
-
- void dump(String8 *dst, int spaces) const;
-
-private:
- String8 mName;
- audio_format_t mFormat;
- ChannelMaskSet mChannelMasks;
- SampleRateSet mSamplingRates;
-
- bool mIsDynamicFormat = false;
- bool mIsDynamicChannels = false;
- bool mIsDynamicRate = false;
-};
-
-
-class AudioProfileVector : public std::vector<sp<AudioProfile> >
-{
-public:
- ssize_t add(const sp<AudioProfile> &profile);
- // This API is intended to be used by the policy manager once retrieving capabilities
- // for a profile with dynamic format, rate and channels attributes
- ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
- void appendProfiles(const AudioProfileVector& audioProfiles) {
- insert(end(), audioProfiles.begin(), audioProfiles.end());
- }
-
- status_t checkExactProfile(uint32_t samplingRate, audio_channel_mask_t channelMask,
- audio_format_t format) const;
- status_t checkCompatibleProfile(uint32_t &samplingRate, audio_channel_mask_t &channelMask,
- audio_format_t &format,
- audio_port_type_t portType,
- audio_port_role_t portRole) const;
- void clearProfiles();
- // Assuming that this profile vector contains input profiles,
- // find the best matching config from 'outputProfiles', according to
- // the given preferences for audio formats and channel masks.
- // Note: std::vectors are used because specialized containers for formats
- // and channels can be sorted and use their own ordering.
- status_t findBestMatchingOutputConfig(const AudioProfileVector& outputProfiles,
- const std::vector<audio_format_t>& preferredFormats, // order: most pref -> least pref
- const std::vector<audio_channel_mask_t>& preferredOutputChannels,
- bool preferHigherSamplingRates,
- audio_config_base *bestOutputConfig) const;
-
- sp<AudioProfile> getFirstValidProfile() const;
- sp<AudioProfile> getFirstValidProfileFor(audio_format_t format) const;
- bool hasValidProfile() const { return getFirstValidProfile() != 0; }
-
- FormatVector getSupportedFormats() const;
- bool hasDynamicChannelsFor(audio_format_t format) const;
- bool hasDynamicFormat() const { return getProfileFor(gDynamicFormat) != 0; }
- bool hasDynamicProfile() const;
- bool hasDynamicRateFor(audio_format_t format) const;
-
- // One audio profile will be added for each format supported by Audio HAL
- void setFormats(const FormatVector &formats);
-
- void dump(String8 *dst, int spaces) const;
-
-private:
- sp<AudioProfile> getProfileFor(audio_format_t format) const;
- void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
- void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
-};
-
-bool operator == (const AudioProfile &left, const AudioProfile &right);
-
-} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h
new file mode 100644
index 0000000..2e7328d
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioProfileVector.h
@@ -0,0 +1,68 @@
+/*
+ * 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 <media/AudioProfile.h>
+#include <system/audio.h>
+
+namespace android {
+
+class AudioProfileVector : public AudioProfileVectorBase {
+public:
+ virtual ~AudioProfileVector() = default;
+
+ ssize_t add(const sp<AudioProfile> &profile) override;
+
+ // This API is intended to be used by the policy manager once retrieving capabilities
+ // for a profile with dynamic format, rate and channels attributes
+ ssize_t addProfileFromHal(const sp<AudioProfile> &profileToAdd);
+ void appendProfiles(const AudioProfileVectorBase& audioProfiles) {
+ insert(end(), audioProfiles.begin(), audioProfiles.end());
+ }
+
+ status_t checkExactProfile(const uint32_t samplingRate,
+ audio_channel_mask_t channelMask,
+ audio_format_t format) const;
+
+ status_t checkCompatibleProfile(uint32_t &samplingRate,
+ audio_channel_mask_t &channelMask,
+ audio_format_t &format,
+ audio_port_type_t portType,
+ audio_port_role_t portRole) const;
+
+ // Assuming that this profile vector contains input profiles,
+ // find the best matching config from 'outputProfiles', according to
+ // the given preferences for audio formats and channel masks.
+ // Note: std::vectors are used because specialized containers for formats
+ // and channels can be sorted and use their own ordering.
+ status_t findBestMatchingOutputConfig(
+ const AudioProfileVector &outputProfiles,
+ const std::vector<audio_format_t> &preferredFormats, // order: most pref -> least pref
+ const std::vector<audio_channel_mask_t> &preferredOutputChannels,
+ bool preferHigherSamplingRates,
+ audio_config_base *bestOutputConfig) const;
+
+ // One audio profile will be added for each format supported by Audio HAL
+ void setFormats(const FormatVector &formats);
+
+private:
+ sp<AudioProfile> getProfileFor(audio_format_t format) const;
+ void setSampleRatesFor(const SampleRateSet &sampleRates, audio_format_t format);
+ void setChannelsFor(const ChannelMaskSet &channelMasks, audio_format_t format);
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index c7c1fee..c2f1d93 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -30,13 +30,13 @@
{
public:
// Note that empty name refers by convention to a generic device.
- explicit DeviceDescriptor(audio_devices_t type, const String8 &tagName = String8(""));
+ explicit DeviceDescriptor(audio_devices_t type, const std::string &tagName = "");
DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
- const String8 &tagName = String8(""));
+ const std::string &tagName = "");
virtual ~DeviceDescriptor() {}
- virtual const String8 getTagName() const { return mTagName; }
+ virtual const std::string getTagName() const { return mTagName; }
audio_devices_t type() const { return mDeviceType; }
String8 address() const { return mAddress; }
@@ -75,7 +75,7 @@
private:
String8 mAddress{""};
- String8 mTagName; // Unique human readable identifier for a device port found in conf file.
+ std::string mTagName; // Unique human readable identifier for a device port found in conf file.
audio_devices_t mDeviceType;
FormatVector mEncodedFormats;
audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
@@ -112,7 +112,7 @@
* equal to AUDIO_PORT_HANDLE_NONE, it also returns a nullptr.
*/
sp<DeviceDescriptor> getDeviceFromId(audio_port_handle_t id) const;
- sp<DeviceDescriptor> getDeviceFromTagName(const String8 &tagName) const;
+ sp<DeviceDescriptor> getDeviceFromTagName(const std::string &tagName) const;
DeviceVector getDevicesFromHwModule(audio_module_handle_t moduleHandle) const;
audio_devices_t getDeviceTypesFromHwModule(audio_module_handle_t moduleHandle) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index eb34da4..65c886a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -82,17 +82,17 @@
status_t addInputProfile(const sp<IOProfile> &profile);
status_t addProfile(const sp<IOProfile> &profile);
- status_t addOutputProfile(const String8& name, const audio_config_t *config,
+ status_t addOutputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address);
- status_t removeOutputProfile(const String8& name);
- status_t addInputProfile(const String8& name, const audio_config_t *config,
+ status_t removeOutputProfile(const std::string& name);
+ status_t addInputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address);
- status_t removeInputProfile(const String8& name);
+ status_t removeInputProfile(const std::string& name);
audio_module_handle_t getHandle() const { return mHandle; }
void setHandle(audio_module_handle_t handle);
- sp<AudioPort> findPortByTagName(const String8 &tagName) const
+ sp<AudioPort> findPortByTagName(const std::string &tagName) const
{
return mPorts.findByTagName(tagName);
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index e0b56d4..419dd35 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -18,6 +18,7 @@
#include "AudioPort.h"
#include "DeviceDescriptor.h"
+#include "policy.h"
#include <utils/String8.h>
#include <system/audio.h>
@@ -33,7 +34,7 @@
class IOProfile : public AudioPort
{
public:
- IOProfile(const String8 &name, audio_port_role_t role)
+ IOProfile(const std::string &name, audio_port_role_t role)
: AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
maxOpenCount(1),
curOpenCount(0),
@@ -41,7 +42,7 @@
curActiveCount(0) {}
// For a Profile aka MixPort, tag name and name are equivalent.
- virtual const String8 getTagName() const { return getName(); }
+ virtual const std::string getTagName() const { return getName(); }
// FIXME: this is needed because shared MMAP stream clients use the same audio session.
// Once capture clients are tracked individually and not per session this can be removed
@@ -183,13 +184,13 @@
class InputProfile : public IOProfile
{
public:
- explicit InputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
+ explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
};
class OutputProfile : public IOProfile
{
public:
- explicit OutputProfile(const String8 &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
+ explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
index e8cf485..b391a09 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioCollections.cpp
@@ -24,7 +24,7 @@
namespace android {
-sp<AudioPort> AudioPortVector::findByTagName(const String8 &tagName) const
+sp<AudioPort> AudioPortVector::findByTagName(const std::string &tagName) const
{
for (const auto& port : *this) {
if (port->getTagName() == tagName) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index a9b87e3..5813937 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -34,8 +34,8 @@
{
if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
- if (profile->mGains.size() > 0) {
- profile->mGains[0]->getDefaultConfig(&mGain);
+ if (profile->getGains().size() > 0) {
+ profile->getGains()[0]->getDefaultConfig(&mGain);
}
}
}
@@ -212,7 +212,7 @@
mDevice = device;
ALOGV("opening input for device %s profile %p name %s",
- mDevice->toString().c_str(), mProfile.get(), mProfile->getName().string());
+ mDevice->toString().c_str(), mProfile.get(), mProfile->getName().c_str());
audio_devices_t deviceType = mDevice->type();
@@ -450,13 +450,13 @@
return enabledEffects;
}
-void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state)
+void AudioInputDescriptor::setAppState(audio_port_handle_t portId, app_state_t state)
{
RecordClientVector clients = clientsList(false /*activeOnly*/);
RecordClientVector updatedClients;
for (const auto& client : clients) {
- if (uid == client->uid()) {
+ if (portId == client->portId()) {
bool wasSilenced = client->isSilenced();
client->setAppState(state);
if (client->active() && wasSilenced != client->isSilenced()) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 49524b0..6f0c3f5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -40,8 +40,8 @@
{
if (mPort.get() != nullptr) {
mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
- if (mPort->mGains.size() > 0) {
- mPort->mGains[0]->getDefaultConfig(&mGain);
+ if (mPort->getGains().size() > 0) {
+ mPort->getGains()[0]->getDefaultConfig(&mGain);
}
}
}
@@ -483,7 +483,7 @@
mFlags = (audio_output_flags_t)(mFlags | flags);
ALOGV("opening output for device %s profile %p name %s",
- mDevices.toString().c_str(), mProfile.get(), mProfile->getName().string());
+ mDevices.toString().c_str(), mProfile.get(), mProfile->getName().c_str());
status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
output,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index ff32284..decfad1 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -30,7 +30,7 @@
// --- AudioPort class implementation
void AudioPort::attach(const sp<HwModule>& module)
{
- ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.string());
+ ALOGV("%s: attaching module %s to port %s", __FUNCTION__, getModuleName(), mName.c_str());
mModule = module;
}
@@ -60,49 +60,6 @@
return mModule != 0 ? mModule->getName() : "invalid module";
}
-void AudioPort::toAudioPort(struct audio_port *port) const
-{
- // TODO: update this function once audio_port structure reflects the new profile definition.
- // For compatibility reason: flatening the AudioProfile into audio_port structure.
- FormatSet flatenedFormats;
- SampleRateSet flatenedRates;
- ChannelMaskSet flatenedChannels;
- for (const auto& profile : mProfiles) {
- if (profile->isValid()) {
- audio_format_t formatToExport = profile->getFormat();
- const SampleRateSet &ratesToExport = profile->getSampleRates();
- const ChannelMaskSet &channelsToExport = profile->getChannels();
-
- flatenedFormats.insert(formatToExport);
- flatenedRates.insert(ratesToExport.begin(), ratesToExport.end());
- flatenedChannels.insert(channelsToExport.begin(), channelsToExport.end());
-
- if (flatenedRates.size() > AUDIO_PORT_MAX_SAMPLING_RATES ||
- flatenedChannels.size() > AUDIO_PORT_MAX_CHANNEL_MASKS ||
- flatenedFormats.size() > AUDIO_PORT_MAX_FORMATS) {
- ALOGE("%s: bailing out: cannot export profiles to port config", __FUNCTION__);
- return;
- }
- }
- }
- port->role = mRole;
- port->type = mType;
- strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
- port->num_sample_rates = flatenedRates.size();
- port->num_channel_masks = flatenedChannels.size();
- port->num_formats = flatenedFormats.size();
- std::copy(flatenedRates.begin(), flatenedRates.end(), port->sample_rates);
- std::copy(flatenedChannels.begin(), flatenedChannels.end(), port->channel_masks);
- std::copy(flatenedFormats.begin(), flatenedFormats.end(), port->formats);
-
- ALOGV("AudioPort::toAudioPort() num gains %zu", mGains.size());
-
- port->num_gains = std::min(mGains.size(), (size_t) AUDIO_PORT_MAX_GAINS);
- for (size_t i = 0; i < port->num_gains; i++) {
- port->gains[i] = mGains[i]->getGain();
- }
-}
-
void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{
for (const auto& profileToImport : port->mProfiles) {
@@ -324,40 +281,13 @@
}
}
}
- ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.string(),
+ ALOGV("%s Port[nm:%s] profile rate=%d, format=%d, channels=%d", __FUNCTION__, mName.c_str(),
samplingRate, channelMask, format);
}
-status_t AudioPort::checkGain(const struct audio_gain_config *gainConfig, int index) const
-{
- if (index < 0 || (size_t)index >= mGains.size()) {
- return BAD_VALUE;
- }
- return mGains[index]->checkConfig(gainConfig);
-}
-
-void AudioPort::dump(String8 *dst, int spaces, bool verbose) const
-{
- if (!mName.isEmpty()) {
- dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
- }
- if (verbose) {
- mProfiles.dump(dst, spaces);
-
- if (mGains.size() != 0) {
- dst->appendFormat("%*s- gains:\n", spaces, "");
- for (size_t i = 0; i < mGains.size(); i++) {
- std::string gainStr;
- mGains[i]->dump(&gainStr, spaces + 2, i);
- dst->append(gainStr.c_str());
- }
- }
- }
-}
-
void AudioPort::log(const char* indent) const
{
- ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.string(), mType, mRole);
+ ALOGI("%s Port[nm:%s, type:%d, role:%d]", indent, mName.c_str(), mType, mRole);
}
// --- AudioPortConfig class implementation
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
similarity index 70%
rename from services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
rename to services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
index d1082e8..c17df37 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVector.cpp
@@ -26,95 +26,31 @@
#include <utils/Errors.h>
#include "AudioPort.h"
-#include "AudioProfile.h"
+#include "AudioProfileVector.h"
#include "HwModule.h"
-#include "TypeConverter.h"
+#include "policy.h"
namespace android {
-bool operator == (const AudioProfile &left, const AudioProfile &compareTo)
+status_t checkExact(const sp<AudioProfile> &audioProfile, uint32_t samplingRate,
+ audio_channel_mask_t channelMask, audio_format_t format)
{
- return (left.getFormat() == compareTo.getFormat()) &&
- (left.getChannels() == compareTo.getChannels()) &&
- (left.getSampleRates() == compareTo.getSampleRates());
-}
-
-static AudioProfile* createFullDynamicImpl()
-{
- AudioProfile* dynamicProfile = new AudioProfile(gDynamicFormat,
- ChannelMaskSet(), SampleRateSet());
- dynamicProfile->setDynamicFormat(true);
- dynamicProfile->setDynamicChannels(true);
- dynamicProfile->setDynamicRate(true);
- return dynamicProfile;
-}
-
-// static
-sp<AudioProfile> AudioProfile::createFullDynamic()
-{
- static sp<AudioProfile> dynamicProfile = createFullDynamicImpl();
- return dynamicProfile;
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
- audio_channel_mask_t channelMasks,
- uint32_t samplingRate) :
- mName(String8("")),
- mFormat(format)
-{
- mChannelMasks.insert(channelMasks);
- mSamplingRates.insert(samplingRate);
-}
-
-AudioProfile::AudioProfile(audio_format_t format,
- const ChannelMaskSet &channelMasks,
- const SampleRateSet &samplingRateCollection) :
- mName(String8("")),
- mFormat(format),
- mChannelMasks(channelMasks),
- mSamplingRates(samplingRateCollection) {}
-
-void AudioProfile::setChannels(const ChannelMaskSet &channelMasks)
-{
- if (mIsDynamicChannels) {
- mChannelMasks = channelMasks;
- }
-}
-
-void AudioProfile::setSampleRates(const SampleRateSet &sampleRates)
-{
- if (mIsDynamicRate) {
- mSamplingRates = sampleRates;
- }
-}
-
-void AudioProfile::clear()
-{
- if (mIsDynamicChannels) {
- mChannelMasks.clear();
- }
- if (mIsDynamicRate) {
- mSamplingRates.clear();
- }
-}
-
-status_t AudioProfile::checkExact(uint32_t samplingRate, audio_channel_mask_t channelMask,
- audio_format_t format) const
-{
- if (audio_formats_match(format, mFormat) &&
- supportsChannels(channelMask) &&
- supportsRate(samplingRate)) {
+ if (audio_formats_match(format, audioProfile->getFormat()) &&
+ audioProfile->supportsChannels(channelMask) &&
+ audioProfile->supportsRate(samplingRate)) {
return NO_ERROR;
}
return BAD_VALUE;
}
-status_t AudioProfile::checkCompatibleSamplingRate(uint32_t samplingRate,
- uint32_t &updatedSamplingRate) const
+status_t checkCompatibleSamplingRate(const sp<AudioProfile> &audioProfile,
+ uint32_t samplingRate,
+ uint32_t &updatedSamplingRate)
{
ALOG_ASSERT(samplingRate > 0);
- if (mSamplingRates.empty()) {
+ const SampleRateSet sampleRates = audioProfile->getSampleRates();
+ if (sampleRates.empty()) {
updatedSamplingRate = samplingRate;
return NO_ERROR;
}
@@ -122,17 +58,17 @@
// Search for the closest supported sampling rate that is above (preferred)
// or below (acceptable) the desired sampling rate, within a permitted ratio.
// The sampling rates are sorted in ascending order.
- auto desiredRate = mSamplingRates.lower_bound(samplingRate);
+ auto desiredRate = sampleRates.lower_bound(samplingRate);
// Prefer to down-sample from a higher sampling rate, as we get the desired frequency spectrum.
- if (desiredRate != mSamplingRates.end()) {
+ if (desiredRate != sampleRates.end()) {
if (*desiredRate / AUDIO_RESAMPLER_DOWN_RATIO_MAX <= samplingRate) {
updatedSamplingRate = *desiredRate;
return NO_ERROR;
}
}
// But if we have to up-sample from a lower sampling rate, that's OK.
- if (desiredRate != mSamplingRates.begin()) {
+ if (desiredRate != sampleRates.begin()) {
uint32_t candidate = *(--desiredRate);
if (candidate * AUDIO_RESAMPLER_UP_RATIO_MAX >= samplingRate) {
updatedSamplingRate = candidate;
@@ -143,12 +79,14 @@
return BAD_VALUE;
}
-status_t AudioProfile::checkCompatibleChannelMask(audio_channel_mask_t channelMask,
- audio_channel_mask_t &updatedChannelMask,
- audio_port_type_t portType,
- audio_port_role_t portRole) const
+status_t checkCompatibleChannelMask(const sp<AudioProfile> &audioProfile,
+ audio_channel_mask_t channelMask,
+ audio_channel_mask_t &updatedChannelMask,
+ audio_port_type_t portType,
+ audio_port_role_t portRole)
{
- if (mChannelMasks.empty()) {
+ const ChannelMaskSet channelMasks = audioProfile->getChannels();
+ if (channelMasks.empty()) {
updatedChannelMask = channelMask;
return NO_ERROR;
}
@@ -157,7 +95,7 @@
== AUDIO_CHANNEL_REPRESENTATION_INDEX;
const uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
int bestMatch = 0;
- for (const auto &supported : mChannelMasks) {
+ for (const auto &supported : channelMasks) {
if (supported == channelMask) {
// Exact matches always taken.
updatedChannelMask = channelMask;
@@ -235,37 +173,6 @@
return bestMatch > 0 ? NO_ERROR : BAD_VALUE;
}
-void AudioProfile::dump(String8 *dst, int spaces) const
-{
- dst->appendFormat("%s%s%s\n", mIsDynamicFormat ? "[dynamic format]" : "",
- mIsDynamicChannels ? "[dynamic channels]" : "",
- mIsDynamicRate ? "[dynamic rates]" : "");
- if (mName.length() != 0) {
- dst->appendFormat("%*s- name: %s\n", spaces, "", mName.string());
- }
- std::string formatLiteral;
- if (FormatConverter::toString(mFormat, formatLiteral)) {
- dst->appendFormat("%*s- format: %s\n", spaces, "", formatLiteral.c_str());
- }
- if (!mSamplingRates.empty()) {
- dst->appendFormat("%*s- sampling rates:", spaces, "");
- for (auto it = mSamplingRates.begin(); it != mSamplingRates.end();) {
- dst->appendFormat("%d", *it);
- dst->append(++it == mSamplingRates.end() ? "" : ", ");
- }
- dst->append("\n");
- }
-
- if (!mChannelMasks.empty()) {
- dst->appendFormat("%*s- channel masks:", spaces, "");
- for (auto it = mChannelMasks.begin(); it != mChannelMasks.end();) {
- dst->appendFormat("0x%04x", *it);
- dst->append(++it == mChannelMasks.end() ? "" : ", ");
- }
- dst->append("\n");
- }
-}
-
ssize_t AudioProfileVector::add(const sp<AudioProfile> &profile)
{
ssize_t index = size();
@@ -311,7 +218,7 @@
return add(profileToAdd);
}
-status_t AudioProfileVector::checkExactProfile(uint32_t samplingRate,
+status_t AudioProfileVector::checkExactProfile(const uint32_t samplingRate,
audio_channel_mask_t channelMask,
audio_format_t format) const
{
@@ -320,7 +227,7 @@
}
for (const auto& profile : *this) {
- if (profile->checkExact(samplingRate, channelMask, format) == NO_ERROR) {
+ if (checkExact(profile, samplingRate, channelMask, format) == NO_ERROR) {
return NO_ERROR;
}
}
@@ -353,9 +260,9 @@
// rate and channels as well
audio_channel_mask_t updatedChannels;
uint32_t updatedRate;
- if (profile->checkCompatibleChannelMask(channelMask, updatedChannels,
- portType, portRole) == NO_ERROR &&
- profile->checkCompatibleSamplingRate(samplingRate, updatedRate) == NO_ERROR) {
+ if (checkCompatibleChannelMask(profile, channelMask, updatedChannels,
+ portType, portRole) == NO_ERROR &&
+ checkCompatibleSamplingRate(profile, samplingRate, updatedRate) == NO_ERROR) {
// for inexact checks we take the first linear pcm format due to sorting.
format = formatToCompare;
channelMask = updatedChannels;
@@ -367,18 +274,6 @@
return BAD_VALUE;
}
-void AudioProfileVector::clearProfiles()
-{
- for (auto it = begin(); it != end();) {
- if ((*it)->isDynamicFormat() && (*it)->hasValidFormat()) {
- it = erase(it);
- } else {
- (*it)->clear();
- ++it;
- }
- }
-}
-
// Returns an intersection between two possibly unsorted vectors and the contents of 'order'.
// The result is ordered according to 'order'.
template<typename T, typename Order>
@@ -449,67 +344,6 @@
return BAD_VALUE;
}
-sp<AudioProfile> AudioProfileVector::getFirstValidProfile() const
-{
- for (const auto &profile : *this) {
- if (profile->isValid()) {
- return profile;
- }
- }
- return nullptr;
-}
-
-sp<AudioProfile> AudioProfileVector::getFirstValidProfileFor(audio_format_t format) const
-{
- for (const auto &profile : *this) {
- if (profile->isValid() && profile->getFormat() == format) {
- return profile;
- }
- }
- return nullptr;
-}
-
-FormatVector AudioProfileVector::getSupportedFormats() const
-{
- FormatVector supportedFormats;
- for (const auto &profile : *this) {
- if (profile->hasValidFormat()) {
- supportedFormats.push_back(profile->getFormat());
- }
- }
- return supportedFormats;
-}
-
-bool AudioProfileVector::hasDynamicChannelsFor(audio_format_t format) const
-{
- for (const auto &profile : *this) {
- if (profile->getFormat() == format && profile->isDynamicChannels()) {
- return true;
- }
- }
- return false;
-}
-
-bool AudioProfileVector::hasDynamicProfile() const
-{
- for (const auto &profile : *this) {
- if (profile->isDynamic()) {
- return true;
- }
- }
- return false;
-}
-
-bool AudioProfileVector::hasDynamicRateFor(audio_format_t format) const
-{
- for (const auto &profile : *this) {
- if (profile->getFormat() == format && profile->isDynamicRate()) {
- return true;
- }
- }
- return false;
-}
-
void AudioProfileVector::setFormats(const FormatVector &formats)
{
// Only allow to change the format of dynamic profile
@@ -528,15 +362,6 @@
}
}
-void AudioProfileVector::dump(String8 *dst, int spaces) const
-{
- dst->appendFormat("%*s- Profiles:\n", spaces, "");
- for (size_t i = 0; i < size(); i++) {
- dst->appendFormat("%*sProfile %zu:", spaces + 4, "", i);
- at(i)->dump(dst, spaces + 8);
- }
-}
-
sp<AudioProfile> AudioProfileVector::getProfileFor(audio_format_t format) const
{
for (const auto &profile : *this) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
index 92cbe4e..0f35ff8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioRoute.cpp
@@ -26,11 +26,11 @@
void AudioRoute::dump(String8 *dst, int spaces) const
{
dst->appendFormat("%*s- Type: %s\n", spaces, "", mType == AUDIO_ROUTE_MUX ? "Mux" : "Mix");
- dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().string());
+ dst->appendFormat("%*s- Sink: %s\n", spaces, "", mSink->getTagName().c_str());
if (mSources.size() != 0) {
dst->appendFormat("%*s- Sources: \n", spaces, "");
for (size_t i = 0; i < mSources.size(); i++) {
- dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().string());
+ dst->appendFormat("%*s%s \n", spaces + 4, "", mSources[i]->getTagName().c_str());
}
}
dst->append("\n");
@@ -41,10 +41,10 @@
if (mSink == 0 || dstPort == 0 || dstPort != mSink) {
return false;
}
- ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().string());
+ ALOGV("%s: sinks %s matching", __FUNCTION__, mSink->getTagName().c_str());
for (const auto &sourcePort : mSources) {
if (sourcePort == srcPort) {
- ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().string());
+ ALOGV("%s: sources %s matching", __FUNCTION__, sourcePort->getTagName().c_str());
return true;
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index e395caa..018636d 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -26,14 +26,14 @@
namespace android {
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const String8 &tagName) :
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagName) :
DeviceDescriptor(type, FormatVector{}, tagName)
{
}
DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
- const String8 &tagName) :
- AudioPort(String8(""), AUDIO_PORT_TYPE_DEVICE,
+ const std::string &tagName) :
+ AudioPort("", AUDIO_PORT_TYPE_DEVICE,
audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
AUDIO_PORT_ROLE_SOURCE),
mTagName(tagName), mDeviceType(type), mEncodedFormats(encodedFormats)
@@ -262,7 +262,7 @@
return devices;
}
-sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const String8 &tagName) const
+sp<DeviceDescriptor> DeviceVector::getDeviceFromTagName(const std::string &tagName) const
{
for (const auto& device : *this) {
if (device->getTagName() == tagName) {
@@ -374,8 +374,8 @@
if (mId != 0) {
dst->appendFormat("%*s- id: %2d\n", spaces, "", mId);
}
- if (!mTagName.isEmpty()) {
- dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.string());
+ if (!mTagName.empty()) {
+ dst->appendFormat("%*s- tag name: %s\n", spaces, "", mTagName.c_str());
}
dst->appendFormat("%*s- type: %-48s\n", spaces, "", ::android::toString(mDeviceType).c_str());
@@ -383,7 +383,9 @@
if (mAddress.size() != 0) {
dst->appendFormat("%*s- address: %-32s\n", spaces, "", mAddress.string());
}
- AudioPort::dump(dst, spaces, verbose);
+ std::string portStr;
+ AudioPort::dump(&portStr, spaces, verbose);
+ dst->append(portStr.c_str());
}
std::string DeviceDescriptor::toString() const
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 99e282e..c232775 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -41,7 +41,7 @@
}
}
-status_t HwModule::addOutputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addOutputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address)
{
sp<IOProfile> profile = new OutputProfile(name);
@@ -95,7 +95,7 @@
}
}
-status_t HwModule::removeOutputProfile(const String8& name)
+status_t HwModule::removeOutputProfile(const std::string& name)
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
if (mOutputProfiles[i]->getName() == name) {
@@ -110,7 +110,7 @@
return NO_ERROR;
}
-status_t HwModule::addInputProfile(const String8& name, const audio_config_t *config,
+status_t HwModule::addInputProfile(const std::string& name, const audio_config_t *config,
audio_devices_t device, const String8& address)
{
sp<IOProfile> profile = new InputProfile(name);
@@ -125,12 +125,12 @@
profile->addSupportedDevice(devDesc);
ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
- name.string(), config->sample_rate, config->channel_mask);
+ name.c_str(), config->sample_rate, config->channel_mask);
return addInputProfile(profile);
}
-status_t HwModule::removeInputProfile(const String8& name)
+status_t HwModule::removeInputProfile(const std::string& name)
{
for (size_t i = 0; i < mInputProfiles.size(); i++) {
if (mInputProfiles[i]->getName() == name) {
@@ -193,13 +193,13 @@
}
DeviceVector sourceDevicesForRoute = getRouteSourceDevices(route);
if (sourceDevicesForRoute.isEmpty()) {
- ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+ ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
continue;
}
sourceDevices.add(sourceDevicesForRoute);
}
if (sourceDevices.isEmpty()) {
- ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
+ ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().c_str());
continue;
}
stream->setSupportedDevices(sourceDevices);
@@ -214,7 +214,7 @@
}
sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(route);
if (sinkDevice == 0) {
- ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string());
+ ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().c_str());
continue;
}
sinkDevices.add(sinkDevice);
@@ -335,7 +335,7 @@
if (allowToCreate) {
moduleDevice->attach(hwModule);
moduleDevice->setAddress(devAddress);
- moduleDevice->setName(String8(name));
+ moduleDevice->setName(name);
}
return moduleDevice;
}
@@ -359,8 +359,8 @@
address);
return nullptr;
}
- sp<DeviceDescriptor> device = new DeviceDescriptor(type, String8(name));
- device->setName(String8(name));
+ sp<DeviceDescriptor> device = new DeviceDescriptor(type, name);
+ device->setName(name);
device->setAddress(String8(address));
device->setEncodedFormat(encodedFormat);
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 5662dcf..bf1a0f7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -78,7 +78,10 @@
}
}
- if (isPlaybackThread && (getFlags() & flags) != flags) {
+ const uint32_t mustMatchOutputFlags =
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ if (isPlaybackThread && (((getFlags() ^ flags) & mustMatchOutputFlags)
+ || (getFlags() & flags) != flags)) {
return false;
}
// The only input flag that is allowed to be different is the fast flag.
@@ -104,7 +107,9 @@
void IOProfile::dump(String8 *dst) const
{
- AudioPort::dump(dst, 4);
+ std::string portStr;
+ AudioPort::dump(&portStr, 4);
+ dst->append(portStr.c_str());
dst->appendFormat(" - flags: 0x%04x", getFlags());
std::string flagsLiteral;
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index c699aa7..707169b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -430,7 +430,7 @@
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
- Element mixPort = new IOProfile(String8(name.c_str()), portRole);
+ Element mixPort = new IOProfile(name, portRole);
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
@@ -438,7 +438,7 @@
return Status::fromStatusT(status);
}
if (profiles.empty()) {
- profiles.add(AudioProfile::createFullDynamic());
+ profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
mixPort->setAudioProfiles(profiles);
@@ -508,7 +508,7 @@
if (!encodedFormatsLiteral.empty()) {
encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
}
- Element deviceDesc = new DeviceDescriptor(type, encodedFormats, String8(name.c_str()));
+ Element deviceDesc = new DeviceDescriptor(type, encodedFormats, name);
std::string address = getXmlAttribute(cur, Attributes::address);
if (!address.empty()) {
@@ -522,7 +522,7 @@
return Status::fromStatusT(status);
}
if (profiles.empty()) {
- profiles.add(AudioProfile::createFullDynamic());
+ profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
}
deviceDesc->setAudioProfiles(profiles);
@@ -532,7 +532,7 @@
return Status::fromStatusT(status);
}
ALOGV("%s: adding device tag %s type %08x address %s", __func__,
- deviceDesc->getName().string(), type, deviceDesc->address().string());
+ deviceDesc->getName().c_str(), type, deviceDesc->address().string());
return deviceDesc;
}
@@ -555,7 +555,7 @@
return Status::fromStatusT(BAD_VALUE);
}
// Convert Sink name to port pointer
- sp<AudioPort> sink = ctx->findPortByTagName(String8(sinkAttr.c_str()));
+ sp<AudioPort> sink = ctx->findPortByTagName(sinkAttr);
if (sink == NULL) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
return Status::fromStatusT(BAD_VALUE);
@@ -574,7 +574,7 @@
char *devTag = strtok(sourcesLiteral.get(), ",");
while (devTag != NULL) {
if (strlen(devTag) != 0) {
- sp<AudioPort> source = ctx->findPortByTagName(String8(devTag));
+ sp<AudioPort> source = ctx->findPortByTagName(devTag);
if (source == NULL) {
ALOGE("%s: no source found with name=%s", __func__, devTag);
return Status::fromStatusT(BAD_VALUE);
@@ -648,7 +648,7 @@
ALOGV("%s: %s %s=%s", __func__, tag, childAttachedDeviceTag,
reinterpret_cast<const char*>(attachedDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().
- getDeviceFromTagName(String8(reinterpret_cast<const char*>(
+ getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
ctx->addAvailableDevice(device);
}
@@ -663,7 +663,7 @@
ALOGV("%s: %s %s=%s", __func__, tag, childDefaultOutputDeviceTag,
reinterpret_cast<const char*>(defaultOutputDevice.get()));
sp<DeviceDescriptor> device = module->getDeclaredDevices().getDeviceFromTagName(
- String8(reinterpret_cast<const char*>(defaultOutputDevice.get())));
+ std::string(reinterpret_cast<const char*>(defaultOutputDevice.get())));
if (device != 0 && ctx->getDefaultOutputDevice() == 0) {
ctx->setDefaultOutputDevice(device);
ALOGV("%s: default is %08x",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index cbc46d5..b895c2f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -342,7 +342,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);
- if (desc->isActive() && !audio_is_linear_pcm(desc->mFormat)) {
+ if (desc->isActive() && !audio_is_linear_pcm(desc->getFormat())) {
availableOutputDevices.remove(desc->devices().getDevicesFromTypeMask(
AUDIO_DEVICE_OUT_HDMI | AUDIO_DEVICE_OUT_SPDIF
| AUDIO_DEVICE_OUT_HDMI_ARC));
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 499fc8a..1f8ceec 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1205,9 +1205,9 @@
if (!desc->isDuplicated() && (profile == desc->mProfile)) {
// reuse direct output if currently open by the same client
// and configured with same parameters
- if ((config->sample_rate == desc->mSamplingRate) &&
- (config->format == desc->mFormat) &&
- (channelMask == desc->mChannelMask) &&
+ if ((config->sample_rate == desc->getSamplingRate()) &&
+ (config->format == desc->getFormat()) &&
+ (channelMask == desc->getChannelMask()) &&
(session == desc->mDirectClientSession)) {
desc->mDirectOpenCount++;
ALOGI("%s reusing direct output %d for session %d", __func__,
@@ -1247,13 +1247,13 @@
// 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) ||
- (channelMask != 0 && channelMask != outputDesc->mChannelMask)) {
+ (config->sample_rate != 0 && config->sample_rate != outputDesc->getSamplingRate()) ||
+ (config->format != AUDIO_FORMAT_DEFAULT && config->format != outputDesc->getFormat()) ||
+ (channelMask != 0 && channelMask != outputDesc->getChannelMask())) {
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,
- channelMask, outputDesc->mChannelMask);
+ outputDesc->getSamplingRate(), config->format, outputDesc->getFormat(),
+ channelMask, outputDesc->getChannelMask());
if (output != AUDIO_IO_HANDLE_NONE) {
outputDesc->close();
}
@@ -1524,13 +1524,13 @@
// If haptic channel is specified, use the haptic output if present.
// When using haptic output, same audio format and sample rate are required.
const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
- outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
+ outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
continue;
}
if (outputHapticChannelCount >= hapticChannelCount
- && format == outputDesc->mFormat
- && samplingRate == outputDesc->mSamplingRate) {
+ && format == outputDesc->getFormat()
+ && samplingRate == outputDesc->getSamplingRate()) {
currentMatchCriteria[0] = outputHapticChannelCount;
}
@@ -1538,12 +1538,13 @@
currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);
// channel mask and channel count match
- uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask);
+ uint32_t outputChannelCount = audio_channel_count_from_out_mask(
+ outputDesc->getChannelMask());
if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
channelCount <= outputChannelCount) {
if ((audio_channel_mask_get_representation(channelMask) ==
- audio_channel_mask_get_representation(outputDesc->mChannelMask)) &&
- ((channelMask & outputDesc->mChannelMask) == channelMask)) {
+ audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
+ ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
currentMatchCriteria[2] = outputChannelCount;
}
currentMatchCriteria[3] = outputChannelCount;
@@ -1551,8 +1552,8 @@
// sampling rate match
if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
- samplingRate <= outputDesc->mSamplingRate) {
- currentMatchCriteria[4] = outputDesc->mSamplingRate;
+ samplingRate <= outputDesc->getSamplingRate()) {
+ currentMatchCriteria[4] = outputDesc->getSamplingRate();
}
// performance flags match
@@ -1562,7 +1563,7 @@
if (format != AUDIO_FORMAT_INVALID) {
currentMatchCriteria[6] =
AudioPort::kFormatDistanceMax -
- AudioPort::formatDistance(format, outputDesc->mFormat);
+ AudioPort::formatDistance(format, outputDesc->getFormat());
}
// primary output match
@@ -2921,9 +2922,9 @@
// stereo and let audio flinger do the channel conversion if needed.
outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
- rSubmixModule->addOutputProfile(address, &outputConfig,
+ rSubmixModule->addOutputProfile(address.c_str(), &outputConfig,
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
- rSubmixModule->addInputProfile(address, &inputConfig,
+ rSubmixModule->addInputProfile(address.c_str(), &inputConfig,
AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
@@ -3019,8 +3020,8 @@
}
}
}
- rSubmixModule->removeOutputProfile(address);
- rSubmixModule->removeInputProfile(address);
+ rSubmixModule->removeOutputProfile(address.c_str());
+ rSubmixModule->removeInputProfile(address.c_str());
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
@@ -3232,7 +3233,7 @@
ALOGV("%s() profile %sfound with name: %s, "
"sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x",
__FUNCTION__, profile != 0 ? "" : "NOT ",
- (profile != 0 ? profile->getTagName().string() : "null"),
+ (profile != 0 ? profile->getTagName().c_str() : "null"),
config.sample_rate, config.format, config.channel_mask, output_flags);
return (profile != 0);
}
@@ -3896,7 +3897,7 @@
if (srcDevice->hasSameHwModuleAs(sinkDevice) &&
srcDevice->getModuleVersionMajor() >= 3 &&
sinkDevice->getModule()->supportsPatch(srcDevice, sinkDevice) &&
- srcDevice->getAudioPort()->mGains.size() > 0) {
+ srcDevice->getAudioPort()->getGains().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
@@ -4136,7 +4137,7 @@
for (size_t i = 0; i < hdmiOutputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiOutputDevices[i]->address();
- String8 name = hdmiOutputDevices[i]->getName();
+ std::string name = hdmiOutputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
@@ -4158,7 +4159,7 @@
for (size_t i = 0; i < hdmiInputDevices.size(); i++) {
// Simulate reconnection to update enabled surround sound formats.
String8 address = hdmiInputDevices[i]->address();
- String8 name = hdmiInputDevices[i]->getName();
+ std::string name = hdmiInputDevices[i]->getName();
status_t status = setDeviceConnectionStateInt(AUDIO_DEVICE_IN_HDMI,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
address.c_str(),
@@ -4183,11 +4184,11 @@
return profileUpdated ? NO_ERROR : INVALID_OPERATION;
}
-void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
+void AudioPolicyManager::setAppState(audio_port_handle_t portId, app_state_t state)
{
- ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
+ ALOGV("%s(portId:%d, state:%d)", __func__, portId, state);
for (size_t i = 0; i < mInputs.size(); i++) {
- mInputs.valueAt(i)->setAppState(uid, state);
+ mInputs.valueAt(i)->setAppState(portId, state);
}
}
@@ -4641,7 +4642,7 @@
}
ALOGV("opening output for device %08x with params %s profile %p name %s",
- deviceType, address.string(), profile.get(), profile->getName().string());
+ deviceType, address.string(), profile.get(), profile->getName().c_str());
desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = desc->open(nullptr, DeviceVector(device),
@@ -5063,10 +5064,12 @@
// also take into account external policy-related changes: add all outputs which are
// associated with policies in the "before" and "after" output vectors
ALOGVV("%s(): policy related outputs", __func__);
+ bool hasDynamicPolicy = false;
for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
if (desc != 0 && desc->mPolicyMix != NULL) {
srcOutputs.add(desc->mIoHandle);
+ hasDynamicPolicy = true;
ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
}
}
@@ -5074,6 +5077,7 @@
const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (desc != 0 && desc->mPolicyMix != NULL) {
dstOutputs.add(desc->mIoHandle);
+ hasDynamicPolicy = true;
ALOGVV(" new outputs: adding %d", desc->mIoHandle);
}
}
@@ -5082,12 +5086,45 @@
// 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;
+ bool invalidate = hasDynamicPolicy;
for (audio_io_handle_t srcOut : srcOutputs) {
sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
- if (desc != 0 && maxLatency < desc->latency()) {
+ if (desc == nullptr) continue;
+
+ if (desc->isStrategyActive(psId) && maxLatency < desc->latency()) {
maxLatency = desc->latency();
}
+
+ if (invalidate) continue;
+
+ for (auto client : desc->clientsList(false /*activeOnly*/)) {
+ if (!desc->mProfile->isDirectOutput()) {
+ // a client on a non direct outputs has necessarily a linear PCM format
+ // so we can call selectOutput() safely
+ const audio_io_handle_t newOutput = selectOutput(dstOutputs,
+ client->flags(),
+ client->config().format,
+ client->config().channel_mask,
+ client->config().sample_rate);
+ if (newOutput != srcOut) {
+ invalidate = true;
+ break;
+ }
+ } else {
+ sp<IOProfile> profile = getProfileForOutput(newDevices,
+ client->config().sample_rate,
+ client->config().format,
+ client->config().channel_mask,
+ client->flags(),
+ true /* directOnly */);
+ if (profile != desc->mProfile) {
+ invalidate = true;
+ break;
+ }
+ }
+ }
}
+
ALOGV_IF(!(srcOutputs.isEmpty() || dstOutputs.isEmpty()),
"%s: strategy %d, moving from output %s to output %s", __func__, psId,
std::to_string(srcOutputs[0]).c_str(),
@@ -5095,7 +5132,9 @@
// 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 && desc->isStrategyActive(psId)) {
+ if (desc == nullptr) continue;
+
+ if (desc->isStrategyActive(psId)) {
setStrategyMute(psId, true, desc);
setStrategyMute(psId, false, desc, maxLatency * LATENCY_MUTE_FACTOR,
newDevices.types());
@@ -5111,8 +5150,10 @@
selectOutputForMusicEffects();
}
// Move tracks associated to this stream (and linked) from previous output to new output
- for (auto stream : mEngine->getStreamTypesForProductStrategy(psId)) {
- mpClientInterface->invalidateStream(stream);
+ if (invalidate) {
+ for (auto stream : mEngine->getStreamTypesForProductStrategy(psId)) {
+ mpClientInterface->invalidateStream(stream);
+ }
}
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 02c6171..9d97195 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -38,7 +38,7 @@
#include <AudioPolicyConfig.h>
#include <AudioPort.h>
#include <AudioPatch.h>
-#include <AudioProfile.h>
+#include <AudioProfileVector.h>
#include <DeviceDescriptor.h>
#include <IOProfile.h>
#include <HwModule.h>
@@ -278,7 +278,7 @@
virtual status_t getHwOffloadEncodingFormatsSupportedForA2DP(
std::vector<audio_format_t> *formats);
- virtual void setAppState(uid_t uid, app_state_t state);
+ virtual void setAppState(audio_port_handle_t portId, app_state_t state);
virtual bool isHapticPlaybackSupported();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fa8da89..389f861 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -222,7 +222,7 @@
if (result == NO_ERROR) {
sp <AudioPlaybackClient> client =
- new AudioPlaybackClient(*attr, *output, uid, pid, session, *selectedDeviceId, *stream);
+ new AudioPlaybackClient(*attr, *output, uid, pid, session, *portId, *selectedDeviceId, *stream);
mAudioPlaybackClients.add(*portId, client);
}
return result;
@@ -451,7 +451,7 @@
return status;
}
- sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session,
+ sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session, *portId,
*selectedDeviceId, opPackageName,
canCaptureOutput, canCaptureHotword);
mAudioRecordClients.add(*portId, client);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index d1b59c1..7dfc205 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -406,8 +406,7 @@
{
// Go over all active clients and allow capture (does not force silence) in the
// following cases:
-// Another client in the same UID has already been allowed to capture
-// OR The client is the assistant
+// The client is the assistant
// AND an accessibility service is on TOP or a RTT call is active
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR uses VOICE_RECOGNITION AND is on TOP
@@ -498,21 +497,12 @@
topActive = latestActive;
}
- std::vector<uid_t> enabledUids;
-
for (size_t i =0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
if (!current->active) {
continue;
}
- // keep capture allowed if another client with the same UID has already
- // been allowed to capture
- if (std::find(enabledUids.begin(), enabledUids.end(), current->uid)
- != enabledUids.end()) {
- continue;
- }
-
audio_source_t source = current->attributes.source;
bool isTopOrLatestActive = topActive == nullptr ? false : current->uid == topActive->uid;
bool isLatestSensitive = latestSensitiveActive == nullptr ?
@@ -552,29 +542,24 @@
}
} else if (mUidPolicy->isA11yUid(current->uid)) {
// For accessibility service allow capture if:
- // Is on TOP
- // AND the source is VOICE_RECOGNITION or HOTWORD
- // Or
- // The assistant is not on TOP
- // AND there is no active privacy sensitive capture or call
+ // The assistant is not on TOP
+ // AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
+ // OR
+ // Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
+ if (!isAssistantOnTop
+ && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ allowCapture = true;
+ }
if (isA11yOnTop) {
if (source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD) {
allowCapture = true;
}
- } else {
- if (!isAssistantOnTop
- && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
- allowCapture = true;
- }
}
}
- setAppState_l(current->uid,
+ setAppState_l(current->portId,
allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(current->uid)) :
APP_STATE_IDLE);
- if (allowCapture) {
- enabledUids.push_back(current->uid);
- }
}
}
@@ -582,7 +567,7 @@
for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
if (!isVirtualSource(current->attributes.source)) {
- setAppState_l(current->uid, APP_STATE_IDLE);
+ setAppState_l(current->portId, APP_STATE_IDLE);
}
}
}
@@ -628,17 +613,17 @@
return false;
}
-void AudioPolicyService::setAppState_l(uid_t uid, app_state_t state)
+void AudioPolicyService::setAppState_l(audio_port_handle_t portId, app_state_t state)
{
AutoCallerClear acc;
if (mAudioPolicyManager) {
- mAudioPolicyManager->setAppState(uid, state);
+ mAudioPolicyManager->setAppState(portId, state);
}
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af) {
bool silenced = state == APP_STATE_IDLE;
- af->setRecordSilenced(uid, silenced);
+ af->setRecordSilenced(portId, silenced);
}
}
@@ -725,11 +710,11 @@
if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
return BAD_VALUE;
}
- if (args.size() == 3 && args[0] == String16("set-uid-state")) {
+ if (args.size() >= 3 && args[0] == String16("set-uid-state")) {
return handleSetUidState(args, err);
- } else if (args.size() == 2 && args[0] == String16("reset-uid-state")) {
+ } else if (args.size() >= 2 && args[0] == String16("reset-uid-state")) {
return handleResetUidState(args, err);
- } else if (args.size() == 2 && args[0] == String16("get-uid-state")) {
+ } else if (args.size() >= 2 && args[0] == String16("get-uid-state")) {
return handleGetUidState(args, out, err);
} else if (args.size() == 1 && args[0] == String16("help")) {
printHelp(out);
@@ -739,14 +724,32 @@
return BAD_VALUE;
}
-status_t AudioPolicyService::handleSetUidState(Vector<String16>& args, int err) {
- PermissionController pc;
- int uid = pc.getPackageUid(args[1], 0);
- if (uid <= 0) {
- ALOGE("Unknown package: '%s'", String8(args[1]).string());
- dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+static status_t getUidForPackage(String16 packageName, int userId, /*inout*/uid_t& uid, int err) {
+ if (userId < 0) {
+ ALOGE("Invalid user: %d", userId);
+ dprintf(err, "Invalid user: %d\n", userId);
return BAD_VALUE;
}
+
+ PermissionController pc;
+ uid = pc.getPackageUid(packageName, 0);
+ if (uid <= 0) {
+ ALOGE("Unknown package: '%s'", String8(packageName).string());
+ dprintf(err, "Unknown package: '%s'\n", String8(packageName).string());
+ return BAD_VALUE;
+ }
+
+ uid = multiuser_get_uid(userId, uid);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::handleSetUidState(Vector<String16>& args, int err) {
+ // Valid arg.size() is 3 or 5, args.size() is 5 with --user option.
+ if (!(args.size() == 3 || args.size() == 5)) {
+ printHelp(err);
+ return BAD_VALUE;
+ }
+
bool active = false;
if (args[2] == String16("active")) {
active = true;
@@ -754,30 +757,59 @@
ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
return BAD_VALUE;
}
+
+ int userId = 0;
+ if (args.size() >= 5 && args[3] == String16("--user")) {
+ userId = atoi(String8(args[4]));
+ }
+
+ uid_t uid;
+ if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
+
mUidPolicy->addOverrideUid(uid, active);
return NO_ERROR;
}
status_t AudioPolicyService::handleResetUidState(Vector<String16>& args, int err) {
- PermissionController pc;
- int uid = pc.getPackageUid(args[1], 0);
- if (uid < 0) {
- ALOGE("Unknown package: '%s'", String8(args[1]).string());
- dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+ // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
+ if (!(args.size() == 2 || args.size() == 4)) {
+ printHelp(err);
return BAD_VALUE;
}
+
+ int userId = 0;
+ if (args.size() >= 4 && args[2] == String16("--user")) {
+ userId = atoi(String8(args[3]));
+ }
+
+ uid_t uid;
+ if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
+
mUidPolicy->removeOverrideUid(uid);
return NO_ERROR;
}
status_t AudioPolicyService::handleGetUidState(Vector<String16>& args, int out, int err) {
- PermissionController pc;
- int uid = pc.getPackageUid(args[1], 0);
- if (uid < 0) {
- ALOGE("Unknown package: '%s'", String8(args[1]).string());
- dprintf(err, "Unknown package: '%s'\n", String8(args[1]).string());
+ // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
+ if (!(args.size() == 2 || args.size() == 4)) {
+ printHelp(err);
return BAD_VALUE;
}
+
+ int userId = 0;
+ if (args.size() >= 4 && args[2] == String16("--user")) {
+ userId = atoi(String8(args[3]));
+ }
+
+ uid_t uid;
+ if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
+ return BAD_VALUE;
+ }
+
if (mUidPolicy->isUidActive(uid)) {
return dprintf(out, "active\n");
} else {
@@ -787,9 +819,9 @@
status_t AudioPolicyService::printHelp(int out) {
return dprintf(out, "Audio policy service commands:\n"
- " get-uid-state <PACKAGE> gets the uid state\n"
- " set-uid-state <PACKAGE> <active|idle> overrides the uid state\n"
- " reset-uid-state <PACKAGE> clears the uid state override\n"
+ " get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
+ " set-uid-state <PACKAGE> <active|idle> [--user USER_ID] overrides the uid state\n"
+ " reset-uid-state <PACKAGE> [--user USER_ID] clears the uid state override\n"
" help print this message\n");
}
@@ -993,8 +1025,7 @@
bool AudioPolicyService::UidPolicy::isA11yOnTop() {
for (const auto &uid : mCachedUids) {
- std::vector<uid_t>::iterator it = find(mA11yUids.begin(), mA11yUids.end(), uid.first);
- if (it == mA11yUids.end()) {
+ if (!isA11yUid(uid.first)) {
continue;
}
if (uid.second.second >= ActivityManager::PROCESS_STATE_TOP
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 74aea0d..939df2c 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -311,7 +311,7 @@
virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
// Sets whether the given UID records only silence
- virtual void setAppState_l(uid_t uid, app_state_t state);
+ virtual void setAppState_l(audio_port_handle_t portId, app_state_t state);
// Overrides the UID state as if it is idle
status_t handleSetUidState(Vector<String16>& args, int err);
@@ -759,9 +759,10 @@
public:
AudioClient(const audio_attributes_t attributes,
const audio_io_handle_t io, uid_t uid, pid_t pid,
- const audio_session_t session, const audio_port_handle_t deviceId) :
+ const audio_session_t session, audio_port_handle_t portId,
+ const audio_port_handle_t deviceId) :
attributes(attributes), io(io), uid(uid), pid(pid),
- session(session), deviceId(deviceId), active(false) {}
+ session(session), portId(portId), deviceId(deviceId), active(false) {}
~AudioClient() override = default;
@@ -770,6 +771,7 @@
const uid_t uid; // client UID
const pid_t pid; // client PID
const audio_session_t session; // audio session ID
+ const audio_port_handle_t portId;
const audio_port_handle_t deviceId; // selected input device port ID
bool active; // Playback/Capture is active or inactive
};
@@ -781,10 +783,10 @@
public:
AudioRecordClient(const audio_attributes_t attributes,
const audio_io_handle_t io, uid_t uid, pid_t pid,
- const audio_session_t session, const audio_port_handle_t deviceId,
- const String16& opPackageName,
+ const audio_session_t session, audio_port_handle_t portId,
+ const audio_port_handle_t deviceId, const String16& opPackageName,
bool canCaptureOutput, bool canCaptureHotword) :
- AudioClient(attributes, io, uid, pid, session, deviceId),
+ AudioClient(attributes, io, uid, pid, session, portId, deviceId),
opPackageName(opPackageName), startTimeNs(0),
canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
~AudioRecordClient() override = default;
@@ -802,9 +804,9 @@
public:
AudioPlaybackClient(const audio_attributes_t attributes,
const audio_io_handle_t io, uid_t uid, pid_t pid,
- const audio_session_t session, audio_port_handle_t deviceId,
- audio_stream_type_t stream) :
- AudioClient(attributes, io, uid, pid, session, deviceId), stream(stream) {}
+ const audio_session_t session, audio_port_handle_t portId,
+ audio_port_handle_t deviceId, audio_stream_type_t stream) :
+ AudioClient(attributes, io, uid, pid, session, portId, deviceId), stream(stream) {}
~AudioPlaybackClient() override = default;
const audio_stream_type_t stream;
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
new file mode 100644
index 0000000..df23410
--- /dev/null
+++ b/services/audiopolicy/tests/Android.bp
@@ -0,0 +1,66 @@
+cc_test {
+ name: "audiopolicy_tests",
+
+ include_dirs: [
+ "frameworks/av/services/audiopolicy",
+ ],
+
+ shared_libs: [
+ "libaudioclient",
+ "libaudiofoundation",
+ "libaudiopolicy",
+ "libaudiopolicymanagerdefault",
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
+ ],
+
+ static_libs: ["libaudiopolicycomponents"],
+
+ header_libs: [
+ "libaudiopolicycommon",
+ "libaudiopolicyengine_interface_headers",
+ "libaudiopolicymanager_interface_headers",
+ ],
+
+ srcs: ["audiopolicymanager_tests.cpp"],
+
+ data: [":audiopolicytest_configuration_files",],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ test_suites: ["device-tests"],
+
+}
+
+// system/audio.h utilities test
+
+cc_test {
+ name: "systemaudio_tests",
+
+ shared_libs: [
+ "libaudiofoundation",
+ "libbase",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ ],
+
+ header_libs: ["libmedia_headers"],
+
+ srcs: ["systemaudio_tests.cpp"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ test_suites: ["device-tests"],
+
+}
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
deleted file mode 100644
index c8d1459..0000000
--- a/services/audiopolicy/tests/Android.mk
+++ /dev/null
@@ -1,67 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := \
- frameworks/av/services/audiopolicy \
- $(call include-path-for, audio-utils) \
-
-LOCAL_SHARED_LIBRARIES := \
- libaudiofoundation \
- libaudiopolicymanagerdefault \
- libbase \
- liblog \
- libmedia_helper \
- libutils \
-
-LOCAL_STATIC_LIBRARIES := \
- libaudiopolicycomponents \
-
-LOCAL_HEADER_LIBRARIES := \
- libaudiopolicycommon \
- libaudiopolicyengine_interface_headers \
- libaudiopolicymanager_interface_headers
-
-LOCAL_SRC_FILES := \
- audiopolicymanager_tests.cpp \
-
-LOCAL_MODULE := audiopolicy_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_NATIVE_TEST)
-
-# system/audio.h utilities test
-
-include $(CLEAR_VARS)
-
-LOCAL_SHARED_LIBRARIES := \
- libaudiofoundation \
- libbase \
- liblog \
- libmedia_helper \
- libutils
-
-LOCAL_HEADER_LIBRARIES := \
- libmedia_headers
-
-LOCAL_SRC_FILES := \
- systemaudio_tests.cpp \
-
-LOCAL_MODULE := systemaudio_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_NATIVE_TEST)
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index fe543a6..ba1412b 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -25,6 +25,7 @@
: AudioPolicyManager(clientInterface, true /*forTesting*/) { }
using AudioPolicyManager::getConfig;
using AudioPolicyManager::initialize;
+ using AudioPolicyManager::getOutputs;
};
} // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index e10a716..d3d839e 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -14,17 +14,24 @@
* limitations under the License.
*/
+#include <map>
#include <memory>
-#include <set>
+#include <string>
#include <sys/wait.h>
#include <unistd.h>
#include <gtest/gtest.h>
#define LOG_TAG "APM_Test"
-#include <log/log.h>
+#include <Serializer.h>
+#include <android-base/file.h>
+#include <media/AudioPolicy.h>
#include <media/PatchBuilder.h>
+#include <media/RecordingActivityTracker.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include "AudioPolicyInterface.h"
#include "AudioPolicyTestClient.h"
#include "AudioPolicyTestManager.h"
@@ -73,6 +80,12 @@
return NO_ERROR;
}
+ audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
+ audio_io_handle_t /*output2*/) override {
+ audio_io_handle_t id = mNextIoHandle++;
+ return id;
+ }
+
status_t openInput(audio_module_handle_t module,
audio_io_handle_t* input,
audio_config_t* /*config*/,
@@ -89,11 +102,11 @@
return NO_ERROR;
}
- status_t createAudioPatch(const struct audio_patch* /*patch*/,
+ status_t createAudioPatch(const struct audio_patch* patch,
audio_patch_handle_t* handle,
int /*delayMs*/) override {
*handle = mNextPatchHandle++;
- mActivePatches.insert(*handle);
+ mActivePatches.insert(std::make_pair(*handle, *patch));
return NO_ERROR;
}
@@ -114,11 +127,19 @@
// Helper methods for tests
size_t getActivePatchesCount() const { return mActivePatches.size(); }
+ const struct audio_patch* getLastAddedPatch() const {
+ if (mActivePatches.empty()) {
+ return nullptr;
+ }
+ auto it = --mActivePatches.end();
+ return &it->second;
+ };
+
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
- std::set<audio_patch_handle_t> mActivePatches;
+ std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
};
class PatchCountCheck {
@@ -143,18 +164,35 @@
protected:
void SetUp() override;
void TearDown() override;
- virtual void SetUpConfig(AudioPolicyConfig *config) { (void)config; }
+ virtual void SetUpManagerConfig();
void dumpToLog();
+ // When explicit routing is needed, selectedDeviceId needs to be set as the wanted port
+ // id. Otherwise, selectedDeviceId needs to be initialized as AUDIO_PORT_HANDLE_NONE.
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_io_handle_t *output = nullptr,
+ audio_port_handle_t *portId = nullptr,
+ audio_attributes_t attr = {});
+ void getInputForAttr(
+ const audio_attributes_t &attr,
+ audio_unique_id_t riid,
+ audio_port_handle_t *selectedDeviceId,
+ audio_format_t format,
+ int channelMask,
+ int sampleRate,
+ audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
audio_port_handle_t *portId = nullptr);
PatchCountCheck snapshotPatchCount() { return PatchCountCheck(mClient.get()); }
+ void findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
+ const std::string &address, audio_port &foundPort);
+ static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
+
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
};
@@ -162,8 +200,7 @@
void AudioPolicyManagerTest::SetUp() {
mClient.reset(new AudioPolicyManagerTestClient);
mManager.reset(new AudioPolicyTestManager(mClient.get()));
- mManager->getConfig().setDefault();
- SetUpConfig(&mManager->getConfig()); // Subclasses may want to customize the config.
+ SetUpManagerConfig(); // Subclasses may want to customize the config.
ASSERT_EQ(NO_ERROR, mManager->initialize());
ASSERT_EQ(NO_ERROR, mManager->initCheck());
}
@@ -173,6 +210,10 @@
mClient.reset();
}
+void AudioPolicyManagerTest::SetUpManagerConfig() {
+ mManager->getConfig().setDefault();
+}
+
void AudioPolicyManagerTest::dumpToLog() {
int pipefd[2];
ASSERT_NE(-1, pipe(pipefd));
@@ -209,22 +250,90 @@
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_io_handle_t *output,
+ audio_port_handle_t *portId,
+ audio_attributes_t attr) {
+ audio_io_handle_t localOutput;
+ if (!output) output = &localOutput;
+ *output = AUDIO_IO_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,
+ &attr, output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
selectedDeviceId, portId, {}));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+ ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
+}
+
+void AudioPolicyManagerTest::getInputForAttr(
+ const audio_attributes_t &attr,
+ audio_unique_id_t riid,
+ audio_port_handle_t *selectedDeviceId,
+ audio_format_t format,
+ int channelMask,
+ int sampleRate,
+ audio_input_flags_t flags,
+ audio_port_handle_t *portId) {
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+ config.sample_rate = sampleRate;
+ config.channel_mask = channelMask;
+ config.format = format;
+ audio_port_handle_t localPortId;
+ if (!portId) portId = &localPortId;
+ *portId = AUDIO_PORT_HANDLE_NONE;
+ AudioPolicyInterface::input_type_t inputType;
+ ASSERT_EQ(OK, mManager->getInputForAttr(
+ &attr, &input, riid, AUDIO_SESSION_NONE, 0 /*uid*/, &config, flags,
+ selectedDeviceId, &inputType, portId));
+ ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
+}
+
+void AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
+ audio_devices_t deviceType, const std::string &address, audio_port &foundPort) {
+ uint32_t numPorts = 0;
+ uint32_t generation1;
+ status_t ret;
+
+ ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ uint32_t generation2;
+ struct audio_port ports[numPorts];
+ ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
+ ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_EQ(generation1, generation2);
+
+ for (const auto &port : ports) {
+ if (port.role == role && port.ext.device.type == deviceType &&
+ (strncmp(port.ext.device.address, address.c_str(),
+ AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
+ foundPort = port;
+ return;
+ }
+ }
+ GTEST_FAIL() << "Device port with role " << role << " and address " << address << "not found";
+}
+
+audio_port_handle_t AudioPolicyManagerTest::getDeviceIdFromPatch(
+ const struct audio_patch* patch) {
+ // The logic here is the same as the one in AudioIoDescriptor.
+ // Note this function is aim to get routed device id for test.
+ // In that case, device to device patch is not expected here.
+ if (patch->num_sources != 0 && patch->num_sinks != 0) {
+ if (patch->sources[0].type == AUDIO_PORT_TYPE_MIX) {
+ return patch->sinks[0].id;
+ } else {
+ return patch->sources[0].id;
+ }
+ }
+ return AUDIO_PORT_HANDLE_NONE;
}
@@ -286,15 +395,17 @@
class AudioPolicyManagerTestMsd : public AudioPolicyManagerTest {
protected:
- void SetUpConfig(AudioPolicyConfig *config) override;
+ void SetUpManagerConfig() override;
void TearDown() override;
sp<DeviceDescriptor> mMsdOutputDevice;
sp<DeviceDescriptor> mMsdInputDevice;
};
-void AudioPolicyManagerTestMsd::SetUpConfig(AudioPolicyConfig *config) {
+void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
+ AudioPolicyManagerTest::SetUpManagerConfig();
+ AudioPolicyConfig& config = mManager->getConfig();
mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
sp<AudioProfile> pcmOutputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
@@ -307,22 +418,21 @@
sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile);
- config->addAvailableDevice(mMsdOutputDevice);
- config->addAvailableDevice(mMsdInputDevice);
+ config.addAvailableDevice(mMsdOutputDevice);
+ config.addAvailableDevice(mMsdInputDevice);
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
- HwModuleCollection modules = config->getHwModules();
+ HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
- config->setHwModules(modules);
+ config.setHwModules(modules);
mMsdOutputDevice->attach(msdModule);
mMsdInputDevice->attach(msdModule);
- sp<OutputProfile> msdOutputProfile = new OutputProfile(String8("msd input"));
+ sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile);
msdOutputProfile->addSupportedDevice(mMsdOutputDevice);
msdModule->addOutputProfile(msdOutputProfile);
- sp<OutputProfile> msdCompressedOutputProfile =
- new OutputProfile(String8("msd compressed input"));
+ sp<OutputProfile> msdCompressedOutputProfile = new OutputProfile("msd compressed input");
msdCompressedOutputProfile->addAudioProfile(ac3OutputProfile);
msdCompressedOutputProfile->setFlags(
AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
@@ -330,7 +440,7 @@
msdCompressedOutputProfile->addSupportedDevice(mMsdOutputDevice);
msdModule->addOutputProfile(msdCompressedOutputProfile);
- sp<InputProfile> msdInputProfile = new InputProfile(String8("msd output"));
+ sp<InputProfile> msdInputProfile = new InputProfile("msd output");
msdInputProfile->addAudioProfile(pcmInputProfile);
msdInputProfile->addSupportedDevice(mMsdInputDevice);
msdModule->addInputProfile(msdInputProfile);
@@ -339,12 +449,12 @@
// 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"));
+ config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+ sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
- primaryEncodedOutputProfile->addSupportedDevice(config->getDefaultOutputDevice());
- config->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
+ config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(primaryEncodedOutputProfile);
}
@@ -372,7 +482,7 @@
TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -381,7 +491,7 @@
TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000);
ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -390,7 +500,7 @@
TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrEncodedPlusPcmRoutesToMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
@@ -403,7 +513,7 @@
TEST_F(AudioPolicyManagerTestMsd, GetOutputForAttrUnsupportedFormatBypassesMsd) {
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
@@ -414,10 +524,11 @@
// Switch between formats that are supported and not supported by MSD.
{
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId, portId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t portId;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
- &portId);
+ nullptr /*output*/, &portId);
ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
ASSERT_EQ(1, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
@@ -425,10 +536,11 @@
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId, portId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t portId;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT,
- &portId);
+ nullptr /*output*/, &portId);
ASSERT_NE(selectedDeviceId, mMsdOutputDevice->getId());
ASSERT_EQ(-1, patchCount.deltaFromSnapshot());
mManager->releaseOutput(portId);
@@ -436,10 +548,662 @@
}
{
const PatchCountCheck patchCount = snapshotPatchCount();
- audio_port_handle_t selectedDeviceId;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
getOutputForAttr(&selectedDeviceId,
AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, 48000, AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(selectedDeviceId, mMsdOutputDevice->getId());
ASSERT_EQ(0, patchCount.deltaFromSnapshot());
}
}
+
+class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest {
+protected:
+ void SetUpManagerConfig() override;
+ virtual std::string getConfigFile() { return sDefaultConfig; }
+
+ static const std::string sExecutableDir;
+ static const std::string sDefaultConfig;
+};
+
+const std::string AudioPolicyManagerTestWithConfigurationFile::sExecutableDir =
+ base::GetExecutableDirectory() + "/";
+
+const std::string AudioPolicyManagerTestWithConfigurationFile::sDefaultConfig =
+ sExecutableDir + "test_audio_policy_configuration.xml";
+
+void AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig() {
+ status_t status = deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
+ ASSERT_EQ(NO_ERROR, status);
+}
+
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, Dump) {
+ dumpToLog();
+}
+
+using PolicyMixTuple = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+
+class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+ void TearDown() override;
+
+ status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType,
+ std::string mixAddress, const audio_config_t& audioConfig,
+ const std::vector<PolicyMixTuple>& rules);
+ void clearPolicyMix();
+
+ Vector<AudioMix> mAudioMixes;
+ const std::string mMixAddress = "remote_submix_media";
+};
+
+void AudioPolicyManagerTestDynamicPolicy::TearDown() {
+ mManager->unregisterPolicyMixes(mAudioMixes);
+ AudioPolicyManagerTestWithConfigurationFile::TearDown();
+}
+
+status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixFlag,
+ audio_devices_t deviceType, std::string mixAddress, const audio_config_t& audioConfig,
+ const std::vector<PolicyMixTuple>& rules) {
+ Vector<AudioMixMatchCriterion> myMixMatchCriteria;
+
+ for(const auto &rule: rules) {
+ myMixMatchCriteria.add(AudioMixMatchCriterion(
+ std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
+ }
+
+ AudioMix myAudioMix(myMixMatchCriteria, mixType, audioConfig, mixFlag,
+ String8(mixAddress.c_str()), 0);
+ myAudioMix.mDeviceType = deviceType;
+ // Clear mAudioMix before add new one to make sure we don't add already exist mixes.
+ mAudioMixes.clear();
+ mAudioMixes.add(myAudioMix);
+
+ // As the policy mixes registration may fail at some case,
+ // caller need to check the returned status.
+ status_t ret = mManager->registerPolicyMixes(mAudioMixes);
+ return ret;
+}
+
+void AudioPolicyManagerTestDynamicPolicy::clearPolicyMix() {
+ if (mManager != nullptr) {
+ mManager->unregisterPolicyMixes(mAudioMixes);
+ }
+ mAudioMixes.clear();
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, InitSuccess) {
+ // SetUp must finish with no assertions
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, Dump) {
+ dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyMixes) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+
+ // Only capture of playback is allowed in LOOP_BACK &RENDER mode
+ ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ // Fail due to the device is already connected.
+ clearPolicyMix();
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ // The first time to register policy mixes with valid parameter should succeed.
+ clearPolicyMix();
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = 48000;
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+ std::vector<PolicyMixTuple>());
+ ASSERT_EQ(NO_ERROR, ret);
+ // Registering the same policy mixes should fail.
+ ret = mManager->registerPolicyMixes(mAudioMixes);
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ // Registration should fail due to device not found.
+ // Note that earpiece is not present in the test configuration file.
+ // This will need to be updated if earpiece is added in the test configuration file.
+ clearPolicyMix();
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ // Registration should fail due to output not found.
+ clearPolicyMix();
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ // The first time to register valid policy mixes should succeed.
+ clearPolicyMix();
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(NO_ERROR, ret);
+ // Registering the same policy mixes should fail.
+ ret = mManager->registerPolicyMixes(mAudioMixes);
+ ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, UnregisterPolicyMixes) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = 48000;
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+ std::vector<PolicyMixTuple>());
+ ASSERT_EQ(NO_ERROR, ret);
+
+ // After successfully registering policy mixes, it should be able to unregister.
+ ret = mManager->unregisterPolicyMixes(mAudioMixes);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ // After unregistering policy mixes successfully, it should fail unregistering
+ // the same policy mixes as they are not registered.
+ ret = mManager->unregisterPolicyMixes(mAudioMixes);
+ ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+class AudioPolicyManagerTestDPNoRemoteSubmixModule : public AudioPolicyManagerTestDynamicPolicy {
+protected:
+ std::string getConfigFile() override { return sPrimaryOnlyConfig; }
+
+ static const std::string sPrimaryOnlyConfig;
+};
+
+const std::string AudioPolicyManagerTestDPNoRemoteSubmixModule::sPrimaryOnlyConfig =
+ sExecutableDir + "test_audio_policy_primary_only_configuration.xml";
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, Dump) {
+ dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTestDPNoRemoteSubmixModule, RegistrationFailure) {
+ // Registration/Unregistration should fail due to module for remote submix not found.
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = 48000;
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+ ASSERT_EQ(INVALID_OPERATION, ret);
+
+ ret = mManager->unregisterPolicyMixes(mAudioMixes);
+ ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
+class AudioPolicyManagerTestDPPlaybackReRouting : public AudioPolicyManagerTestDynamicPolicy,
+ public testing::WithParamInterface<audio_attributes_t> {
+protected:
+ void SetUp() override;
+ void TearDown() override;
+
+ std::unique_ptr<RecordingActivityTracker> mTracker;
+
+ std::vector<PolicyMixTuple> mUsageRules = {
+ {AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE},
+ {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
+ };
+
+ struct audio_port mInjectionPort;
+ audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
+};
+
+void AudioPolicyManagerTestDPPlaybackReRouting::SetUp() {
+ AudioPolicyManagerTestDynamicPolicy::SetUp();
+
+ mTracker.reset(new RecordingActivityTracker());
+
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = 48000;
+ status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, mUsageRules);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ struct audio_port extractionPort;
+ findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mMixAddress, extractionPort);
+
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
+ audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, 0, ""};
+ std::string tags = "addr=" + mMixAddress;
+ strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ getInputForAttr(attr, mTracker->getRiid(), &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &mPortId);
+ ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
+ ASSERT_EQ(extractionPort.id, selectedDeviceId);
+
+ findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ mMixAddress, mInjectionPort);
+}
+
+void AudioPolicyManagerTestDPPlaybackReRouting::TearDown() {
+ mManager->stopInput(mPortId);
+ AudioPolicyManagerTestDynamicPolicy::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestDPPlaybackReRouting, InitSuccess) {
+ // SetUp must finish with no assertions
+}
+
+TEST_F(AudioPolicyManagerTestDPPlaybackReRouting, Dump) {
+ dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDPPlaybackReRouting, PlaybackReRouting) {
+ const audio_attributes_t attr = GetParam();
+ const audio_usage_t usage = attr.usage;
+
+ audio_port_handle_t playbackRoutedPortId = AUDIO_PORT_HANDLE_NONE;
+ getOutputForAttr(&playbackRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE,
+ nullptr /*output*/, nullptr /*portId*/, attr);
+ if (std::find_if(begin(mUsageRules), end(mUsageRules), [&usage](const auto &usageRule) {
+ return (std::get<0>(usageRule) == usage) &&
+ (std::get<2>(usageRule) == RULE_MATCH_ATTRIBUTE_USAGE);}) != end(mUsageRules) ||
+ (strncmp(attr.tags, "addr=", strlen("addr=")) == 0 &&
+ strncmp(attr.tags + strlen("addr="), mMixAddress.c_str(),
+ AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0)) {
+ EXPECT_EQ(mInjectionPort.id, playbackRoutedPortId);
+ } else {
+ EXPECT_NE(mInjectionPort.id, playbackRoutedPortId);
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ PlaybackReroutingUsageMatch,
+ AudioPolicyManagerTestDPPlaybackReRouting,
+ testing::Values(
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
+ AUDIO_SOURCE_DEFAULT, 0, ""}
+ )
+ );
+
+INSTANTIATE_TEST_CASE_P(
+ PlaybackReroutingAddressPriorityMatch,
+ AudioPolicyManagerTestDPPlaybackReRouting,
+ testing::Values(
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ALARM,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VIRTUAL_SOURCE,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
+ AUDIO_SOURCE_DEFAULT, 0, "addr=remote_submix_media"}
+ )
+ );
+
+INSTANTIATE_TEST_CASE_P(
+ PlaybackReroutingUnHandledUsages,
+ AudioPolicyManagerTestDPPlaybackReRouting,
+ testing::Values(
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_VOICE_COMMUNICATION,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_NOTIFICATION_EVENT,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC,
+ AUDIO_USAGE_ASSISTANCE_SONIFICATION,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_GAME,
+ AUDIO_SOURCE_DEFAULT, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_MUSIC, AUDIO_USAGE_ASSISTANT,
+ AUDIO_SOURCE_DEFAULT, 0, ""}
+ )
+ );
+
+class AudioPolicyManagerTestDPMixRecordInjection : public AudioPolicyManagerTestDynamicPolicy,
+ public testing::WithParamInterface<audio_attributes_t> {
+protected:
+ void SetUp() override;
+ void TearDown() override;
+
+ std::unique_ptr<RecordingActivityTracker> mTracker;
+
+ std::vector<PolicyMixTuple> mSourceRules = {
+ {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_CAMCORDER, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
+ {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_MIC, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
+ {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
+ };
+
+ struct audio_port mExtractionPort;
+ audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
+};
+
+void AudioPolicyManagerTestDPMixRecordInjection::SetUp() {
+ AudioPolicyManagerTestDynamicPolicy::SetUp();
+
+ mTracker.reset(new RecordingActivityTracker());
+
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = 48000;
+ status_t ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, mMixAddress, audioConfig, mSourceRules);
+ ASSERT_EQ(NO_ERROR, ret);
+
+ struct audio_port injectionPort;
+ findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ mMixAddress, injectionPort);
+
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
+ audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, usage, AUDIO_SOURCE_DEFAULT, 0, ""};
+ std::string tags = std::string("addr=") + mMixAddress;
+ strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, &mPortId, attr);
+ ASSERT_EQ(NO_ERROR, mManager->startOutput(mPortId));
+ ASSERT_EQ(injectionPort.id, getDeviceIdFromPatch(mClient->getLastAddedPatch()));
+
+ findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mMixAddress, mExtractionPort);
+}
+
+void AudioPolicyManagerTestDPMixRecordInjection::TearDown() {
+ mManager->stopOutput(mPortId);
+ AudioPolicyManagerTestDynamicPolicy::TearDown();
+}
+
+TEST_F(AudioPolicyManagerTestDPMixRecordInjection, InitSuccess) {
+ // SetUp mush finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDPMixRecordInjection, Dump) {
+ dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDPMixRecordInjection, RecordingInjection) {
+ const audio_attributes_t attr = GetParam();
+ const audio_source_t source = attr.source;
+
+ audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+ getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE, &portId);
+ if (std::find_if(begin(mSourceRules), end(mSourceRules), [&source](const auto &sourceRule) {
+ return (std::get<1>(sourceRule) == source) &&
+ (std::get<2>(sourceRule) == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET);})
+ != end(mSourceRules)) {
+ EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
+ } else {
+ EXPECT_NE(mExtractionPort.id, captureRoutedPortId);
+ }
+}
+
+// No address priority rule for remote recording, address is a "don't care"
+INSTANTIATE_TEST_CASE_P(
+ RecordInjectionSourceMatch,
+ AudioPolicyManagerTestDPMixRecordInjection,
+ testing::Values(
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_CAMCORDER, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_CAMCORDER, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_MIC, 0, "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_MIC, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_COMMUNICATION, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_COMMUNICATION, 0,
+ "addr=remote_submix_media"}
+ )
+ );
+
+// No address priority rule for remote recording
+INSTANTIATE_TEST_CASE_P(
+ RecordInjectionSourceNotMatch,
+ AudioPolicyManagerTestDPMixRecordInjection,
+ testing::Values(
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_RECOGNITION, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_HOTWORD, 0, ""},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_VOICE_RECOGNITION, 0,
+ "addr=remote_submix_media"},
+ (audio_attributes_t){AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN,
+ AUDIO_SOURCE_HOTWORD, 0, "addr=remote_submix_media"}
+ )
+ );
+
+using DeviceConnectionTestParams =
+ std::tuple<audio_devices_t /*type*/, std::string /*name*/, std::string /*address*/>;
+
+class AudioPolicyManagerTestDeviceConnection : public AudioPolicyManagerTestWithConfigurationFile,
+ public testing::WithParamInterface<DeviceConnectionTestParams> {
+};
+
+TEST_F(AudioPolicyManagerTestDeviceConnection, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTestDeviceConnection, Dump) {
+ dumpToLog();
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, SetDeviceConnectionState) {
+ const audio_devices_t type = std::get<0>(GetParam());
+ const std::string name = std::get<1>(GetParam());
+ const std::string address = std::get<2>(GetParam());
+
+ if (type == AUDIO_DEVICE_OUT_HDMI) {
+ // Set device connection state failed due to no device descriptor found
+ // For HDMI case, it is easier to simulate device descriptor not found error
+ // by using a undeclared encoded format.
+ ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_MAT_2_1));
+ }
+ // Connect with valid parameters should succeed
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+ // Try to connect with the same device again should fail
+ ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+ // Disconnect the connected device should succeed
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+ // Disconnect device that is not connected should fail
+ ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+ // Try to set device connection state with a invalid connection state should fail
+ ASSERT_EQ(BAD_VALUE, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_CNT,
+ "", "", AUDIO_FORMAT_DEFAULT));
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, ExplicitlyRoutingAfterConnection) {
+ const audio_devices_t type = std::get<0>(GetParam());
+ const std::string name = std::get<1>(GetParam());
+ const std::string address = std::get<2>(GetParam());
+
+ // Connect device to do explicitly routing test
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+
+ audio_port devicePort;
+ const audio_port_role_t role = audio_is_output_device(type)
+ ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
+ findDevicePort(role, type, address, devicePort);
+
+ audio_port_handle_t routedPortId = devicePort.id;
+ // Try start input or output according to the device type
+ if (audio_is_output_devices(type)) {
+ getOutputForAttr(&routedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000 /*sampleRate*/, AUDIO_OUTPUT_FLAG_NONE);
+ } else if (audio_is_input_device(type)) {
+ RecordingActivityTracker tracker;
+ getInputForAttr({}, tracker.getRiid(), &routedPortId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_STEREO, 48000 /*sampleRate*/, AUDIO_INPUT_FLAG_NONE);
+ }
+ ASSERT_EQ(devicePort.id, routedPortId);
+
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ DeviceConnectionState,
+ AudioPolicyManagerTestDeviceConnection,
+ testing::Values(
+ DeviceConnectionTestParams({AUDIO_DEVICE_IN_HDMI, "test_in_hdmi",
+ "audio_policy_test_in_hdmi"}),
+ DeviceConnectionTestParams({AUDIO_DEVICE_OUT_HDMI, "test_out_hdmi",
+ "audio_policy_test_out_hdmi"}),
+ DeviceConnectionTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "bt_hfp_in",
+ "hfp_client_in"}),
+ DeviceConnectionTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "bt_hfp_out",
+ "hfp_client_out"})
+ )
+ );
+
+class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+ std::string getConfigFile() override { return sTvConfig; }
+ void testHDMIPortSelection(audio_output_flags_t flags, const char* expectedMixPortName);
+
+ static const std::string sTvConfig;
+};
+
+const std::string AudioPolicyManagerTVTest::sTvConfig =
+ AudioPolicyManagerTVTest::sExecutableDir + "test_tv_apm_configuration.xml";
+
+// SwAudioOutputDescriptor doesn't populate flags so check against the port name.
+void AudioPolicyManagerTVTest::testHDMIPortSelection(
+ audio_output_flags_t flags, const char* expectedMixPortName) {
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 48000,
+ flags, &output, &portId);
+ sp<SwAudioOutputDescriptor> outDesc = mManager->getOutputs().valueFor(output);
+ ASSERT_NE(nullptr, outDesc.get());
+ audio_port port = {};
+ outDesc->toAudioPort(&port);
+ mManager->releaseOutput(portId);
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_AUX_DIGITAL, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "" /*address*/, "" /*name*/, AUDIO_FORMAT_DEFAULT));
+ ASSERT_EQ(AUDIO_PORT_TYPE_MIX, port.type);
+ ASSERT_EQ(AUDIO_PORT_ROLE_SOURCE, port.role);
+ ASSERT_STREQ(expectedMixPortName, port.name);
+}
+
+TEST_F(AudioPolicyManagerTVTest, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerTVTest, Dump) {
+ dumpToLog();
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchNoFlags) {
+ testHDMIPortSelection(AUDIO_OUTPUT_FLAG_NONE, "primary output");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectNoHwAvSync) {
+ // b/140447125: The selected port must not have HW AV Sync flag (see the config file).
+ testHDMIPortSelection(AUDIO_OUTPUT_FLAG_DIRECT, "direct");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectHwAvSync) {
+ testHDMIPortSelection(static_cast<audio_output_flags_t>(
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC),
+ "tunnel");
+}
+
+TEST_F(AudioPolicyManagerTVTest, MatchOutputDirectMMapNoIrq) {
+ testHDMIPortSelection(static_cast<audio_output_flags_t>(
+ AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
+ "low latency");
+}
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
new file mode 100644
index 0000000..d9476d9
--- /dev/null
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -0,0 +1,8 @@
+filegroup {
+ name: "audiopolicytest_configuration_files",
+ srcs: [
+ "test_audio_policy_configuration.xml",
+ "test_audio_policy_primary_only_configuration.xml",
+ "test_tv_apm_configuration.xml",
+ ],
+}
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
new file mode 100644
index 0000000..87f0ab9
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+ <modules>
+ <!-- Primary module -->
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bt_hfp_output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="mixport_bt_hfp_input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,16000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
+ </devicePort>
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ </devicePort>
+ <devicePort tagName="Hdmi" type="AUDIO_DEVICE_OUT_HDMI" role="sink">
+ </devicePort>
+ <devicePort tagName="Hdmi-In Mic" type="AUDIO_DEVICE_IN_HDMI" role="source">
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"
+ role="sink" address="hfp_client_out">
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"
+ role="source" address="hfp_client_in">
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Speaker"
+ sources="primary output"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Hdmi-In Mic"/>
+ <route type="mix" sink="Hdmi"
+ sources="primary output"/>
+ <route type="mix" sink="BT SCO"
+ sources="mixport_bt_hfp_output"/>
+ <route type="mix" sink="mixport_bt_hfp_input"
+ sources="BT SCO Headset Mic"/>
+ </routes>
+ </module>
+
+ <!-- Remote Submix module -->
+ <module name="r_submix" halVersion="2.0">
+ <attachedDevices>
+ <item>Remote Submix In</item>
+ </attachedDevices>
+ <mixPorts>
+ <mixPort name="r_submix output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="r_submix input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Remote Submix Out" type="AUDIO_DEVICE_OUT_REMOTE_SUBMIX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Remote Submix In" type="AUDIO_DEVICE_IN_REMOTE_SUBMIX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Remote Submix Out"
+ sources="r_submix output"/>
+ <route type="mix" sink="r_submix input"
+ sources="Remote Submix In"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml
new file mode 100644
index 0000000..edc0adb
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_audio_policy_primary_only_configuration.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+ <modules>
+ <!-- Primary module -->
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
+ </devicePort>
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Speaker"
+ sources="primary output"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml b/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml
new file mode 100644
index 0000000..f1638f3
--- /dev/null
+++ b/services/audiopolicy/tests/resources/test_tv_apm_configuration.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <globalConfiguration speaker_drc_enabled="false"/>
+ <modules>
+ <module name="primary" halVersion="2.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <!-- Profiles on the HDMI port are explicit for simplicity. In reality they are dynamic -->
+ <!-- Note: ports are intentionally arranged from more specific to less
+ specific in order to test b/140447125 for HW AV Sync, and similar "explicit matches" -->
+ <mixPort name="tunnel" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="low latency" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="direct" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink" />
+ <devicePort tagName="Out Aux Digital" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink" />
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="Speaker" sources="primary output"/>
+ <route type="mix" sink="Out Aux Digital" sources="primary output,tunnel,direct,low latency"/>
+ </routes>
+ </module>
+ </modules>
+</audioPolicyConfiguration>
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1c1f5e6..b26398e 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -86,9 +86,7 @@
"libfmq",
"libgui",
"libhardware",
- "libhwbinder",
"libhidlbase",
- "libhidltransport",
"libjpeg",
"libmedia_omx",
"libmemunreachable",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 9a91ea0..a503838 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -135,7 +135,8 @@
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0),
- mSoundRef(0), mInitialized(false) {
+ mSoundRef(0), mInitialized(false),
+ mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
}
@@ -164,6 +165,7 @@
mUidPolicy->registerSelf();
mSensorPrivacyPolicy = new SensorPrivacyPolicy(this);
mSensorPrivacyPolicy->registerSelf();
+ mAppOps.setCameraAudioRestriction(mAudioRestriction);
sp<HidlCameraService> hcs = HidlCameraService::getInstance(this);
if (hcs->registerAsService() != android::OK) {
ALOGE("%s: Failed to register default android.frameworks.cameraservice.service@1.0",
@@ -2027,6 +2029,7 @@
mActiveClientManager.remove(i);
}
}
+ updateAudioRestrictionLocked();
}
bool CameraService::evictClientIdByRemote(const wp<IBinder>& remote) {
@@ -2400,6 +2403,7 @@
mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
mDisconnected(false),
+ mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
mRemoteBinder(remoteCallback)
{
if (sCameraService == nullptr) {
@@ -2503,6 +2507,35 @@
return level == API_2;
}
+status_t CameraService::BasicClient::setAudioRestriction(int32_t mode) {
+ {
+ Mutex::Autolock l(mAudioRestrictionLock);
+ mAudioRestriction = mode;
+ }
+ sCameraService->updateAudioRestriction();
+ return OK;
+}
+
+int32_t CameraService::BasicClient::getServiceAudioRestriction() const {
+ return sCameraService->updateAudioRestriction();
+}
+
+int32_t CameraService::BasicClient::getAudioRestriction() const {
+ Mutex::Autolock l(mAudioRestrictionLock);
+ return mAudioRestriction;
+}
+
+bool CameraService::BasicClient::isValidAudioRestriction(int32_t mode) {
+ switch (mode) {
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE:
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION:
+ case hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_VIBRATION_SOUND:
+ return true;
+ default:
+ return false;
+ }
+}
+
status_t CameraService::BasicClient::startCameraOps() {
ATRACE_CALL();
@@ -3532,4 +3565,25 @@
" help print this message\n");
}
+int32_t CameraService::updateAudioRestriction() {
+ Mutex::Autolock lock(mServiceLock);
+ return updateAudioRestrictionLocked();
+}
+
+int32_t CameraService::updateAudioRestrictionLocked() {
+ int32_t mode = 0;
+ // iterate through all active client
+ for (const auto& i : mActiveClientManager.getAll()) {
+ const auto clientSp = i->getValue();
+ mode |= clientSp->getAudioRestriction();
+ }
+
+ bool modeChanged = (mAudioRestriction != mode);
+ mAudioRestriction = mode;
+ if (modeChanged) {
+ mAppOps.setCameraAudioRestriction(mode);
+ }
+ return mode;
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 67829dd..7c77e16 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -258,6 +258,19 @@
// Block the client form using the camera
virtual void block();
+
+ // set audio restriction from client
+ // Will call into camera service and hold mServiceLock
+ virtual status_t setAudioRestriction(int32_t mode);
+
+ // Get current global audio restriction setting
+ // Will call into camera service and hold mServiceLock
+ virtual int32_t getServiceAudioRestriction() const;
+
+ // Get current audio restriction setting for this client
+ virtual int32_t getAudioRestriction() const;
+
+ static bool isValidAudioRestriction(int32_t mode);
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
@@ -286,6 +299,9 @@
const pid_t mServicePid;
bool mDisconnected;
+ mutable Mutex mAudioRestrictionLock;
+ int32_t mAudioRestriction;
+
// - The app-side Binder interface to receive callbacks from us
sp<IBinder> mRemoteBinder; // immutable after constructor
@@ -439,6 +455,9 @@
}; // class CameraClientManager
+ int32_t updateAudioRestriction();
+ int32_t updateAudioRestrictionLocked();
+
private:
typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus;
@@ -966,6 +985,13 @@
void broadcastTorchModeStatus(const String8& cameraId,
hardware::camera::common::V1_0::TorchModeStatus status);
+
+ // TODO: right now each BasicClient holds one AppOpsManager instance.
+ // We can refactor the code so all of clients share this instance
+ AppOpsManager mAppOps;
+
+ // Aggreated audio restriction mode for all camera clients
+ int32_t mAudioRestriction;
};
} // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 162b50f..c273881 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -959,6 +959,11 @@
case Parameters::RECORD:
case Parameters::PREVIEW:
syncWithDevice();
+ // Due to flush a camera device sync is not a sufficient
+ // guarantee that the current client parameters are
+ // correctly applied. To resolve this wait for the current
+ // request id to return in the results.
+ waitUntilCurrentRequestIdLocked();
res = stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Can't stop streaming: %s (%d)",
@@ -2253,6 +2258,58 @@
return OK;
}
+status_t Camera2Client::setAudioRestriction(int /*mode*/) {
+ // Empty implementation. setAudioRestriction is hidden interface and not
+ // supported by android.hardware.Camera API
+ return INVALID_OPERATION;
+}
+
+int32_t Camera2Client::getGlobalAudioRestriction() {
+ // Empty implementation. getAudioRestriction is hidden interface and not
+ // supported by android.hardware.Camera API
+ return INVALID_OPERATION;
+}
+
+status_t Camera2Client::waitUntilCurrentRequestIdLocked() {
+ int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
+ if (activeRequestId != 0) {
+ auto res = waitUntilRequestIdApplied(activeRequestId,
+ mDevice->getExpectedInFlightDuration());
+ if (res == TIMED_OUT) {
+ ALOGE("%s: Camera %d: Timed out waiting for current request id to return in results!",
+ __FUNCTION__, mCameraId);
+ return res;
+ } else if (res != OK) {
+ ALOGE("%s: Camera %d: Error while waiting for current request id to return in results!",
+ __FUNCTION__, mCameraId);
+ return res;
+ }
+ }
+
+ return OK;
+}
+
+status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout) {
+ Mutex::Autolock l(mLatestRequestMutex);
+ while (mLatestRequestId != requestId) {
+ nsecs_t startTime = systemTime();
+
+ auto res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout);
+ if (res != OK) return res;
+
+ timeout -= (systemTime() - startTime);
+ }
+
+ return OK;
+}
+
+void Camera2Client::notifyRequestId(int32_t requestId) {
+ Mutex::Autolock al(mLatestRequestMutex);
+
+ mLatestRequestId = requestId;
+ mLatestRequestSignal.signal();
+}
+
const char* Camera2Client::kAutofocusLabel = "autofocus";
const char* Camera2Client::kTakepictureLabel = "take_picture";
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index a9ea271..8a17b17 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -83,6 +83,8 @@
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras);
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual status_t setAudioRestriction(int mode);
+ virtual int32_t getGlobalAudioRestriction();
/**
* Interface used by CameraService
@@ -122,6 +124,8 @@
camera2::SharedParameters& getParameters();
+ void notifyRequestId(int32_t requestId);
+
int getPreviewStreamId() const;
int getCaptureStreamId() const;
int getCallbackStreamId() const;
@@ -227,6 +231,12 @@
status_t initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
bool isZslEnabledInStillTemplate();
+
+ mutable Mutex mLatestRequestMutex;
+ Condition mLatestRequestSignal;
+ int32_t mLatestRequestId = -1;
+ status_t waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout);
+ status_t waitUntilCurrentRequestIdLocked();
};
}; // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index d65ac7b..764b3a9 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -1171,4 +1171,25 @@
return INVALID_OPERATION;
}
+status_t CameraClient::setAudioRestriction(int mode) {
+ if (!isValidAudioRestriction(mode)) {
+ ALOGE("%s: invalid audio restriction mode %d", __FUNCTION__, mode);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ return BasicClient::setAudioRestriction(mode);
+}
+
+int32_t CameraClient::getGlobalAudioRestriction() {
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ return BasicClient::getServiceAudioRestriction();
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 9530b6c..b26b612 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -59,6 +59,8 @@
virtual String8 getParameters() const;
virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
virtual status_t setVideoTarget(const sp<IGraphicBufferProducer>& bufferProducer);
+ virtual status_t setAudioRestriction(int mode);
+ virtual int32_t getGlobalAudioRestriction();
// Interface used by CameraService
CameraClient(const sp<CameraService>& cameraService,
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
index 683e84d..63e293a 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp
@@ -86,6 +86,12 @@
process3aState(frame, client);
}
+ if (mCurrentRequestId != frame.mResultExtras.requestId) {
+ mCurrentRequestId = frame.mResultExtras.requestId;
+
+ client->notifyRequestId(mCurrentRequestId);
+ }
+
return FrameProcessorBase::processSingleFrame(frame, device);
}
diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.h b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
index 8183c12..142b8cd 100644
--- a/services/camera/libcameraservice/api1/client2/FrameProcessor.h
+++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.h
@@ -94,6 +94,7 @@
};
AlgState m3aState;
+ int32_t mCurrentRequestId = -1;
// frame number -> pending 3A states that not all data are received yet.
KeyedVector<int32_t, AlgState> mPending3AStates;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c7a4f2b..d93d26f 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1870,6 +1870,34 @@
return res;
}
+binder::Status CameraDeviceClient::setCameraAudioRestriction(int32_t mode) {
+ ATRACE_CALL();
+ binder::Status res;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+ if (!isValidAudioRestriction(mode)) {
+ String8 msg = String8::format("Camera %s: invalid audio restriction mode %d",
+ mCameraIdStr.string(), mode);
+ ALOGW("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+
+ Mutex::Autolock icl(mBinderSerializationLock);
+ BasicClient::setAudioRestriction(mode);
+ return binder::Status::ok();
+}
+
+binder::Status CameraDeviceClient::getGlobalAudioRestriction(/*out*/ int32_t* outMode) {
+ ATRACE_CALL();
+ binder::Status res;
+ if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+ Mutex::Autolock icl(mBinderSerializationLock);
+ if (outMode != nullptr) {
+ *outMode = BasicClient::getServiceAudioRestriction();
+ }
+ return binder::Status::ok();
+}
+
status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
return BasicClient::dump(fd, args);
}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1c5abb0..fe25010 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -152,6 +152,10 @@
virtual binder::Status finalizeOutputConfigurations(int32_t streamId,
const hardware::camera2::params::OutputConfiguration &outputConfiguration) override;
+ virtual binder::Status setCameraAudioRestriction(int32_t mode) override;
+
+ virtual binder::Status getGlobalAudioRestriction(/*out*/int32_t* outMode) override;
+
/**
* Interface used by CameraService
*/
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 98c1b5e..935bc37 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -383,6 +383,12 @@
* drop buffers for stream of streamId.
*/
virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0;
+
+ /**
+ * Returns the maximum expected time it'll take for all currently in-flight
+ * requests to complete, based on their settings
+ */
+ virtual nsecs_t getExpectedInFlightDuration() = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cae34ce..2573b48 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -194,6 +194,8 @@
*/
status_t dropStreamBuffers(bool dropping, int streamId) override;
+ nsecs_t getExpectedInFlightDuration() override;
+
/**
* Helper functions to map between framework and HIDL values
*/
@@ -1111,12 +1113,6 @@
const SurfaceMap& outputSurfaces);
/**
- * Returns the maximum expected time it'll take for all currently in-flight
- * requests to complete, based on their settings
- */
- nsecs_t getExpectedInFlightDuration();
-
- /**
* Tracking for idle detection
*/
sp<camera3::StatusTracker> mStatusTracker;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index acb8b3c..e1d35e8 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -54,9 +54,8 @@
mState = STATE_ERROR;
}
- if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
- mBufferReleasedListener = new BufferReleasedListener(this);
- }
+ bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
+ mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
}
Camera3OutputStream::Camera3OutputStream(int id,
@@ -87,9 +86,8 @@
mState = STATE_ERROR;
}
- if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
- mBufferReleasedListener = new BufferReleasedListener(this);
- }
+ bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
+ mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
}
Camera3OutputStream::Camera3OutputStream(int id,
@@ -124,10 +122,8 @@
}
mConsumerName = String8("Deferred");
- if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
- mBufferReleasedListener = new BufferReleasedListener(this);
- }
-
+ bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
+ mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
}
Camera3OutputStream::Camera3OutputStream(int id, camera3_stream_type_t type,
@@ -151,9 +147,8 @@
mDropBuffers(false),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
- if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
- mBufferReleasedListener = new BufferReleasedListener(this);
- }
+ bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
+ mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
// Subclasses expected to initialize mConsumer themselves
}
@@ -261,7 +256,7 @@
notifyBufferReleased(anwBuffer);
if (mUseBufferManager) {
// Return this buffer back to buffer manager.
- mBufferReleasedListener->onBufferReleased();
+ mBufferProducerListener->onBufferReleased();
}
} else {
if (mTraceFirstBuffer && (stream_type == CAMERA3_STREAM_OUTPUT)) {
@@ -387,8 +382,8 @@
// Configure consumer-side ANativeWindow interface. The listener may be used
// to notify buffer manager (if it is used) of the returned buffers.
res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA,
- /*listener*/mBufferReleasedListener,
- /*reportBufferRemoval*/true);
+ /*reportBufferRemoval*/true,
+ /*listener*/mBufferProducerListener);
if (res != OK) {
ALOGE("%s: Unable to connect to native window for stream %d",
__FUNCTION__, mId);
@@ -790,7 +785,7 @@
return INVALID_OPERATION;
}
-void Camera3OutputStream::BufferReleasedListener::onBufferReleased() {
+void Camera3OutputStream::BufferProducerListener::onBufferReleased() {
sp<Camera3OutputStream> stream = mParent.promote();
if (stream == nullptr) {
ALOGV("%s: Parent camera3 output stream was destroyed", __FUNCTION__);
@@ -823,6 +818,25 @@
}
}
+void Camera3OutputStream::BufferProducerListener::onBuffersDiscarded(
+ const std::vector<sp<GraphicBuffer>>& buffers) {
+ sp<Camera3OutputStream> stream = mParent.promote();
+ if (stream == nullptr) {
+ ALOGV("%s: Parent camera3 output stream was destroyed", __FUNCTION__);
+ return;
+ }
+
+ if (buffers.size() > 0) {
+ Mutex::Autolock l(stream->mLock);
+ stream->onBuffersRemovedLocked(buffers);
+ if (stream->mUseBufferManager) {
+ stream->mBufferManager->onBuffersRemoved(stream->getId(),
+ stream->getStreamSetId(), buffers.size());
+ }
+ ALOGV("Stream %d: %zu Buffers discarded.", stream->getId(), buffers.size());
+ }
+}
+
void Camera3OutputStream::onBuffersRemovedLocked(
const std::vector<sp<GraphicBuffer>>& removedBuffers) {
sp<Camera3StreamBufferFreedListener> callback = mBufferFreedListener.promote();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 729c655..b4e49f9 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -146,18 +146,22 @@
*/
virtual status_t setConsumers(const std::vector<sp<Surface>>& consumers);
- class BufferReleasedListener : public BnProducerListener {
+ class BufferProducerListener : public SurfaceListener {
public:
- BufferReleasedListener(wp<Camera3OutputStream> parent) : mParent(parent) {}
+ BufferProducerListener(wp<Camera3OutputStream> parent, bool needsReleaseNotify)
+ : mParent(parent), mNeedsReleaseNotify(needsReleaseNotify) {}
- /**
- * Implementation of IProducerListener, used to notify this stream that the consumer
- * has returned a buffer and it is ready to return to Camera3BufferManager for reuse.
- */
- virtual void onBufferReleased();
+ /**
+ * Implementation of IProducerListener, used to notify this stream that the consumer
+ * has returned a buffer and it is ready to return to Camera3BufferManager for reuse.
+ */
+ virtual void onBufferReleased();
+ virtual bool needsReleaseNotify() { return mNeedsReleaseNotify; }
+ virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers);
private:
- wp<Camera3OutputStream> mParent;
+ wp<Camera3OutputStream> mParent;
+ bool mNeedsReleaseNotify;
};
virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
@@ -262,10 +266,10 @@
sp<Camera3BufferManager> mBufferManager;
/**
- * Buffer released listener, used to notify the buffer manager that a buffer is released
- * from consumer side.
+ * Buffer producer listener, used to handle notification when a buffer is released
+ * from consumer side, or a set of buffers are discarded by the consumer.
*/
- sp<BufferReleasedListener> mBufferReleasedListener;
+ sp<BufferProducerListener> mBufferProducerListener;
/**
* Flag indicating if the buffer manager is used to allocate the stream buffers
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 84c2ec7..80df7db 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -496,7 +496,7 @@
mInputSlots[bufferItem.mSlot].mFrameNumber = bufferItem.mFrameNumber;
} else {
SP_LOGE("%s: Invalid input graphic buffer!", __FUNCTION__);
- res = BAD_VALUE;
+ mOnFrameAvailableRes.store(BAD_VALUE);
return;
}
bufferId = bufferItem.mGraphicBuffer->getId();
@@ -541,6 +541,11 @@
mOnFrameAvailableRes.store(res);
}
+void Camera3StreamSplitter::onFrameReplaced(const BufferItem& item) {
+ ATRACE_CALL();
+ onFrameAvailable(item);
+}
+
void Camera3StreamSplitter::decrementBufRefCountLocked(uint64_t id, size_t surfaceId) {
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 960f7aa..4eb455a 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -102,6 +102,13 @@
void onFrameAvailable(const BufferItem& item) override;
// From IConsumerListener
+ //
+ // Similar to onFrameAvailable, but buffer item is indeed replacing a buffer
+ // in the buffer queue. This can happen when buffer queue is in droppable
+ // mode.
+ void onFrameReplaced(const BufferItem& item) override;
+
+ // From IConsumerListener
// We don't care about released buffers because we detach each buffer as
// soon as we acquire it. See the comment for onBufferReleased below for
// some clarifying notes about the name.
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index b4e7c32..ec5e876 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -23,7 +23,6 @@
libcameraservice \
libhidlbase \
liblog \
- libhidltransport \
libcamera_client \
libcamera_metadata \
libutils \
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 99a6d6b..36042a4 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -10,8 +10,6 @@
"libavservices_minijail",
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libmedia_codecserviceregistrant",
],
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index ecc8408..d878d72 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -39,9 +39,7 @@
libbase \
libavservices_minijail_vendor \
libcutils \
- libhwbinder \
libhidlbase \
- libhidltransport \
libstagefright_omx \
libstagefright_xmlparser \
android.hardware.media.omx@1.0 \
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index 227a29d..3e94596 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -27,7 +27,6 @@
libutils \
libhidlbase \
libhidlmemory \
- libhidltransport \
android.hardware.drm@1.0 \
android.hardware.drm@1.1 \
android.hardware.drm@1.2
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
index 3f02f48..1bbd591 100644
--- a/services/soundtrigger/Android.bp
+++ b/services/soundtrigger/Android.bp
@@ -31,10 +31,8 @@
"libaudioutils",
"libmediautils",
- "libhwbinder",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"libbase",
"libaudiohal",
"libaudiohal_deathhandler",