Merge "Remove NdkJavaVMHelper.h from NDK directory"
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index 15c295e..4745ee8 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -50,6 +50,15 @@
mBuffer = clone_camera_metadata(other.mBuffer);
}
+CameraMetadata::CameraMetadata(CameraMetadata &&other) :mBuffer(NULL), mLocked(false) {
+ acquire(other);
+}
+
+CameraMetadata &CameraMetadata::operator=(CameraMetadata &&other) {
+ acquire(other);
+ return *this;
+}
+
CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
mBuffer(NULL), mLocked(false) {
acquire(buffer);
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index 1d8e8c4..9cbfdb0 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -117,6 +117,12 @@
mMetadata(), mResultExtras() {
}
+CaptureResult::CaptureResult(CaptureResult &&otherResult) {
+ mMetadata = std::move(otherResult.mMetadata);
+ mResultExtras = otherResult.mResultExtras;
+ mPhysicalMetadatas = std::move(otherResult.mPhysicalMetadatas);
+}
+
CaptureResult::CaptureResult(const CaptureResult &otherResult) {
mResultExtras = otherResult.mResultExtras;
mMetadata = otherResult.mMetadata;
diff --git a/camera/include/camera/CameraMetadata.h b/camera/include/camera/CameraMetadata.h
index 844bb80..9d1b5c7 100644
--- a/camera/include/camera/CameraMetadata.h
+++ b/camera/include/camera/CameraMetadata.h
@@ -40,6 +40,11 @@
* dataCapacity extra storage */
CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10);
+ /**
+ * Move constructor, acquires other's metadata buffer
+ */
+ CameraMetadata(CameraMetadata &&other);
+
~CameraMetadata();
/** Takes ownership of passed-in buffer */
@@ -54,6 +59,11 @@
CameraMetadata &operator=(const camera_metadata_t *buffer);
/**
+ * Move assignment operator, acquires other's metadata buffer
+ */
+ CameraMetadata &operator=(CameraMetadata &&other);
+
+ /**
* Get reference to the underlying metadata buffer. Ownership remains with
* the CameraMetadata object, but non-const CameraMetadata methods will not
* work until unlock() is called. Note that the lock has nothing to do with
diff --git a/camera/include/camera/CaptureResult.h b/camera/include/camera/CaptureResult.h
index ef830b5..dc3d282 100644
--- a/camera/include/camera/CaptureResult.h
+++ b/camera/include/camera/CaptureResult.h
@@ -135,6 +135,8 @@
CaptureResult(const CaptureResult& otherResult);
+ CaptureResult(CaptureResult &&captureResult);
+
status_t readFromParcel(android::Parcel* parcel);
status_t writeToParcel(android::Parcel* parcel) const;
};
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index fd71837..f427834 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -26,11 +26,13 @@
shared_libs: [
"libmedia",
"libmediametrics",
+ "libcutils",
"libutils",
"liblog",
"libbinder",
"libdl",
"libselinux",
+ "libstagefright_foundation",
],
static_libs: ["libdrmframeworkcommon"],
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 38dc052..9a32cc5 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -16,9 +16,10 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmManager(Native)"
-#include "utils/Log.h"
+#include <cutils/properties.h>
#include <utils/String8.h>
+#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <drm/DrmInfo.h>
@@ -37,12 +38,30 @@
#include "DrmManager.h"
#include "ReadWriteUtils.h"
+#include <algorithm>
+
#define DECRYPT_FILE_ERROR (-1)
using namespace android;
const String8 DrmManager::EMPTY_STRING("");
+const std::map<const char*, size_t> DrmManager::kMethodIdMap {
+ {"getConstraints" , DrmManagerMethodId::GET_CONSTRAINTS },
+ {"getMetadata" , DrmManagerMethodId::GET_METADATA },
+ {"canHandle" , DrmManagerMethodId::CAN_HANDLE },
+ {"processDrmInfo" , DrmManagerMethodId::PROCESS_DRM_INFO },
+ {"acquireDrmInfo" , DrmManagerMethodId::ACQUIRE_DRM_INFO },
+ {"saveRights" , DrmManagerMethodId::SAVE_RIGHTS },
+ {"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
+ {"getDrmObjectType" , DrmManagerMethodId::GET_DRM_OBJECT_TYPE },
+ {"checkRightsStatus" , DrmManagerMethodId::CHECK_RIGHTS_STATUS },
+ {"removeRights" , DrmManagerMethodId::REMOVE_RIGHTS },
+ {"removeAllRights" , DrmManagerMethodId::REMOVE_ALL_RIGHTS },
+ {"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION },
+ {"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION }
+};
+
DrmManager::DrmManager() :
mDecryptSessionId(0),
mConvertId(0) {
@@ -51,42 +70,106 @@
}
DrmManager::~DrmManager() {
-
+ if (mMetricsLooper != NULL) {
+ mMetricsLooper->stop();
+ }
+ flushEngineMetrics();
}
-void DrmManager::reportEngineMetrics(
- const char func[], const String8& plugInId, const String8& mimeType) {
- IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId);
+void DrmManager::initMetricsLooper() {
+ if (mMetricsLooper != NULL) {
+ return;
+ }
+ mMetricsLooper = new ALooper;
+ mMetricsLooper->setName("DrmManagerMetricsLooper");
+ mMetricsLooper->start();
+ mMetricsLooper->registerHandler(this);
- std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
- item->setUid(IPCThreadState::self()->getCallingUid());
- item->setCString("function_name", func);
- item->setCString("plugin_id", plugInId.getPathLeaf().getBasePath().c_str());
+ sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
+ msg->post(getMetricsFlushPeriodUs());
+}
+void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatFlushMetrics:
+ {
+ flushEngineMetrics();
+ msg->post(getMetricsFlushPeriodUs());
+ break;
+ }
+ default:
+ {
+ ALOGW("Unrecognized message type: %zd", msg->what());
+ }
+ }
+}
+
+int64_t DrmManager::getMetricsFlushPeriodUs() {
+ return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
+}
+
+void DrmManager::recordEngineMetrics(
+ const char func[], const String8& plugInId8, const String8& mimeType) {
+ IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
- if (NULL != info) {
- item->setCString("description", info->getDescription().c_str());
+
+ uid_t callingUid = IPCThreadState::self()->getCallingUid();
+ std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
+ ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
+
+ Mutex::Autolock _l(mMetricsLock);
+ auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
+ if (metrics.mPluginId.empty()) {
+ metrics.mPluginId = plugInId;
+ metrics.mCallingUid = callingUid;
+ if (NULL != info) {
+ metrics.mDescription = info->getDescription().c_str();
+ }
}
if (!mimeType.isEmpty()) {
- item->setCString("mime_types", mimeType.c_str());
+ metrics.mMimeTypes.insert(mimeType.c_str());
} else if (NULL != info) {
DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
- String8 mimes;
while (mimeIter.hasNext()) {
- mimes += mimeIter.next();
- if (mimeIter.hasNext()) {
- mimes += ",";
- }
+ metrics.mMimeTypes.insert(mimeIter.next().c_str());
}
- item->setCString("mime_types", mimes.c_str());
}
- if (!item->selfrecord()) {
- ALOGE("Failed to record metrics");
+ size_t methodId = kMethodIdMap.at(func);
+ if (methodId < metrics.mMethodCounts.size()) {
+ metrics.mMethodCounts[methodId]++;
}
}
+void DrmManager::flushEngineMetrics() {
+ using namespace std::string_literals;
+ Mutex::Autolock _l(mMetricsLock);
+ for (auto kv : mPluginMetrics) {
+ DrmManagerMetrics& metrics = kv.second;
+ std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
+ item->setUid(metrics.mCallingUid);
+ item->setCString("plugin_id", metrics.mPluginId.c_str());
+ item->setCString("description", metrics.mDescription.c_str());
+
+ std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
+ std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
+ for (size_t i = 1; i < mimeTypes.size() ; i++) {
+ mimeTypesStr.append(",").append(mimeTypes[i]);
+ }
+ item->setCString("mime_types", mimeTypesStr.c_str());
+
+ for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
+ item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
+ }
+
+ if (!item->selfrecord()) {
+ ALOGE("Failed to record metrics");
+ }
+ }
+ mPluginMetrics.clear();
+}
+
int DrmManager::addUniqueId(bool isNative) {
Mutex::Autolock _l(mLock);
@@ -184,7 +267,6 @@
for (size_t index = 0; index < plugInIdList.size(); index++) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
rDrmEngine.terminate(uniqueId);
- reportEngineMetrics(__func__, plugInIdList[index]);
}
}
@@ -197,7 +279,7 @@
constraints = rDrmEngine.getConstraints(uniqueId, path, action);
}
if (NULL != constraints) {
- reportEngineMetrics(__func__, plugInId);
+ recordEngineMetrics(__func__, plugInId);
}
return constraints;
}
@@ -211,7 +293,7 @@
meta = rDrmEngine.getMetadata(uniqueId, path);
}
if (NULL != meta) {
- reportEngineMetrics(__func__, plugInId);
+ recordEngineMetrics(__func__, plugInId);
}
return meta;
}
@@ -222,7 +304,7 @@
bool result = (EMPTY_STRING != plugInId) ? true : false;
if (result) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
if (0 < path.length()) {
@@ -249,7 +331,7 @@
infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
}
if (NULL != infoStatus) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
return infoStatus;
}
@@ -263,7 +345,7 @@
result = rDrmEngine.canHandle(uniqueId, path);
if (result) {
- reportEngineMetrics(__func__, plugInPathList[i]);
+ recordEngineMetrics(__func__, plugInPathList[i]);
break;
}
}
@@ -280,7 +362,7 @@
info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
}
if (NULL != info) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
return info;
}
@@ -296,7 +378,7 @@
result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
}
if (DRM_NO_ERROR == result) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
return result;
}
@@ -310,7 +392,7 @@
mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
}
if (!mimeType.isEmpty()) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
return mimeType;
}
@@ -324,7 +406,7 @@
type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
}
if (DrmObjectType::UNKNOWN != type) {
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
return type;
}
@@ -338,7 +420,7 @@
rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
}
if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
- reportEngineMetrics(__func__, plugInId);
+ recordEngineMetrics(__func__, plugInId);
}
return rightsStatus;
}
@@ -385,7 +467,7 @@
result = rDrmEngine.removeRights(uniqueId, path);
}
if (DRM_NO_ERROR == result) {
- reportEngineMetrics(__func__, plugInId);
+ recordEngineMetrics(__func__, plugInId);
}
return result;
}
@@ -399,7 +481,7 @@
if (DRM_NO_ERROR != result) {
break;
}
- reportEngineMetrics(__func__, plugInIdList[index]);
+ recordEngineMetrics(__func__, plugInIdList[index]);
}
return result;
}
@@ -416,7 +498,7 @@
++mConvertId;
convertId = mConvertId;
mConvertSessionMap.add(convertId, &rDrmEngine);
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
}
}
return convertId;
@@ -497,7 +579,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
- reportEngineMetrics(__func__, plugInId, String8(mime));
+ recordEngineMetrics(__func__, plugInId, String8(mime));
break;
}
}
@@ -526,7 +608,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
- reportEngineMetrics(__func__, plugInId, String8(mime));
+ recordEngineMetrics(__func__, plugInId, String8(mime));
break;
}
}
@@ -556,7 +638,7 @@
if (DRM_NO_ERROR == result) {
++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
- reportEngineMetrics(__func__, plugInId, mimeType);
+ recordEngineMetrics(__func__, plugInId, mimeType);
break;
}
}
diff --git a/drm/drmserver/DrmManager.h b/drm/drmserver/DrmManager.h
index 75fc1a8..350fcf4 100644
--- a/drm/drmserver/DrmManager.h
+++ b/drm/drmserver/DrmManager.h
@@ -17,13 +17,26 @@
#ifndef __DRM_MANAGER_H__
#define __DRM_MANAGER_H__
+#include <drm/drm_framework_common.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/threads.h>
-#include <drm/drm_framework_common.h>
+
#include "IDrmEngine.h"
#include "PlugInManager.h"
#include "IDrmServiceListener.h"
+#include <array>
+#include <cstddef>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
namespace android {
class IDrmManager;
@@ -40,6 +53,31 @@
class DrmSupportInfo;
class ActionDescription;
+enum DrmManagerMethodId {
+ GET_CONSTRAINTS,
+ GET_METADATA,
+ CAN_HANDLE,
+ PROCESS_DRM_INFO,
+ ACQUIRE_DRM_INFO,
+ SAVE_RIGHTS,
+ GET_ORIGINAL_MIME_TYPE,
+ GET_DRM_OBJECT_TYPE,
+ CHECK_RIGHTS_STATUS,
+ REMOVE_RIGHTS,
+ REMOVE_ALL_RIGHTS,
+ OPEN_CONVERT_SESSION,
+ OPEN_DECRYPT_SESSION,
+ NUM_METHODS,
+};
+
+struct DrmManagerMetrics {
+ std::string mPluginId;
+ std::string mDescription;
+ std::set<std::string> mMimeTypes;
+ std::array<int64_t, DrmManagerMethodId::NUM_METHODS> mMethodCounts{};
+ uid_t mCallingUid;
+};
+
/**
* This is implementation class for DRM Manager. This class delegates the
* functionality to corresponding DRM Engine.
@@ -47,7 +85,7 @@
* The DrmManagerService class creates an instance of this class.
*
*/
-class DrmManager : public IDrmEngine::OnInfoListener {
+class DrmManager : public AHandler, public IDrmEngine::OnInfoListener {
public:
DrmManager();
virtual ~DrmManager();
@@ -134,6 +172,8 @@
void onInfo(const DrmInfoEvent& event);
+ void initMetricsLooper();
+
private:
String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
@@ -143,16 +183,24 @@
bool canHandle(int uniqueId, const String8& path);
- void reportEngineMetrics(const char func[],
+ void onMessageReceived(const sp<AMessage> &msg);
+
+ int64_t getMetricsFlushPeriodUs();
+
+ void recordEngineMetrics(const char func[],
const String8& plugInId, const String8& mimeType = String8(""));
+ void flushEngineMetrics();
+
private:
enum {
kMaxNumUniqueIds = 0x1000,
+ kWhatFlushMetrics = 'metr',
};
bool mUniqueIdArray[kMaxNumUniqueIds];
static const String8 EMPTY_STRING;
+ static const std::map<const char*, size_t> kMethodIdMap;
int mDecryptSessionId;
int mConvertId;
@@ -160,11 +208,15 @@
Mutex mListenerLock;
Mutex mDecryptLock;
Mutex mConvertLock;
+ Mutex mMetricsLock;
TPlugInManager<IDrmEngine> mPlugInManager;
KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
KeyedVector< int, IDrmEngine*> mConvertSessionMap;
KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+
+ std::map<std::pair<uid_t, std::string>, DrmManagerMetrics> mPluginMetrics;
+ sp<ALooper> mMetricsLooper;
};
};
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 2600a2c..4b8b3f6 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -130,13 +130,14 @@
mDrmManager(NULL) {
ALOGV("created");
mDrmManager = new DrmManager();
+ mDrmManager->initMetricsLooper();
mDrmManager->loadPlugIns();
}
DrmManagerService::~DrmManagerService() {
ALOGV("Destroyed");
mDrmManager->unloadPlugIns();
- delete mDrmManager; mDrmManager = NULL;
+ mDrmManager = NULL;
}
int DrmManagerService::addUniqueId(bool isNative) {
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index 2e27a3c..f9b8bef 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -142,7 +142,7 @@
virtual status_t dump(int fd, const Vector<String16>& args);
private:
- DrmManager* mDrmManager;
+ sp<DrmManager> mDrmManager;
};
};
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 5b32a04..f218041 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -713,7 +713,8 @@
} while (retry);
if (err == OK) {
- std::shared_ptr<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+ std::shared_ptr<DrmSessionClient> client =
+ ndk::SharedRefBase::make<DrmSessionClient>(this, sessionId);
DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
mOpenSessions.push_back(client);
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 3568f7b..f39620e 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -40,6 +40,8 @@
#define DRC_DEFAULT_MOBILE_DRC_BOOST 1.0 /* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_HEAVY C2Config::DRC_COMPRESSION_HEAVY /* switch for heavy compression for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0 /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS (0.25) /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#define DRC_DEFAULT_MOBILE_ENC_LEVEL (0.25) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */
// names of properties that can be used to override the default DRC settings
@@ -190,6 +192,24 @@
})
.withSetter(Setter<decltype(*mDrcEffectType)>::StrictValueWithNoDeps)
.build());
+
+ addParameter(
+ DefineParam(mDrcAlbumMode, C2_PARAMKEY_DRC_ALBUM_MODE)
+ .withDefault(new C2StreamDrcAlbumModeTuning::input(0u, C2Config::DRC_ALBUM_MODE_OFF))
+ .withFields({
+ C2F(mDrcAlbumMode, value).oneOf({
+ C2Config::DRC_ALBUM_MODE_OFF,
+ C2Config::DRC_ALBUM_MODE_ON})
+ })
+ .withSetter(Setter<decltype(*mDrcAlbumMode)>::StrictValueWithNoDeps)
+ .build());
+
+ addParameter(
+ DefineParam(mDrcOutputLoudness, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS)
+ .withDefault(new C2StreamDrcOutputLoudnessTuning::output(0u, DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS))
+ .withFields({C2F(mDrcOutputLoudness, value).inRange(-57.75, 0.25)})
+ .withSetter(Setter<decltype(*mDrcOutputLoudness)>::StrictValueWithNoDeps)
+ .build());
}
bool isAdts() const { return mAacFormat->value == C2Config::AAC_PACKAGING_ADTS; }
@@ -204,6 +224,8 @@
int32_t getDrcBoostFactor() const { return mDrcBoostFactor->value * 127. + 0.5; }
int32_t getDrcAttenuationFactor() const { return mDrcAttenuationFactor->value * 127. + 0.5; }
int32_t getDrcEffectType() const { return mDrcEffectType->value; }
+ int32_t getDrcAlbumMode() const { return mDrcAlbumMode->value; }
+ int32_t getDrcOutputLoudness() const { return (mDrcOutputLoudness->value <= 0 ? -mDrcOutputLoudness->value * 4. + 0.5 : -1); }
private:
std::shared_ptr<C2StreamSampleRateInfo::output> mSampleRate;
@@ -218,6 +240,8 @@
std::shared_ptr<C2StreamDrcBoostFactorTuning::input> mDrcBoostFactor;
std::shared_ptr<C2StreamDrcAttenuationFactorTuning::input> mDrcAttenuationFactor;
std::shared_ptr<C2StreamDrcEffectTypeTuning::input> mDrcEffectType;
+ std::shared_ptr<C2StreamDrcAlbumModeTuning::input> mDrcAlbumMode;
+ std::shared_ptr<C2StreamDrcOutputLoudnessTuning::output> mDrcOutputLoudness;
// TODO Add : C2StreamAacSbrModeTuning
};
@@ -324,7 +348,7 @@
// DRC_PRES_MODE_WRAP_DESIRED_HEAVY
int32_t compressMode = mIntf->getDrcCompressMode();
- ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+ ALOGV("AAC decoder using desired DRC heavy compression switch of %d", compressMode);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
// DRC_PRES_MODE_WRAP_ENCODER_TARGET
@@ -337,6 +361,11 @@
ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+ // AAC_UNIDRC_ALBUM_MODE
+ int32_t albumMode = mIntf->getDrcAlbumMode();
+ ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+ aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
// By default, the decoder creates a 5.1 channel downmix signal.
// For seven and eight channel input streams, enable 6.1 and 7.1 channel output
aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1);
@@ -632,6 +661,7 @@
INT prevSampleRate = mStreamInfo->sampleRate;
INT prevNumChannels = mStreamInfo->numChannels;
+ INT prevOutLoudness = mStreamInfo->outputLoudness;
aacDecoder_Fill(mAACDecoder,
inBuffer,
@@ -640,6 +670,43 @@
// run DRC check
mDrcWrap.submitStreamData(mStreamInfo);
+
+ // apply runtime updates
+ // DRC_PRES_MODE_WRAP_DESIRED_TARGET
+ int32_t targetRefLevel = mIntf->getDrcTargetRefLevel();
+ ALOGV("AAC decoder using desired DRC target reference level of %d", targetRefLevel);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, (unsigned)targetRefLevel);
+
+ // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR
+ int32_t attenuationFactor = mIntf->getDrcAttenuationFactor();
+ ALOGV("AAC decoder using desired DRC attenuation factor of %d", attenuationFactor);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, (unsigned)attenuationFactor);
+
+ // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR
+ int32_t boostFactor = mIntf->getDrcBoostFactor();
+ ALOGV("AAC decoder using desired DRC boost factor of %d", boostFactor);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, (unsigned)boostFactor);
+
+ // DRC_PRES_MODE_WRAP_DESIRED_HEAVY
+ int32_t compressMode = mIntf->getDrcCompressMode();
+ ALOGV("AAC decoder using desried DRC heavy compression switch of %d", compressMode);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, (unsigned)compressMode);
+
+ // DRC_PRES_MODE_WRAP_ENCODER_TARGET
+ int32_t encTargetLevel = mIntf->getDrcEncTargetLevel();
+ ALOGV("AAC decoder using encoder-side DRC reference level of %d", encTargetLevel);
+ mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, (unsigned)encTargetLevel);
+
+ // AAC_UNIDRC_SET_EFFECT
+ int32_t effectType = mIntf->getDrcEffectType();
+ ALOGV("AAC decoder using MPEG-D DRC effect type %d", effectType);
+ aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+
+ // AAC_UNIDRC_ALBUM_MODE
+ int32_t albumMode = mIntf->getDrcAlbumMode();
+ ALOGV("AAC decoder using MPEG-D DRC album mode %d", albumMode);
+ aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
+
mDrcWrap.update();
UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0];
@@ -763,6 +830,23 @@
}
}
ALOGV("size = %zu", size);
+
+ if (mStreamInfo->outputLoudness != prevOutLoudness) {
+ C2StreamDrcOutputLoudnessTuning::output
+ drcOutLoudness(0u, (float) (mStreamInfo->outputLoudness*-0.25));
+
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = mIntf->config(
+ { &drcOutLoudness },
+ C2_MAY_BLOCK,
+ &failures);
+ if (err == OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(drcOutLoudness));
+ } else {
+ ALOGE("Getting output loudness failed");
+ }
+ }
} while (decoderErr == AAC_DEC_OK);
}
diff --git a/media/codec2/components/aac/DrcPresModeWrap.cpp b/media/codec2/components/aac/DrcPresModeWrap.cpp
index 5b9aebc..bee969b 100644
--- a/media/codec2/components/aac/DrcPresModeWrap.cpp
+++ b/media/codec2/components/aac/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
mEncoderTarget = -1;
/* Values from last time. */
- /* Initialized to the same values as the desired values */
- mLastTarget = -1;
- mLastAttFactor = 0;
- mLastBoostFactor = 0;
+ mLastTarget = -2;
+ mLastAttFactor = -1;
+ mLastBoostFactor = -1;
mLastHeavy = 0;
}
@@ -163,7 +162,7 @@
if (mDataUpdate) {
// sanity check
- if (mDesTarget < MAX_TARGET_LEVEL){
+ if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
mDesTarget = MAX_TARGET_LEVEL; // limit target level to -10 dB or below
newTarget = MAX_TARGET_LEVEL;
}
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index f9eb2fa..74fdc8b 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -58,6 +58,8 @@
enum bitrate_mode_t : uint32_t; ///< bitrate control mode
enum drc_compression_mode_t : int32_t; ///< DRC compression mode
enum drc_effect_type_t : int32_t; ///< DRC effect type
+ enum drc_album_mode_t : int32_t; ///< DRC album mode
+ enum drc_output_loudness : int32_t; ///< DRC output loudness
enum intra_refresh_mode_t : uint32_t; ///< intra refresh modes
enum level_t : uint32_t; ///< coding level
enum ordinal_key_t : uint32_t; ///< work ordering keys
@@ -218,6 +220,8 @@
kParamIndexDrcBoostFactor, // drc, float (0-1)
kParamIndexDrcAttenuationFactor, // drc, float (0-1)
kParamIndexDrcEffectType, // drc, enum
+ kParamIndexDrcOutputLoudness, // drc, float (dBFS)
+ kParamIndexDrcAlbumMode, // drc, enum
/* ============================== platform-defined parameters ============================== */
@@ -1941,6 +1945,24 @@
C2StreamDrcEffectTypeTuning;
constexpr char C2_PARAMKEY_DRC_EFFECT_TYPE[] = "coding.drc.effect-type";
+/**
+ * DRC album mode. Used during decoding.
+ */
+C2ENUM(C2Config::drc_album_mode_t, int32_t,
+ DRC_ALBUM_MODE_OFF = 0,
+ DRC_ALBUM_MODE_ON = 1
+)
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<C2Config::drc_album_mode_t>, kParamIndexDrcAlbumMode>
+ C2StreamDrcAlbumModeTuning;
+constexpr char C2_PARAMKEY_DRC_ALBUM_MODE[] = "coding.drc.album-mode";
+
+/**
+ * DRC output loudness in dBFS. Retrieved during decoding
+ */
+ typedef C2StreamParam<C2Info, C2FloatValue, kParamIndexDrcOutputLoudness>
+ C2StreamDrcOutputLoudnessTuning;
+ constexpr char C2_PARAMKEY_DRC_OUTPUT_LOUDNESS[] = "output.drc.output-loudness";
+
/* --------------------------------------- AAC components --------------------------------------- */
/**
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index d2f5ea7..b019d0d 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -34,6 +34,8 @@
#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0 /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
+#define DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS -1 /* decoder output loudness; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
// names of properties that can be used to override the default DRC settings
#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
@@ -700,63 +702,101 @@
// convert to dBFS and add default
add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
- if (!v.get(&value) || value < 0) {
+ if (!v.get(&value) || value < -1) {
value = property_get_int32(PROP_DRC_OVERRIDE_REF_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL);
}
return float(-0.25 * c2_min(value, 127));
+ },[](C2Value v) -> C2Value {
+ float value;
+ if (v.get(&value)) {
+ return (int32_t) (-4. * value);
+ }
+ return C2Value();
}));
// convert to 0-1 (%) and add default
add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_CUT, DRC_DEFAULT_MOBILE_DRC_CUT);
}
return float(c2_min(value, 127) / 127.);
+ },[](C2Value v) -> C2Value {
+ float value;
+ if (v.get(&value)) {
+ return (int32_t) (value * 127. + 0.5);
+ }
+ else {
+ return C2Value();
+ }
}));
// convert to 0-1 (%) and add default
add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_BOOST, DRC_DEFAULT_MOBILE_DRC_BOOST);
}
return float(c2_min(value, 127) / 127.);
+ },[](C2Value v) -> C2Value {
+ float value;
+ if (v.get(&value)) {
+ return (int32_t) (value * 127. + 0.5);
+ }
+ else {
+ return C2Value();
+ }
}));
// convert to compression type and add default
add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY);
}
return value == 1 ? C2Config::DRC_COMPRESSION_HEAVY : C2Config::DRC_COMPRESSION_LIGHT;
+ },[](C2Value v) -> C2Value {
+ int32_t value;
+ if (v.get(&value)) {
+ return value;
+ }
+ else {
+ return C2Value();
+ }
}));
// convert to dBFS and add default
add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
value = property_get_int32(PROP_DRC_OVERRIDE_ENC_LEVEL, DRC_DEFAULT_MOBILE_ENC_LEVEL);
}
return float(-0.25 * c2_min(value, 127));
+ },[](C2Value v) -> C2Value {
+ float value;
+ if (v.get(&value)) {
+ return (int32_t) (-4. * value);
+ }
+ else {
+ return C2Value();
+ }
}));
// convert to effect type (these map to SDK values) and add default
add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value")
- .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
- .withMapper([](C2Value v) -> C2Value {
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < -1 || value > 8) {
value = property_get_int32(PROP_DRC_OVERRIDE_EFFECT, DRC_DEFAULT_MOBILE_DRC_EFFECT);
@@ -766,13 +806,60 @@
}
}
return value;
+ },[](C2Value v) -> C2Value {
+ int32_t value;
+ if (v.get(&value)) {
+ return value;
+ }
+ else {
+ return C2Value();
+ }
+ }));
+
+ // convert to album mode and add default
+ add(ConfigMapper(KEY_AAC_DRC_ALBUM_MODE, C2_PARAMKEY_DRC_ALBUM_MODE, "value")
+ .limitTo(D::AUDIO & D::DECODER & (D::CONFIG | D::PARAM | D::READ))
+ .withMappers([](C2Value v) -> C2Value {
+ int32_t value;
+ if (!v.get(&value) || value < 0 || value > 1) {
+ value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+ // ensure value is within range
+ if (value < 0 || value > 1) {
+ value = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+ }
+ }
+ return value;
+ },[](C2Value v) -> C2Value {
+ int32_t value;
+ if (v.get(&value)) {
+ return value;
+ }
+ else {
+ return C2Value();
+ }
+ }));
+
+ add(ConfigMapper(KEY_AAC_DRC_OUTPUT_LOUDNESS, C2_PARAMKEY_DRC_OUTPUT_LOUDNESS, "value")
+ .limitTo(D::OUTPUT & D::DECODER & D::READ)
+ .withMappers([](C2Value v) -> C2Value {
+ int32_t value;
+ if (!v.get(&value) || value < -1) {
+ value = DRC_DEFAULT_MOBILE_OUTPUT_LOUDNESS;
+ }
+ return float(-0.25 * c2_min(value, 127));
+ },[](C2Value v) -> C2Value {
+ float value;
+ if (v.get(&value)) {
+ return (int32_t) (-4. * value);
+ }
+ return C2Value();
}));
add(ConfigMapper(KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT, C2_PARAMKEY_MAX_CHANNEL_COUNT, "value")
- .limitTo(D::AUDIO));
+ .limitTo(D::AUDIO & (D::CONFIG | D::PARAM | D::READ)));
add(ConfigMapper(KEY_AAC_SBR_MODE, C2_PARAMKEY_AAC_SBR_MODE, "value")
- .limitTo(D::AUDIO & D::ENCODER & D::CONFIG)
+ .limitTo(D::AUDIO & D::ENCODER & (D::CONFIG | D::PARAM | D::READ))
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 91d2eff..abc3239 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -72,7 +72,7 @@
// Implement FixedBlockProcessor
int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
- int32_t numFrames = numBytes / getBytesPerDeviceFrame();
+ int32_t numFrames = numBytes / mBlockAdapterBytesPerFrame;
return (int32_t) callDataCallbackFrames(buffer, numFrames);
}
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
index 8e78554..da9205f 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.h
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -133,6 +133,7 @@
MonotonicCounter mTimestampPosition;
FixedBlockAdapter *mBlockAdapter = nullptr;
+ int32_t mBlockAdapterBytesPerFrame = 0;
aaudio_wrapping_frames_t mPositionWhenStarting = 0;
int32_t mCallbackBufferSize = 0;
const android::sp<StreamDeviceCallback> mDeviceCallback;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 2ed82d2..904edd1 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -213,7 +213,10 @@
// We may need to pass the data through a block size adapter to guarantee constant size.
if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
- int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+ // The block adapter runs before the format conversion.
+ // So we need to use the device frame size.
+ mBlockAdapterBytesPerFrame = getBytesPerDeviceFrame();
+ int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
mFixedBlockWriter.open(callbackSizeBytes);
mBlockAdapter = &mFixedBlockWriter;
} else {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 00963d6..d54d043 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -196,7 +196,10 @@
// We may need to pass the data through a block size adapter to guarantee constant size.
if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
- int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+ // This may need to change if we add format conversion before
+ // the block size adaptation.
+ mBlockAdapterBytesPerFrame = getBytesPerFrame();
+ int callbackSizeBytes = mBlockAdapterBytesPerFrame * mCallbackBufferSize;
mFixedBlockReader.open(callbackSizeBytes);
mBlockAdapter = &mFixedBlockReader;
} else {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1769062..2f67a18 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -842,13 +842,13 @@
return aps->handleDeviceConfigChange(device, address, name, encodedFormat);
}
-status_t AudioSystem::setPhoneState(audio_mode_t state)
+status_t AudioSystem::setPhoneState(audio_mode_t state, uid_t uid)
{
if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- return aps->setPhoneState(state);
+ return aps->setPhoneState(state, uid);
}
status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
@@ -879,6 +879,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -888,7 +889,7 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
- config,
+ opPackageName, config,
flags, selectedDeviceId, portId, secondaryOutputs);
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index cc78ec1..cccb131 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -170,11 +170,12 @@
return static_cast <status_t> (reply.readInt32());
}
- virtual status_t setPhoneState(audio_mode_t state)
+ virtual status_t setPhoneState(audio_mode_t state, uid_t uid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(state);
+ data.writeInt32(uid);
remote()->transact(SET_PHONE_STATE, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -213,6 +214,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -251,6 +253,7 @@
}
data.writeInt32(pid);
data.writeInt32(uid);
+ data.writeString16(opPackageName);
data.write(config, sizeof(audio_config_t));
data.writeInt32(static_cast <uint32_t>(flags));
data.writeInt32(*selectedDeviceId);
@@ -1596,7 +1599,8 @@
case SET_PHONE_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
reply->writeInt32(static_cast <uint32_t>(setPhoneState(
- (audio_mode_t) data.readInt32())));
+ (audio_mode_t) data.readInt32(),
+ (uid_t) data.readInt32())));
return NO_ERROR;
} break;
@@ -1643,6 +1647,11 @@
}
pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
+ String16 opPackageName;
+ status = data.readString16(&opPackageName);
+ if (status != NO_ERROR) {
+ return status;
+ }
audio_config_t config;
memset(&config, 0, sizeof(audio_config_t));
data.read(&config, sizeof(audio_config_t));
@@ -1654,7 +1663,7 @@
std::vector<audio_io_handle_t> secondaryOutputs;
status = getOutputForAttr(&attr,
&output, session, &stream, pid, uid,
- &config,
+ opPackageName, &config,
flags, &selectedDeviceId, &portId, &secondaryOutputs);
reply->writeInt32(status);
status = reply->write(&attr, sizeof(audio_attributes_t));
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9d3f8b6..07a2292 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -230,7 +230,7 @@
const char *device_address,
const char *device_name,
audio_format_t encodedFormat);
- static status_t setPhoneState(audio_mode_t state);
+ static status_t setPhoneState(audio_mode_t state, uid_t uid);
static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
@@ -240,6 +240,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 8bc1d83..8658cfa 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -70,6 +70,7 @@
if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
return DEAD_OBJECT;
}
+ opPackageName = parcel->readString16();
if (parcel->readInt32() != 0) {
// TODO: Using unsecurePointer() has some associated security
// pitfalls (see declaration for details).
@@ -97,6 +98,7 @@
(void)parcel->write(&attr, sizeof(audio_attributes_t));
(void)parcel->write(&config, sizeof(audio_config_t));
(void)clientInfo.writeToParcel(parcel);
+ (void)parcel->writeString16(opPackageName);
if (sharedBuffer != 0) {
(void)parcel->writeInt32(1);
(void)parcel->writeStrongBinder(IInterface::asBinder(sharedBuffer));
@@ -119,6 +121,7 @@
audio_attributes_t attr;
audio_config_t config;
AudioClient clientInfo;
+ String16 opPackageName;
sp<IMemory> sharedBuffer;
uint32_t notificationsPerBuffer;
float speed;
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index caa1d13..779ca43 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -53,7 +53,7 @@
const char *device_address,
const char *device_name,
audio_format_t encodedFormat) = 0;
- virtual status_t setPhoneState(audio_mode_t state) = 0;
+ virtual status_t setPhoneState(audio_mode_t state, uid_t uid) = 0;
virtual status_t setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config) = 0;
virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
@@ -64,6 +64,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 1a6a5a2..39b0ceb 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -19,6 +19,25 @@
// uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
// "-DUSE_NEON=false",
],
+
+ arch: {
+ x86: {
+ avx2: {
+ cflags: [
+ "-mavx2",
+ "-mfma",
+ ],
+ },
+ },
+ x86_64: {
+ avx2: {
+ cflags: [
+ "-mavx2",
+ "-mfma",
+ ],
+ },
+ },
+ },
}
cc_library_shared {
diff --git a/media/libaudioprocessing/AudioResamplerFirOps.h b/media/libaudioprocessing/AudioResamplerFirOps.h
index 2e4cee3..a3f5ff5 100644
--- a/media/libaudioprocessing/AudioResamplerFirOps.h
+++ b/media/libaudioprocessing/AudioResamplerFirOps.h
@@ -36,13 +36,20 @@
#include <arm_neon.h>
#endif
-#if defined(__SSSE3__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#if defined(__AVX2__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_AVX2 (true) // Inference AVX2/FMA Intrinsics
#define USE_SSE (true)
+#include <immintrin.h>
+#elif defined(__SSSE3__) // Should be supported in x86 ABI for both 32 & 64-bit.
+#define USE_SSE (true) // Inference SSE Intrinsics
+#define USE_AVX2 (false)
#include <tmmintrin.h>
#else
#define USE_SSE (false)
+#define USE_AVX2(false)
#endif
+
template<typename T, typename U>
struct is_same
{
diff --git a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
index 30233b5..1c16bc4 100644
--- a/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
+++ b/media/libaudioprocessing/AudioResamplerFirProcessSSE.h
@@ -80,11 +80,16 @@
posCoef1 = _mm_sub_ps(posCoef1, posCoef);
negCoef = _mm_sub_ps(negCoef, negCoef1);
+
+ #if USE_AVX2
+ posCoef = _mm_fmadd_ps(posCoef1, interp, posCoef);
+ negCoef = _mm_fmadd_ps(negCoef, interp, negCoef1);
+ #else
posCoef1 = _mm_mul_ps(posCoef1, interp);
negCoef = _mm_mul_ps(negCoef, interp);
-
posCoef = _mm_add_ps(posCoef1, posCoef);
negCoef = _mm_add_ps(negCoef, negCoef1);
+ #endif //USE_AVX2
}
switch (CHANNELS) {
case 1: {
@@ -94,11 +99,17 @@
sN += 4;
posSamp = _mm_shuffle_ps(posSamp, posSamp, 0x1B);
+
+ #if USE_AVX2
+ accL = _mm_fmadd_ps(posSamp, posCoef, accL);
+ accL = _mm_fmadd_ps(negSamp, negCoef, accL);
+ #else
posSamp = _mm_mul_ps(posSamp, posCoef);
negSamp = _mm_mul_ps(negSamp, negCoef);
-
accL = _mm_add_ps(accL, posSamp);
accL = _mm_add_ps(accL, negSamp);
+ #endif
+
} break;
case 2: {
__m128 posSamp0 = _mm_loadu_ps(sP);
@@ -114,15 +125,23 @@
__m128 negSampL = _mm_shuffle_ps(negSamp0, negSamp1, 0x88);
__m128 negSampR = _mm_shuffle_ps(negSamp0, negSamp1, 0xDD);
- posSampL = _mm_mul_ps(posSampL, posCoef);
- posSampR = _mm_mul_ps(posSampR, posCoef);
- negSampL = _mm_mul_ps(negSampL, negCoef);
- negSampR = _mm_mul_ps(negSampR, negCoef);
+ #if USE_AVX2
+ accL = _mm_fmadd_ps(posSampL, posCoef, accL);
+ accR = _mm_fmadd_ps(posSampR, posCoef, accR);
+ accL = _mm_fmadd_ps(negSampL, negCoef, accL);
+ accR = _mm_fmadd_ps(negSampR, negCoef, accR);
+ #else
+ posSampL = _mm_mul_ps(posSampL, posCoef);
+ posSampR = _mm_mul_ps(posSampR, posCoef);
+ negSampL = _mm_mul_ps(negSampL, negCoef);
+ negSampR = _mm_mul_ps(negSampR, negCoef);
- accL = _mm_add_ps(accL, posSampL);
- accR = _mm_add_ps(accR, posSampR);
- accL = _mm_add_ps(accL, negSampL);
- accR = _mm_add_ps(accR, negSampR);
+ accL = _mm_add_ps(accL, posSampL);
+ accR = _mm_add_ps(accR, posSampR);
+ accL = _mm_add_ps(accL, negSampL);
+ accR = _mm_add_ps(accR, negSampR);
+ #endif
+
} break;
}
} while (count -= 4);
@@ -144,9 +163,13 @@
outAccum = _mm_hadd_ps(accL, accR);
outAccum = _mm_hadd_ps(outAccum, outAccum);
}
-
+ #if USE_AVX2
+ outSamp = _mm_fmadd_ps(outAccum, vLR,outSamp);
+ #else
outAccum = _mm_mul_ps(outAccum, vLR);
outSamp = _mm_add_ps(outSamp, outAccum);
+ #endif
+
_mm_storel_pi(reinterpret_cast<__m64*>(out), outSamp);
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index cc9643d..53feae8 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -115,8 +115,7 @@
* Setup the high pass filter
*/
LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pInstance->pData->HPFTaps, /* Destination */
sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
&pInstance->pData->HPFTaps,
@@ -126,8 +125,7 @@
* Setup the band pass filter
*/
LoadConst_Float(0, /* Clear the history, value 0 */
- (LVM_FLOAT *)&pInstance->pData->BPFTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pInstance->pData->BPFTaps, /* Destination */
sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
&pInstance->pData->BPFTaps,
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 86a4ca2..1f0d39b 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -83,8 +83,7 @@
FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs,
&pPrivate->pFastData->HPTaps, &Coeffs);
LoadConst_Float(0,
- (LVM_FLOAT *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pPrivate->pFastData->HPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
}
@@ -116,8 +115,7 @@
FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs,
&pPrivate->pFastData->LPTaps, &Coeffs);
LoadConst_Float(0,
- (LVM_FLOAT *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pPrivate->pFastData->LPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 8b38a16..586539f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -60,12 +60,10 @@
*/
LoadConst_Float(0,
- (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pLVREV_Private->pFastData->HPTaps,
2);
LoadConst_Float(0,
- (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: \
- no dereferencing in function*/
+ (LVM_FLOAT *)&pLVREV_Private->pFastData->LPTaps,
2);
if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
{
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index ecf949d..431b7e3 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -91,8 +91,7 @@
Coeffs.B2 = (LVM_FLOAT)-pEqualiserCoefTable[Offset].B2;
LoadConst_Float((LVM_INT16)0, /* Value */
- (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->EqualiserBiquadTaps, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps) / sizeof(LVM_FLOAT)));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index 68a7120..d0e6e09 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -109,8 +109,7 @@
Coeffs.B2 = (LVM_FLOAT)-pReverbCoefTable[Offset].B2;
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination Cast to void:
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->ReverbBiquadTaps, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->ReverbBiquadTaps) / sizeof(LVM_FLOAT)));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index 9cfc9a0..7fd8444 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -87,8 +87,7 @@
/* Clear the taps */
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->SEBiquadTapsMid, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->SEBiquadTapsMid, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->SEBiquadTapsMid) / sizeof(LVM_FLOAT)));
@@ -115,8 +114,7 @@
/* Clear the taps */
LoadConst_Float(0, /* Value */
- (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
- no dereferencing in function*/
+ (LVM_FLOAT *)&pData->SEBiquadTapsSide, /* Destination */
/* Number of words */
(LVM_UINT16)(sizeof(pData->SEBiquadTapsSide) / sizeof(LVM_FLOAT)));
/* Callbacks */
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 960120f..73d3a0b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2181,12 +2181,20 @@
}
if (!msg->findInt32("aac-target-ref-level", &drc.targetRefLevel)) {
// value is unknown
- drc.targetRefLevel = -1;
+ drc.targetRefLevel = -2;
}
if (!msg->findInt32("aac-drc-effect-type", &drc.effectType)) {
// value is unknown
drc.effectType = -2; // valid values are -1 and over
}
+ if (!msg->findInt32("aac-drc-album-mode", &drc.albumMode)) {
+ // value is unknown
+ drc.albumMode = -1; // valid values are 0 and 1
+ }
+ if (!msg->findInt32("aac-drc-output-loudness", &drc.outputLoudness)) {
+ // value is unknown
+ drc.outputLoudness = -1;
+ }
err = setupAACCodec(
encoder, numChannels, sampleRate, bitrate, aacProfile,
@@ -2876,6 +2884,8 @@
presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
presentation.nPCMLimiterEnable = pcmLimiterEnable;
presentation.nDrcEffectType = drc.effectType;
+ presentation.nDrcAlbumMode = drc.albumMode;
+ presentation.nDrcOutputLoudness = drc.outputLoudness;
status_t res = mOMXNode->setParameter(
OMX_IndexParamAudioAac, &profile, sizeof(profile));
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index d75b317..3c4524b 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -647,7 +647,9 @@
crop_left, crop_top, crop_right, crop_bottom,
mFrame->getFlattenedData(),
mFrame->mWidth, mFrame->mHeight, mFrame->mRowBytes,
- crop_left, crop_top, crop_right, crop_bottom);
+ // since the frame is allocated with top-left adjusted,
+ // the dst rect should start at {0,0} as well.
+ 0, 0, mFrame->mWidth - 1, mFrame->mHeight - 1);
return OK;
}
diff --git a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
index 95d3724..168d140 100644
--- a/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
+++ b/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp
@@ -47,10 +47,9 @@
mEncoderTarget = -1;
/* Values from last time. */
- /* Initialized to the same values as the desired values */
- mLastTarget = -1;
- mLastAttFactor = 0;
- mLastBoostFactor = 0;
+ mLastTarget = -2;
+ mLastAttFactor = -1;
+ mLastBoostFactor = -1;
mLastHeavy = 0;
}
@@ -163,7 +162,7 @@
if (mDataUpdate) {
// sanity check
- if (mDesTarget < MAX_TARGET_LEVEL){
+ if ((mDesTarget < MAX_TARGET_LEVEL) && (mDesTarget != -1)){
mDesTarget = MAX_TARGET_LEVEL; // limit target level to -10 dB or below
newTarget = MAX_TARGET_LEVEL;
}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 41bc16c..2aeddd7 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -37,6 +37,7 @@
#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_EFFECT 3 /* MPEG-D DRC effect type; 3 => Limited playback range */
+#define DRC_DEFAULT_MOBILE_DRC_ALBUM 0 /* MPEG-D DRC album mode; 0 => album mode is disabled, 1 => album mode is enabled */
#define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */
#define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */
// names of properties that can be used to override the default DRC settings
@@ -219,6 +220,11 @@
ALOGV("AAC decoder using MPEG-D DRC effect type %d (default=%d)",
effectType, DRC_DEFAULT_MOBILE_DRC_EFFECT);
aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, effectType);
+ // AAC_UNIDRC_ALBUM_MODE
+ int32_t albumMode = DRC_DEFAULT_MOBILE_DRC_ALBUM;
+ ALOGV("AAC decoder using MPEG-D Album mode value %d (default=%d)", albumMode,
+ DRC_DEFAULT_MOBILE_DRC_ALBUM);
+ aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE, albumMode);
// By default, the decoder creates a 5.1 channel downmix signal.
// For seven and eight channel input streams, enable 6.1 and 7.1 channel output
@@ -459,6 +465,11 @@
ALOGV("set nDrcEffectType=%d", aacPresParams->nDrcEffectType);
aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_SET_EFFECT, aacPresParams->nDrcEffectType);
}
+ if (aacPresParams->nDrcAlbumMode >= -1) {
+ ALOGV("set nDrcAlbumMode=%d", aacPresParams->nDrcAlbumMode);
+ aacDecoder_SetParam(mAACDecoder, AAC_UNIDRC_ALBUM_MODE,
+ aacPresParams->nDrcAlbumMode);
+ }
bool updateDrcWrapper = false;
if (aacPresParams->nDrcBoost >= 0) {
ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost);
@@ -477,7 +488,7 @@
aacPresParams->nHeavyCompression);
updateDrcWrapper = true;
}
- if (aacPresParams->nTargetReferenceLevel >= 0) {
+ if (aacPresParams->nTargetReferenceLevel >= -1) {
ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel);
mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET,
aacPresParams->nTargetReferenceLevel);
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
new file mode 100644
index 0000000..b9a8117
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+ name: "Mpeg4H263EncoderTest",
+ gtest: true,
+
+ srcs : [ "Mpeg4H263EncoderTest.cpp" ],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ ],
+
+ static_libs: [
+ "libstagefright_m4vh263enc",
+ ],
+
+ cflags: [
+ "-DOSCL_IMPORT_REF=",
+ "-Wall",
+ "-Werror",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "signed-integer-overflow",
+ "unsigned-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
new file mode 100644
index 0000000..5218932
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test module config for MPEG4H263 encoder unit tests">
+ <option name="test-suite-tag" value="Mpeg4H263EncoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
+ value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="Mpeg4H263EncoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
new file mode 100644
index 0000000..78c705a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Mpeg4H263EncoderTest"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "mp4enc_api.h"
+
+#include "Mpeg4H263EncoderTestEnvironment.h"
+
+#define ENCODED_FILE "/data/local/tmp/Mpeg4H263Output"
+
+// assuming a worst case compression of 2X
+constexpr int16_t kCompressionRatio = 2;
+constexpr int8_t kIDRFrameRefreshIntervalInSec = 1;
+
+static Mpeg4H263EncoderTestEnvironment *gEnv = nullptr;
+
+class Mpeg4H263EncoderTest
+ : public ::testing::TestWithParam<tuple<string, bool, int32_t, int32_t, float, int32_t>> {
+ private:
+ void initEncoderParams();
+
+ public:
+ Mpeg4H263EncoderTest()
+ : mInputBuffer(nullptr),
+ mOutputBuffer(nullptr),
+ mFpInput(nullptr),
+ mFpOutput(nullptr),
+ mEncodeHandle(nullptr),
+ mEncodeControl(nullptr) {}
+
+ ~Mpeg4H263EncoderTest() {
+ if(mFpInput) {
+ fclose(mFpInput);
+ }
+ if(mFpOutput) {
+ fclose(mFpOutput);
+ }
+ if(mInputBuffer) free(mInputBuffer);
+ if(mOutputBuffer) free(mOutputBuffer);
+ if(mEncodeHandle) free(mEncodeHandle);
+ if(mEncodeControl) free(mEncodeControl);
+ }
+
+ void SetUp() override {
+ tuple<string /* fileName */, bool /* isMpeg4 */, int32_t /* frameWidth */,
+ int32_t /* frameHeight */, float /* frameRate */, int32_t /* bitRate */>
+ params = GetParam();
+ mFileName = gEnv->getRes() + get<0>(params);
+ mIsMpeg4 = get<1>(params);
+ mFrameWidth = get<2>(params);
+ mFrameHeight = get<3>(params);
+ mFrameRate = get<4>(params);
+ mBitRate = get<5>(params);
+
+ ASSERT_TRUE(mFrameWidth % 16 == 0) << "Frame Width should be multiple of 16";
+ ASSERT_TRUE(mFrameHeight % 16 == 0) << "Frame Height should be multiple of 16";
+ ASSERT_LE(mFrameWidth, (mIsMpeg4 ? 720 : 352))
+ << "Frame Width <= 720 for Mpeg4 and <= 352 for H263";
+ ASSERT_LE(mFrameHeight, (mIsMpeg4 ? 480 : 288))
+ << "Frame Height <= 480 for Mpeg4 and <= 288 for H263";
+ ASSERT_LE(mFrameRate, 30) << "Frame rate less than or equal to 30";
+ ASSERT_LE(mBitRate, 2048) << "Bit rate less than or equal to 2048 kbps";
+
+ mOutputBufferSize = ( mFrameWidth * mFrameHeight * 3/2 ) / kCompressionRatio;
+ mEncodeHandle = new VideoEncOptions;
+ ASSERT_NE(mEncodeHandle, nullptr) << "Failed to get Video Encoding options object";
+ memset(mEncodeHandle, 0, sizeof(VideoEncOptions));
+ mEncodeControl = new VideoEncControls;
+ ASSERT_NE(mEncodeControl, nullptr) << "Failed to get Video Encoding control object";
+ memset(mEncodeControl, 0, sizeof(VideoEncControls));
+ ASSERT_NO_FATAL_FAILURE(initEncoderParams())
+ << "Failed to get the default Encoding parameters!";
+ }
+
+ int64_t getTotalFrames();
+ void processEncoder(int32_t);
+ bool mIsMpeg4;
+ int32_t mFrameWidth, mFrameHeight, mBitRate;
+ int64_t mOutputBufferSize;
+ float mFrameRate;
+ string mFileName;
+ uint8_t *mInputBuffer, *mOutputBuffer;
+ FILE *mFpInput, *mFpOutput;
+ VideoEncOptions *mEncodeHandle;
+ VideoEncControls *mEncodeControl;
+};
+
+void Mpeg4H263EncoderTest::initEncoderParams() {
+ bool status = PVGetDefaultEncOption(mEncodeHandle, 0);
+ ASSERT_TRUE(status);
+
+ mEncodeHandle->rcType = VBR_1;
+ mEncodeHandle->vbvDelay = 5.0f;
+ mEncodeHandle->profile_level = CORE_PROFILE_LEVEL2;
+ mEncodeHandle->packetSize = 32;
+ mEncodeHandle->rvlcEnable = PV_OFF;
+ mEncodeHandle->numLayers = 1;
+ mEncodeHandle->timeIncRes = 1000;
+ mEncodeHandle->iQuant[0] = 15;
+ mEncodeHandle->pQuant[0] = 12;
+ mEncodeHandle->quantType[0] = 0;
+ mEncodeHandle->noFrameSkipped = PV_OFF;
+ mEncodeHandle->numIntraMB = 0;
+ mEncodeHandle->sceneDetect = PV_ON;
+ mEncodeHandle->searchRange = 16;
+ mEncodeHandle->mv8x8Enable = PV_OFF;
+ mEncodeHandle->gobHeaderInterval = 0;
+ mEncodeHandle->useACPred = PV_ON;
+ mEncodeHandle->intraDCVlcTh = 0;
+ if(!mIsMpeg4) {
+ mEncodeHandle->encMode = H263_MODE;
+ } else {
+ mEncodeHandle->encMode = COMBINE_MODE_WITH_ERR_RES;
+ }
+ mEncodeHandle->encWidth[0] = mFrameWidth;
+ mEncodeHandle->encHeight[0] = mFrameHeight;
+ mEncodeHandle->encFrameRate[0] = mFrameRate;
+ mEncodeHandle->bitRate[0] = mBitRate * 1024;
+ mEncodeHandle->tickPerSrc = mEncodeHandle->timeIncRes / mFrameRate;
+ if (kIDRFrameRefreshIntervalInSec == 0) {
+ // All I frames.
+ mEncodeHandle->intraPeriod = 1;
+ } else {
+ mEncodeHandle->intraPeriod = (kIDRFrameRefreshIntervalInSec * mFrameRate);
+ }
+}
+
+int64_t Mpeg4H263EncoderTest::getTotalFrames() {
+ int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+ struct stat buf;
+ stat(mFileName.c_str(), &buf);
+ size_t fileSize = buf.st_size;
+ int64_t totalFrames = (int64_t)(fileSize/frameSize);
+ return totalFrames;
+}
+
+void Mpeg4H263EncoderTest::processEncoder(int32_t numFramesToEncode) {
+ bool status;
+ int64_t numEncodedFrames = 0;
+ int32_t bytesRead;
+ int32_t frameSize = (mFrameWidth * mFrameHeight * 3) / 2;
+ while(numFramesToEncode != 0) {
+ bytesRead = fread(mInputBuffer, 1, frameSize, mFpInput);
+ // End of file.
+ if (bytesRead != frameSize) {
+ break;
+ }
+
+ VideoEncFrameIO videoIn, videoOut;
+ videoIn.height = mFrameHeight;
+ videoIn.pitch = mFrameWidth;
+ videoIn.timestamp = (numEncodedFrames * 1000) / mFrameRate; // in ms.
+ videoIn.yChan = mInputBuffer;
+ videoIn.uChan = videoIn.yChan + videoIn.height * videoIn.pitch;
+ videoIn.vChan = videoIn.uChan + ((videoIn.height * videoIn.pitch) >> 2);
+ uint32_t modTimeMs = 0;
+ int32_t dataLength = mOutputBufferSize;
+ int32_t nLayer = 0;
+ status = PVEncodeVideoFrame(mEncodeControl, &videoIn, &videoOut, &modTimeMs, mOutputBuffer,
+ &dataLength, &nLayer);
+ ASSERT_TRUE(status) << "Failed to Encode: " << mFileName;
+
+ MP4HintTrack hintTrack;
+ status = PVGetHintTrack(mEncodeControl, &hintTrack);
+ ASSERT_TRUE(status) << "Failed to get hint track!";
+ UChar *overrunBuffer = PVGetOverrunBuffer(mEncodeControl);
+ ASSERT_EQ(overrunBuffer, nullptr) << "Overrun of buffer!";
+
+ int64_t numBytes = fwrite(mOutputBuffer, 1, dataLength, mFpOutput);
+ ASSERT_EQ(numBytes, dataLength) << "Failed to write to the output file!";
+ numEncodedFrames++;
+ numFramesToEncode--;
+ }
+}
+
+TEST_P(Mpeg4H263EncoderTest, EncodeTest) {
+ mInputBuffer = (uint8_t *)malloc((mFrameWidth * mFrameWidth * 3) / 2);
+ ASSERT_NE(mInputBuffer, nullptr) << "Failed to allocate the input buffer!";
+
+ mOutputBuffer = (uint8_t *)malloc(mOutputBufferSize);
+ ASSERT_NE(mOutputBuffer, nullptr) << "Failed to allocate the output buffer!";
+
+ mFpInput = fopen(mFileName.c_str(), "rb");
+ ASSERT_NE(mFpInput, nullptr) << "Failed to open the input file: " << mFileName;
+
+ mFpOutput = fopen(ENCODED_FILE, "wb");
+ ASSERT_NE(mFpOutput, nullptr) << "Failed to open the output file:" << ENCODED_FILE;
+
+ bool status = PVInitVideoEncoder(mEncodeControl, mEncodeHandle);
+ ASSERT_TRUE(status) << "Failed to initialize the encoder!";
+
+ // Get VOL header.
+ int32_t size = mOutputBufferSize;
+ status = PVGetVolHeader(mEncodeControl, mOutputBuffer, &size, 0);
+ ASSERT_TRUE(status) << "Failed to get the VOL header!";
+
+ // Write the VOL header on the first frame.
+ int32_t numBytes = fwrite(mOutputBuffer, 1, size, mFpOutput);
+ ASSERT_EQ(numBytes, size) << "Failed to write the VOL header!";
+
+ int64_t totalFrames = getTotalFrames();
+ ASSERT_NO_FATAL_FAILURE(processEncoder(totalFrames)) << "Failed to Encode: " << mFileName;
+ status = PVCleanUpVideoEncoder(mEncodeControl);
+ ASSERT_TRUE(status) << "Failed to clean up the encoder resources!";
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EncodeTest, Mpeg4H263EncoderTest,
+ ::testing::Values(
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 352, 288, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 352, 288, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", false, 176, 144, 25, 1024),
+ make_tuple("bbb_352x288_420p_30fps_32frames.yuv", true, 176, 144, 25, 1024),
+ make_tuple("football_qvga.yuv", false, 352, 288, 25, 1024),
+ make_tuple("football_qvga.yuv", true, 352, 288, 25, 1024),
+ make_tuple("football_qvga.yuv", false, 176, 144, 30, 1024),
+ make_tuple("football_qvga.yuv", true, 176, 144, 30, 1024)));
+
+int32_t main(int argc, char **argv) {
+ gEnv = new Mpeg4H263EncoderTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ uint8_t status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGI("Encoder Test Result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
new file mode 100644
index 0000000..7ee36e0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+#define __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class Mpeg4H263EncoderTestEnvironment : public::testing::Environment {
+ public:
+ Mpeg4H263EncoderTestEnvironment() : res("/data/local/tmp/Mpeg4H263EncoderTest/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int Mpeg4H263EncoderTestEnvironment::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 // __MPEG4_H263_ENCODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/codecs/m4v_h263/enc/test/README.md b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
new file mode 100644
index 0000000..25de878
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/test/README.md
@@ -0,0 +1,38 @@
+## Media Testing ##
+---
+
+#### Mpeg4H263Encoder :
+The Mpeg4H263Encoder Test Suite validates the Mpeg4 and H263 encoder available in libstagefright.
+Run the following steps to build the test suite:
+```
+m Mpeg4H263EncoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/Mpeg4H263EncoderTest/Mpeg4H263EncoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip ) Download, unzip and push these files into device for testing.
+
+```
+adb push Mpeg4H263Encoder/. /data/local/tmp/
+```
+
+usage: Mpeg4H263EncoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/Mpeg4H263EncoderTest -P /data/local/tmp/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest Mpeg4H263EncoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/libstagefright/flac/dec/test/Android.bp
new file mode 100644
index 0000000..70ca80a
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/Android.bp
@@ -0,0 +1,50 @@
+/*
+ * 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: "FlacDecoderTest",
+ gtest: true,
+
+ srcs: [
+ "FlacDecoderTest.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ ],
+
+ static_libs: [
+ "libstagefright_flacdec",
+ "libFLAC",
+ ],
+
+ header_libs: [
+ "libstagefright_foundation_headers",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ cfi: true,
+ },
+}
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/libstagefright/flac/dec/test/AndroidTest.xml
new file mode 100644
index 0000000..bebba8e
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test module config for flac decoder unit tests">
+ <option name="test-suite-tag" value="FlacDecoderTest" />
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
+ <option name="push-file"
+ key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
+ value="/data/local/tmp/FlacDecoderTestRes/" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="FlacDecoderTest" />
+ <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
new file mode 100644
index 0000000..34f12db
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
@@ -0,0 +1,270 @@
+/*
+ * 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 "FlacDecoderTest"
+
+#include <utils/Log.h>
+#include <fstream>
+
+#include "FLACDecoder.h"
+
+#include "FlacDecoderTestEnvironment.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/FlacDecoderOutput.raw"
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCount = 10;
+constexpr int32_t kMaxBlockSize = 4096;
+
+using namespace android;
+
+struct FrameInfo {
+ int32_t bytesCount;
+ uint32_t flags;
+ int64_t timestamp;
+};
+
+static FlacDecoderTestEnvironment *gEnv = nullptr;
+
+class FLACDecoderTest : public ::testing::TestWithParam<tuple<string, string, bool>> {
+ public:
+ FLACDecoderTest() : mFLACDecoder(nullptr), mHasStreamInfo(false), mInputBufferCount(0) {}
+
+ ~FLACDecoderTest() {
+ if (mEleStream.is_open()) mEleStream.close();
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+ }
+
+ virtual void SetUp() override {
+ mFLACDecoder = FLACDecoder::Create();
+ ASSERT_NE(mFLACDecoder, nullptr) << "initDecoder: failed to create FLACDecoder";
+ }
+
+ int32_t processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+ bool outputFloat, ofstream &ostrm);
+
+ FLACDecoder *mFLACDecoder;
+ FLAC__StreamMetadata_StreamInfo mStreamInfo;
+
+ bool mHasStreamInfo;
+ int32_t mInputBufferCount;
+ ifstream mEleStream;
+};
+
+void getInfo(string infoFileName, vector<FrameInfo> &Info) {
+ ifstream eleInfo;
+ eleInfo.open(infoFileName);
+ ASSERT_EQ(eleInfo.is_open(), true);
+ int32_t bytesCount = 0;
+ uint32_t flags = 0;
+ uint32_t timestamp = 0;
+ while (1) {
+ if (!(eleInfo >> bytesCount)) break;
+ eleInfo >> flags;
+ eleInfo >> timestamp;
+ Info.push_back({bytesCount, flags, timestamp});
+ }
+ if (eleInfo.is_open()) eleInfo.close();
+}
+
+int32_t FLACDecoderTest::processFlacDecoder(vector<FrameInfo> Info, int32_t offset, int32_t range,
+ bool outputFloat, ofstream &ostrm) {
+ memset(&mStreamInfo, 0, sizeof(mStreamInfo));
+
+ int32_t frameID = offset;
+ if (range + offset > Info.size() || range < 0 || offset > Info.size() - 1 || offset < 0) {
+ ALOGE("Invalid offset or range or both passed for decoding");
+ ALOGE("offset = %d \t range = %d \t Info.size() = %zu", offset, range, Info.size());
+ return -1;
+ }
+
+ while (1) {
+ if (frameID == Info.size() || frameID == (offset + range)) break;
+ int64_t flags = (Info)[frameID].flags;
+ int32_t size = (Info)[frameID].bytesCount;
+ if (size < 0) {
+ ALOGE("Size for the memory allocation is negative");
+ return -1;
+ }
+ char *data = (char *)malloc(size);
+ if (!data) {
+ ALOGE("Insufficient memory to read frame");
+ return -1;
+ }
+
+ mEleStream.read(data, size);
+ if (mEleStream.gcount() != size) {
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ ALOGE("Invalid size read, requested: %d and read: %zu", size, mEleStream.gcount());
+ return -1;
+ }
+
+ if (flags == CODEC_CONFIG_FLAG && mInputBufferCount == 0) {
+ status_t decoderErr = mFLACDecoder->parseMetadata((uint8_t *)data, size);
+ if (decoderErr == WOULD_BLOCK) {
+ ALOGV("process: parseMetadata is Blocking, Continue %d", decoderErr);
+ } else if (decoderErr == OK) {
+ mStreamInfo = mFLACDecoder->getStreamInfo();
+ if (mStreamInfo.sample_rate && mStreamInfo.max_blocksize && mStreamInfo.channels) {
+ mHasStreamInfo = true;
+ }
+ ALOGV("decoder configuration : %d Hz, %d channels, %d samples,"
+ " %d block size",
+ mStreamInfo.sample_rate, mStreamInfo.channels,
+ (int32_t)mStreamInfo.total_samples, mStreamInfo.max_blocksize);
+ } else {
+ ALOGE("FLACDecoder parseMetaData returns error %d", decoderErr);
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ return decoderErr;
+ }
+ } else {
+ const size_t sampleSize = outputFloat ? sizeof(float) : sizeof(int16_t);
+ size_t outSize = mHasStreamInfo
+ ? mStreamInfo.max_blocksize * mStreamInfo.channels * sampleSize
+ : kMaxBlockSize * FLACDecoder::kMaxChannels * sampleSize;
+
+ void *out_buf = malloc(outSize);
+ if (!out_buf) {
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ ALOGE("Output buffer allocation failed");
+ return -1;
+ }
+ status_t decoderErr = mFLACDecoder->decodeOneFrame((uint8_t *)data, size, out_buf,
+ &outSize, outputFloat);
+ if (decoderErr != OK) {
+ ALOGE("decodeOneFrame returns error %d", decoderErr);
+ if (data) {
+ free(data);
+ data = nullptr;
+ }
+ if (out_buf) {
+ free(out_buf);
+ out_buf = nullptr;
+ }
+ return decoderErr;
+ }
+ ostrm.write(reinterpret_cast<char *>(out_buf), outSize);
+ free(out_buf);
+ out_buf = nullptr;
+ }
+ mInputBufferCount++;
+ frameID++;
+ free(data);
+ data = nullptr;
+ }
+ ALOGV("frameID=%d", frameID);
+ return 0;
+}
+
+TEST_F(FLACDecoderTest, CreateDeleteTest) {
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+
+ for (int32_t i = 0; i < kMaxCount; i++) {
+ mFLACDecoder = FLACDecoder::Create();
+ ASSERT_NE(mFLACDecoder, nullptr) << "FLACDecoder Creation Failed";
+ if (mFLACDecoder) delete mFLACDecoder;
+ mFLACDecoder = nullptr;
+ }
+}
+
+TEST_P(FLACDecoderTest, FlushTest) {
+ tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+ GetParam();
+
+ string inputFileName = gEnv->getRes() + get<0>(params);
+ string infoFileName = gEnv->getRes() + get<1>(params);
+ bool outputFloat = get<2>(params);
+
+ vector<FrameInfo> Info;
+ getInfo(infoFileName, Info);
+
+ mEleStream.open(inputFileName, ifstream::binary);
+ ASSERT_EQ(mEleStream.is_open(), true);
+
+ ofstream ostrm;
+ ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+ ASSERT_EQ(ostrm.is_open(), true);
+
+ int32_t status = processFlacDecoder(Info, 0, Info.size() / 3, outputFloat, ostrm);
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+ mFLACDecoder->flush();
+ mHasStreamInfo = false;
+ status = processFlacDecoder(Info, (Info.size() / 3), Info.size() - (Info.size() / 3),
+ outputFloat, ostrm);
+ ostrm.close();
+ Info.clear();
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+TEST_P(FLACDecoderTest, DecodeTest) {
+ tuple<string /* InputFileName */, string /* InfoFileName */, bool /* outputfloat */> params =
+ GetParam();
+
+ string inputFileName = gEnv->getRes() + get<0>(params);
+ string infoFileName = gEnv->getRes() + get<1>(params);
+ bool outputFloat = get<2>(params);
+
+ vector<FrameInfo> Info;
+ getInfo(infoFileName, Info);
+
+ mEleStream.open(inputFileName, ifstream::binary);
+ ASSERT_EQ(mEleStream.is_open(), true);
+
+ ofstream ostrm;
+ ostrm.open(OUTPUT_FILE_NAME, std::ofstream::binary);
+ ASSERT_EQ(ostrm.is_open(), true);
+
+ int32_t status = processFlacDecoder(Info, 0, Info.size(), outputFloat, ostrm);
+ ostrm.close();
+ Info.clear();
+ ASSERT_EQ(status, 0) << "Test Failed. Decode returned error = " << status << endl;
+}
+
+// TODO: Add remaining tests
+INSTANTIATE_TEST_SUITE_P(
+ FLACDecoderTestAll, FLACDecoderTest,
+ ::testing::Values(make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+ "bbb_flac_stereo_680kbps_48000hz.info", true),
+ make_tuple("bbb_flac_stereo_680kbps_48000hz.flac",
+ "bbb_flac_stereo_680kbps_48000hz.info", false),
+ make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+ "bbb_flac_stereo_600kbps_44100hz.info", true),
+ make_tuple("bbb_flac_stereo_600kbps_44100hz.flac",
+ "bbb_flac_stereo_600kbps_44100hz.info", false)));
+
+int main(int argc, char **argv) {
+ gEnv = new FlacDecoderTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Flac Decoder Test Result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
new file mode 100644
index 0000000..1334bba
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.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 __FLAC_DECODER_TEST_ENVIRONMENT_H__
+#define __FLAC_DECODER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class FlacDecoderTestEnvironment : public ::testing::Environment {
+ public:
+ FlacDecoderTestEnvironment() : res("/data/local/tmp/") {}
+
+ // Parses the command line arguments
+ int initFromOptions(int argc, char **argv);
+
+ void setRes(const char *_res) { res = _res; }
+
+ const string getRes() const { return res; }
+
+ private:
+ string res;
+};
+
+int FlacDecoderTestEnvironment::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 // __FLAC_DECODER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/libstagefright/flac/dec/test/README.md
new file mode 100644
index 0000000..4d194cd
--- /dev/null
+++ b/media/libstagefright/flac/dec/test/README.md
@@ -0,0 +1,40 @@
+## Media Testing ##
+---
+#### FlacDecoder :
+The FlacDecoder Test Suite validates the FlacDecoder available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+m FlacDecoderTest
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+To test 64-bit binary push binaries from nativetest64.
+```
+adb push ${OUT}/data/nativetest64/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+To test 32-bit binary push binaries from nativetest.
+```
+adb push ${OUT}/data/nativetest/FlacDecoderTest/FlacDecoderTest /data/local/tmp/
+```
+
+The resource file for the tests is taken from [here](https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip).
+Download, unzip and push these files into device for testing.
+
+```
+adb push FlacDecoder /data/local/tmp/
+```
+
+usage: FlacDecoderTest -P \<path_to_folder\>
+```
+adb shell /data/local/tmp/FlacDecoderTest -P /data/local/tmp/FlacDecoder/
+```
+Alternatively, the test can also be run using atest command.
+
+```
+atest FlacDecoderTest -- --enable-module-dynamic-download=true
+```
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index d56ec4f..83e92b9 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -476,6 +476,8 @@
int32_t targetRefLevel;
int32_t encodedTargetLevel;
int32_t effectType;
+ int32_t albumMode;
+ int32_t outputLoudness;
} drcParams_t;
status_t setupAACCodec(
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index eb7e5f7..bfdc9e7 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -733,10 +733,12 @@
constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
constexpr char KEY_AAC_DRC_EFFECT_TYPE[] = "aac-drc-effect-type";
constexpr char KEY_AAC_DRC_HEAVY_COMPRESSION[] = "aac-drc-heavy-compression";
+constexpr char KEY_AAC_DRC_OUTPUT_LOUDNESS[] = "aac-drc-output-loudness";
constexpr char KEY_AAC_DRC_TARGET_REFERENCE_LEVEL[] = "aac-target-ref-level";
constexpr char KEY_AAC_ENCODED_TARGET_LEVEL[] = "aac-encoded-target-level";
constexpr char KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT[] = "aac-max-output-channel_count";
diff --git a/media/libstagefright/webm/tests/Android.bp b/media/libstagefright/webm/tests/Android.bp
new file mode 100644
index 0000000..5183a49
--- /dev/null
+++ b/media/libstagefright/webm/tests/Android.bp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+ name: "WebmFrameThreadUnitTest",
+ gtest: true,
+
+ srcs: [
+ "WebmFrameThreadUnitTest.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
+ ],
+
+ static_libs: [
+ "libdatasource",
+ "libstagefright",
+ "libstagefright_webm",
+ "libstagefright_foundation",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libstagefright/webm/tests/README.md b/media/libstagefright/webm/tests/README.md
new file mode 100644
index 0000000..2e74f34
--- /dev/null
+++ b/media/libstagefright/webm/tests/README.md
@@ -0,0 +1,26 @@
+## Media Testing ##
+---
+#### Webm Writer Utility Tests :
+The Webm Writer Utility Test Suite validates the APIs being used by the WebmWriter.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/webm/tests/
+```
+
+The 32-bit binaries will be created in the following path : ${OUT}/data/nativetest/
+
+The 64-bit binaries will be created in the following path : ${OUT}/data/nativetest64/
+
+#### WebmFrameThread
+To test 64-bit binary push binaries from nativetest64.
+
+adb push ${OUT}/data/nativetest64/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/WebmFrameThreadUnitTest/WebmFrameThreadUnitTest /data/local/tmp/
+
+```
+adb shell /data/local/tmp/WebmFrameThreadUnitTest
+```
diff --git a/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
new file mode 100644
index 0000000..89cd2ca
--- /dev/null
+++ b/media/libstagefright/webm/tests/WebmFrameThreadUnitTest.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "WebmFrameThreadUnitTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <media/stagefright/MediaAdapter.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/OpusHeader.h>
+
+#include "webm/EbmlUtil.h"
+#include "webm/WebmConstants.h"
+#include "webm/WebmFrameThread.h"
+
+using namespace android;
+using namespace webm;
+
+static constexpr int32_t kVideoIdx = 0;
+static constexpr int32_t kAudioIdx = 1;
+static constexpr int32_t kMaxStreamCount = 2;
+
+static constexpr int32_t kCsdSize = 32;
+static constexpr int32_t kFrameSize = 128;
+
+static constexpr int32_t kMaxLoopCount = 20;
+static constexpr int32_t kNumFramesToWrite = 32;
+static constexpr int32_t kSyncFrameInterval = 10;
+static constexpr uint64_t kDefaultTimeCodeScaleUs = 1000000; /* 1sec */
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/webmFrameThreadOutput.webm"
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+ const char *mime;
+ int32_t firstParam;
+ int32_t secondParam;
+ bool isAudio;
+} kInputData[] = {
+ {MEDIA_MIMETYPE_AUDIO_OPUS, 48000, 6, true},
+ {MEDIA_MIMETYPE_AUDIO_VORBIS, 44100, 1, true},
+ {MEDIA_MIMETYPE_VIDEO_VP9, 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_VP8, 1920, 1080, false},
+};
+
+class WebmFrameThreadUnitTest : public ::testing::TestWithParam<std::pair<int32_t, int32_t>> {
+ public:
+ WebmFrameThreadUnitTest()
+ : mSinkThread(nullptr), mAudioThread(nullptr), mVideoThread(nullptr), mSource{} {}
+
+ ~WebmFrameThreadUnitTest() {
+ if (mSinkThread) mSinkThread.clear();
+ if (mAudioThread) mAudioThread.clear();
+ if (mVideoThread) mVideoThread.clear();
+ }
+
+ virtual void SetUp() override {
+ mSegmentDataStart = 0;
+ mFd = open(OUTPUT_FILE_NAME, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ ASSERT_GE(mFd, 0) << "Failed to open output file " << OUTPUT_FILE_NAME;
+ }
+
+ virtual void TearDown() override {
+ if (mFd >= 0) close(mFd);
+ for (int32_t idx = 0; idx < kMaxStreamCount; idx++) {
+ if (mSource[idx] != nullptr) {
+ mSource[idx].clear();
+ }
+ }
+ mVSink.clear();
+ mASink.clear();
+ mCuePoints.clear();
+ }
+
+ void addTrack(bool isAudio, int32_t index);
+ void writeFileData(int32_t inputFrameId, int32_t range);
+
+ void createWebmThreads(std::initializer_list<int32_t> indexList);
+ void startWebmFrameThreads();
+ void stopWebmFrameThreads();
+
+ int32_t mFd;
+ uint64_t mSegmentDataStart;
+
+ sp<WebmFrameSinkThread> mSinkThread;
+ sp<WebmFrameSourceThread> mAudioThread;
+ sp<WebmFrameSourceThread> mVideoThread;
+
+ List<sp<WebmElement>> mCuePoints;
+ sp<MediaAdapter> mSource[kMaxStreamCount];
+ LinkedBlockingQueue<const sp<WebmFrame>> mVSink;
+ LinkedBlockingQueue<const sp<WebmFrame>> mASink;
+};
+
+void writeAudioHeaderData(const sp<AMessage> &format, const char *mimeType) {
+ if (strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_OPUS, strlen(MEDIA_MIMETYPE_AUDIO_OPUS) + 1) &&
+ strncasecmp(mimeType, MEDIA_MIMETYPE_AUDIO_VORBIS,
+ strlen(MEDIA_MIMETYPE_AUDIO_VORBIS) + 1)) {
+ ASSERT_TRUE(false) << "Unsupported mime type";
+ }
+
+ // Dummy CSD buffers for Opus and Vorbis
+ char csdBuffer[kCsdSize];
+ memset(csdBuffer, 0xFF, sizeof(csdBuffer));
+
+ sp<ABuffer> csdBuffer0 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+ ASSERT_NE(csdBuffer0.get(), nullptr) << "Unable to allocate buffer for CSD0 data";
+ ASSERT_NE(csdBuffer0->base(), nullptr) << "ABuffer base is null for CSD0";
+
+ sp<ABuffer> csdBuffer1 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+ ASSERT_NE(csdBuffer1.get(), nullptr) << "Unable to allocate buffer for CSD1 data";
+ ASSERT_NE(csdBuffer1->base(), nullptr) << "ABuffer base is null for CSD1";
+
+ sp<ABuffer> csdBuffer2 = ABuffer::CreateAsCopy((void *)csdBuffer, kCsdSize);
+ ASSERT_NE(csdBuffer2.get(), nullptr) << "Unable to allocate buffer for CSD2 data";
+ ASSERT_NE(csdBuffer2->base(), nullptr) << "ABuffer base is null for CSD2";
+
+ format->setBuffer("csd-0", csdBuffer0);
+ format->setBuffer("csd-1", csdBuffer1);
+ format->setBuffer("csd-2", csdBuffer2);
+}
+
+void WebmFrameThreadUnitTest::addTrack(bool isAudio, int32_t index) {
+ ASSERT_LT(index, sizeof(kInputData) / sizeof(kInputData[0]))
+ << "Invalid index for loopup table";
+
+ sp<AMessage> format = new AMessage;
+ format->setString("mime", kInputData[index].mime);
+ if (!isAudio) {
+ format->setInt32("width", kInputData[index].firstParam);
+ format->setInt32("height", kInputData[index].secondParam);
+ } else {
+ format->setInt32("sample-rate", kInputData[index].firstParam);
+ format->setInt32("channel-count", kInputData[index].secondParam);
+ ASSERT_NO_FATAL_FAILURE(writeAudioHeaderData(format, kInputData[index].mime));
+ }
+
+ sp<MetaData> trackMeta = new MetaData;
+ convertMessageToMetaData(format, trackMeta);
+
+ if (!isAudio) {
+ mSource[kVideoIdx] = new MediaAdapter(trackMeta);
+ ASSERT_NE(mSource[kVideoIdx], nullptr) << "Unable to create source";
+ } else {
+ mSource[kAudioIdx] = new MediaAdapter(trackMeta);
+ ASSERT_NE(mSource[kAudioIdx], nullptr) << "Unable to create source";
+ }
+}
+
+void WebmFrameThreadUnitTest::createWebmThreads(std::initializer_list<int32_t> indexList) {
+ mSinkThread = new WebmFrameSinkThread(mFd, mSegmentDataStart, mVSink, mASink, mCuePoints);
+ ASSERT_NE(mSinkThread, nullptr) << "Failed to create Sink Thread";
+
+ bool isAudio;
+ // MultiTrack input
+ for (int32_t index : indexList) {
+ isAudio = kInputData[index].isAudio;
+ ASSERT_NO_FATAL_FAILURE(addTrack(isAudio, index));
+ if (!isAudio) {
+ mVideoThread = new WebmFrameMediaSourceThread(mSource[kVideoIdx], kVideoType, mVSink,
+ kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+ } else {
+ mAudioThread = new WebmFrameMediaSourceThread(mSource[kAudioIdx], kAudioType, mASink,
+ kDefaultTimeCodeScaleUs, 0, 0, 1, 0);
+ }
+ }
+ // To handle single track file
+ if (!mVideoThread) {
+ mVideoThread = new WebmFrameEmptySourceThread(kVideoType, mVSink);
+ } else if (!mAudioThread) {
+ mAudioThread = new WebmFrameEmptySourceThread(kAudioType, mASink);
+ }
+ ASSERT_NE(mVideoThread, nullptr) << "Failed to create Video Thread";
+ ASSERT_NE(mAudioThread, nullptr) << "Failed to create Audio Thread";
+}
+
+void WebmFrameThreadUnitTest::startWebmFrameThreads() {
+ status_t status = mAudioThread->start();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Audio Thread";
+ status = mVideoThread->start();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Video Thread";
+ status = mSinkThread->start();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to start Sink Thread";
+}
+
+void WebmFrameThreadUnitTest::stopWebmFrameThreads() {
+ status_t status = mAudioThread->stop();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Audio Thread";
+ status = mVideoThread->stop();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Video Thread";
+ status = mSinkThread->stop();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to stop Sink Thread";
+}
+
+// Write dummy data to a file
+void WebmFrameThreadUnitTest::writeFileData(int32_t inputFrameId, int32_t range) {
+ char data[kFrameSize];
+ memset(data, 0xFF, sizeof(data));
+ int32_t status = OK;
+ do {
+ // Queue frames for both A/V tracks
+ for (int32_t idx = kVideoIdx; idx < kMaxStreamCount; idx++) {
+ sp<ABuffer> buffer = new ABuffer((void *)data, kFrameSize);
+ ASSERT_NE(buffer.get(), nullptr) << "ABuffer returned nullptr";
+
+ // Released in MediaAdapter::signalBufferReturned().
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+ ASSERT_NE(mediaBuffer, nullptr) << "MediaBuffer returned nullptr";
+
+ mediaBuffer->add_ref();
+ mediaBuffer->set_range(buffer->offset(), buffer->size());
+
+ MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+ sampleMetaData.setInt64(kKeyTime, inputFrameId * kDefaultTimeCodeScaleUs);
+
+ // For audio codecs, treat all frame as sync frame
+ if ((idx == kAudioIdx) || (inputFrameId % kSyncFrameInterval == 0)) {
+ sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+ }
+
+ // This pushBuffer will wait until the mediaBuffer is consumed.
+ if (mSource[idx] != nullptr) {
+ status = mSource[idx]->pushBuffer(mediaBuffer);
+ }
+ ASSERT_EQ(status, OK);
+ }
+ inputFrameId++;
+ } while (inputFrameId < range);
+}
+
+TEST_P(WebmFrameThreadUnitTest, WriteTest) {
+ int32_t index1 = GetParam().first;
+ int32_t index2 = GetParam().second;
+ ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+ ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+ ASSERT_NO_FATAL_FAILURE(writeFileData(0, kNumFramesToWrite));
+
+ if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+ if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+
+ ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+TEST_P(WebmFrameThreadUnitTest, PauseTest) {
+ int32_t index1 = GetParam().first;
+ int32_t index2 = GetParam().second;
+ ASSERT_NO_FATAL_FAILURE(createWebmThreads({index1, index2}));
+
+ ASSERT_NO_FATAL_FAILURE(startWebmFrameThreads());
+
+ int32_t offset = 0;
+ ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+ offset += kNumFramesToWrite;
+
+ for (int idx = 0; idx < kMaxLoopCount; idx++) {
+ // pause the threads
+ status_t status = mAudioThread->pause();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Audio Thread";
+ status = mVideoThread->pause();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to pause Video Thread";
+
+ // Under pause state, no write should happen
+ ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+ offset += kNumFramesToWrite;
+
+ status = mAudioThread->resume();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Audio Thread";
+ status = mVideoThread->resume();
+ ASSERT_EQ(status, AMEDIA_OK) << "Failed to resume Video Thread";
+
+ ASSERT_NO_FATAL_FAILURE(writeFileData(offset, kNumFramesToWrite));
+ offset += kNumFramesToWrite;
+ }
+
+ if (mSource[kAudioIdx]) mSource[kAudioIdx]->stop();
+ if (mSource[kVideoIdx]) mSource[kVideoIdx]->stop();
+ ASSERT_NO_FATAL_FAILURE(stopWebmFrameThreads());
+}
+
+INSTANTIATE_TEST_SUITE_P(WebmFrameThreadUnitTestAll, WebmFrameThreadUnitTest,
+ ::testing::Values(std::make_pair(0, 1), std::make_pair(0, 2),
+ std::make_pair(0, 3), std::make_pair(1, 0),
+ std::make_pair(1, 2), std::make_pair(1, 3),
+ std::make_pair(2, 3)));
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ return status;
+}
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index fdf51b1..8677b90 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -969,7 +969,7 @@
modifiedTime = 0;
if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0) ||
- (strcmp(name, "/") == 0) || (strcmp(basename(name), name) != 0)) {
+ (strchr(name, '/') != NULL)) {
char errMsg[80];
snprintf(errMsg, sizeof(errMsg), "Invalid name: %s", (const char *) name);
@@ -981,7 +981,7 @@
}
if (path[path.size() - 1] != '/')
path.append("/");
- path.append(basename(name));
+ path.append(name);
// check space first
if (mSendObjectFileSize > storage->getFreeSpace())
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 87ea084..7fd4d0a 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -223,6 +223,25 @@
return ok;
}
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid) {
+ static const String16 sAccessCallAudio("android.permission.ACCESS_CALL_AUDIO");
+ PermissionController permissionController;
+ const String16 resolvedOpPackageName = resolveCallingPackage(
+ permissionController, opPackageName, uid);
+ if (resolvedOpPackageName.size() == 0) {
+ ALOGE("accessCallAudioAllowed - FAIL - package not found.");
+ return false;
+ }
+ AppOpsManager appOps;
+ const int32_t op = appOps.permissionToOpCode(sAccessCallAudio);
+ const int32_t opResult = appOps.noteOp(op, uid, resolvedOpPackageName);
+ if (opResult == PermissionController::MODE_DEFAULT) {
+ // Only allow in case this is a system app with the proper privilege permission
+ return PermissionCache::checkPermission(sAccessCallAudio, pid, uid);
+ }
+ return opResult == PermissionController::MODE_ALLOWED;
+}
+
// privileged behavior needed by Dialer, Settings, SetupWizard and CellBroadcastReceiver
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid) {
static const String16 sWriteSecureSettings("android.permission.WRITE_SECURE_SETTINGS");
@@ -259,28 +278,29 @@
return NO_ERROR;
}
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+void MediaPackageManager::loadPackageManager() {
+ if (mPackageManager != nullptr) {
+ return;
+ }
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
- return nullptr;
+ return;
}
sp<IBinder> packageManager = sm->checkService(String16(nativePackageManagerName));
if (packageManager == nullptr) {
ALOGW("%s: failed to retrieve native package manager", __func__);
- return nullptr;
+ return;
}
- return interface_cast<content::pm::IPackageManagerNative>(packageManager);
+ mPackageManager = interface_cast<content::pm::IPackageManagerNative>(packageManager);
}
std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
+ /** Can not fetch package manager at construction it may not yet be registered. */
+ loadPackageManager();
if (mPackageManager == nullptr) {
- /** Can not fetch package manager at construction it may not yet be registered. */
- mPackageManager = retreivePackageManager();
- if (mPackageManager == nullptr) {
- ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
- return std::nullopt;
- }
+ ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
+ return std::nullopt;
}
std::vector<std::string> packageNames;
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 212599a..060e849 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -93,6 +93,7 @@
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);
+bool accessCallAudioAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
status_t checkIMemory(const sp<IMemory>& iMemory);
@@ -110,7 +111,7 @@
private:
static constexpr const char* nativePackageManagerName = "package_native";
std::optional<bool> doIsAllowed(uid_t uid);
- sp<content::pm::IPackageManagerNative> retreivePackageManager();
+ void loadPackageManager();
sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
uint_t mPackageManagerErrors = 0;
struct Package {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5c5c5bb..e5a6e27 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -326,7 +326,7 @@
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
&streamType, client.clientPid, client.clientUid,
- &fullConfig,
+ client.packageName, &fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
deviceId, &portId, &secondaryOutputs);
@@ -766,8 +766,9 @@
output.outputId = AUDIO_IO_HANDLE_NONE;
output.selectedDeviceId = input.selectedDeviceId;
lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
- clientPid, clientUid, &input.config, input.flags,
- &output.selectedDeviceId, &portId, &secondaryOutputs);
+ clientPid, clientUid, input.opPackageName,
+ &input.config, input.flags, &output.selectedDeviceId,
+ &portId, &secondaryOutputs);
if (lStatus != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
ALOGE("createTrack() getOutputForAttr() return error %d or invalid output handle", lStatus);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3726b9a..2833525 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1872,7 +1872,7 @@
// and the mute set to false).
mMasterVolume = audioFlinger->masterVolume_l();
mMasterMute = audioFlinger->masterMute_l();
- if (mOutput && mOutput->audioHwDev) {
+ if (mOutput->audioHwDev) {
if (mOutput->audioHwDev->canSetMasterVolume()) {
mMasterVolume = 1.0;
}
@@ -2832,7 +2832,7 @@
this/* srcThread */, this/* dstThread */);
}
- audio_output_flags_t flags = mOutput != nullptr ? mOutput->flags : AUDIO_OUTPUT_FLAG_NONE;
+ audio_output_flags_t flags = mOutput->flags;
mediametrics::LogItem item(mMetricsId);
item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_READPARAMETERS)
.set(AMEDIAMETRICS_PROP_ENCODING, formatToString(mFormat).c_str())
@@ -8731,6 +8731,7 @@
&stream,
client.clientPid,
client.clientUid,
+ client.packageName,
&config,
flags,
&deviceId,
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 2044863..5f551d5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -135,8 +135,10 @@
}
DeviceVector deviceList =
mSupportedDevices.getDevicesFromTypes(deviceTypes);
- if (!deviceList.empty()) {
- return deviceList.itemAt(0)->hasCurrentEncodedFormat();
+ for (const auto& device : deviceList) {
+ if (device->hasCurrentEncodedFormat()) {
+ return true;
+ }
}
return false;
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ba3d4ff..38801ec 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -121,7 +121,7 @@
device_name, encodedFormat);
}
-status_t AudioPolicyService::setPhoneState(audio_mode_t state)
+status_t AudioPolicyService::setPhoneState(audio_mode_t state, uid_t uid)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
@@ -145,6 +145,7 @@
AutoCallerClear acc;
mAudioPolicyManager->setPhoneState(state);
mPhoneState = state;
+ mPhoneStateOwnerUid = uid;
return NO_ERROR;
}
@@ -210,6 +211,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -256,7 +258,8 @@
case AudioPolicyInterface::API_OUTPUT_LEGACY:
break;
case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
- if (!modifyPhoneStateAllowed(pid, uid)) {
+ if (!modifyPhoneStateAllowed(pid, uid) &&
+ !accessCallAudioAllowed(opPackageName, pid, uid)) {
ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
__func__, uid);
result = PERMISSION_DENIED;
@@ -453,15 +456,22 @@
}
bool canCaptureOutput = captureAudioOutputAllowed(pid, uid);
- if ((inputSource == AUDIO_SOURCE_VOICE_UPLINK ||
- inputSource == AUDIO_SOURCE_VOICE_DOWNLINK ||
- inputSource == AUDIO_SOURCE_VOICE_CALL ||
- inputSource == AUDIO_SOURCE_ECHO_REFERENCE||
- inputSource == AUDIO_SOURCE_FM_TUNER) &&
+ bool canCaptureTelephonyOutput = canCaptureOutput
+ || accessCallAudioAllowed(opPackageName, pid, uid);
+
+ if ((attr->source == AUDIO_SOURCE_ECHO_REFERENCE ||
+ attr->source == AUDIO_SOURCE_FM_TUNER) &&
!canCaptureOutput) {
return PERMISSION_DENIED;
}
+ if ((attr->source == AUDIO_SOURCE_VOICE_UPLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+ attr->source == AUDIO_SOURCE_VOICE_CALL) &&
+ !canCaptureTelephonyOutput) {
+ return PERMISSION_DENIED;
+ }
+
bool canCaptureHotword = captureHotwordAllowed(opPackageName, pid, uid);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return BAD_VALUE;
@@ -493,6 +503,11 @@
break;
case AudioPolicyInterface::API_INPUT_TELEPHONY_RX:
// FIXME: use the same permission as for remote submix for now.
+ if (!canCaptureTelephonyOutput) {
+ ALOGE("getInputForAttr() permission denied: call capture not allowed");
+ status = PERMISSION_DENIED;
+ }
+ break;
case AudioPolicyInterface::API_INPUT_MIX_CAPTURE:
if (!canCaptureOutput) {
ALOGE("getInputForAttr() permission denied: capture not allowed");
@@ -520,9 +535,13 @@
return status;
}
+ bool allowAudioCapture = canCaptureOutput ||
+ (inputType == AudioPolicyInterface::API_INPUT_TELEPHONY_RX &&
+ canCaptureTelephonyOutput);
+
sp<AudioRecordClient> client = new AudioRecordClient(*attr, *input, uid, pid, session, *portId,
*selectedDeviceId, opPackageName,
- canCaptureOutput, canCaptureHotword);
+ allowAudioCapture, canCaptureHotword);
mAudioRecordClients.add(*portId, client);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e5c36ea..99cec5a 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -534,8 +534,8 @@
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
bool allowCapture = !isAssistantOnTop
&& ((isTopOrLatestActive && !isLatestSensitive) || isLatestSensitive)
- && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureOutput))
- && !(isInCall && !current->canCaptureOutput);
+ && !(isSensitiveActive && !(isLatestSensitive || current->canCaptureCallOrOutput))
+ && !(isInCall && !current->canCaptureCallOrOutput);
if (isVirtualSource(source)) {
// Allow capture for virtual (remote submix, call audio TX or RX...) sources
@@ -555,7 +555,7 @@
} else {
if (((isAssistantOnTop && source == AUDIO_SOURCE_VOICE_RECOGNITION) ||
source == AUDIO_SOURCE_HOTWORD) &&
- (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
allowCapture = true;
}
}
@@ -567,7 +567,7 @@
// OR
// Is on TOP AND the source is VOICE_RECOGNITION or HOTWORD
if (!isAssistantOnTop
- && (!(isSensitiveActive || isInCall) || current->canCaptureOutput)) {
+ && (!(isSensitiveActive || isInCall) || current->canCaptureCallOrOutput)) {
allowCapture = true;
}
if (isA11yOnTop) {
@@ -580,7 +580,7 @@
// All active clients are using HOTWORD source
// AND no call is active
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
- if (onlyHotwordActive && !(isInCall && !current->canCaptureOutput)) {
+ if (onlyHotwordActive && !(isInCall && !current->canCaptureCallOrOutput)) {
allowCapture = true;
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index e297f34..c3c87f1 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -72,7 +72,7 @@
const char *device_address,
const char *device_name,
audio_format_t encodedFormat);
- virtual status_t setPhoneState(audio_mode_t state);
+ virtual status_t setPhoneState(audio_mode_t state, uid_t uid);
virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
virtual audio_io_handle_t getOutput(audio_stream_type_t stream);
@@ -82,6 +82,7 @@
audio_stream_type_t *stream,
pid_t pid,
uid_t uid,
+ const String16& opPackageName,
const audio_config_t *config,
audio_output_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@@ -807,15 +808,16 @@
const audio_io_handle_t io, uid_t uid, pid_t pid,
const audio_session_t session, audio_port_handle_t portId,
const audio_port_handle_t deviceId, const String16& opPackageName,
- bool canCaptureOutput, bool canCaptureHotword) :
+ bool canCaptureCallOrOutput, bool canCaptureHotword) :
AudioClient(attributes, io, uid, pid, session, portId, deviceId),
opPackageName(opPackageName), startTimeNs(0),
- canCaptureOutput(canCaptureOutput), canCaptureHotword(canCaptureHotword) {}
+ canCaptureCallOrOutput(canCaptureCallOrOutput),
+ canCaptureHotword(canCaptureHotword) {}
~AudioRecordClient() override = default;
const String16 opPackageName; // client package name
nsecs_t startTimeNs;
- const bool canCaptureOutput;
+ const bool canCaptureCallOrOutput;
const bool canCaptureHotword;
};
@@ -880,6 +882,7 @@
// those can call back into AudioPolicyService methods and try to acquire the mutex
sp<AudioPolicyEffects> mAudioPolicyEffects;
audio_mode_t mPhoneState;
+ uid_t mPhoneStateOwnerUid;
sp<UidPolicy> mUidPolicy;
sp<SensorPrivacyPolicy> mSensorPrivacyPolicy;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index b20774a..2c97a38 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -1352,29 +1352,9 @@
// Get list of concurrent streaming camera device combinations
if (mMinorVersion >= 6) {
- hardware::Return<void> ret = interface2_6->getConcurrentStreamingCameraIds([&status, this](
- Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
- const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
- cameraDeviceIdCombinations) {
- status = concurrentIdStatus;
- if (status == Status::OK) {
- for (auto& combination : cameraDeviceIdCombinations) {
- std::unordered_set<std::string> deviceIds;
- for (auto &cameraDeviceId : combination) {
- deviceIds.insert(cameraDeviceId.c_str());
- }
- mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
- }
- } });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to query for camera devices from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
+ res = getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+ if (res != OK) {
+ return res;
}
}
@@ -1626,6 +1606,75 @@
return OK;
}
+status_t CameraProviderManager::ProviderInfo::getConcurrentStreamingCameraIdsInternalLocked(
+ sp<provider::V2_6::ICameraProvider> &interface2_6) {
+ if (interface2_6 == nullptr) {
+ ALOGE("%s: null interface provided", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ Status status = Status::OK;
+ hardware::Return<void> ret =
+ interface2_6->getConcurrentStreamingCameraIds([&status, this](
+ Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+ const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+ cameraDeviceIdCombinations) {
+ status = concurrentIdStatus;
+ if (status == Status::OK) {
+ mConcurrentCameraIdCombinations.clear();
+ for (auto& combination : cameraDeviceIdCombinations) {
+ std::unordered_set<std::string> deviceIds;
+ for (auto &cameraDeviceId : combination) {
+ deviceIds.insert(cameraDeviceId.c_str());
+ }
+ mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+ return OK;
+}
+
+status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+ if (mMinorVersion < 6) {
+ // Unsupported operation, nothing to do here
+ return OK;
+ }
+ // Check if the provider is currently active - not going to start it up for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+ mProviderName.c_str());
+ return INVALID_OPERATION;
+ }
+ auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+ if (castResult.isOk()) {
+ sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+ if (interface2_6 != nullptr) {
+ return getConcurrentStreamingCameraIdsInternalLocked(interface2_6);
+ } else {
+ // This should not happen since mMinorVersion >= 6
+ ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+ }
+ return OK;
+}
+
+std::vector<std::unordered_set<std::string>>
+CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
+ std::lock_guard<std::mutex> lock(mLock);
+ return mConcurrentCameraIdCombinations;
+}
+
hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
const hardware::hidl_string& cameraDeviceName,
CameraDeviceStatus newStatus) {
@@ -1659,6 +1708,10 @@
}
listener = mManager->getStatusListener();
initialized = mInitialized;
+ if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+ ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+ __FUNCTION__, mProviderName.c_str());
+ }
}
// Call without lock held to allow reentrancy into provider manager
// Don't send the callback if providerInfo hasn't been initialized.
@@ -2747,7 +2800,7 @@
std::vector<std::unordered_set<std::string>> deviceIdCombinations;
std::lock_guard<std::mutex> lock(mInterfaceMutex);
for (auto &provider : mProviders) {
- for (auto &combinations : provider->mConcurrentCameraIdCombinations) {
+ for (auto &combinations : provider->getConcurrentCameraIdCombinations()) {
deviceIdCombinations.push_back(combinations);
}
}
@@ -2831,7 +2884,7 @@
// TODO: we should also do a findDeviceInfoLocked here ?
for (auto &provider : mProviders) {
if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
- provider->mConcurrentCameraIdCombinations)) {
+ provider->getConcurrentCameraIdCombinations())) {
// For each camera device in cameraIdsAndSessionConfigs collect
// the streamConfigs and create the HAL
// CameraIdAndStreamCombination, exit early if needed
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 42da227..1a02980 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -417,6 +417,9 @@
status_t notifyDeviceStateChange(
hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
newDeviceState);
+
+ std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
+
/**
* Query the camera provider for concurrent stream configuration support
*/
@@ -510,8 +513,6 @@
// physical camera IDs.
std::vector<std::string> mProviderPublicCameraIds;
- std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
-
// HALv1-specific camera fields, including the actual device interface
struct DeviceInfo1 : public DeviceInfo {
typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
@@ -600,6 +601,8 @@
bool mInitialized = false;
+ std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
+
// Templated method to instantiate the right kind of DeviceInfo and call the
// right CameraProvider getCameraDeviceInterface_* method.
template<class DeviceInfoT>
@@ -623,6 +626,12 @@
static metadata_vendor_id_t generateVendorTagId(const std::string &name);
void removeDevice(std::string id);
+
+ // Expects to have mLock locked
+ status_t reCacheConcurrentStreamingCameraIdsLocked();
+ // Expects to have mLock locked
+ status_t getConcurrentStreamingCameraIdsInternalLocked(
+ sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
};
// Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 90d21a2..f29431c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -364,100 +364,103 @@
status_t Camera3Device::disconnectImpl() {
ATRACE_CALL();
- Mutex::Autolock il(mInterfaceLock);
-
ALOGI("%s: E", __FUNCTION__);
status_t res = OK;
std::vector<wp<Camera3StreamInterface>> streams;
- nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
{
- Mutex::Autolock l(mLock);
- if (mStatus == STATUS_UNINITIALIZED) return res;
+ Mutex::Autolock il(mInterfaceLock);
+ nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
+ {
+ Mutex::Autolock l(mLock);
+ if (mStatus == STATUS_UNINITIALIZED) return res;
- if (mStatus == STATUS_ACTIVE ||
- (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
- res = mRequestThread->clearRepeatingRequests();
- if (res != OK) {
- SET_ERR_L("Can't stop streaming");
- // Continue to close device even in case of error
- } else {
- res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ if (mStatus == STATUS_ACTIVE ||
+ (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
+ res = mRequestThread->clearRepeatingRequests();
if (res != OK) {
- SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
- maxExpectedDuration);
+ SET_ERR_L("Can't stop streaming");
// Continue to close device even in case of error
+ } else {
+ res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+ if (res != OK) {
+ SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+ maxExpectedDuration);
+ // Continue to close device even in case of error
+ }
}
}
- }
- if (mStatus == STATUS_ERROR) {
- CLOGE("Shutting down in an error state");
- }
+ if (mStatus == STATUS_ERROR) {
+ CLOGE("Shutting down in an error state");
+ }
- if (mStatusTracker != NULL) {
- mStatusTracker->requestExit();
- }
+ if (mStatusTracker != NULL) {
+ mStatusTracker->requestExit();
+ }
- if (mRequestThread != NULL) {
- mRequestThread->requestExit();
- }
+ if (mRequestThread != NULL) {
+ mRequestThread->requestExit();
+ }
- streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
- for (size_t i = 0; i < mOutputStreams.size(); i++) {
- streams.push_back(mOutputStreams[i]);
- }
- if (mInputStream != nullptr) {
- streams.push_back(mInputStream);
+ streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
+ for (size_t i = 0; i < mOutputStreams.size(); i++) {
+ streams.push_back(mOutputStreams[i]);
+ }
+ if (mInputStream != nullptr) {
+ streams.push_back(mInputStream);
+ }
}
}
-
- // Joining done without holding mLock, otherwise deadlocks may ensue
- // as the threads try to access parent state
+ // Joining done without holding mLock and mInterfaceLock, otherwise deadlocks may ensue
+ // as the threads try to access parent state (b/143513518)
if (mRequestThread != NULL && mStatus != STATUS_ERROR) {
// HAL may be in a bad state, so waiting for request thread
// (which may be stuck in the HAL processCaptureRequest call)
// could be dangerous.
+ // give up mInterfaceLock here and then lock it again. Could this lead
+ // to other deadlocks
mRequestThread->join();
}
-
- if (mStatusTracker != NULL) {
- mStatusTracker->join();
- }
-
- HalInterface* interface;
{
- Mutex::Autolock l(mLock);
- mRequestThread.clear();
- Mutex::Autolock stLock(mTrackerLock);
- mStatusTracker.clear();
- interface = mInterface.get();
- }
+ Mutex::Autolock il(mInterfaceLock);
+ if (mStatusTracker != NULL) {
+ mStatusTracker->join();
+ }
- // Call close without internal mutex held, as the HAL close may need to
- // wait on assorted callbacks,etc, to complete before it can return.
- interface->close();
+ HalInterface* interface;
+ {
+ Mutex::Autolock l(mLock);
+ mRequestThread.clear();
+ Mutex::Autolock stLock(mTrackerLock);
+ mStatusTracker.clear();
+ interface = mInterface.get();
+ }
- flushInflightRequests();
+ // Call close without internal mutex held, as the HAL close may need to
+ // wait on assorted callbacks,etc, to complete before it can return.
+ interface->close();
- {
- Mutex::Autolock l(mLock);
- mInterface->clear();
- mOutputStreams.clear();
- mInputStream.clear();
- mDeletedStreams.clear();
- mBufferManager.clear();
- internalUpdateStatusLocked(STATUS_UNINITIALIZED);
- }
+ flushInflightRequests();
- for (auto& weakStream : streams) {
- sp<Camera3StreamInterface> stream = weakStream.promote();
- if (stream != nullptr) {
- ALOGE("%s: Stream %d leaked! strong reference (%d)!",
- __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+ {
+ Mutex::Autolock l(mLock);
+ mInterface->clear();
+ mOutputStreams.clear();
+ mInputStream.clear();
+ mDeletedStreams.clear();
+ mBufferManager.clear();
+ internalUpdateStatusLocked(STATUS_UNINITIALIZED);
+ }
+
+ for (auto& weakStream : streams) {
+ sp<Camera3StreamInterface> stream = weakStream.promote();
+ if (stream != nullptr) {
+ ALOGE("%s: Stream %d leaked! strong reference (%d)!",
+ __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
+ }
}
}
-
ALOGI("%s: X", __FUNCTION__);
return res;
}
@@ -1768,9 +1771,7 @@
}
void Camera3Device::pauseStateNotify(bool enable) {
- // We must not hold mInterfaceLock here since this function is called from
- // RequestThread::threadLoop and holding mInterfaceLock could lead to
- // deadlocks (http://b/143513518)
+ Mutex::Autolock il(mInterfaceLock);
Mutex::Autolock l(mLock);
mPauseStateNotify = enable;
@@ -2340,9 +2341,7 @@
ATRACE_CALL();
bool ret = false;
- // We must not hold mInterfaceLock here since this function is called from
- // RequestThread::threadLoop and holding mInterfaceLock could lead to
- // deadlocks (http://b/143513518)
+ Mutex::Autolock il(mInterfaceLock);
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index e13e45f..0069fb3 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -278,7 +278,6 @@
// A lock to enforce serialization on the input/configure side
// of the public interface.
- // Only locked by public methods inherited from CameraDeviceBase.
// Not locked by methods guarded by mOutputLock, since they may act
// concurrently to the input/configure side of the interface.
// Must be locked before mLock if both will be locked by a method
@@ -1102,7 +1101,7 @@
uint32_t mNextReprocessShutterFrameNumber;
// the minimal frame number of the next ZSL still capture shutter
uint32_t mNextZslStillShutterFrameNumber;
- List<CaptureResult> mResultQueue;
+ std::list<CaptureResult> mResultQueue;
std::condition_variable mResultSignal;
wp<NotificationListener> mListener;
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 27043d2..208f70d 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -212,7 +212,7 @@
const uint32_t mNumPartialResults;
std::mutex mOutputLock;
- List<CaptureResult> mResultQueue;
+ std::list<CaptureResult> mResultQueue;
std::condition_variable mResultSignal;
// the minimal frame number of the next non-reprocess result
uint32_t mNextResultFrameNumber;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 39b7db4..238356e 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -153,9 +153,9 @@
}
// Valid result, insert into queue
- List<CaptureResult>::iterator queuedResult =
+ std::list<CaptureResult>::iterator queuedResult =
states.resultQueue.insert(states.resultQueue.end(), CaptureResult(*result));
- ALOGVV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
+ ALOGV("%s: result requestId = %" PRId32 ", frameNumber = %" PRId64
", burstId = %" PRId32, __FUNCTION__,
queuedResult->mResultExtras.requestId,
queuedResult->mResultExtras.frameNumber,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 300df5b..fbb47f8 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -62,7 +62,7 @@
std::mutex& inflightLock;
InFlightRequestMap& inflightMap; // end of inflightLock scope
std::mutex& outputLock;
- List<CaptureResult>& resultQueue;
+ std::list<CaptureResult>& resultQueue;
std::condition_variable& resultSignal;
uint32_t& nextShutterFrameNum;
uint32_t& nextReprocShutterFrameNum;
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index f825373..0441cfa 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -13,10 +13,11 @@
"libcodec2-hidl-defaults",
],
shared_libs: [
- "android.hardware.media.c2@1.0",
- "android.hardware.media.c2@1.1",
"libbase",
- "libcodec2_hidl@1.1",
+ "libcodec2_hidl@1.0",
+ "libcodec2_vndk",
+ "libhidlbase",
+ "libutils",
],
// Codecs
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 450af79..83d233e 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -22,10 +22,9 @@
#include <C2Component.h>
#include <C2PlatformSupport.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
#include <codec2/hidl/1.1/ComponentStore.h>
-#include <codec2/hidl/1.0/Configurable.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
#include <hidl/HidlSupport.h>
#include <media/CodecServiceRegistrant.h>
@@ -36,8 +35,8 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
+using namespace ::android::hardware::media::c2::V1_1;
+using namespace ::android::hardware::media::c2::V1_1::utils;
constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
@@ -400,11 +399,10 @@
} // unnamed namespace
extern "C" void RegisterCodecServices() {
- using ComponentStore_Latest = ::android::hardware::media::c2::V1_1::
- utils::ComponentStore;
+ using namespace ::android::hardware::media::c2::V1_1;
LOG(INFO) << "Creating software Codec2 service...";
- sp<ComponentStore_Latest> store =
- new ComponentStore_Latest(::android::GetCodec2PlatformComponentStore());
+ sp<ComponentStore> store =
+ new ComponentStore(::android::GetCodec2PlatformComponentStore());
if (store == nullptr) {
LOG(ERROR) <<
"Cannot create software Codec2 service.";