Merge changes Ie20ffc1a,Ie6af19a5
* changes:
Libaaudio Integer Overflow Sanitizer Bug Fix
Libaaudio Enable Integer Overflow and Bound Sanitizers
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 701ced7..477c371 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -15,7 +15,7 @@
apex {
name: "test_com.android.media",
manifest: "test_manifest.json",
- file_contexts: "com.android.media",
+ file_contexts: ":com.android.media-file_contexts",
defaults: ["com.android.media-defaults"],
installable: false,
}
@@ -23,7 +23,7 @@
apex {
name: "test_com.android.media.swcodec",
manifest: "test_manifest_codec.json",
- file_contexts: "com.android.media.swcodec",
+ file_contexts: ":com.android.media.swcodec-file_contexts",
defaults: ["com.android.media.swcodec-defaults"],
installable: false,
}
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 3e8992a..62dbb5e 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -87,6 +87,7 @@
ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
String cameraId,
String opPackageName,
+ @nullable String featureId,
int clientUid);
/**
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 9d40fd7..8eb030a 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -517,7 +517,7 @@
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
binder::Status serviceRet = cs->connectDevice(
- callbacks, String16(cameraId), String16(""),
+ callbacks, String16(cameraId), String16(""), std::unique_ptr<String16>(),
hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
if (!serviceRet.isOk()) {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index f07a1e6..9a18b10 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -361,7 +361,8 @@
sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
sp<hardware::camera2::ICameraDeviceUser> device;
res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
- hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+ std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+ /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
ASSERT_NE(nullptr, device.get());
device->disconnect();
@@ -403,7 +404,8 @@
{
SCOPED_TRACE("openNewDevice");
binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
- hardware::ICameraService::USE_CALLING_UID, /*out*/&device);
+ std::unique_ptr<String16>(), hardware::ICameraService::USE_CALLING_UID,
+ /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
}
auto p = std::make_pair(callbacks, device);
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 9ae87d8..e8cfece 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -304,7 +304,7 @@
seekTimeUs = -1;
if (shouldSeek) {
- seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
+ seekTimeUs = (rand() * (float)durationUs) / (float)RAND_MAX;
options.setSeekTo(seekTimeUs);
printf("seeking to %" PRId64 " us (%.2f secs)\n",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 52c7438..34a2f69 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -17,13 +17,10 @@
srcs: [
"DrmPluginPath.cpp",
"DrmSessionManager.cpp",
- "ICrypto.cpp",
- "IDrm.cpp",
- "IDrmClient.cpp",
- "IMediaDrmService.cpp",
"SharedLibrary.cpp",
"DrmHal.cpp",
"CryptoHal.cpp",
+ "DrmUtils.cpp",
],
local_include_dirs: [
@@ -41,14 +38,14 @@
shared_libs: [
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libdl",
"liblog",
"libmedia",
"libmediadrmmetrics_lite",
- "libmediametrics",
+ "libmediametrics#1",
"libmediautils",
- "libresourcemanagerservice",
"libstagefright_foundation",
"libutils",
"android.hardware.drm@1.0",
@@ -58,6 +55,16 @@
"libhidlbase",
],
+ static_libs: [
+ "resourcemanager_aidl_interface-ndk_platform",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
+ ],
+
cflags: [
"-Werror",
"-Wall",
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index 6a0e75e..55b9bb8 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -45,6 +45,7 @@
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
@@ -255,10 +256,7 @@
* size. Once the heap base is established, shared memory buffers
* are sent by providing an offset into the heap and a buffer size.
*/
-int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) {
- using ::android::hardware::fromHeap;
- using ::android::hardware::HidlMemory;
-
+int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) {
if (heap == NULL || mHeapSeqNum < 0) {
ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
return -1;
@@ -268,9 +266,8 @@
int32_t seqNum = mHeapSeqNum++;
uint32_t bufferId = static_cast<uint32_t>(seqNum);
- sp<HidlMemory> hidlMemory = fromHeap(heap);
- mHeapBases.add(seqNum, HeapBase(bufferId, heap->getSize()));
- Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, bufferId);
+ mHeapSizes.add(seqNum, heap->size());
+ Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
return seqNum;
}
@@ -285,64 +282,40 @@
* TODO: Add a releaseSharedBuffer method in a future DRM HAL
* API version to make this explicit.
*/
- ssize_t index = mHeapBases.indexOfKey(seqNum);
+ ssize_t index = mHeapSizes.indexOfKey(seqNum);
if (index >= 0) {
if (mPlugin != NULL) {
- uint32_t bufferId = mHeapBases[index].getBufferId();
+ uint32_t bufferId = static_cast<uint32_t>(seqNum);
Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
}
- mHeapBases.removeItem(seqNum);
+ mHeapSizes.removeItem(seqNum);
}
}
-status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) {
- ssize_t offset;
- size_t size;
-
- if (memory == NULL || buffer == NULL) {
- return UNEXPECTED_NULL;
- }
-
- sp<IMemoryHeap> heap = memory->getMemory(&offset, &size);
- if (heap == NULL) {
- return UNEXPECTED_NULL;
- }
-
+status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) {
+ int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
// memory must be in one of the heaps that have been set
- if (mHeapBases.indexOfKey(seqNum) < 0) {
+ if (mHeapSizes.indexOfKey(seqNum) < 0) {
return UNKNOWN_ERROR;
}
- // heap must be the same size as the one that was set in setHeapBase
- if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) {
- android_errorWriteLog(0x534e4554, "76221123");
- return UNKNOWN_ERROR;
- }
-
// memory must be within the address space of the heap
- // TODO: Using unsecurePointer() has some associated security pitfalls
- // (see declaration for details).
- // Either document why it is safe in this case or address the
- // issue (e.g. by copying).
- if (memory->unsecurePointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset() ||
- heap->getSize() < memory->offset() + memory->size() ||
- SIZE_MAX - memory->offset() < memory->size()) {
+ size_t heapSize = mHeapSizes.valueFor(seqNum);
+ if (heapSize < buffer.offset + buffer.size ||
+ SIZE_MAX - buffer.offset < buffer.size) {
android_errorWriteLog(0x534e4554, "76221123");
return UNKNOWN_ERROR;
}
- buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId();
- buffer->offset = offset >= 0 ? offset : 0;
- buffer->size = size;
return OK;
}
ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const ICrypto::SourceBuffer &source, size_t offset,
+ const ::SharedBuffer &hSource, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) {
+ const ::DestinationBuffer &hDestination, AString *errorDetailMsg) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -380,28 +353,21 @@
}
auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);
- int32_t heapSeqNum = source.mHeapSeqNum;
bool secure;
- ::DestinationBuffer hDestination;
- if (destination.mType == kDestinationTypeSharedMemory) {
- hDestination.type = BufferType::SHARED_MEMORY;
- status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum,
- &hDestination.nonsecureMemory);
+ if (hDestination.type == BufferType::SHARED_MEMORY) {
+ status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
if (status != OK) {
return status;
}
secure = false;
- } else if (destination.mType == kDestinationTypeNativeHandle) {
- hDestination.type = BufferType::NATIVE_HANDLE;
- hDestination.secureMemory = hidl_handle(destination.mHandle);
+ } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
secure = true;
} else {
android_errorWriteLog(0x534e4554, "70526702");
return UNKNOWN_ERROR;
}
- ::SharedBuffer hSource;
- status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource);
+ status_t status = checkSharedBuffer(hSource);
if (status != OK) {
return status;
}
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 8a08a7b..f3028d8 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,14 +20,14 @@
#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <android/binder_manager.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
#include <android/hardware/drm/1.2/types.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <android/media/BnResourceManagerClient.h>
#include <hidl/ServiceManagement.h>
#include <media/EventMetric.h>
+#include <media/MediaMetrics.h>
#include <media/PluginMetricsReporting.h>
#include <media/drm/DrmAPI.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -39,6 +39,8 @@
#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
+#include <vector>
+
using drm::V1_0::KeyedVector;
using drm::V1_0::KeyRequestType;
using drm::V1_0::KeyType;
@@ -96,17 +98,6 @@
#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
-static inline int getCallingPid() {
- return IPCThreadState::self()->getCallingPid();
-}
-
-static bool checkPermission(const char* permissionString) {
- if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
- bool ok = checkCallingPermission(String16(permissionString));
- if (!ok) ALOGE("Request requires %s", permissionString);
- return ok;
-}
-
static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
Vector<uint8_t> vector;
vector.appendArray(vec.data(), vec.size());
@@ -296,17 +287,16 @@
Mutex DrmHal::mLock;
-struct DrmHal::DrmSessionClient : public android::media::BnResourceManagerClient {
+struct DrmHal::DrmSessionClient : public aidl::android::media::BnResourceManagerClient {
explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId)
: mSessionId(sessionId),
mDrm(drm) {}
- ::android::binder::Status reclaimResource(bool* _aidl_return) override;
- ::android::binder::Status getName(::std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus reclaimResource(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getName(::std::string* _aidl_return) override;
const Vector<uint8_t> mSessionId;
-protected:
virtual ~DrmSessionClient();
private:
@@ -315,24 +305,25 @@
DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
};
-::android::binder::Status DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::reclaimResource(bool* _aidl_return) {
+ auto sessionId = mSessionId;
sp<DrmHal> drm = mDrm.promote();
if (drm == NULL) {
*_aidl_return = true;
- return ::android::binder::Status::ok();
+ return ::ndk::ScopedAStatus::ok();
}
- status_t err = drm->closeSession(mSessionId);
+ status_t err = drm->closeSession(sessionId);
if (err != OK) {
*_aidl_return = false;
- return ::android::binder::Status::ok();
+ return ::ndk::ScopedAStatus::ok();
}
drm->sendEvent(EventType::SESSION_RECLAIMED,
- toHidlVec(mSessionId), hidl_vec<uint8_t>());
+ toHidlVec(sessionId), hidl_vec<uint8_t>());
*_aidl_return = true;
- return ::android::binder::Status::ok();
+ return ::ndk::ScopedAStatus::ok();
}
-::android::binder::Status DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
+::ndk::ScopedAStatus DrmHal::DrmSessionClient::getName(::std::string* _aidl_return) {
String8 name;
sp<DrmHal> drm = mDrm.promote();
if (drm == NULL) {
@@ -347,7 +338,7 @@
}
name.append("]");
*_aidl_return = name;
- return ::android::binder::Status::ok();
+ return ::ndk::ScopedAStatus::ok();
}
DrmHal::DrmSessionClient::~DrmSessionClient() {
@@ -451,6 +442,7 @@
const uint8_t uuid[16], const String8& appPackageName) {
mAppPackageName = appPackageName;
mMetrics.SetAppPackageName(appPackageName);
+ mMetrics.SetAppUid(AIBinder_getCallingUid());
sp<IDrmPlugin> plugin;
Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
@@ -477,12 +469,6 @@
status_t DrmHal::setListener(const sp<IDrmClient>& listener)
{
Mutex::Autolock lock(mEventLock);
- if (mListener != NULL){
- IInterface::asBinder(mListener)->unlinkToDeath(this);
- }
- if (listener != NULL) {
- IInterface::asBinder(listener)->linkToDeath(this);
- }
mListener = listener;
return NO_ERROR;
}
@@ -496,10 +482,6 @@
mEventLock.unlock();
if (listener != NULL) {
- Parcel obj;
- writeByteArray(obj, sessionId);
- writeByteArray(obj, data);
-
Mutex::Autolock lock(mNotifyLock);
DrmPlugin::EventType eventType;
switch(hEventType) {
@@ -521,7 +503,7 @@
default:
return Void();
}
- listener->notify(eventType, 0, &obj);
+ listener->sendEvent(eventType, sessionId, data);
}
return Void();
}
@@ -534,12 +516,8 @@
mEventLock.unlock();
if (listener != NULL) {
- Parcel obj;
- writeByteArray(obj, sessionId);
- obj.writeInt64(expiryTimeInMS);
-
Mutex::Autolock lock(mNotifyLock);
- listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+ listener->sendExpirationUpdate(sessionId, expiryTimeInMS);
}
return Void();
}
@@ -556,21 +534,17 @@
}
Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+ const hidl_vec<KeyStatus>& hKeyStatusList, bool hasNewUsableKey) {
mEventLock.lock();
sp<IDrmClient> listener = mListener;
mEventLock.unlock();
if (listener != NULL) {
- Parcel obj;
- writeByteArray(obj, sessionId);
-
- size_t nKeys = keyStatusList.size();
- obj.writeInt32(nKeys);
+ std::vector<DrmKeyStatus> keyStatusList;
+ size_t nKeys = hKeyStatusList.size();
for (size_t i = 0; i < nKeys; ++i) {
- const KeyStatus &keyStatus = keyStatusList[i];
- writeByteArray(obj, keyStatus.keyId);
+ const KeyStatus &keyStatus = hKeyStatusList[i];
uint32_t type;
switch(keyStatus.type) {
case KeyStatusType::USABLE:
@@ -593,19 +567,18 @@
type = DrmPlugin::kKeyStatusType_InternalError;
break;
}
- obj.writeInt32(type);
+ keyStatusList.push_back({type, keyStatus.keyId});
mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
}
- obj.writeInt32(hasNewUsableKey);
Mutex::Autolock lock(mNotifyLock);
- listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+ listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
} else {
// There's no listener. But we still want to count the key change
// events.
- size_t nKeys = keyStatusList.size();
+ size_t nKeys = hKeyStatusList.size();
for (size_t i = 0; i < nKeys; i++) {
- mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
+ mMetrics.mKeyStatusChangeCounter.Increment(hKeyStatusList[i].type);
}
}
@@ -620,10 +593,8 @@
mEventLock.unlock();
if (listener != NULL) {
- Parcel obj;
- writeByteArray(obj, sessionId);
Mutex::Autolock lock(mNotifyLock);
- listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+ listener->sendSessionLostState(sessionId);
}
return Void();
}
@@ -768,7 +739,7 @@
// reclaimSession may call back to closeSession, since mLock is
// shared between Drm instances, we should unlock here to avoid
// deadlock.
- retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+ retry = DrmSessionManager::Instance()->reclaimSession(AIBinder_getCallingPid());
mLock.lock();
} else {
retry = false;
@@ -776,9 +747,10 @@
} while (retry);
if (err == OK) {
- sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
- DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId);
- mOpenSessions.push(client);
+ std::shared_ptr<DrmSessionClient> client(new DrmSessionClient(this, sessionId));
+ DrmSessionManager::Instance()->addSession(AIBinder_getCallingPid(),
+ std::static_pointer_cast<IResourceManagerClient>(client), sessionId);
+ mOpenSessions.push_back(client);
mMetrics.SetSessionStart(sessionId);
}
@@ -794,9 +766,9 @@
if (status.isOk()) {
if (status == Status::OK) {
DrmSessionManager::Instance()->removeSession(sessionId);
- for (size_t i = 0; i < mOpenSessions.size(); i++) {
- if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) {
- mOpenSessions.removeAt(i);
+ for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
+ if (isEqualSessionId((*i)->mSessionId, sessionId)) {
+ mOpenSessions.erase(i);
break;
}
}
@@ -1559,10 +1531,6 @@
Mutex::Autolock autoLock(mLock);
INIT_CHECK();
- if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
- return -EPERM;
- }
-
DrmSessionManager::Instance()->useSession(sessionId);
status_t err = UNKNOWN_ERROR;
@@ -1580,38 +1548,23 @@
return hResult.isOk() ? err : DEAD_OBJECT;
}
-void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
-{
- cleanup();
-}
-
-void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
-{
- if (vec.size()) {
- obj.writeInt32(vec.size());
- obj.write(vec.data(), vec.size());
- } else {
- obj.writeInt32(0);
- }
-}
-
void DrmHal::reportFrameworkMetrics() const
{
- std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm"));
- item->setPkgName(mMetrics.GetAppPackageName().c_str());
+ mediametrics_handle_t item(mediametrics_create("mediadrm"));
+ mediametrics_setUid(item, mMetrics.GetAppUid());
String8 vendor;
String8 description;
status_t result = getPropertyStringInternal(String8("vendor"), vendor);
if (result != OK) {
ALOGE("Failed to get vendor from drm plugin: %d", result);
} else {
- item->setCString("vendor", vendor.c_str());
+ mediametrics_setCString(item, "vendor", vendor.c_str());
}
result = getPropertyStringInternal(String8("description"), description);
if (result != OK) {
ALOGE("Failed to get description from drm plugin: %d", result);
} else {
- item->setCString("description", description.c_str());
+ mediametrics_setCString(item, "description", description.c_str());
}
std::string serializedMetrics;
@@ -1622,11 +1575,12 @@
std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
serializedMetrics.size());
if (!b64EncodedMetrics.empty()) {
- item->setCString("serialized_metrics", b64EncodedMetrics.c_str());
+ mediametrics_setCString(item, "serialized_metrics", b64EncodedMetrics.c_str());
}
- if (!item->selfrecord()) {
+ if (!mediametrics_selfRecord(item)) {
ALOGE("Failed to self record framework metrics");
}
+ mediametrics_delete(item);
}
void DrmHal::reportPluginMetrics() const
@@ -1640,7 +1594,7 @@
std::string metricsString = toBase64StringNoPad(metricsVector.array(),
metricsVector.size());
status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
- description, mAppPackageName);
+ description, mMetrics.GetAppUid());
if (res != OK) {
ALOGE("Metrics were retrieved but could not be reported: %d", res);
}
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 0b91b85..7a4e1ae 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -18,23 +18,31 @@
#define LOG_TAG "DrmSessionManager"
#include <utils/Log.h>
-#include <android/media/IResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IProcessInfoService.h>
-#include <binder/IServiceManager.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <aidl/android/media/MediaResourceParcel.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
#include <cutils/properties.h>
-#include <media/MediaResource.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/DrmSessionManager.h>
#include <unistd.h>
#include <utils/String8.h>
#include <vector>
-#include "ResourceManagerService.h"
-
namespace android {
-using android::binder::Status;
+
+using aidl::android::media::MediaResourceParcel;
+
+namespace {
+void ResourceManagerServiceDied(void* cookie) {
+ auto thiz = static_cast<DrmSessionManager*>(cookie);
+ thiz->binderDied();
+}
+}
+
+using ::ndk::ScopedAStatus;
static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
String8 sessionIdStr;
@@ -44,33 +52,28 @@
return sessionIdStr;
}
-static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) {
- const uint8_t *v = vector.array();
- std::vector<uint8_t> vec(v, v + vector.size());
+template <typename Byte = uint8_t>
+static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
+ auto v = reinterpret_cast<const Byte *>(vector.array());
+ std::vector<Byte> vec(v, v + vector.size());
return vec;
}
-static uint64_t toClientId(const sp<IResourceManagerClient>& drm) {
- return reinterpret_cast<int64_t>(drm.get());
-}
-
static std::vector<MediaResourceParcel> toResourceVec(
const Vector<uint8_t> &sessionId, int64_t value) {
+ using Type = aidl::android::media::MediaResourceType;
+ using SubType = aidl::android::media::MediaResourceSubType;
std::vector<MediaResourceParcel> resources;
- resources.push_back(MediaResource::DrmSessionResource(toStdVec(sessionId), value));
+ MediaResourceParcel resource{
+ Type::kDrmSession, SubType::kUnspecifiedSubType,
+ toStdVec<int8_t>(sessionId), value};
+ resources.push_back(resource);
return resources;
}
-static sp<IResourceManagerService> getResourceManagerService() {
- if (property_get_bool("persist.device_config.media_native.mediadrmserver", 1)) {
- return new android::media::ResourceManagerService();
- }
- sp<IServiceManager> sm = defaultServiceManager();
- if (sm == NULL) {
- return NULL;
- }
- sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
- return interface_cast<IResourceManagerService>(binder);
+static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
+ ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+ return IResourceManagerService::fromBinder(binder);
}
bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
@@ -86,7 +89,7 @@
}
sp<DrmSessionManager> DrmSessionManager::Instance() {
- static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
+ auto drmSessionManager = new DrmSessionManager();
drmSessionManager->init();
return drmSessionManager;
}
@@ -95,9 +98,10 @@
: DrmSessionManager(getResourceManagerService()) {
}
-DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service)
+DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
: mService(service),
- mInitialized(false) {
+ mInitialized(false),
+ mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
if (mService == NULL) {
ALOGE("Failed to init ResourceManagerService");
}
@@ -105,7 +109,7 @@
DrmSessionManager::~DrmSessionManager() {
if (mService != NULL) {
- IInterface::asBinder(mService)->unlinkToDeath(this);
+ AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
}
}
@@ -116,13 +120,13 @@
}
mInitialized = true;
if (mService != NULL) {
- IInterface::asBinder(mService)->linkToDeath(this);
+ AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
}
}
void DrmSessionManager::addSession(int pid,
- const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
- uid_t uid = IPCThreadState::self()->getCallingUid();
+ const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
+ uid_t uid = AIBinder_getCallingUid();
ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
GetSessionIdString(sessionId).string());
@@ -131,9 +135,9 @@
return;
}
- int64_t clientId = toClientId(drm);
+ static int64_t clientId = 0;
mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
- mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId, INT64_MAX));
+ mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
}
void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -168,7 +172,7 @@
// unlock early because reclaimResource might callback into removeSession
mLock.lock();
- sp<IResourceManagerService> service(mService);
+ std::shared_ptr<IResourceManagerService> service(mService);
mLock.unlock();
if (service == NULL) {
@@ -179,7 +183,7 @@
// we rely on IResourceManagerClient to removeSession in reclaimResource
Vector<uint8_t> dummy;
bool success;
- Status status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+ ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
return status.isOk() && success;
}
@@ -193,10 +197,10 @@
return mSessionMap.count(toStdVec(sessionId));
}
-void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) {
+void DrmSessionManager::binderDied() {
ALOGW("ResourceManagerService died.");
Mutex::Autolock lock(mLock);
- mService.clear();
+ mService.reset();
}
} // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
new file mode 100644
index 0000000..a126a1d
--- /dev/null
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "DrmUtils"
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.2/ICryptoFactory.h>
+#include <android/hardware/drm/1.2/IDrmFactory.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/HidlSupport.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/String16.h>
+#include <cutils/properties.h>
+
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmUtils.h>
+#include <mediadrm/ICrypto.h>
+#include <mediadrm/IDrm.h>
+
+using HServiceManager = ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using namespace ::android::hardware::drm;
+
+namespace android {
+namespace DrmUtils {
+
+namespace {
+
+template<typename Hal>
+Hal *MakeObject(status_t *pstatus) {
+ status_t err = OK;
+ status_t &status = pstatus ? *pstatus : err;
+ auto obj = new Hal();
+ status = obj->initCheck();
+ if (status != OK && status != NO_INIT) {
+ return NULL;
+ }
+ return obj;
+}
+
+template <typename Hal, typename V>
+void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
+ sp<HServiceManager> serviceManager = HServiceManager::getService();
+ if (serviceManager == nullptr) {
+ ALOGE("Failed to get service manager");
+ exit(-1);
+ }
+
+ serviceManager->listByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
+ for (const auto &instance : registered) {
+ auto factory = Hal::getService(instance);
+ if (factory != nullptr) {
+ ALOGI("found %s %s", Hal::descriptor, instance.c_str());
+ if (factory->isCryptoSchemeSupported(uuid)) {
+ factories.push_back(factory);
+ }
+ }
+ }
+ });
+}
+
+hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
+ hidl_vec<uint8_t> vec(size);
+ if (ptr != nullptr) {
+ memcpy(vec.data(), ptr, size);
+ }
+ return vec;
+}
+
+hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
+ if (ptr == nullptr) {
+ return hidl_array<uint8_t, 16>();
+ }
+ return hidl_array<uint8_t, 16>(ptr);
+}
+
+sp<::V1_0::IDrmPlugin> MakeDrmPlugin(const sp<::V1_0::IDrmFactory> &factory,
+ const uint8_t uuid[16], const char *appPackageName) {
+ sp<::V1_0::IDrmPlugin> plugin;
+ factory->createPlugin(toHidlArray16(uuid), hidl_string(appPackageName),
+ [&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
+ if (status != ::V1_0::Status::OK) {
+ return;
+ }
+ plugin = hPlugin;
+ });
+ return plugin;
+}
+
+sp<::V1_0::ICryptoPlugin> MakeCryptoPlugin(const sp<::V1_0::ICryptoFactory> &factory,
+ const uint8_t uuid[16], const void *initData,
+ size_t initDataSize) {
+ sp<::V1_0::ICryptoPlugin> plugin;
+ factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
+ [&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
+ if (status != ::V1_0::Status::OK) {
+ return;
+ }
+ plugin = hPlugin;
+ });
+ return plugin;
+}
+
+} // namespace
+
+bool UseDrmService() {
+ return property_get_bool("mediadrm.use_mediadrmserver", true);
+}
+
+sp<IDrm> MakeDrm(status_t *pstatus) {
+ return MakeObject<DrmHal>(pstatus);
+}
+
+sp<ICrypto> MakeCrypto(status_t *pstatus) {
+ return MakeObject<CryptoHal>(pstatus);
+}
+
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16]) {
+ std::vector<sp<::V1_0::IDrmFactory>> drmFactories;
+ MakeHidlFactories<::V1_0::IDrmFactory>(uuid, drmFactories);
+ MakeHidlFactories<::V1_1::IDrmFactory>(uuid, drmFactories);
+ MakeHidlFactories<::V1_2::IDrmFactory>(uuid, drmFactories);
+ return drmFactories;
+}
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+ const char *appPackageName) {
+ std::vector<sp<::V1_0::IDrmPlugin>> plugins;
+ for (const auto &factory : MakeDrmFactories(uuid)) {
+ plugins.push_back(MakeDrmPlugin(factory, uuid, appPackageName));
+ }
+ return plugins;
+}
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]) {
+ std::vector<sp<::V1_0::ICryptoFactory>> cryptoFactories;
+ MakeHidlFactories<::V1_0::ICryptoFactory>(uuid, cryptoFactories);
+ MakeHidlFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
+ MakeHidlFactories<::V1_2::ICryptoFactory>(uuid, cryptoFactories);
+ return cryptoFactories;
+}
+
+std::vector<sp<ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16], const void *initData,
+ size_t initDataSize) {
+ std::vector<sp<ICryptoPlugin>> plugins;
+ for (const auto &factory : MakeCryptoFactories(uuid)) {
+ plugins.push_back(MakeCryptoPlugin(factory, uuid, initData, initDataSize));
+ }
+ return plugins;
+}
+
+} // namespace DrmUtils
+} // namespace android
diff --git a/drm/libmediadrm/ICrypto.cpp b/drm/libmediadrm/ICrypto.cpp
deleted file mode 100644
index a2594aa..0000000
--- a/drm/libmediadrm/ICrypto.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2012 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 "ICrypto"
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <cutils/log.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/ICrypto.h>
-#include <utils/Log.h>
-
-namespace android {
-
-enum {
- INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
- IS_CRYPTO_SUPPORTED,
- CREATE_PLUGIN,
- DESTROY_PLUGIN,
- REQUIRES_SECURE_COMPONENT,
- DECRYPT,
- NOTIFY_RESOLUTION,
- SET_MEDIADRM_SESSION,
- SET_HEAP,
- UNSET_HEAP,
-};
-
-struct BpCrypto : public BpInterface<ICrypto> {
- explicit BpCrypto(const sp<IBinder> &impl)
- : BpInterface<ICrypto>(impl) {
- }
-
- virtual status_t initCheck() const {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- remote()->transact(INIT_CHECK, data, &reply);
-
- return reply.readInt32();
- }
-
- virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.write(uuid, 16);
- remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
-
- return reply.readInt32() != 0;
- }
-
- virtual status_t createPlugin(
- const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.write(uuid, 16);
- data.writeInt32(opaqueSize);
-
- if (opaqueSize > 0) {
- data.write(opaqueData, opaqueSize);
- }
-
- remote()->transact(CREATE_PLUGIN, data, &reply);
-
- return reply.readInt32();
- }
-
- virtual status_t destroyPlugin() {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- remote()->transact(DESTROY_PLUGIN, data, &reply);
-
- return reply.readInt32();
- }
-
- virtual bool requiresSecureDecoderComponent(
- const char *mime) const {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeCString(mime);
- remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);
-
- return reply.readInt32() != 0;
- }
-
- virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
- CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const SourceBuffer &source, size_t offset,
- const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const DestinationBuffer &destination, AString *errorDetailMsg) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32(mode);
- data.writeInt32(pattern.mEncryptBlocks);
- data.writeInt32(pattern.mSkipBlocks);
-
- static const uint8_t kDummy[16] = { 0 };
-
- if (key == NULL) {
- key = kDummy;
- }
-
- if (iv == NULL) {
- iv = kDummy;
- }
-
- data.write(key, 16);
- data.write(iv, 16);
-
- size_t totalSize = 0;
- for (size_t i = 0; i < numSubSamples; ++i) {
- totalSize += subSamples[i].mNumBytesOfEncryptedData;
- totalSize += subSamples[i].mNumBytesOfClearData;
- }
-
- data.writeInt32(totalSize);
- data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory));
- data.writeInt32(source.mHeapSeqNum);
- data.writeInt32(offset);
-
- data.writeInt32(numSubSamples);
- data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
- data.writeInt32((int32_t)destination.mType);
- if (destination.mType == kDestinationTypeNativeHandle) {
- if (destination.mHandle == NULL) {
- return BAD_VALUE;
- }
- data.writeNativeHandle(destination.mHandle);
- } else {
- if (destination.mSharedMemory == NULL) {
- return BAD_VALUE;
- }
- data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory));
- }
-
- remote()->transact(DECRYPT, data, &reply);
-
- ssize_t result = reply.readInt32();
-
- if (isCryptoError(result)) {
- AString msg = reply.readCString();
- if (errorDetailMsg) {
- *errorDetailMsg = msg;
- }
- }
-
- return result;
- }
-
- virtual void notifyResolution(
- uint32_t width, uint32_t height) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32(width);
- data.writeInt32(height);
- remote()->transact(NOTIFY_RESOLUTION, data, &reply);
- }
-
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- remote()->transact(SET_MEDIADRM_SESSION, data, &reply);
-
- return reply.readInt32();
- }
-
- virtual int32_t setHeap(const sp<IMemoryHeap> &heap) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(heap));
- status_t err = remote()->transact(SET_HEAP, data, &reply);
- if (err != NO_ERROR) {
- return -1;
- }
- int32_t seqNum;
- if (reply.readInt32(&seqNum) != NO_ERROR) {
- return -1;
- }
- return seqNum;
- }
-
- virtual void unsetHeap(int32_t seqNum) {
- Parcel data, reply;
- data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
- data.writeInt32(seqNum);
- remote()->transact(UNSET_HEAP, data, &reply);
- return;
- }
-
-
-private:
- void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
- uint32_t size = reply.readInt32();
- vector.insertAt((size_t)0, size);
- reply.read(vector.editArray(), size);
- }
-
- void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
- data.writeInt32(vector.size());
- data.write(vector.array(), vector.size());
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
-};
-
-IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
- uint32_t size = data.readInt32();
- if (vector.insertAt((size_t)0, size) < 0) {
- vector.clear();
- }
- if (data.read(vector.editArray(), size) != NO_ERROR) {
- vector.clear();
- android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
- }
-}
-
-void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
- reply->writeInt32(vector.size());
- reply->write(vector.array(), vector.size());
-}
-
-status_t BnCrypto::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch (code) {
- case INIT_CHECK:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
- reply->writeInt32(initCheck());
-
- return OK;
- }
-
- case IS_CRYPTO_SUPPORTED:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
- uint8_t uuid[16];
- data.read(uuid, sizeof(uuid));
- reply->writeInt32(isCryptoSchemeSupported(uuid));
-
- return OK;
- }
-
- case CREATE_PLUGIN:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
-
- uint8_t uuid[16];
- data.read(uuid, sizeof(uuid));
-
- size_t opaqueSize = data.readInt32();
- void *opaqueData = NULL;
-
- const size_t kMaxOpaqueSize = 100 * 1024;
- if (opaqueSize > kMaxOpaqueSize) {
- return BAD_VALUE;
- }
-
- opaqueData = malloc(opaqueSize);
- if (NULL == opaqueData) {
- return NO_MEMORY;
- }
-
- data.read(opaqueData, opaqueSize);
- reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize));
-
- free(opaqueData);
- opaqueData = NULL;
-
- return OK;
- }
-
- case DESTROY_PLUGIN:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
- reply->writeInt32(destroyPlugin());
-
- return OK;
- }
-
- case REQUIRES_SECURE_COMPONENT:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
-
- const char *mime = data.readCString();
- if (mime == NULL) {
- reply->writeInt32(BAD_VALUE);
- } else {
- reply->writeInt32(requiresSecureDecoderComponent(mime));
- }
-
- return OK;
- }
-
- case DECRYPT:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
-
- CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32();
- CryptoPlugin::Pattern pattern;
- pattern.mEncryptBlocks = data.readInt32();
- pattern.mSkipBlocks = data.readInt32();
-
- uint8_t key[16];
- data.read(key, sizeof(key));
-
- uint8_t iv[16];
- data.read(iv, sizeof(iv));
-
- size_t totalSize = data.readInt32();
-
- SourceBuffer source;
-
- source.mSharedMemory =
- interface_cast<IMemory>(data.readStrongBinder());
- if (source.mSharedMemory == NULL) {
- reply->writeInt32(BAD_VALUE);
- return OK;
- }
- source.mHeapSeqNum = data.readInt32();
-
- int32_t offset = data.readInt32();
-
- int32_t numSubSamples = data.readInt32();
- if (numSubSamples < 0 || numSubSamples > 0xffff) {
- reply->writeInt32(BAD_VALUE);
- return OK;
- }
-
- std::unique_ptr<CryptoPlugin::SubSample[]> subSamples =
- std::make_unique<CryptoPlugin::SubSample[]>(numSubSamples);
-
- data.read(subSamples.get(),
- sizeof(CryptoPlugin::SubSample) * numSubSamples);
-
- DestinationBuffer destination;
- destination.mType = (DestinationType)data.readInt32();
- if (destination.mType == kDestinationTypeNativeHandle) {
- destination.mHandle = data.readNativeHandle();
- if (destination.mHandle == NULL) {
- reply->writeInt32(BAD_VALUE);
- return OK;
- }
- } else if (destination.mType == kDestinationTypeSharedMemory) {
- destination.mSharedMemory =
- interface_cast<IMemory>(data.readStrongBinder());
- if (destination.mSharedMemory == NULL) {
- reply->writeInt32(BAD_VALUE);
- return OK;
- }
- sp<IMemory> dest = destination.mSharedMemory;
- if (totalSize > dest->size() ||
- (size_t)dest->offset() > dest->size() - totalSize) {
- reply->writeInt32(BAD_VALUE);
- android_errorWriteLog(0x534e4554, "71389378");
- return OK;
- }
- } else {
- reply->writeInt32(BAD_VALUE);
- android_errorWriteLog(0x534e4554, "70526702");
- return OK;
- }
-
- AString errorDetailMsg;
- ssize_t result;
-
- size_t sumSubsampleSizes = 0;
- bool overflow = false;
- for (int32_t i = 0; i < numSubSamples; ++i) {
- CryptoPlugin::SubSample &ss = subSamples[i];
- if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) {
- sumSubsampleSizes += ss.mNumBytesOfEncryptedData;
- } else {
- overflow = true;
- }
- if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) {
- sumSubsampleSizes += ss.mNumBytesOfClearData;
- } else {
- overflow = true;
- }
- }
-
- if (overflow || sumSubsampleSizes != totalSize) {
- result = -EINVAL;
- } else if (totalSize > source.mSharedMemory->size()) {
- result = -EINVAL;
- } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) {
- result = -EINVAL;
- } else {
- result = decrypt(key, iv, mode, pattern, source, offset,
- subSamples.get(), numSubSamples, destination, &errorDetailMsg);
- }
-
- reply->writeInt32(result);
-
- if (isCryptoError(result)) {
- reply->writeCString(errorDetailMsg.c_str());
- }
-
- if (destination.mType == kDestinationTypeNativeHandle) {
- int err;
- if ((err = native_handle_close(destination.mHandle)) < 0) {
- ALOGW("secure buffer native_handle_close failed: %d", err);
- }
- if ((err = native_handle_delete(destination.mHandle)) < 0) {
- ALOGW("secure buffer native_handle_delete failed: %d", err);
- }
- }
-
- subSamples.reset();
- return OK;
- }
-
- case NOTIFY_RESOLUTION:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
-
- int32_t width = data.readInt32();
- int32_t height = data.readInt32();
- notifyResolution(width, height);
-
- return OK;
- }
-
- case SET_MEDIADRM_SESSION:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- reply->writeInt32(setMediaDrmSession(sessionId));
- return OK;
- }
-
- case SET_HEAP:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
- sp<IMemoryHeap> heap =
- interface_cast<IMemoryHeap>(data.readStrongBinder());
- reply->writeInt32(setHeap(heap));
- return OK;
- }
-
- case UNSET_HEAP:
- {
- CHECK_INTERFACE(ICrypto, data, reply);
- int32_t seqNum = data.readInt32();
- unsetHeap(seqNum);
- return OK;
- }
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
deleted file mode 100644
index 51274d1..0000000
--- a/drm/libmediadrm/IDrm.cpp
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Copyright (C) 2013 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 "IDrm"
-#include <utils/Log.h>
-
-#include <binder/Parcel.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AString.h>
-#include <mediadrm/IDrm.h>
-
-namespace android {
-
-enum {
- INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION,
- IS_CRYPTO_SUPPORTED,
- CREATE_PLUGIN,
- DESTROY_PLUGIN,
- OPEN_SESSION,
- CLOSE_SESSION,
- GET_KEY_REQUEST,
- PROVIDE_KEY_RESPONSE,
- REMOVE_KEYS,
- RESTORE_KEYS,
- QUERY_KEY_STATUS,
- GET_PROVISION_REQUEST,
- PROVIDE_PROVISION_RESPONSE,
- GET_SECURE_STOPS,
- RELEASE_SECURE_STOPS,
- GET_PROPERTY_STRING,
- GET_PROPERTY_BYTE_ARRAY,
- SET_PROPERTY_STRING,
- SET_PROPERTY_BYTE_ARRAY,
- GET_METRICS,
- SET_CIPHER_ALGORITHM,
- SET_MAC_ALGORITHM,
- ENCRYPT,
- DECRYPT,
- SIGN,
- SIGN_RSA,
- VERIFY,
- SET_LISTENER,
- GET_SECURE_STOP,
- REMOVE_ALL_SECURE_STOPS,
- GET_HDCP_LEVELS,
- GET_NUMBER_OF_SESSIONS,
- GET_SECURITY_LEVEL,
- REMOVE_SECURE_STOP,
- GET_SECURE_STOP_IDS,
- GET_OFFLINE_LICENSE_KEYSET_IDS,
- REMOVE_OFFLINE_LICENSE,
- GET_OFFLINE_LICENSE_STATE
-};
-
-struct BpDrm : public BpInterface<IDrm> {
- explicit BpDrm(const sp<IBinder> &impl)
- : BpInterface<IDrm>(impl) {
- }
-
- virtual status_t initCheck() const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- status_t status = remote()->transact(INIT_CHECK, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType,
- DrmPlugin::SecurityLevel level, bool *isSupported) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- data.write(uuid, 16);
- data.writeString8(mimeType);
- data.writeInt32(level);
-
- status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
- if (status != OK) {
- ALOGE("isCryptoSchemeSupported: binder call failed: %d", status);
- return status;
- }
- *isSupported = static_cast<bool>(reply.readInt32());
-
- return reply.readInt32();
- }
-
- virtual status_t createPlugin(const uint8_t uuid[16],
- const String8& appPackageName) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- data.write(uuid, 16);
- data.writeString8(appPackageName);
- status_t status = remote()->transact(CREATE_PLUGIN, data, &reply);
- if (status != OK) {
- ALOGE("createPlugin: binder call failed: %d", status);
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t destroyPlugin() {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- status_t status = remote()->transact(DESTROY_PLUGIN, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t openSession(DrmPlugin::SecurityLevel level,
- Vector<uint8_t> &sessionId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- data.writeInt32(level);
-
- status_t status = remote()->transact(OPEN_SESSION, data, &reply);
- if (status != OK) {
- return status;
- }
- readVector(reply, sessionId);
-
- return reply.readInt32();
- }
-
- virtual status_t closeSession(Vector<uint8_t> const &sessionId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- status_t status = remote()->transact(CLOSE_SESSION, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t
- getKeyRequest(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &initData,
- String8 const &mimeType, DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const &optionalParameters,
- Vector<uint8_t> &request, String8 &defaultUrl,
- DrmPlugin::KeyRequestType *keyRequestType) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, initData);
- data.writeString8(mimeType);
- data.writeInt32((uint32_t)keyType);
-
- data.writeInt32(optionalParameters.size());
- for (size_t i = 0; i < optionalParameters.size(); ++i) {
- data.writeString8(optionalParameters.keyAt(i));
- data.writeString8(optionalParameters.valueAt(i));
- }
-
- status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, request);
- defaultUrl = reply.readString8();
- *keyRequestType = static_cast<DrmPlugin::KeyRequestType>(reply.readInt32());
-
- return reply.readInt32();
- }
-
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- writeVector(data, sessionId);
- writeVector(data, response);
-
- status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, keySetId);
-
- return reply.readInt32();
- }
-
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, keySetId);
- status_t status = remote()->transact(REMOVE_KEYS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, keySetId);
- status_t status = remote()->transact(RESTORE_KEYS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- status_t status = remote()->transact(QUERY_KEY_STATUS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- infoMap.clear();
- size_t count = reply.readInt32();
- for (size_t i = 0; i < count; i++) {
- String8 key = reply.readString8();
- String8 value = reply.readString8();
- infoMap.add(key, value);
- }
- return reply.readInt32();
- }
-
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaultUrl) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- data.writeString8(certType);
- data.writeString8(certAuthority);
- status_t status = remote()->transact(GET_PROVISION_REQUEST, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, request);
- defaultUrl = reply.readString8();
-
- return reply.readInt32();
- }
-
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, response);
- status_t status = remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, certificate);
- readVector(reply, wrappedKey);
-
- return reply.readInt32();
- }
-
- virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_SECURE_STOPS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- secureStops.clear();
- uint32_t count = reply.readInt32();
- for (size_t i = 0; i < count; i++) {
- Vector<uint8_t> secureStop;
- readVector(reply, secureStop);
- secureStops.push_back(secureStop);
- }
- return reply.readInt32();
- }
-
- virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- secureStopIds.clear();
- uint32_t count = reply.readInt32();
- for (size_t i = 0; i < count; i++) {
- Vector<uint8_t> secureStopId;
- readVector(reply, secureStopId);
- secureStopIds.push_back(secureStopId);
- }
- return reply.readInt32();
- }
-
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, ssid);
- status_t status = remote()->transact(GET_SECURE_STOP, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, secureStop);
- return reply.readInt32();
- }
-
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, ssRelease);
- status_t status = remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, ssid);
- status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t removeAllSecureStops() {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t> > &keySetIds) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_OFFLINE_LICENSE_KEYSET_IDS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- keySetIds.clear();
- uint32_t count = reply.readInt32();
- for (size_t i = 0; i < count; i++) {
- Vector<uint8_t> keySetId;
- readVector(reply, keySetId);
- keySetIds.push_back(keySetId);
- }
- return reply.readInt32();
- }
-
- virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, keySetId);
- status_t status = remote()->transact(REMOVE_OFFLINE_LICENSE, data, &reply);
- if (status != OK) {
- return status;
- }
- return reply.readInt32();
- }
-
- virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
- DrmPlugin::OfflineLicenseState *licenseState) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, keySetId);
- status_t status = remote()->transact(GET_OFFLINE_LICENSE_STATE, data, &reply);
- if (status != OK) {
- *licenseState = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown;
- return status;
- }
- *licenseState = static_cast<DrmPlugin::OfflineLicenseState>(reply.readInt32());
- return reply.readInt32();
- }
-
- virtual status_t getPropertyString(String8 const &name, String8 &value) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- data.writeString8(name);
- status_t status = remote()->transact(GET_PROPERTY_STRING, data, &reply);
- if (status != OK) {
- return status;
- }
-
- value = reply.readString8();
- return reply.readInt32();
- }
-
- virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connected,
- DrmPlugin::HdcpLevel *max) const {
- Parcel data, reply;
-
- if (connected == NULL || max == NULL) {
- return BAD_VALUE;
- }
-
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_HDCP_LEVELS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- *connected = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
- *max = static_cast<DrmPlugin::HdcpLevel>(reply.readInt32());
- return reply.readInt32();
- }
-
- virtual status_t getNumberOfSessions(uint32_t *open, uint32_t *max) const {
- Parcel data, reply;
-
- if (open == NULL || max == NULL) {
- return BAD_VALUE;
- }
-
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_NUMBER_OF_SESSIONS, data, &reply);
- if (status != OK) {
- return status;
- }
-
- *open = reply.readInt32();
- *max = reply.readInt32();
- return reply.readInt32();
- }
-
- virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
- DrmPlugin::SecurityLevel *level) const {
- Parcel data, reply;
-
- if (level == NULL) {
- return BAD_VALUE;
- }
-
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- status_t status = remote()->transact(GET_SECURITY_LEVEL, data, &reply);
- if (status != OK) {
- return status;
- }
-
- *level = static_cast<DrmPlugin::SecurityLevel>(reply.readInt32());
- return reply.readInt32();
- }
-
- virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- data.writeString8(name);
- status_t status = remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
- if (status != OK) {
- return status;
- }
-
- readVector(reply, value);
- return reply.readInt32();
- }
-
- virtual status_t setPropertyString(String8 const &name, String8 const &value) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- data.writeString8(name);
- data.writeString8(value);
- status_t status = remote()->transact(SET_PROPERTY_STRING, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value) const {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- data.writeString8(name);
- writeVector(data, value);
- status_t status = remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
- if (status != OK) {
- return status;
- }
-
- return reply.readInt32();
- }
-
- virtual status_t getMetrics(os::PersistableBundle *metrics) {
- if (metrics == NULL) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- status_t status = remote()->transact(GET_METRICS, data, &reply);
- if (status != OK) {
- return status;
- }
- // The reply data is ordered as
- // 1) 32 bit integer reply followed by
- // 2) Serialized PersistableBundle containing metrics.
- status_t reply_status;
- if (reply.readInt32(&reply_status) != OK
- || reply_status != OK) {
- ALOGE("Failed to read getMetrics response code from parcel. %d",
- reply_status);
- return reply_status;
- }
-
- status = metrics->readFromParcel(&reply);
- if (status != OK) {
- ALOGE("Failed to read metrics from parcel. %d", status);
- return status;
- }
- return reply_status;
- }
-
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- data.writeString8(algorithm);
- status_t status = remote()->transact(SET_CIPHER_ALGORITHM, data, &reply);
- if (status != OK) {
- return status;
- }
- return reply.readInt32();
- }
-
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- data.writeString8(algorithm);
- status_t status = remote()->transact(SET_MAC_ALGORITHM, data, &reply);
- if (status != OK) {
- return status;
- }
- return reply.readInt32();
- }
-
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, keyId);
- writeVector(data, input);
- writeVector(data, iv);
-
- status_t status = remote()->transact(ENCRYPT, data, &reply);
- if (status != OK) {
- return status;
- }
- readVector(reply, output);
-
- return reply.readInt32();
- }
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, keyId);
- writeVector(data, input);
- writeVector(data, iv);
-
- status_t status = remote()->transact(DECRYPT, data, &reply);
- if (status != OK) {
- return status;
- }
- readVector(reply, output);
-
- return reply.readInt32();
- }
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, keyId);
- writeVector(data, message);
-
- status_t status = remote()->transact(SIGN, data, &reply);
- if (status != OK) {
- return status;
- }
- readVector(reply, signature);
-
- return reply.readInt32();
- }
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- writeVector(data, keyId);
- writeVector(data, message);
- writeVector(data, signature);
-
- status_t status = remote()->transact(VERIFY, data, &reply);
- if (status != OK) {
- return status;
- }
- match = (bool)reply.readInt32();
- return reply.readInt32();
- }
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
-
- writeVector(data, sessionId);
- data.writeString8(algorithm);
- writeVector(data, message);
- writeVector(data, wrappedKey);
-
- status_t status = remote()->transact(SIGN_RSA, data, &reply);
- if (status != OK) {
- return status;
- }
- readVector(reply, signature);
-
- return reply.readInt32();
- }
-
- virtual status_t setListener(const sp<IDrmClient>& listener) {
- Parcel data, reply;
- data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(listener));
- status_t status = remote()->transact(SET_LISTENER, data, &reply);
- if (status != OK) {
- return status;
- }
- return reply.readInt32();
- }
-
-private:
- void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
- uint32_t size = reply.readInt32();
- vector.insertAt((size_t)0, size);
- reply.read(vector.editArray(), size);
- }
-
- void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
- data.writeInt32(vector.size());
- data.write(vector.array(), vector.size());
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(BpDrm);
-};
-
-IMPLEMENT_META_INTERFACE(Drm, "android.drm.IDrm");
-
-////////////////////////////////////////////////////////////////////////////////
-
-void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
- uint32_t size = data.readInt32();
- if (vector.insertAt((size_t)0, size) < 0) {
- vector.clear();
- }
- if (data.read(vector.editArray(), size) != NO_ERROR) {
- vector.clear();
- android_errorWriteWithInfoLog(0x534e4554, "62872384", -1, NULL, 0);
- }
-}
-
-void BnDrm::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
- reply->writeInt32(vector.size());
- reply->write(vector.array(), vector.size());
-}
-
-status_t BnDrm::onTransact(
- uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
- switch (code) {
- case INIT_CHECK:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- reply->writeInt32(initCheck());
- return OK;
- }
-
- case IS_CRYPTO_SUPPORTED:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- uint8_t uuid[16];
- data.read(uuid, sizeof(uuid));
- String8 mimeType = data.readString8();
- DrmPlugin::SecurityLevel level =
- static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
- bool isSupported = false;
- status_t result = isCryptoSchemeSupported(uuid, mimeType, level, &isSupported);
- reply->writeInt32(isSupported);
- reply->writeInt32(result);
- return OK;
- }
-
- case CREATE_PLUGIN:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- uint8_t uuid[16];
- data.read(uuid, sizeof(uuid));
- String8 appPackageName = data.readString8();
- reply->writeInt32(createPlugin(uuid, appPackageName));
- return OK;
- }
-
- case DESTROY_PLUGIN:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- reply->writeInt32(destroyPlugin());
- return OK;
- }
-
- case OPEN_SESSION:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- DrmPlugin::SecurityLevel level =
- static_cast<DrmPlugin::SecurityLevel>(data.readInt32());
- Vector<uint8_t> sessionId;
- status_t result = openSession(level, sessionId);
- writeVector(reply, sessionId);
- reply->writeInt32(result);
- return OK;
- }
-
- case CLOSE_SESSION:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- reply->writeInt32(closeSession(sessionId));
- return OK;
- }
-
- case GET_KEY_REQUEST:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, initData;
-
- readVector(data, sessionId);
- readVector(data, initData);
- String8 mimeType = data.readString8();
- DrmPlugin::KeyType keyType = (DrmPlugin::KeyType)data.readInt32();
-
- KeyedVector<String8, String8> optionalParameters;
- uint32_t count = data.readInt32();
- for (size_t i = 0; i < count; ++i) {
- String8 key, value;
- key = data.readString8();
- value = data.readString8();
- optionalParameters.add(key, value);
- }
-
- Vector<uint8_t> request;
- String8 defaultUrl;
- DrmPlugin::KeyRequestType keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
-
- status_t result = getKeyRequest(sessionId, initData, mimeType,
- keyType, optionalParameters, request, defaultUrl,
- &keyRequestType);
-
- writeVector(reply, request);
- reply->writeString8(defaultUrl);
- reply->writeInt32(static_cast<int32_t>(keyRequestType));
- reply->writeInt32(result);
- return OK;
- }
-
- case PROVIDE_KEY_RESPONSE:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, response, keySetId;
- readVector(data, sessionId);
- readVector(data, response);
- uint32_t result = provideKeyResponse(sessionId, response, keySetId);
- writeVector(reply, keySetId);
- reply->writeInt32(result);
- return OK;
- }
-
- case REMOVE_KEYS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> keySetId;
- readVector(data, keySetId);
- reply->writeInt32(removeKeys(keySetId));
- return OK;
- }
-
- case RESTORE_KEYS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, keySetId;
- readVector(data, sessionId);
- readVector(data, keySetId);
- reply->writeInt32(restoreKeys(sessionId, keySetId));
- return OK;
- }
-
- case QUERY_KEY_STATUS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- KeyedVector<String8, String8> infoMap;
- status_t result = queryKeyStatus(sessionId, infoMap);
- size_t count = infoMap.size();
- reply->writeInt32(count);
- for (size_t i = 0; i < count; ++i) {
- reply->writeString8(infoMap.keyAt(i));
- reply->writeString8(infoMap.valueAt(i));
- }
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_PROVISION_REQUEST:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- String8 certType = data.readString8();
- String8 certAuthority = data.readString8();
-
- Vector<uint8_t> request;
- String8 defaultUrl;
- status_t result = getProvisionRequest(certType, certAuthority,
- request, defaultUrl);
- writeVector(reply, request);
- reply->writeString8(defaultUrl);
- reply->writeInt32(result);
- return OK;
- }
-
- case PROVIDE_PROVISION_RESPONSE:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> response;
- Vector<uint8_t> certificate;
- Vector<uint8_t> wrappedKey;
- readVector(data, response);
- status_t result = provideProvisionResponse(response, certificate, wrappedKey);
- writeVector(reply, certificate);
- writeVector(reply, wrappedKey);
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_SECURE_STOPS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- List<Vector<uint8_t> > secureStops;
- status_t result = getSecureStops(secureStops);
- size_t count = secureStops.size();
- reply->writeInt32(count);
- List<Vector<uint8_t> >::iterator iter = secureStops.begin();
- while(iter != secureStops.end()) {
- size_t size = iter->size();
- reply->writeInt32(size);
- reply->write(iter->array(), iter->size());
- iter++;
- }
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_SECURE_STOP_IDS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- List<Vector<uint8_t> > secureStopIds;
- status_t result = getSecureStopIds(secureStopIds);
- size_t count = secureStopIds.size();
- reply->writeInt32(count);
- List<Vector<uint8_t> >::iterator iter = secureStopIds.begin();
- while(iter != secureStopIds.end()) {
- size_t size = iter->size();
- reply->writeInt32(size);
- reply->write(iter->array(), iter->size());
- iter++;
- }
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_SECURE_STOP:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> ssid, secureStop;
- readVector(data, ssid);
- status_t result = getSecureStop(ssid, secureStop);
- writeVector(reply, secureStop);
- reply->writeInt32(result);
- return OK;
- }
-
- case RELEASE_SECURE_STOPS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> ssRelease;
- readVector(data, ssRelease);
- reply->writeInt32(releaseSecureStops(ssRelease));
- return OK;
- }
-
- case REMOVE_SECURE_STOP:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> ssid;
- readVector(data, ssid);
- reply->writeInt32(removeSecureStop(ssid));
- return OK;
- }
-
- case REMOVE_ALL_SECURE_STOPS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- reply->writeInt32(removeAllSecureStops());
- return OK;
- }
-
- case GET_HDCP_LEVELS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
- DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
- status_t result = getHdcpLevels(&connected, &max);
- reply->writeInt32(connected);
- reply->writeInt32(max);
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_NUMBER_OF_SESSIONS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- uint32_t open = 0, max = 0;
- status_t result = getNumberOfSessions(&open, &max);
- reply->writeInt32(open);
- reply->writeInt32(max);
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_SECURITY_LEVEL:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
- status_t result = getSecurityLevel(sessionId, &level);
- reply->writeInt32(level);
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_OFFLINE_LICENSE_KEYSET_IDS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- List<Vector<uint8_t> > keySetIds;
- status_t result = getOfflineLicenseKeySetIds(keySetIds);
- size_t count = keySetIds.size();
- reply->writeInt32(count);
- List<Vector<uint8_t> >::iterator iter = keySetIds.begin();
- while(iter != keySetIds.end()) {
- size_t size = iter->size();
- reply->writeInt32(size);
- reply->write(iter->array(), iter->size());
- iter++;
- }
- reply->writeInt32(result);
- return OK;
- }
-
- case REMOVE_OFFLINE_LICENSE:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> keySetId;
- readVector(data, keySetId);
- reply->writeInt32(removeOfflineLicense(keySetId));
- return OK;
- }
-
- case GET_OFFLINE_LICENSE_STATE:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> keySetId;
- readVector(data, keySetId);
- DrmPlugin::OfflineLicenseState state;
- status_t result = getOfflineLicenseState(keySetId, &state);
- reply->writeInt32(static_cast<DrmPlugin::OfflineLicenseState>(state));
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_PROPERTY_STRING:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- String8 name = data.readString8();
- String8 value;
- status_t result = getPropertyString(name, value);
- reply->writeString8(value);
- reply->writeInt32(result);
- return OK;
- }
-
- case GET_PROPERTY_BYTE_ARRAY:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- String8 name = data.readString8();
- Vector<uint8_t> value;
- status_t result = getPropertyByteArray(name, value);
- writeVector(reply, value);
- reply->writeInt32(result);
- return OK;
- }
-
- case SET_PROPERTY_STRING:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- String8 name = data.readString8();
- String8 value = data.readString8();
- reply->writeInt32(setPropertyString(name, value));
- return OK;
- }
-
- case SET_PROPERTY_BYTE_ARRAY:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- String8 name = data.readString8();
- Vector<uint8_t> value;
- readVector(data, value);
- reply->writeInt32(setPropertyByteArray(name, value));
- return OK;
- }
-
- case GET_METRICS:
- {
- CHECK_INTERFACE(IDrm, data, reply);
-
- os::PersistableBundle metrics;
- status_t result = getMetrics(&metrics);
- // The reply data is ordered as
- // 1) 32 bit integer reply followed by
- // 2) Serialized PersistableBundle containing metrics.
- // Only write the metrics if the getMetrics result was
- // OK and we successfully added the status to reply.
- status_t parcel_result = reply->writeInt32(result);
- if (result == OK && parcel_result == OK) {
- parcel_result = metrics.writeToParcel(reply);
- }
- return parcel_result;
- }
-
- case SET_CIPHER_ALGORITHM:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- String8 algorithm = data.readString8();
- reply->writeInt32(setCipherAlgorithm(sessionId, algorithm));
- return OK;
- }
-
- case SET_MAC_ALGORITHM:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId;
- readVector(data, sessionId);
- String8 algorithm = data.readString8();
- reply->writeInt32(setMacAlgorithm(sessionId, algorithm));
- return OK;
- }
-
- case ENCRYPT:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, keyId, input, iv, output;
- readVector(data, sessionId);
- readVector(data, keyId);
- readVector(data, input);
- readVector(data, iv);
- uint32_t result = encrypt(sessionId, keyId, input, iv, output);
- writeVector(reply, output);
- reply->writeInt32(result);
- return OK;
- }
-
- case DECRYPT:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, keyId, input, iv, output;
- readVector(data, sessionId);
- readVector(data, keyId);
- readVector(data, input);
- readVector(data, iv);
- uint32_t result = decrypt(sessionId, keyId, input, iv, output);
- writeVector(reply, output);
- reply->writeInt32(result);
- return OK;
- }
-
- case SIGN:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, keyId, message, signature;
- readVector(data, sessionId);
- readVector(data, keyId);
- readVector(data, message);
- uint32_t result = sign(sessionId, keyId, message, signature);
- writeVector(reply, signature);
- reply->writeInt32(result);
- return OK;
- }
-
- case VERIFY:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, keyId, message, signature;
- readVector(data, sessionId);
- readVector(data, keyId);
- readVector(data, message);
- readVector(data, signature);
- bool match = false;
- uint32_t result = verify(sessionId, keyId, message, signature, match);
- reply->writeInt32(match);
- reply->writeInt32(result);
- return OK;
- }
-
- case SIGN_RSA:
- {
- CHECK_INTERFACE(IDrm, data, reply);
- Vector<uint8_t> sessionId, message, wrappedKey, signature;
- readVector(data, sessionId);
- String8 algorithm = data.readString8();
- readVector(data, message);
- readVector(data, wrappedKey);
- uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature);
- writeVector(reply, signature);
- reply->writeInt32(result);
- return OK;
- }
-
- case SET_LISTENER: {
- CHECK_INTERFACE(IDrm, data, reply);
- sp<IDrmClient> listener =
- interface_cast<IDrmClient>(data.readStrongBinder());
- reply->writeInt32(setListener(listener));
- return NO_ERROR;
- } break;
-
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/IDrmClient.cpp b/drm/libmediadrm/IDrmClient.cpp
deleted file mode 100644
index 357de9d..0000000
--- a/drm/libmediadrm/IDrmClient.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-**
-** Copyright 2013, 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 "IDrmClient"
-#include <utils/Log.h>
-
-#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-#include <media/IMediaPlayerClient.h>
-#include <mediadrm/IDrmClient.h>
-
-namespace android {
-
-enum {
- NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpDrmClient: public BpInterface<IDrmClient>
-{
-public:
- explicit BpDrmClient(const sp<IBinder>& impl)
- : BpInterface<IDrmClient>(impl)
- {
- }
-
- virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IDrmClient::getInterfaceDescriptor());
- data.writeInt32((int)eventType);
- data.writeInt32(extra);
- if (obj && obj->dataSize() > 0) {
- data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
- }
- remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(DrmClient, "android.media.IDrmClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnDrmClient::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case NOTIFY: {
- CHECK_INTERFACE(IDrmClient, data, reply);
- int eventType = data.readInt32();
- int extra = data.readInt32();
- Parcel obj;
- if (data.dataAvail() > 0) {
- obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
- }
-
- notify((DrmPlugin::EventType)eventType, extra, &obj);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace android
diff --git a/drm/libmediadrm/IMediaDrmService.cpp b/drm/libmediadrm/IMediaDrmService.cpp
deleted file mode 100644
index f320d0b..0000000
--- a/drm/libmediadrm/IMediaDrmService.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-**
-** Copyright 2015, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-#include <binder/IMemory.h>
-#include <mediadrm/ICrypto.h>
-#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
-
-#include <utils/Errors.h> // for status_t
-#include <utils/String8.h>
-
-namespace android {
-
-enum {
- MAKE_CRYPTO = IBinder::FIRST_CALL_TRANSACTION,
- MAKE_DRM,
-};
-
-class BpMediaDrmService: public BpInterface<IMediaDrmService>
-{
-public:
- explicit BpMediaDrmService(const sp<IBinder>& impl)
- : BpInterface<IMediaDrmService>(impl)
- {
- }
-
- virtual sp<ICrypto> makeCrypto() {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
- remote()->transact(MAKE_CRYPTO, data, &reply);
- return interface_cast<ICrypto>(reply.readStrongBinder());
- }
-
- virtual sp<IDrm> makeDrm() {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaDrmService::getInterfaceDescriptor());
- remote()->transact(MAKE_DRM, data, &reply);
- return interface_cast<IDrm>(reply.readStrongBinder());
- }
-
-};
-
-IMPLEMENT_META_INTERFACE(MediaDrmService, "android.media.IMediaDrmService");
-
-// ----------------------------------------------------------------------
-
-status_t BnMediaDrmService::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch (code) {
- case MAKE_CRYPTO: {
- CHECK_INTERFACE(IMediaDrmService, data, reply);
- sp<ICrypto> crypto = makeCrypto();
- reply->writeStrongBinder(IInterface::asBinder(crypto));
- return NO_ERROR;
- } break;
- case MAKE_DRM: {
- CHECK_INTERFACE(IMediaDrmService, data, reply);
- sp<IDrm> drm = makeDrm();
- reply->writeStrongBinder(IInterface::asBinder(drm));
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-// ----------------------------------------------------------------------------
-
-} // namespace android
diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp
index 098f07b..b0abf83 100644
--- a/drm/libmediadrm/PluginMetricsReporting.cpp
+++ b/drm/libmediadrm/PluginMetricsReporting.cpp
@@ -21,7 +21,7 @@
#include <inttypes.h>
-#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
#include <utils/Log.h>
@@ -33,18 +33,18 @@
status_t reportVendorMetrics(const std::string& metrics,
const String8& name,
- const String8& appPackageName) {
- std::unique_ptr<MediaAnalyticsItem> analyticsItem(MediaAnalyticsItem::create(name.c_str()));
- std::string app_package_name(appPackageName.c_str(), appPackageName.size());
- analyticsItem->setPkgName(app_package_name);
+ uid_t appUid) {
+ mediametrics_handle_t analyticsItem(mediametrics_create(name.c_str()));
+ mediametrics_setUid(analyticsItem, appUid);
if (metrics.size() > 0) {
- analyticsItem->setCString(kSerializedMetricsField, metrics.c_str());
+ mediametrics_setCString(analyticsItem, kSerializedMetricsField, metrics.c_str());
}
- if (!analyticsItem->selfrecord()) {
+ if (!mediametrics_selfRecord(analyticsItem)) {
ALOGE("%s: selfrecord() returned false", __func__);
}
+ mediametrics_delete(analyticsItem);
return OK;
}
@@ -67,13 +67,13 @@
status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
const String8& vendor,
const String8& description,
- const String8& appPackageName) {
+ uid_t appUid) {
String8 name = String8::format("drm.vendor.%s.%s",
sanitize(vendor).c_str(),
sanitize(description).c_str());
- return reportVendorMetrics(b64EncodedMetrics, name, appPackageName);
+ return reportVendorMetrics(b64EncodedMetrics, name, appUid);
}
} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/BundleDrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/BundleDrmMetricsConsumer.h
new file mode 100644
index 0000000..1bcb352
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/BundleDrmMetricsConsumer.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/PersistableBundle.h>
+#include <mediadrm/IDrmMetricsConsumer.h>
+#include <utils/Errors.h>
+
+#ifndef ANDROID_BUNDLEMETRICSCONSUMER_H_
+
+#define ANDROID_BUNDLEMETRICSCONSUMER_H_
+
+namespace android {
+
+/**
+ * IDrmMetricsConsumer which saves IDrm/ICrypto metrics into a PersistableBundle.
+ *
+ * Example usage:
+ *
+ * PersistableBundle bundle;
+ * BundleDrmMetricsConsumer consumer(&bundle);
+ * drm->exportMetrics(&consumer);
+ * crypto->exportMetrics(&consumer);
+ * // bundle now contains metrics from drm/crypto.
+ *
+ */
+struct BundleDrmMetricsConsumer : public IDrmMetricsConsumer {
+ BundleDrmMetricsConsumer(os::PersistableBundle*) {}
+
+ status_t consumeFrameworkMetrics(const MediaDrmMetrics &) override {
+ return OK;
+ }
+
+ status_t consumeHidlMetrics(
+ const String8 &/*vendor*/,
+ const hidl_vec<DrmMetricGroup> &/*pluginMetrics*/) override {
+ return OK;
+ }
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(BundleDrmMetricsConsumer);
+};
+
+} // namespace android
+
+#endif // ANDROID_BUNDLEMETRICSCONSUMER_H_
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 9e61777..c9fda67 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -31,12 +31,15 @@
using drm::V1_0::ICryptoFactory;
using drm::V1_0::ICryptoPlugin;
using drm::V1_0::SharedBuffer;
+using drm::V1_0::DestinationBuffer;
+
+using ::android::hardware::HidlMemory;
class IMemoryHeap;
namespace android {
-struct CryptoHal : public BnCrypto {
+struct CryptoHal : public ICrypto {
CryptoHal();
virtual ~CryptoHal();
@@ -58,12 +61,12 @@
virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const ICrypto::SourceBuffer &source, size_t offset,
+ const ::SharedBuffer &source, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const ICrypto::DestinationBuffer &destination,
+ const ::DestinationBuffer &destination,
AString *errorDetailMsg);
- virtual int32_t setHeap(const sp<IMemoryHeap>& heap) {
+ virtual int32_t setHeap(const sp<HidlMemory>& heap) {
return setHeapBase(heap);
}
virtual void unsetHeap(int32_t seqNum) { clearHeapBase(seqNum); }
@@ -83,30 +86,17 @@
*/
status_t mInitCheck;
- struct HeapBase {
- HeapBase() : mBufferId(0), mSize(0) {}
- HeapBase(uint32_t bufferId, size_t size) :
- mBufferId(bufferId), mSize(size) {}
-
- uint32_t getBufferId() const {return mBufferId;}
- size_t getSize() const {return mSize;}
-
- private:
- uint32_t mBufferId;
- size_t mSize;
- };
-
- KeyedVector<int32_t, HeapBase> mHeapBases;
+ KeyedVector<int32_t, size_t> mHeapSizes;
int32_t mHeapSeqNum;
Vector<sp<ICryptoFactory>> makeCryptoFactories();
sp<ICryptoPlugin> makeCryptoPlugin(const sp<ICryptoFactory>& factory,
const uint8_t uuid[16], const void *initData, size_t size);
- int32_t setHeapBase(const sp<IMemoryHeap>& heap);
+ int32_t setHeapBase(const sp<HidlMemory>& heap);
void clearHeapBase(int32_t seqNum);
- status_t toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer);
+ status_t checkSharedBuffer(const ::SharedBuffer& buffer);
DISALLOW_EVIL_CONSTRUCTORS(CryptoHal);
};
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index 0431c93..f261d89 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -26,7 +26,6 @@
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-#include <media/MediaAnalyticsItem.h>
#include <mediadrm/DrmMetrics.h>
#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/IDrm.h>
@@ -57,8 +56,7 @@
return memcmp(l.array(), r.array(), l.size()) == 0;
}
-struct DrmHal : public BnDrm,
- public IBinder::DeathRecipient,
+struct DrmHal : public IDrm,
public IDrmPluginListener_V1_2 {
struct DrmSessionClient;
@@ -192,8 +190,6 @@
Return<void> sendSessionLostState(const hidl_vec<uint8_t>& sessionId);
- virtual void binderDied(const wp<IBinder> &the_late_who);
-
private:
static Mutex mLock;
@@ -210,7 +206,7 @@
// Mutable to allow modification within GetPropertyByteArray.
mutable MediaDrmMetrics mMetrics;
- Vector<sp<DrmSessionClient>> mOpenSessions;
+ std::vector<std::shared_ptr<DrmSessionClient>> mOpenSessions;
void closeOpenSessions();
void cleanup();
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetrics.h b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
index 6f132bf..833ffa4 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetrics.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetrics.h
@@ -25,6 +25,7 @@
#include <binder/PersistableBundle.h>
#include <media/CounterMetric.h>
#include <media/EventMetric.h>
+#include <sys/types.h>
namespace android {
@@ -71,6 +72,9 @@
void SetAppPackageName(const String8& appPackageName) { mAppPackageName = appPackageName; }
const String8& GetAppPackageName() { return mAppPackageName; }
+ void SetAppUid(uid_t appUid) { mAppUid = appUid; }
+ uid_t GetAppUid() const { return mAppUid; }
+
// Export the metrics to a PersistableBundle.
void Export(os::PersistableBundle* metricsBundle);
@@ -131,6 +135,7 @@
std::map<std::string, std::pair<int64_t, int64_t>> mSessionLifespans;
String8 mAppPackageName;
+ uid_t mAppUid{~0u};
};
} // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
index 3258f7a..9e43504 100644
--- a/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
+++ b/drm/libmediadrm/include/mediadrm/DrmSessionManager.h
@@ -18,7 +18,9 @@
#define DRM_SESSION_MANAGER_H_
-#include <binder/IBinder.h>
+#include <aidl/android/media/IResourceManagerClient.h>
+#include <aidl/android/media/IResourceManagerService.h>
+#include <android/binder_auto_utils.h>
#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
#include <utils/KeyedVector.h>
@@ -26,6 +28,7 @@
#include <utils/Vector.h>
#include <map>
+#include <memory>
#include <utility>
#include <vector>
@@ -33,12 +36,8 @@
class DrmSessionManagerTest;
-namespace media {
-class IResourceManagerClient;
-class IResourceManagerService;
-}
-using android::media::IResourceManagerClient;
-using android::media::IResourceManagerService;
+using aidl::android::media::IResourceManagerClient;
+using aidl::android::media::IResourceManagerService;
bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2);
@@ -50,13 +49,15 @@
typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap;
-struct DrmSessionManager : public IBinder::DeathRecipient {
+struct DrmSessionManager : public RefBase {
static sp<DrmSessionManager> Instance();
DrmSessionManager();
- explicit DrmSessionManager(const sp<IResourceManagerService> &service);
+ explicit DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service);
- void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId);
+ void addSession(int pid,
+ const std::shared_ptr<IResourceManagerClient>& drm,
+ const Vector<uint8_t>& sessionId);
void useSession(const Vector<uint8_t>& sessionId);
void removeSession(const Vector<uint8_t>& sessionId);
bool reclaimSession(int callingPid);
@@ -66,7 +67,7 @@
bool containsSession(const Vector<uint8_t>& sessionId) const;
// implements DeathRecipient
- virtual void binderDied(const wp<IBinder>& /*who*/);
+ void binderDied();
protected:
virtual ~DrmSessionManager();
@@ -74,10 +75,11 @@
private:
void init();
- sp<IResourceManagerService> mService;
+ std::shared_ptr<IResourceManagerService> mService;
mutable Mutex mLock;
SessionInfoMap mSessionMap;
bool mInitialized;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager);
};
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index fbe80c6..4103d5d 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -18,7 +18,6 @@
#include <binder/PersistableBundle.h>
#include <media/stagefright/foundation/ABase.h>
#include <media/drm/DrmAPI.h>
-#include <media/MediaAnalyticsItem.h>
#include <mediadrm/IDrmClient.h>
#ifndef ANDROID_IDRM_H_
@@ -29,8 +28,9 @@
struct AString;
-struct IDrm : public IInterface {
- DECLARE_META_INTERFACE(Drm);
+struct IDrm : public virtual RefBase {
+
+ virtual ~IDrm() {}
virtual status_t initCheck() const = 0;
@@ -146,19 +146,13 @@
virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
+protected:
+ IDrm() {}
+
private:
DISALLOW_EVIL_CONSTRUCTORS(IDrm);
};
-struct BnDrm : public BnInterface<IDrm> {
- virtual status_t onTransact(
- uint32_t code, const Parcel &data, Parcel *reply,
- uint32_t flags = 0);
-private:
- void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
- void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
} // namespace android
#endif // ANDROID_IDRM_H_
diff --git a/drm/libmediadrm/include/mediadrm/IDrmClient.h b/drm/libmediadrm/include/mediadrm/IDrmClient.h
index 3b2fc7c..fe25ae1 100644
--- a/drm/libmediadrm/include/mediadrm/IDrmClient.h
+++ b/drm/libmediadrm/include/mediadrm/IDrmClient.h
@@ -18,29 +18,46 @@
#define ANDROID_IDRMCLIENT_H
#include <utils/RefBase.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
+#include <hidl/HidlSupport.h>
#include <media/drm/DrmAPI.h>
+#include <cstdint>
+#include <vector>
+
namespace android {
-class IDrmClient: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(DrmClient);
-
- virtual void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) = 0;
+struct DrmKeyStatus {
+ const uint32_t type;
+ const hardware::hidl_vec<uint8_t> keyId;
};
-// ----------------------------------------------------------------------------
-
-class BnDrmClient: public BnInterface<IDrmClient>
+class IDrmClient: public virtual RefBase
{
public:
- virtual status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ ~IDrmClient() {}
+
+ virtual void sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) = 0;
+
+ virtual void sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) = 0;
+
+ virtual void sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) = 0;
+
+ virtual void sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &sessionId) = 0;
+
+protected:
+ IDrmClient() {}
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(IDrmClient);
};
}; // namespace android
diff --git a/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
new file mode 100644
index 0000000..efa61d8
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/IDrmMetricsConsumer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/drm/1.1/types.h>
+#include <hidl/HidlSupport.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#ifndef ANDROID_IDRMMETRICSCONSUMER_H_
+
+#define ANDROID_IDRMMETRICSCONSUMER_H_
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+
+namespace android {
+
+class MediaDrmMetrics;
+class String8;
+
+/**
+ * Interface to consume metrics produced by the IDrm/ICrypto
+ *
+ * To use with IDrm:
+ * drm->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeFrameworkMetrics &
+ * IDrmMetricsConsumer::consumeHidlMetrics implementations
+ * would each be invoked once per call to IDrm::exportMetrics.
+ * |consumeFrameworkMetrics| would be called for plugin-agnostic
+ * framework metrics; |consumeHidlMetrics| would be called for
+ * plugin specific metrics.
+ *
+ * ----------------------------------------
+ *
+ * To use with ICrypto:
+ * crypto->exportMetrics(&consumer);
+ *
+ * IDrmMetricsConsumer::consumeHidlMetrics implementation
+ * would each be invoked once per call to ICrypto::exportMetrics.
+ * ICrypto metrics are plugin agnostic.
+ *
+ * ----------------------------------------
+ *
+ * For an example implementation of IDrmMetricsConsumer, please
+ * see BundleDrmMetricsConsumer. BundleDrmMetricsConsumer consumes
+ * IDrm/ICrypto metrics and saves the metrics to a PersistableBundle.
+ *
+ */
+struct IDrmMetricsConsumer : public RefBase {
+
+ virtual ~IDrmMetricsConsumer() {}
+
+ /**
+ * Consume framework (plugin agnostic) MediaDrmMetrics
+ */
+ virtual status_t consumeFrameworkMetrics(const MediaDrmMetrics &) = 0;
+
+ /**
+ * Consume list of DrmMetricGroup with optional Drm vendor name
+ */
+ virtual status_t consumeHidlMetrics(
+ const String8 &vendor,
+ const hidl_vec<DrmMetricGroup> &pluginMetrics) = 0;
+
+protected:
+ IDrmMetricsConsumer() {}
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(IDrmMetricsConsumer);
+};
+
+} // namespace android
+
+#endif // ANDROID_IDRMMETRICSCONSUMER_H_
diff --git a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h b/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
deleted file mode 100644
index 323fae5..0000000
--- a/drm/libmediadrm/include/mediadrm/IMediaDrmService.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IMEDIADRMSERVICE_H
-#define ANDROID_IMEDIADRMSERVICE_H
-
-#include <utils/Errors.h> // for status_t
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-
-struct ICrypto;
-struct IDrm;
-
-class IMediaDrmService: public IInterface
-{
-public:
- DECLARE_META_INTERFACE(MediaDrmService);
-
- virtual sp<ICrypto> makeCrypto() = 0;
- virtual sp<IDrm> makeDrm() = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnMediaDrmService: public BnInterface<IMediaDrmService>
-{
-public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IMEDIADRMSERVICE_H
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
new file mode 100644
index 0000000..3017274
--- /dev/null
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -0,0 +1,99 @@
+/*
+ * 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 ANDROID_DRMUTILS_H
+#define ANDROID_DRMUTILS_H
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <utils/Errors.h> // for status_t
+#include <utils/StrongPointer.h>
+#include <binder/Parcel.h>
+#include <vector>
+
+using namespace ::android::hardware::drm;
+
+namespace android {
+
+struct ICrypto;
+struct IDrm;
+
+namespace DrmUtils {
+
+bool UseDrmService();
+
+sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
+
+sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);
+
+template<typename BA>
+void WriteByteArray(Parcel &obj, const BA &vec) {
+ obj.writeInt32(vec.size());
+ if (vec.size()) {
+ obj.write(vec.data(), vec.size());
+ }
+}
+
+template<typename ET, typename BA>
+void WriteEventToParcel(
+ Parcel &obj,
+ ET eventType,
+ const BA &sessionId,
+ const BA &data) {
+ WriteByteArray(obj, sessionId);
+ WriteByteArray(obj, data);
+ obj.writeInt32(eventType);
+}
+
+template<typename BA>
+void WriteExpirationUpdateToParcel(
+ Parcel &obj,
+ const BA &sessionId,
+ int64_t expiryTimeInMS) {
+ WriteByteArray(obj, sessionId);
+ obj.writeInt64(expiryTimeInMS);
+}
+
+template<typename BA, typename KSL>
+void WriteKeysChange(
+ Parcel &obj,
+ const BA &sessionId,
+ const KSL &keyStatusList,
+ bool hasNewUsableKey) {
+ WriteByteArray(obj, sessionId);
+ obj.writeInt32(keyStatusList.size());
+ for (const auto &keyStatus : keyStatusList) {
+ WriteByteArray(obj, keyStatus.keyId);
+ obj.writeInt32(keyStatus.type);
+ }
+ obj.writeInt32(hasNewUsableKey);
+}
+
+std::vector<sp<::V1_0::IDrmFactory>> MakeDrmFactories(const uint8_t uuid[16]);
+
+std::vector<sp<::V1_0::IDrmPlugin>> MakeDrmPlugins(const uint8_t uuid[16],
+ const char *appPackageName);
+
+std::vector<sp<::V1_0::ICryptoFactory>> MakeCryptoFactories(const uint8_t uuid[16]);
+
+std::vector<sp<::V1_0::ICryptoPlugin>> MakeCryptoPlugins(const uint8_t uuid[16],
+ const void *initData, size_t initDataSize);
+
+} // namespace DrmUtils
+
+} // namespace android
+
+#endif // ANDROID_DRMUTILS_H
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 6d896b8..df980ae 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -14,23 +14,38 @@
* limitations under the License.
*/
-#include <binder/IInterface.h>
#include <cutils/native_handle.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
#ifndef ANDROID_ICRYPTO_H_
#define ANDROID_ICRYPTO_H_
namespace android {
+namespace hardware {
+class HidlMemory;
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+struct DestinationBuffer;
+} // namespace V1_0
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+namespace drm = ::android::hardware::drm;
+using drm::V1_0::SharedBuffer;
+
+namespace android {
struct AString;
-class IMemory;
-class IMemoryHeap;
-struct ICrypto : public IInterface {
- DECLARE_META_INTERFACE(Crypto);
+struct ICrypto : public RefBase {
+
+ virtual ~ICrypto() {}
virtual status_t initCheck() const = 0;
@@ -48,27 +63,16 @@
virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
- struct SourceBuffer {
- sp<IMemory> mSharedMemory;
- int32_t mHeapSeqNum;
- };
-
enum DestinationType {
kDestinationTypeSharedMemory, // non-secure
kDestinationTypeNativeHandle // secure
};
- struct DestinationBuffer {
- DestinationType mType;
- native_handle_t *mHandle;
- sp<IMemory> mSharedMemory;
- };
-
- virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
- CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const SourceBuffer &source, size_t offset,
- const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const DestinationBuffer &destination, AString *errorDetailMsg) = 0;
+ virtual ssize_t decrypt(const uint8_t /*key*/[16], const uint8_t /*iv*/[16],
+ CryptoPlugin::Mode /*mode*/, const CryptoPlugin::Pattern &/*pattern*/,
+ const drm::V1_0::SharedBuffer &/*source*/, size_t /*offset*/,
+ const CryptoPlugin::SubSample * /*subSamples*/, size_t /*numSubSamples*/,
+ const drm::V1_0::DestinationBuffer &/*destination*/, AString * /*errorDetailMsg*/) = 0;
/**
* Declare the heap that the shared memory source buffers passed
@@ -76,22 +80,16 @@
* that subsequent decrypt calls can use to refer to the heap,
* with -1 indicating failure.
*/
- virtual int32_t setHeap(const sp<IMemoryHeap>& heap) = 0;
+ virtual int32_t setHeap(const sp<hardware::HidlMemory>& heap) = 0;
virtual void unsetHeap(int32_t seqNum) = 0;
+protected:
+ ICrypto() {}
+
private:
DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
};
-struct BnCrypto : public BnInterface<ICrypto> {
- virtual status_t onTransact(
- uint32_t code, const Parcel &data, Parcel *reply,
- uint32_t flags = 0);
-private:
- void readVector(const Parcel &data, Vector<uint8_t> &vector) const;
- void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const;
-};
-
} // namespace android
#endif // ANDROID_ICRYPTO_H_
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
index d75f71c..d5f3ba2 100644
--- a/include/drm/drm_framework_common.h
+++ b/include/drm/drm_framework_common.h
@@ -317,14 +317,6 @@
~DecryptHandle() {
delete decryptInfo; decryptInfo = NULL;
}
-
- bool operator<(const DecryptHandle& handle) const {
- return (decryptId < handle.decryptId);
- }
-
- bool operator==(const DecryptHandle& handle) const {
- return (decryptId == handle.decryptId);
- }
};
};
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 2d4e126..3568f7b 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -78,7 +78,8 @@
DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
.withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
.withFields({C2F(mSampleRate, value).oneOf({
- 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+ 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+ 44100, 48000, 64000, 88200, 96000
})})
.withSetter(Setter<decltype(*mSampleRate)>::NonStrictValueWithNoDeps)
.build());
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index b41c271..e3d419c 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -40,7 +40,7 @@
namespace {
constexpr char COMPONENT_NAME[] = "c2.android.avc.encoder";
-
+constexpr uint32_t kMinOutBufferSize = 524288;
void ParseGop(
const C2StreamGopTuning::output &gop,
uint32_t *syncInterval, uint32_t *iInterval, uint32_t *maxBframes) {
@@ -440,8 +440,7 @@
mSignalledError(false),
mCodecCtx(nullptr),
mOutBlock(nullptr),
- // TODO: output buffer size
- mOutBufferSize(524288) {
+ mOutBufferSize(kMinOutBufferSize) {
// If dump is enabled, then open create an empty file
GENERATE_FILE_NAMES();
@@ -951,6 +950,9 @@
mStride = width;
+ // Assume worst case output buffer size to be equal to number of bytes in input
+ mOutBufferSize = std::max(width * height * 3 / 2, kMinOutBufferSize);
+
// TODO
mIvVideoColorFormat = IV_YUV_420P;
diff --git a/media/codec2/components/opus/C2SoftOpusDec.cpp b/media/codec2/components/opus/C2SoftOpusDec.cpp
index 6b6974f..b7c1556 100644
--- a/media/codec2/components/opus/C2SoftOpusDec.cpp
+++ b/media/codec2/components/opus/C2SoftOpusDec.cpp
@@ -62,7 +62,7 @@
addParameter(
DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
.withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
- .withFields({C2F(mSampleRate, value).equalTo(48000)})
+ .withFields({C2F(mSampleRate, value).inRange(8000, 48000)})
.withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
.build());
diff --git a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
index 18e6db2..15564d9 100644
--- a/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
+++ b/media/codec2/components/vorbis/C2SoftVorbisDec.cpp
@@ -66,7 +66,7 @@
addParameter(
DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
.withDefault(new C2StreamSampleRateInfo::output(0u, 48000))
- .withFields({C2F(mSampleRate, value).inRange(8000, 96000)})
+ .withFields({C2F(mSampleRate, value).inRange(8000, 192000)})
.withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
.build());
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 62076f8..c7d73f4 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -594,12 +594,10 @@
}
}
- int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
-
if (inSize) {
uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
vpx_codec_err_t err = vpx_codec_decode(
- mCodecCtx, bitstream, inSize, &frameIndex, 0);
+ mCodecCtx, bitstream, inSize, &work->input.ordinal.frameIndex, 0);
if (err != VPX_CODEC_OK) {
ALOGE("on2 decoder failed to decode frame. err: %d", err);
mSignalledError = true;
@@ -609,7 +607,20 @@
}
}
- (void)outputBuffer(pool, work);
+ status_t err = outputBuffer(pool, work);
+ if (err == NOT_ENOUGH_DATA) {
+ if (inSize > 0) {
+ ALOGV("Maybe non-display frame at %lld.",
+ work->input.ordinal.frameIndex.peekll());
+ // send the work back with empty buffer.
+ inSize = 0;
+ }
+ } else if (err != OK) {
+ ALOGD("Error while getting the output frame out");
+ // work->result would be already filled; do fillEmptyWork() below to
+ // send the work back.
+ inSize = 0;
+ }
if (eos) {
drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
@@ -743,16 +754,16 @@
}
return;
}
-bool C2SoftVpxDec::outputBuffer(
+status_t C2SoftVpxDec::outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work)
{
- if (!(work && pool)) return false;
+ if (!(work && pool)) return BAD_VALUE;
vpx_codec_iter_t iter = nullptr;
vpx_image_t *img = vpx_codec_get_frame(mCodecCtx, &iter);
- if (!img) return false;
+ if (!img) return NOT_ENOUGH_DATA;
if (img->d_w != mWidth || img->d_h != mHeight) {
mWidth = img->d_w;
@@ -769,7 +780,7 @@
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
- return false;
+ return UNKNOWN_ERROR;
}
}
@@ -792,18 +803,19 @@
if (err != C2_OK) {
ALOGE("fetchGraphicBlock for Output failed with status %d", err);
work->result = err;
- return false;
+ return UNKNOWN_ERROR;
}
C2GraphicView wView = block->map().get();
if (wView.error()) {
ALOGE("graphic view map failed %d", wView.error());
work->result = C2_CORRUPTED;
- return false;
+ return UNKNOWN_ERROR;
}
- ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
- block->width(), block->height(), mWidth, mHeight, (int)*(int64_t *)img->user_priv);
+ ALOGV("provided (%dx%d) required (%dx%d), out frameindex %lld",
+ block->width(), block->height(), mWidth, mHeight,
+ ((c2_cntr64_t *)img->user_priv)->peekll());
uint8_t *dst = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
size_t srcYStride = img->stride[VPX_PLANE_Y];
@@ -859,8 +871,8 @@
dstYStride, dstUVStride,
mWidth, mHeight);
}
- finishWork(*(int64_t *)img->user_priv, work, std::move(block));
- return true;
+ finishWork(((c2_cntr64_t *)img->user_priv)->peekull(), work, std::move(block));
+ return OK;
}
c2_status_t C2SoftVpxDec::drainInternal(
@@ -876,7 +888,7 @@
return C2_OMITTED;
}
- while ((outputBuffer(pool, work))) {
+ while (outputBuffer(pool, work) == OK) {
}
if (drainMode == DRAIN_COMPONENT_WITH_EOS &&
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.h b/media/codec2/components/vpx/C2SoftVpxDec.h
index e51bcee..2065165 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.h
+++ b/media/codec2/components/vpx/C2SoftVpxDec.h
@@ -85,7 +85,7 @@
status_t destroyDecoder();
void finishWork(uint64_t index, const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2GraphicBlock> &block);
- bool outputBuffer(
+ status_t outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work);
c2_status_t drainInternal(
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 6dab70b..ebc7a8f 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -514,7 +514,7 @@
return;
}
vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, stride, vstride,
- mStrideAlign, (uint8_t*)rView->data()[0]);
+ mStrideAlign, mConversionBuffer.data());
vpx_img_set_rect(&raw_frame, 0, 0, width, height);
} else {
ALOGE("Conversion buffer is too small: %u x %u for %zu",
diff --git a/media/codec2/components/xaac/C2SoftXaacDec.cpp b/media/codec2/components/xaac/C2SoftXaacDec.cpp
index 60ae93c..951d058 100644
--- a/media/codec2/components/xaac/C2SoftXaacDec.cpp
+++ b/media/codec2/components/xaac/C2SoftXaacDec.cpp
@@ -87,7 +87,8 @@
DefineParam(mSampleRate, C2_PARAMKEY_SAMPLE_RATE)
.withDefault(new C2StreamSampleRateInfo::output(0u, 44100))
.withFields({C2F(mSampleRate, value).oneOf({
- 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+ 7350, 8000, 11025, 12000, 16000, 22050, 24000, 32000,
+ 44100, 48000, 64000, 88200, 96000
})})
.withSetter((Setter<decltype(*mSampleRate)>::StrictValueWithNoDeps))
.build());
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 4a9dc55..b96d29b 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -104,7 +104,7 @@
// public dependency for Codec 2.0 HAL service implementations
cc_defaults {
- name: "libcodec2-hidl-defaults",
+ name: "libcodec2-hidl-defaults@1.0",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
@@ -115,7 +115,7 @@
// public dependency for Codec 2.0 HAL client
cc_defaults {
- name: "libcodec2-hidl-client-defaults",
+ name: "libcodec2-hidl-client-defaults@1.0",
defaults: ["libcodec2-impl-defaults"],
shared_libs: [
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index a9f20a4..8a84601 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -204,7 +204,8 @@
const sp<::android::hardware::media::bufferpool::V2_0::
IClientManager>& clientPoolManager)
: mComponent{component},
- mInterface{new ComponentInterface(component->intf(), store.get())},
+ mInterface{new ComponentInterface(component->intf(),
+ store->getParameterCache())},
mListener{listener},
mStore{store},
mBufferPoolSender{clientPoolManager} {
diff --git a/media/codec2/hidl/1.0/utils/ComponentInterface.cpp b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
index 39e5357..12078e0 100644
--- a/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentInterface.cpp
@@ -87,10 +87,10 @@
// ComponentInterface
ComponentInterface::ComponentInterface(
const std::shared_ptr<C2ComponentInterface>& intf,
- ComponentStore* store)
+ const std::shared_ptr<ParameterCache>& cache)
: mInterface{intf},
mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
- mInit = mConfigurable->init(store);
+ mInit = mConfigurable->init(cache);
}
c2_status_t ComponentInterface::status() const {
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index 1e0a190..9b9d449 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -102,8 +102,29 @@
} // unnamed namespace
+struct ComponentStore::StoreParameterCache : public ParameterCache {
+ std::mutex mStoreMutex;
+ ComponentStore* mStore;
+
+ StoreParameterCache(ComponentStore* store): mStore{store} {
+ }
+
+ virtual c2_status_t validate(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params
+ ) override {
+ std::scoped_lock _lock(mStoreMutex);
+ return mStore ? mStore->validateSupportedParams(params) : C2_NO_INIT;
+ }
+
+ void onStoreDestroyed() {
+ std::scoped_lock _lock(mStoreMutex);
+ mStore = nullptr;
+ }
+};
+
ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
: mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+ mParameterCache{std::make_shared<StoreParameterCache>(this)},
mStore{store} {
std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
@@ -113,7 +134,12 @@
mParamReflector = mStore->getParamReflector();
// Retrieve supported parameters from store
- mInit = mConfigurable->init(this);
+ using namespace std::placeholders;
+ mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+ mParameterCache->onStoreDestroyed();
}
c2_status_t ComponentStore::status() const {
@@ -146,6 +172,10 @@
return res;
}
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+ return mParameterCache;
+}
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
Return<void> ComponentStore::createComponent(
const hidl_string& name,
@@ -187,7 +217,7 @@
sp<IComponentInterface> interface;
if (res == C2_OK) {
onInterfaceLoaded(c2interface);
- interface = new ComponentInterface(c2interface, this);
+ interface = new ComponentInterface(c2interface, mParameterCache);
}
_hidl_cb(static_cast<Status>(res), interface);
return Void();
@@ -218,8 +248,9 @@
_hidl_cb(Status::CORRUPTED, nullptr);
return Void();
}
+ using namespace std::placeholders;
sp<InputSurface> inputSurface = new InputSurface(
- this,
+ mParameterCache,
std::make_shared<C2ReflectorHelper>(),
source->getHGraphicBufferProducer(),
source);
diff --git a/media/codec2/hidl/1.0/utils/Configurable.cpp b/media/codec2/hidl/1.0/utils/Configurable.cpp
index ec9c170..530576d 100644
--- a/media/codec2/hidl/1.0/utils/Configurable.cpp
+++ b/media/codec2/hidl/1.0/utils/Configurable.cpp
@@ -38,10 +38,11 @@
: mIntf{std::move(intf)} {
}
-c2_status_t CachedConfigurable::init(ComponentStore* store) {
+c2_status_t CachedConfigurable::init(
+ const std::shared_ptr<ParameterCache>& cache) {
// Retrieve supported parameters from store
c2_status_t init = mIntf->querySupportedParams(&mSupportedParams);
- c2_status_t validate = store->validateSupportedParams(mSupportedParams);
+ c2_status_t validate = cache->validate(mSupportedParams);
return init == C2_OK ? C2_OK : validate;
}
diff --git a/media/codec2/hidl/1.0/utils/InputSurface.cpp b/media/codec2/hidl/1.0/utils/InputSurface.cpp
index 2b4ca85..c3c32e9 100644
--- a/media/codec2/hidl/1.0/utils/InputSurface.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurface.cpp
@@ -137,9 +137,9 @@
}
std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
if (comp) {
- connection = new InputSurfaceConnection(mSource, comp, mStore);
+ connection = new InputSurfaceConnection(mSource, comp, mParameterCache);
} else {
- connection = new InputSurfaceConnection(mSource, sink, mStore);
+ connection = new InputSurfaceConnection(mSource, sink, mParameterCache);
}
if (!connection->init()) {
connection = nullptr;
@@ -153,11 +153,11 @@
// Constructor is exclusive to ComponentStore.
InputSurface::InputSurface(
- const sp<ComponentStore>& store,
+ const std::shared_ptr<ParameterCache>& cache,
const std::shared_ptr<C2ReflectorHelper>& reflector,
const sp<HGraphicBufferProducer>& producer,
const sp<GraphicBufferSource>& source)
- : mStore{store},
+ : mParameterCache{cache},
mProducer{producer},
mSource{source},
mIntf{std::make_shared<Interface>(reflector)},
@@ -165,7 +165,7 @@
std::make_unique<ConfigurableIntf>(
mIntf, source))} {
- mConfigurable->init(store.get());
+ mConfigurable->init(mParameterCache);
}
} // namespace utils
diff --git a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
index c9932ef..5cc0d53 100644
--- a/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
+++ b/media/codec2/hidl/1.0/utils/InputSurfaceConnection.cpp
@@ -445,21 +445,21 @@
InputSurfaceConnection::InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
const std::shared_ptr<C2Component>& comp,
- const sp<ComponentStore>& store)
+ const std::shared_ptr<ParameterCache>& cache)
: mImpl{new Impl(source, comp)},
mConfigurable{new CachedConfigurable(
std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
- mConfigurable->init(store.get());
+ mConfigurable->init(cache);
}
InputSurfaceConnection::InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
const sp<IInputSink>& sink,
- const sp<ComponentStore>& store)
+ const std::shared_ptr<ParameterCache>& cache)
: mImpl{new Impl(source, sink)},
mConfigurable{new CachedConfigurable(
std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
- mConfigurable->init(store.get());
+ mConfigurable->init(cache);
}
Return<Status> InputSurfaceConnection::disconnect() {
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
index a5d235e..9102f92 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentInterface.h
@@ -45,7 +45,7 @@
struct ComponentInterface : public IComponentInterface {
ComponentInterface(
const std::shared_ptr<C2ComponentInterface>& interface,
- ComponentStore* store);
+ const std::shared_ptr<ParameterCache>& cache);
c2_status_t status() const;
virtual Return<sp<IConfigurable>> getConfigurable() override;
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index be80c62..fe7d048 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -54,7 +54,7 @@
struct ComponentStore : public IComponentStore {
ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
- virtual ~ComponentStore() = default;
+ virtual ~ComponentStore();
/**
* Returns the status of the construction of this object.
@@ -68,6 +68,12 @@
c2_status_t validateSupportedParams(
const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
+ /**
+ * Returns the store's ParameterCache. This is used for validation by
+ * Configurable::init().
+ */
+ std::shared_ptr<ParameterCache> getParameterCache() const;
+
// Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
virtual Return<void> createComponent(
const hidl_string& name,
@@ -98,6 +104,8 @@
protected:
sp<CachedConfigurable> mConfigurable;
+ struct StoreParameterCache;
+ std::shared_ptr<StoreParameterCache> mParameterCache;
// Does bookkeeping for an interface that has been loaded.
void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
index 8095185..8f49a97 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Configurable.h
@@ -79,6 +79,20 @@
};
/**
+ * Type for validating and caching parameters when CachedConfigurable is
+ * initialized.
+ *
+ * This is meant to be created by the ComponentStore. The purpose of abstracting
+ * this is to allow different versions of ComponentStore to work with this
+ * CachedConfigurable.
+ */
+struct ParameterCache {
+ virtual c2_status_t validate(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>&) = 0;
+ virtual ~ParameterCache() = default;
+};
+
+/**
* Implementation of the IConfigurable interface that supports caching of
* supported parameters from a supplied ComponentStore.
*
@@ -91,7 +105,8 @@
struct CachedConfigurable : public IConfigurable {
CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
- c2_status_t init(ComponentStore* store);
+ // Populates mSupportedParams.
+ c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
// Methods from ::android::hardware::media::c2::V1_0::IConfigurable
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index 29ed7ff..062dcd9 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -57,30 +57,26 @@
const sp<IInputSink>& sink,
connect_cb _hidl_cb) override;
+ InputSurface(
+ const std::shared_ptr<ParameterCache>& cache,
+ const std::shared_ptr<C2ReflectorHelper>& reflector,
+ const sp<HGraphicBufferProducer>& base,
+ const sp<GraphicBufferSource>& source);
+
protected:
class Interface;
class ConfigurableIntf;
- sp<ComponentStore> mStore;
+ std::shared_ptr<ParameterCache> mParameterCache;
sp<HGraphicBufferProducer> mProducer;
sp<GraphicBufferSource> mSource;
std::shared_ptr<Interface> mIntf;
sp<CachedConfigurable> mConfigurable;
- InputSurface(
- const sp<ComponentStore>& store,
- const std::shared_ptr<C2ReflectorHelper>& reflector,
- const sp<HGraphicBufferProducer>& base,
- const sp<GraphicBufferSource>& source);
-
virtual ~InputSurface() override = default;
-
- friend struct ComponentStore;
-
};
-
} // namespace utils
} // namespace V1_0
} // namespace c2
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
index 758b6b2..475ce8b 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurfaceConnection.h
@@ -62,12 +62,12 @@
InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
const std::shared_ptr<C2Component>& comp,
- const sp<ComponentStore>& store);
+ const std::shared_ptr<ParameterCache>& cache);
InputSurfaceConnection(
const sp<GraphicBufferSource>& source,
const sp<IInputSink>& sink,
- const sp<ComponentStore>& store);
+ const std::shared_ptr<ParameterCache>& cache);
bool init();
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index a8a552c..9656eb4 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -203,7 +203,7 @@
uint32_t mFramesReceived;
std::list<uint64_t> mFlushedIndices;
std::list<uint64_t> mTimestampUslist;
- ::android::List<outputMetaData> oBufferMetaData;
+ std::list<outputMetaData> oBufferMetaData;
C2BlockPool::local_id_t mBlockPoolId;
std::shared_ptr<C2BlockPool> mLinearPool;
@@ -547,10 +547,6 @@
if (mCompName == raw) {
bitStreamInfo[0] = 8000;
bitStreamInfo[1] = 1;
- } else if (mCompName == g711alaw || mCompName == g711mlaw) {
- // g711 test data is all 1-channel and has no embedded config info.
- bitStreamInfo[0] = 8000;
- bitStreamInfo[1] = 1;
} else {
ASSERT_NO_FATAL_FAILURE(
getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
@@ -598,7 +594,7 @@
int nSampleRate = bitStreamInfo[0];
int nChannels = bitStreamInfo[1];
std::list<uint64_t>::iterator itIn = mTimestampUslist.begin();
- android::List<outputMetaData>::iterator itOut = oBufferMetaData.begin();
+ auto itOut = oBufferMetaData.begin();
EXPECT_EQ(*itIn, itOut->timestampUs);
expTs = *itIn;
while (itOut != oBufferMetaData.end()) {
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
index d73b731..2f02913 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.cpp
@@ -20,6 +20,13 @@
#include "media_c2_hidl_test_common.h"
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+
+void ComponentTestEnvironment::registerTestServices() {
+ registerTestService<::android::hardware::media::c2::V1_0::
+ IComponentStore>();
+}
+
// Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
void testInputBuffer(
const std::shared_ptr<android::Codec2Client::Component>& component,
diff --git a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
index db59e54..23e332a 100644
--- a/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h
@@ -17,32 +17,23 @@
#ifndef MEDIA_C2_HIDL_TEST_COMMON_H
#define MEDIA_C2_HIDL_TEST_COMMON_H
-#include <codec2/hidl/client.h>
-
-#include <android/hardware/media/c2/1.0/types.h>
-
#include <C2Component.h>
#include <C2Config.h>
+
+#include <codec2/hidl/client.h>
#include <getopt.h>
#include <hidl/HidlSupport.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/foundation/Mutexed.h>
-
-using namespace ::android::hardware::media::c2::V1_0;
-using namespace ::android::hardware::media::c2::V1_0::utils;
-
-using ::android::Mutexed;
-using ::android::hardware::Void;
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-
#include <VtsHalHidlTargetTestEnvBase.h>
#define MAX_RETRY 20
#define TIME_OUT 400ms
#define MAX_INPUT_BUFFERS 8
+using ::android::hardware::Void;
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+
/*
* Handle Callback functions onWorkDone(), onTripped(),
* onError(), onDeath(), onFramesRendered()
@@ -114,9 +105,7 @@
typedef ::testing::VtsHalHidlTargetTestEnvBase Super;
public:
- virtual void registerTestServices() override {
- registerTestService<IComponentStore>();
- }
+ virtual void registerTestServices() override;
ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
diff --git a/media/codec2/hidl/1.0/vts/functional/video/Android.bp b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
index be35b02..b737323 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/Android.bp
+++ b/media/codec2/hidl/1.0/vts/functional/video/Android.bp
@@ -18,6 +18,14 @@
name: "VtsHalMediaC2V1_0TargetVideoDecTest",
defaults: ["VtsHalMediaC2V1_0Defaults"],
srcs: ["VtsHalMediaC2V1_0TargetVideoDecTest.cpp"],
+ header_libs: [
+ "libnativewindow_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libgui",
+ "libutils",
+ ],
}
cc_test {
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 5e28750..9404aa8 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -28,6 +28,10 @@
#include <C2Debug.h>
#include <C2Buffer.h>
#include <C2BufferPriv.h>
+#include <gui/BufferQueue.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IProducerListener.h>
+#include <system/window.h>
using android::C2AllocatorIon;
@@ -426,6 +430,48 @@
ASSERT_EQ(mDisableTest, false);
}
+TEST_F(Codec2VideoDecHidlTest, configureTunnel) {
+ description("Attempts to configure tunneling");
+ if (mDisableTest) return;
+ ALOGV("Checks if the component can be configured for tunneling");
+ native_handle_t* sidebandStream{};
+ c2_status_t err = mComponent->configureVideoTunnel(0, &sidebandStream);
+ if (err == C2_OMITTED) {
+ return;
+ }
+
+ using namespace android;
+ sp<NativeHandle> nativeHandle = NativeHandle::create(sidebandStream, true);
+
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ class DummyConsumerListener : public BnConsumerListener {
+ public:
+ DummyConsumerListener() : BnConsumerListener() {}
+ void onFrameAvailable(const BufferItem&) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+ consumer->consumerConnect(new DummyConsumerListener(), false);
+
+ class DummyProducerListener : public BnProducerListener {
+ public:
+ DummyProducerListener() : BnProducerListener() {}
+ virtual void onBufferReleased() override {}
+ virtual bool needsReleaseNotify() override { return false; }
+ virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
+ };
+ IGraphicBufferProducer::QueueBufferOutput qbo{};
+ producer->connect(new DummyProducerListener(),
+ NATIVE_WINDOW_API_MEDIA,
+ false,
+ &qbo);
+
+ ASSERT_EQ(producer->setSidebandStream(nativeHandle), NO_ERROR);
+}
+
class Codec2VideoDecDecodeTest
: public Codec2VideoDecHidlTest,
public ::testing::WithParamInterface<std::pair<int32_t, bool>> {
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
new file mode 100644
index 0000000..d48197b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -0,0 +1,154 @@
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-client-defaults instead
+cc_library {
+ name: "libcodec2_hidl_client@1.1",
+
+ defaults: ["hidl_defaults"],
+
+ srcs: [
+ "OutputBufferQueue.cpp",
+ "types.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "libbase",
+ "libcodec2",
+ "libcodec2_hidl_client@1.0",
+ "libcodec2_vndk",
+ "libcutils",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ "libutils",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "libcodec2",
+ "libcodec2_hidl_client@1.0",
+ "libgui",
+ "libstagefright_bufferpool@2.0.1",
+ "libui",
+ ],
+}
+
+
+// DO NOT DEPEND ON THIS DIRECTLY
+// use libcodec2-hidl-defaults instead
+cc_library {
+ name: "libcodec2_hidl@1.1",
+ vendor_available: true,
+
+ defaults: ["hidl_defaults"],
+
+ srcs: [
+ "Component.cpp",
+ "ComponentInterface.cpp",
+ "ComponentStore.cpp",
+ "Configurable.cpp",
+ "InputBufferManager.cpp",
+ "InputSurface.cpp",
+ "InputSurfaceConnection.cpp",
+ "types.cpp",
+ ],
+
+ header_libs: [
+ "libbinder_headers",
+ "libsystem_headers",
+ "libcodec2_internal", // private
+ ],
+
+ shared_libs: [
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.media@1.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "android.hardware.media.omx@1.0",
+ "libbase",
+ "libcodec2",
+ "libcodec2_hidl@1.0",
+ "libcodec2_vndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libstagefright_bufferpool@2.0.1",
+ "libstagefright_bufferqueue_helper",
+ "libui",
+ "libutils",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ export_shared_lib_headers: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "libcodec2",
+ "libcodec2_hidl@1.0",
+ "libcodec2_vndk",
+ "libhidlbase",
+ "libstagefright_bufferpool@2.0.1",
+ "libstagefright_bufferqueue_helper",
+ "libui",
+ ],
+}
+
+// public dependency for Codec 2.0 HAL service implementations
+cc_defaults {
+ name: "libcodec2-hidl-defaults@1.1",
+ defaults: ["libcodec2-impl-defaults"],
+
+ shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "libcodec2_hidl@1.0",
+ "libcodec2_hidl@1.1",
+ "libcodec2_vndk",
+ "libhidlbase",
+ ],
+}
+
+// public dependency for Codec 2.0 HAL client
+cc_defaults {
+ name: "libcodec2-hidl-client-defaults@1.1",
+ defaults: ["libcodec2-impl-defaults"],
+
+ shared_libs: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "libcodec2_hidl_client@1.0",
+ "libcodec2_hidl_client@1.1",
+ "libcodec2_vndk",
+ "libhidlbase",
+ ],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL service implementations
+cc_defaults {
+ name: "libcodec2-hidl-defaults",
+ defaults: ["libcodec2-hidl-defaults@1.1"],
+}
+
+// Alias to the latest "defaults" for Codec 2.0 HAL client
+cc_defaults {
+ name: "libcodec2-hidl-client-defaults",
+ defaults: ["libcodec2-hidl-client-defaults@1.1"],
+}
diff --git a/media/codec2/hidl/1.1/utils/Component.cpp b/media/codec2/hidl/1.1/utils/Component.cpp
new file mode 100644
index 0000000..ed281e6
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Component.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Component@1.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputBufferManager.h>
+
+#include <hidl/HidlBinderSupport.h>
+#include <utils/Timers.h>
+
+#include <C2BqBufferPriv.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using namespace ::android;
+
+// ComponentListener wrapper
+struct Component::Listener : public C2Component::Listener {
+
+ Listener(const sp<Component>& component) :
+ mComponent(component),
+ mListener(component->mListener) {
+ }
+
+ virtual void onError_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ uint32_t errorCode) override {
+ sp<IComponentListener> listener = mListener.promote();
+ if (listener) {
+ Return<void> transStatus = listener->onError(Status::OK, errorCode);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onError_nb -- "
+ << "transaction failed.";
+ }
+ }
+ }
+
+ virtual void onTripped_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ std::vector<std::shared_ptr<C2SettingResult>> c2settingResult
+ ) override {
+ sp<IComponentListener> listener = mListener.promote();
+ if (listener) {
+ hidl_vec<SettingResult> settingResults(c2settingResult.size());
+ size_t ix = 0;
+ for (const std::shared_ptr<C2SettingResult> &c2result :
+ c2settingResult) {
+ if (c2result) {
+ if (!objcpy(&settingResults[ix++], *c2result)) {
+ break;
+ }
+ }
+ }
+ settingResults.resize(ix);
+ Return<void> transStatus = listener->onTripped(settingResults);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onTripped_nb -- "
+ << "transaction failed.";
+ }
+ }
+ }
+
+ virtual void onWorkDone_nb(
+ std::weak_ptr<C2Component> /* c2component */,
+ std::list<std::unique_ptr<C2Work>> c2workItems) override {
+ for (const std::unique_ptr<C2Work>& work : c2workItems) {
+ if (work) {
+ if (work->worklets.empty()
+ || !work->worklets.back()
+ || (work->worklets.back()->output.flags &
+ C2FrameData::FLAG_INCOMPLETE) == 0) {
+ InputBufferManager::
+ unregisterFrameData(mListener, work->input);
+ }
+ }
+ }
+
+ sp<IComponentListener> listener = mListener.promote();
+ if (listener) {
+ WorkBundle workBundle;
+
+ sp<Component> strongComponent = mComponent.promote();
+ beginTransferBufferQueueBlocks(c2workItems, true);
+ if (!objcpy(&workBundle, c2workItems, strongComponent ?
+ &strongComponent->mBufferPoolSender : nullptr)) {
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "received corrupted work items.";
+ endTransferBufferQueueBlocks(c2workItems, false, true);
+ return;
+ }
+ Return<void> transStatus = listener->onWorkDone(workBundle);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Component::Listener::onWorkDone_nb -- "
+ << "transaction failed.";
+ endTransferBufferQueueBlocks(c2workItems, false, true);
+ return;
+ }
+ endTransferBufferQueueBlocks(c2workItems, true, true);
+ }
+ }
+
+protected:
+ wp<Component> mComponent;
+ wp<IComponentListener> mListener;
+};
+
+// Component::Sink
+struct Component::Sink : public IInputSink {
+ std::shared_ptr<Component> mComponent;
+ sp<IConfigurable> mConfigurable;
+
+ virtual Return<Status> queue(const WorkBundle& workBundle) override {
+ return mComponent->queue(workBundle);
+ }
+
+ virtual Return<sp<IConfigurable>> getConfigurable() override {
+ return mConfigurable;
+ }
+
+ Sink(const std::shared_ptr<Component>& component);
+ virtual ~Sink() override;
+
+ // Process-wide map: Component::Sink -> C2Component.
+ static std::mutex sSink2ComponentMutex;
+ static std::map<IInputSink*, std::weak_ptr<C2Component>> sSink2Component;
+
+ static std::shared_ptr<C2Component> findLocalComponent(
+ const sp<IInputSink>& sink);
+};
+
+std::mutex
+ Component::Sink::sSink2ComponentMutex{};
+std::map<IInputSink*, std::weak_ptr<C2Component>>
+ Component::Sink::sSink2Component{};
+
+Component::Sink::Sink(const std::shared_ptr<Component>& component)
+ : mComponent{component},
+ mConfigurable{[&component]() -> sp<IConfigurable> {
+ Return<sp<IComponentInterface>> ret1 = component->getInterface();
+ if (!ret1.isOk()) {
+ LOG(ERROR) << "Sink::Sink -- component's transaction failed.";
+ return nullptr;
+ }
+ Return<sp<IConfigurable>> ret2 =
+ static_cast<sp<IComponentInterface>>(ret1)->
+ getConfigurable();
+ if (!ret2.isOk()) {
+ LOG(ERROR) << "Sink::Sink -- interface's transaction failed.";
+ return nullptr;
+ }
+ return static_cast<sp<IConfigurable>>(ret2);
+ }()} {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ sSink2Component.emplace(this, component->mComponent);
+}
+
+Component::Sink::~Sink() {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ sSink2Component.erase(this);
+}
+
+std::shared_ptr<C2Component> Component::Sink::findLocalComponent(
+ const sp<IInputSink>& sink) {
+ std::lock_guard<std::mutex> lock(sSink2ComponentMutex);
+ auto i = sSink2Component.find(sink.get());
+ if (i == sSink2Component.end()) {
+ return nullptr;
+ }
+ return i->second.lock();
+}
+
+// Component
+Component::Component(
+ const std::shared_ptr<C2Component>& component,
+ const sp<IComponentListener>& listener,
+ const sp<ComponentStore>& store,
+ const sp<::android::hardware::media::bufferpool::V2_0::
+ IClientManager>& clientPoolManager)
+ : mComponent{component},
+ mInterface{new ComponentInterface(component->intf(),
+ store->getParameterCache())},
+ mListener{listener},
+ mStore{store},
+ mBufferPoolSender{clientPoolManager} {
+ // Retrieve supported parameters from store
+ // TODO: We could cache this per component/interface type
+ mInit = mInterface->status();
+}
+
+c2_status_t Component::status() const {
+ return mInit;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponent
+Return<Status> Component::queue(const WorkBundle& workBundle) {
+ std::list<std::unique_ptr<C2Work>> c2works;
+
+ if (!objcpy(&c2works, workBundle)) {
+ return Status::CORRUPTED;
+ }
+
+ // Register input buffers.
+ for (const std::unique_ptr<C2Work>& work : c2works) {
+ if (work) {
+ InputBufferManager::
+ registerFrameData(mListener, work->input);
+ }
+ }
+
+ return static_cast<Status>(mComponent->queue_nb(&c2works));
+}
+
+Return<void> Component::flush(flush_cb _hidl_cb) {
+ std::list<std::unique_ptr<C2Work>> c2flushedWorks;
+ c2_status_t c2res = mComponent->flush_sm(
+ C2Component::FLUSH_COMPONENT,
+ &c2flushedWorks);
+
+ // Unregister input buffers.
+ for (const std::unique_ptr<C2Work>& work : c2flushedWorks) {
+ if (work) {
+ if (work->worklets.empty()
+ || !work->worklets.back()
+ || (work->worklets.back()->output.flags &
+ C2FrameData::FLAG_INCOMPLETE) == 0) {
+ InputBufferManager::
+ unregisterFrameData(mListener, work->input);
+ }
+ }
+ }
+
+ WorkBundle flushedWorkBundle;
+ Status res = static_cast<Status>(c2res);
+ beginTransferBufferQueueBlocks(c2flushedWorks, true);
+ if (c2res == C2_OK) {
+ if (!objcpy(&flushedWorkBundle, c2flushedWorks, &mBufferPoolSender)) {
+ res = Status::CORRUPTED;
+ }
+ }
+ _hidl_cb(res, flushedWorkBundle);
+ endTransferBufferQueueBlocks(c2flushedWorks, true, true);
+ return Void();
+}
+
+Return<Status> Component::drain(bool withEos) {
+ return static_cast<Status>(mComponent->drain_nb(withEos ?
+ C2Component::DRAIN_COMPONENT_WITH_EOS :
+ C2Component::DRAIN_COMPONENT_NO_EOS));
+}
+
+Return<Status> Component::setOutputSurface(
+ uint64_t blockPoolId,
+ const sp<HGraphicBufferProducer2>& surface) {
+ std::shared_ptr<C2BlockPool> pool;
+ GetCodec2BlockPool(blockPoolId, mComponent, &pool);
+ if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
+ C2BufferQueueBlockPool::OnRenderCallback cb =
+ [this](uint64_t producer, int32_t slot, int64_t nsecs) {
+ // TODO: batch this
+ hidl_vec<IComponentListener::RenderedFrame> rendered;
+ rendered.resize(1);
+ rendered[0] = { producer, slot, nsecs };
+ (void)mListener->onFramesRendered(rendered).isOk();
+ };
+ if (bqPool) {
+ bqPool->setRenderCallback(cb);
+ bqPool->configureProducer(surface);
+ }
+ }
+ return Status::OK;
+}
+
+Return<void> Component::connectToInputSurface(
+ const sp<IInputSurface>& inputSurface,
+ connectToInputSurface_cb _hidl_cb) {
+ Status status;
+ sp<IInputSurfaceConnection> connection;
+ auto transStatus = inputSurface->connect(
+ asInputSink(),
+ [&status, &connection](
+ Status s, const sp<IInputSurfaceConnection>& c) {
+ status = s;
+ connection = c;
+ }
+ );
+ _hidl_cb(status, connection);
+ return Void();
+}
+
+Return<void> Component::connectToOmxInputSurface(
+ const sp<HGraphicBufferProducer1>& producer,
+ const sp<::android::hardware::media::omx::V1_0::
+ IGraphicBufferSource>& source,
+ connectToOmxInputSurface_cb _hidl_cb) {
+ (void)producer;
+ (void)source;
+ (void)_hidl_cb;
+ return Void();
+}
+
+Return<Status> Component::disconnectFromInputSurface() {
+ // TODO implement
+ return Status::OK;
+}
+
+namespace /* unnamed */ {
+
+struct BlockPoolIntf : public ConfigurableC2Intf {
+ BlockPoolIntf(const std::shared_ptr<C2BlockPool>& pool)
+ : ConfigurableC2Intf{
+ "C2BlockPool:" +
+ (pool ? std::to_string(pool->getLocalId()) : "null"),
+ 0},
+ mPool{pool} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*>& params,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ (void)params;
+ (void)mayBlock;
+ (void)failures;
+ return C2_OK;
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index>& indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params
+ ) const override {
+ (void)indices;
+ (void)mayBlock;
+ (void)params;
+ return C2_OK;
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ (void)params;
+ return C2_OK;
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ (void)fields;
+ (void)mayBlock;
+ return C2_OK;
+ }
+
+protected:
+ std::shared_ptr<C2BlockPool> mPool;
+};
+
+} // unnamed namespace
+
+Return<void> Component::createBlockPool(
+ uint32_t allocatorId,
+ createBlockPool_cb _hidl_cb) {
+ std::shared_ptr<C2BlockPool> blockPool;
+ c2_status_t status = CreateCodec2BlockPool(
+ static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+ mComponent,
+ &blockPool);
+ if (status != C2_OK) {
+ blockPool = nullptr;
+ }
+ if (blockPool) {
+ mBlockPoolsMutex.lock();
+ mBlockPools.emplace(blockPool->getLocalId(), blockPool);
+ mBlockPoolsMutex.unlock();
+ } else if (status == C2_OK) {
+ status = C2_CORRUPTED;
+ }
+
+ _hidl_cb(static_cast<Status>(status),
+ blockPool ? blockPool->getLocalId() : 0,
+ new CachedConfigurable(
+ std::make_unique<BlockPoolIntf>(blockPool)));
+ return Void();
+}
+
+Return<Status> Component::destroyBlockPool(uint64_t blockPoolId) {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ return mBlockPools.erase(blockPoolId) == 1 ?
+ Status::OK : Status::CORRUPTED;
+}
+
+Return<Status> Component::start() {
+ return static_cast<Status>(mComponent->start());
+}
+
+Return<Status> Component::stop() {
+ InputBufferManager::unregisterFrameData(mListener);
+ return static_cast<Status>(mComponent->stop());
+}
+
+Return<Status> Component::reset() {
+ Status status = static_cast<Status>(mComponent->reset());
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ mBlockPools.clear();
+ }
+ InputBufferManager::unregisterFrameData(mListener);
+ return status;
+}
+
+Return<Status> Component::release() {
+ Status status = static_cast<Status>(mComponent->release());
+ {
+ std::lock_guard<std::mutex> lock(mBlockPoolsMutex);
+ mBlockPools.clear();
+ }
+ InputBufferManager::unregisterFrameData(mListener);
+ return status;
+}
+
+Return<sp<IComponentInterface>> Component::getInterface() {
+ return sp<IComponentInterface>(mInterface);
+}
+
+Return<sp<IInputSink>> Component::asInputSink() {
+ std::lock_guard<std::mutex> lock(mSinkMutex);
+ if (!mSink) {
+ mSink = new Sink(shared_from_this());
+ }
+ return {mSink};
+}
+
+Return<void> Component::configureVideoTunnel(
+ uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) {
+ (void)avSyncHwId;
+ _hidl_cb(Status::OMITTED, hidl_handle{});
+ return Void();
+}
+
+std::shared_ptr<C2Component> Component::findLocalComponent(
+ const sp<IInputSink>& sink) {
+ return Component::Sink::findLocalComponent(sink);
+}
+
+void Component::initListener(const sp<Component>& self) {
+ std::shared_ptr<C2Component::Listener> c2listener =
+ std::make_shared<Listener>(self);
+ c2_status_t res = mComponent->setListener_vb(c2listener, C2_DONT_BLOCK);
+ if (res != C2_OK) {
+ mInit = res;
+ }
+}
+
+Component::~Component() {
+ InputBufferManager::unregisterFrameData(mListener);
+ mStore->reportComponentDeath(this);
+}
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/ComponentInterface.cpp b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
new file mode 100644
index 0000000..ccc30fe
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentInterface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/ComponentInterface.h>
diff --git a/media/codec2/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
new file mode 100644
index 0000000..225cd09
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/ComponentStore.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentStore@1.1"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <codec2/hidl/1.1/InputSurface.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <android-base/file.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+#include <utils/Errors.h>
+
+#include <C2PlatformSupport.h>
+#include <util/C2InterfaceHelper.h>
+
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using namespace ::android;
+using ::android::GraphicBufferSource;
+using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
+
+namespace /* unnamed */ {
+
+struct StoreIntf : public ConfigurableC2Intf {
+ StoreIntf(const std::shared_ptr<C2ComponentStore>& store)
+ : ConfigurableC2Intf{store ? store->getName() : "", 0},
+ mStore{store} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures
+ ) override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && params.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->config_sm(params, failures);
+ }
+
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>> *const params) const override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && indices.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->query_sm({}, indices, params);
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+ ) const override {
+ return mStore->querySupportedParams_nb(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const override {
+ // Assume all params are blocking
+ // TODO: Filter for supported params
+ if (mayBlock == C2_DONT_BLOCK && fields.size() != 0) {
+ return C2_BLOCKING;
+ }
+ return mStore->querySupportedValues_sm(fields);
+ }
+
+protected:
+ std::shared_ptr<C2ComponentStore> mStore;
+};
+
+} // unnamed namespace
+
+struct ComponentStore::StoreParameterCache : public ParameterCache {
+ std::mutex mStoreMutex;
+ ComponentStore* mStore;
+
+ StoreParameterCache(ComponentStore* store): mStore{store} {
+ }
+
+ virtual c2_status_t validate(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params
+ ) override {
+ std::scoped_lock _lock(mStoreMutex);
+ return mStore ? mStore->validateSupportedParams(params) : C2_NO_INIT;
+ }
+
+ void onStoreDestroyed() {
+ std::scoped_lock _lock(mStoreMutex);
+ mStore = nullptr;
+ }
+};
+
+ComponentStore::ComponentStore(const std::shared_ptr<C2ComponentStore>& store)
+ : mConfigurable{new CachedConfigurable(std::make_unique<StoreIntf>(store))},
+ mParameterCache{std::make_shared<StoreParameterCache>(this)},
+ mStore{store} {
+
+ std::shared_ptr<C2ComponentStore> platformStore = android::GetCodec2PlatformComponentStore();
+ SetPreferredCodec2ComponentStore(store);
+
+ // Retrieve struct descriptors
+ mParamReflector = mStore->getParamReflector();
+
+ // Retrieve supported parameters from store
+ using namespace std::placeholders;
+ mInit = mConfigurable->init(mParameterCache);
+}
+
+ComponentStore::~ComponentStore() {
+ mParameterCache->onStoreDestroyed();
+}
+
+c2_status_t ComponentStore::status() const {
+ return mInit;
+}
+
+c2_status_t ComponentStore::validateSupportedParams(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params) {
+ c2_status_t res = C2_OK;
+
+ for (const std::shared_ptr<C2ParamDescriptor> &desc : params) {
+ if (!desc) {
+ // All descriptors should be valid
+ res = res ? res : C2_BAD_VALUE;
+ continue;
+ }
+ C2Param::CoreIndex coreIndex = desc->index().coreIndex();
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ auto it = mStructDescriptors.find(coreIndex);
+ if (it == mStructDescriptors.end()) {
+ std::shared_ptr<C2StructDescriptor> structDesc =
+ mParamReflector->describe(coreIndex);
+ if (!structDesc) {
+ // All supported params must be described
+ res = C2_BAD_INDEX;
+ }
+ mStructDescriptors.insert({ coreIndex, structDesc });
+ }
+ }
+ return res;
+}
+
+std::shared_ptr<ParameterCache> ComponentStore::getParameterCache() const {
+ return mParameterCache;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IComponentStore
+Return<void> ComponentStore::createComponent(
+ const hidl_string& name,
+ const sp<IComponentListener>& listener,
+ const sp<IClientManager>& pool,
+ createComponent_cb _hidl_cb) {
+
+ sp<Component> component;
+ std::shared_ptr<C2Component> c2component;
+ Status status = static_cast<Status>(
+ mStore->createComponent(name, &c2component));
+
+ if (status == Status::OK) {
+ onInterfaceLoaded(c2component->intf());
+ component = new Component(c2component, listener, this, pool);
+ if (!component) {
+ status = Status::CORRUPTED;
+ } else {
+ reportComponentBirth(component.get());
+ if (component->status() != C2_OK) {
+ status = static_cast<Status>(component->status());
+ } else {
+ component->initListener(component);
+ if (component->status() != C2_OK) {
+ status = static_cast<Status>(component->status());
+ }
+ }
+ }
+ }
+ _hidl_cb(status, component);
+ return Void();
+}
+
+Return<void> ComponentStore::createInterface(
+ const hidl_string& name,
+ createInterface_cb _hidl_cb) {
+ std::shared_ptr<C2ComponentInterface> c2interface;
+ c2_status_t res = mStore->createInterface(name, &c2interface);
+ sp<IComponentInterface> interface;
+ if (res == C2_OK) {
+ onInterfaceLoaded(c2interface);
+ interface = new ComponentInterface(c2interface, mParameterCache);
+ }
+ _hidl_cb(static_cast<Status>(res), interface);
+ return Void();
+}
+
+Return<void> ComponentStore::listComponents(listComponents_cb _hidl_cb) {
+ std::vector<std::shared_ptr<const C2Component::Traits>> c2traits =
+ mStore->listComponents();
+ hidl_vec<IComponentStore::ComponentTraits> traits(c2traits.size());
+ size_t ix = 0;
+ for (const std::shared_ptr<const C2Component::Traits> &c2trait : c2traits) {
+ if (c2trait) {
+ if (objcpy(&traits[ix], *c2trait)) {
+ ++ix;
+ } else {
+ break;
+ }
+ }
+ }
+ traits.resize(ix);
+ _hidl_cb(Status::OK, traits);
+ return Void();
+}
+
+Return<void> ComponentStore::createInputSurface(createInputSurface_cb _hidl_cb) {
+ sp<GraphicBufferSource> source = new GraphicBufferSource();
+ if (source->initCheck() != OK) {
+ _hidl_cb(Status::CORRUPTED, nullptr);
+ return Void();
+ }
+ using namespace std::placeholders;
+ sp<InputSurface> inputSurface = new InputSurface(
+ mParameterCache,
+ std::make_shared<C2ReflectorHelper>(),
+ source->getHGraphicBufferProducer(),
+ source);
+ _hidl_cb(inputSurface ? Status::OK : Status::NO_MEMORY,
+ inputSurface);
+ return Void();
+}
+
+void ComponentStore::onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf) {
+ // invalidate unsupported struct descriptors if a new interface is loaded as it may have
+ // exposed new descriptors
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ if (!mLoadedInterfaces.count(intf->getName())) {
+ mUnsupportedStructDescriptors.clear();
+ mLoadedInterfaces.emplace(intf->getName());
+ }
+}
+
+Return<void> ComponentStore::getStructDescriptors(
+ const hidl_vec<uint32_t>& indices,
+ getStructDescriptors_cb _hidl_cb) {
+ hidl_vec<StructDescriptor> descriptors(indices.size());
+ size_t dstIx = 0;
+ Status res = Status::OK;
+ for (size_t srcIx = 0; srcIx < indices.size(); ++srcIx) {
+ std::lock_guard<std::mutex> lock(mStructDescriptorsMutex);
+ const C2Param::CoreIndex coreIndex = C2Param::CoreIndex(indices[srcIx]).coreIndex();
+ const auto item = mStructDescriptors.find(coreIndex);
+ if (item == mStructDescriptors.end()) {
+ // not in the cache, and not known to be unsupported, query local reflector
+ if (!mUnsupportedStructDescriptors.count(coreIndex)) {
+ std::shared_ptr<C2StructDescriptor> structDesc =
+ mParamReflector->describe(coreIndex);
+ if (!structDesc) {
+ mUnsupportedStructDescriptors.emplace(coreIndex);
+ } else {
+ mStructDescriptors.insert({ coreIndex, structDesc });
+ if (objcpy(&descriptors[dstIx], *structDesc)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
+ }
+ }
+ res = Status::NOT_FOUND;
+ } else if (item->second) {
+ if (objcpy(&descriptors[dstIx], *item->second)) {
+ ++dstIx;
+ continue;
+ }
+ res = Status::CORRUPTED;
+ break;
+ } else {
+ res = Status::NO_MEMORY;
+ break;
+ }
+ }
+ descriptors.resize(dstIx);
+ _hidl_cb(res, descriptors);
+ return Void();
+}
+
+Return<sp<IClientManager>> ComponentStore::getPoolClientManager() {
+ return ClientManager::getInstance();
+}
+
+Return<Status> ComponentStore::copyBuffer(const Buffer& src, const Buffer& dst) {
+ // TODO implement
+ (void)src;
+ (void)dst;
+ return Status::OMITTED;
+}
+
+Return<sp<IConfigurable>> ComponentStore::getConfigurable() {
+ return mConfigurable;
+}
+
+// Methods from ::android::hardware::media::c2::V1_1::IComponentStore
+Return<void> ComponentStore::createComponent_1_1(
+ const hidl_string& name,
+ const sp<IComponentListener>& listener,
+ const sp<IClientManager>& pool,
+ createComponent_1_1_cb _hidl_cb) {
+
+ sp<Component> component;
+ std::shared_ptr<C2Component> c2component;
+ Status status = static_cast<Status>(
+ mStore->createComponent(name, &c2component));
+
+ if (status == Status::OK) {
+ onInterfaceLoaded(c2component->intf());
+ component = new Component(c2component, listener, this, pool);
+ if (!component) {
+ status = Status::CORRUPTED;
+ } else {
+ reportComponentBirth(component.get());
+ if (component->status() != C2_OK) {
+ status = static_cast<Status>(component->status());
+ } else {
+ component->initListener(component);
+ if (component->status() != C2_OK) {
+ status = static_cast<Status>(component->status());
+ }
+ }
+ }
+ }
+ _hidl_cb(status, component);
+ return Void();
+}
+
+// Called from createComponent() after a successful creation of `component`.
+void ComponentStore::reportComponentBirth(Component* component) {
+ ComponentStatus componentStatus;
+ componentStatus.c2Component = component->mComponent;
+ componentStatus.birthTime = std::chrono::system_clock::now();
+
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ mComponentRoster.emplace(component, componentStatus);
+}
+
+// Called from within the destructor of `component`. No virtual function calls
+// are made on `component` here.
+void ComponentStore::reportComponentDeath(Component* component) {
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ mComponentRoster.erase(component);
+}
+
+// Dumps component traits.
+std::ostream& ComponentStore::dump(
+ std::ostream& out,
+ const std::shared_ptr<const C2Component::Traits>& comp) {
+
+ constexpr const char indent[] = " ";
+
+ out << indent << "name: " << comp->name << std::endl;
+ out << indent << "domain: " << comp->domain << std::endl;
+ out << indent << "kind: " << comp->kind << std::endl;
+ out << indent << "rank: " << comp->rank << std::endl;
+ out << indent << "mediaType: " << comp->mediaType << std::endl;
+ out << indent << "aliases:";
+ for (const auto& alias : comp->aliases) {
+ out << ' ' << alias;
+ }
+ out << std::endl;
+
+ return out;
+}
+
+// Dumps component status.
+std::ostream& ComponentStore::dump(
+ std::ostream& out,
+ ComponentStatus& compStatus) {
+
+ constexpr const char indent[] = " ";
+
+ // Print birth time.
+ std::chrono::milliseconds ms =
+ std::chrono::duration_cast<std::chrono::milliseconds>(
+ compStatus.birthTime.time_since_epoch());
+ std::time_t birthTime = std::chrono::system_clock::to_time_t(
+ compStatus.birthTime);
+ std::tm tm = *std::localtime(&birthTime);
+ out << indent << "Creation time: "
+ << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
+ << '.' << std::setfill('0') << std::setw(3) << ms.count() % 1000
+ << std::endl;
+
+ // Print name and id.
+ std::shared_ptr<C2ComponentInterface> intf = compStatus.c2Component->intf();
+ if (!intf) {
+ out << indent << "Unknown component -- null interface" << std::endl;
+ return out;
+ }
+ out << indent << "Name: " << intf->getName() << std::endl;
+ out << indent << "Id: " << intf->getId() << std::endl;
+
+ return out;
+}
+
+// Dumps information when lshal is called.
+Return<void> ComponentStore::debug(
+ const hidl_handle& handle,
+ const hidl_vec<hidl_string>& /* args */) {
+ LOG(INFO) << "debug -- dumping...";
+ const native_handle_t *h = handle.getNativeHandle();
+ if (!h || h->numFds != 1) {
+ LOG(ERROR) << "debug -- dumping failed -- "
+ "invalid file descriptor to dump to";
+ return Void();
+ }
+ std::ostringstream out;
+
+ { // Populate "out".
+
+ constexpr const char indent[] = " ";
+
+ // Show name.
+ out << "Beginning of dump -- C2ComponentStore: "
+ << mStore->getName() << std::endl << std::endl;
+
+ // Retrieve the list of supported components.
+ std::vector<std::shared_ptr<const C2Component::Traits>> traitsList =
+ mStore->listComponents();
+
+ // Dump the traits of supported components.
+ out << indent << "Supported components:" << std::endl << std::endl;
+ if (traitsList.size() == 0) {
+ out << indent << indent << "NONE" << std::endl << std::endl;
+ } else {
+ for (const auto& traits : traitsList) {
+ dump(out, traits) << std::endl;
+ }
+ }
+
+ // Dump active components.
+ {
+ out << indent << "Active components:" << std::endl << std::endl;
+ std::lock_guard<std::mutex> lock(mComponentRosterMutex);
+ if (mComponentRoster.size() == 0) {
+ out << indent << indent << "NONE" << std::endl << std::endl;
+ } else {
+ for (auto& pair : mComponentRoster) {
+ dump(out, pair.second) << std::endl;
+ }
+ }
+ }
+
+ out << "End of dump -- C2ComponentStore: "
+ << mStore->getName() << std::endl;
+ }
+
+ if (!android::base::WriteStringToFd(out.str(), h->data[0])) {
+ PLOG(WARNING) << "debug -- dumping failed -- write()";
+ } else {
+ LOG(INFO) << "debug -- dumping succeeded";
+ }
+ return Void();
+}
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hidl/1.1/utils/Configurable.cpp b/media/codec2/hidl/1.1/utils/Configurable.cpp
new file mode 100644
index 0000000..1f3b2c7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/Configurable.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/Configurable.h>
diff --git a/media/codec2/hidl/1.1/utils/InputBufferManager.cpp b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
new file mode 100644
index 0000000..45bfc86
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputBufferManager.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputBufferManager.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurface.cpp b/media/codec2/hidl/1.1/utils/InputSurface.cpp
new file mode 100644
index 0000000..ce40494
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurface.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputSurface.h>
diff --git a/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
new file mode 100644
index 0000000..32154a7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/InputSurfaceConnection.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/InputSurfaceConnection.h>
diff --git a/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
new file mode 100644
index 0000000..65756e8
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/OutputBufferQueue.h>
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
new file mode 100644
index 0000000..16c81d4
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+#include <hidl/Status.h>
+#include <hwbinder/IBinder.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+
+using ::android::hardware::media::c2::V1_1::IComponent;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+
+namespace utils {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::IBinder;
+using ::android::sp;
+using ::android::wp;
+
+struct ComponentStore;
+
+struct Component : public IComponent,
+ public std::enable_shared_from_this<Component> {
+ Component(
+ const std::shared_ptr<C2Component>&,
+ const sp<IComponentListener>& listener,
+ const sp<ComponentStore>& store,
+ const sp<::android::hardware::media::bufferpool::V2_0::
+ IClientManager>& clientPoolManager);
+ c2_status_t status() const;
+
+ typedef ::android::hardware::graphics::bufferqueue::V1_0::
+ IGraphicBufferProducer HGraphicBufferProducer1;
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer2;
+
+ // Methods from IComponent follow.
+ virtual Return<Status> queue(const WorkBundle& workBundle) override;
+ virtual Return<void> flush(flush_cb _hidl_cb) override;
+ virtual Return<Status> drain(bool withEos) override;
+ virtual Return<Status> setOutputSurface(
+ uint64_t blockPoolId,
+ const sp<HGraphicBufferProducer2>& surface) override;
+ virtual Return<void> connectToInputSurface(
+ const sp<IInputSurface>& inputSurface,
+ connectToInputSurface_cb _hidl_cb) override;
+ virtual Return<void> connectToOmxInputSurface(
+ const sp<HGraphicBufferProducer1>& producer,
+ const sp<::android::hardware::media::omx::V1_0::
+ IGraphicBufferSource>& source,
+ connectToOmxInputSurface_cb _hidl_cb) override;
+ virtual Return<Status> disconnectFromInputSurface() override;
+ virtual Return<void> createBlockPool(
+ uint32_t allocatorId,
+ createBlockPool_cb _hidl_cb) override;
+ virtual Return<Status> destroyBlockPool(uint64_t blockPoolId) override;
+ virtual Return<Status> start() override;
+ virtual Return<Status> stop() override;
+ virtual Return<Status> reset() override;
+ virtual Return<Status> release() override;
+ virtual Return<sp<IComponentInterface>> getInterface() override;
+ virtual Return<sp<IInputSink>> asInputSink() override;
+ virtual Return<void> configureVideoTunnel(
+ uint32_t avSyncHwId, configureVideoTunnel_cb _hidl_cb) override;
+
+ // Returns a C2Component associated to the given sink if the sink is indeed
+ // a local component. Returns nullptr otherwise.
+ //
+ // This function is used by InputSurface::connect().
+ static std::shared_ptr<C2Component> findLocalComponent(
+ const sp<IInputSink>& sink);
+
+protected:
+ c2_status_t mInit;
+ std::shared_ptr<C2Component> mComponent;
+ sp<ComponentInterface> mInterface;
+ sp<IComponentListener> mListener;
+ sp<ComponentStore> mStore;
+ ::android::hardware::media::c2::V1_1::utils::DefaultBufferPoolSender
+ mBufferPoolSender;
+
+ struct Sink;
+ std::mutex mSinkMutex;
+ sp<Sink> mSink;
+
+ std::mutex mBlockPoolsMutex;
+ // This map keeps C2BlockPool objects that are created by createBlockPool()
+ // alive. These C2BlockPool objects can be deleted by calling
+ // destroyBlockPool(), reset() or release(), or by destroying the component.
+ std::map<uint64_t, std::shared_ptr<C2BlockPool>> mBlockPools;
+
+ void initListener(const sp<Component>& self);
+
+ virtual ~Component() override;
+
+ friend struct ComponentStore;
+
+ struct Listener;
+};
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
new file mode 100644
index 0000000..723c5bd
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentInterface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ComponentInterface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
new file mode 100644
index 0000000..1f04391
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
+#define CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
+
+#include <codec2/hidl/1.1/Component.h>
+#include <codec2/hidl/1.1/ComponentInterface.h>
+#include <codec2/hidl/1.1/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <chrono>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::bufferpool::V2_0::IClientManager;
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore : public IComponentStore {
+ ComponentStore(const std::shared_ptr<C2ComponentStore>& store);
+ virtual ~ComponentStore();
+
+ /**
+ * Returns the status of the construction of this object.
+ */
+ c2_status_t status() const;
+
+ /**
+ * This function is called by CachedConfigurable::init() to validate
+ * supported parameters.
+ */
+ c2_status_t validateSupportedParams(
+ const std::vector<std::shared_ptr<C2ParamDescriptor>>& params);
+
+ /**
+ * Returns the store's ParameterCache. This is used for validation by
+ * Configurable::init().
+ */
+ std::shared_ptr<ParameterCache> getParameterCache() const;
+
+ // Methods from ::android::hardware::media::c2::V1_0::IComponentStore.
+ virtual Return<void> createComponent(
+ const hidl_string& name,
+ const sp<IComponentListener>& listener,
+ const sp<IClientManager>& pool,
+ createComponent_cb _hidl_cb) override;
+ virtual Return<void> createInterface(
+ const hidl_string& name,
+ createInterface_cb _hidl_cb) override;
+ virtual Return<void> listComponents(listComponents_cb _hidl_cb) override;
+ virtual Return<void> createInputSurface(
+ createInputSurface_cb _hidl_cb) override;
+ virtual Return<void> getStructDescriptors(
+ const hidl_vec<uint32_t>& indices,
+ getStructDescriptors_cb _hidl_cb) override;
+ virtual Return<sp<IClientManager>> getPoolClientManager() override;
+ virtual Return<Status> copyBuffer(
+ const Buffer& src,
+ const Buffer& dst) override;
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+ // Methods from ::android::hardware::media::c2::V1_1::IComponentStore.
+ virtual Return<void> createComponent_1_1(
+ const hidl_string& name,
+ const sp<IComponentListener>& listener,
+ const sp<IClientManager>& pool,
+ createComponent_1_1_cb _hidl_cb) override;
+
+ /**
+ * Dumps information when lshal is called.
+ */
+ virtual Return<void> debug(
+ const hidl_handle& handle,
+ const hidl_vec<hidl_string>& args) override;
+
+protected:
+ sp<CachedConfigurable> mConfigurable;
+ struct StoreParameterCache;
+ std::shared_ptr<StoreParameterCache> mParameterCache;
+
+ // Does bookkeeping for an interface that has been loaded.
+ void onInterfaceLoaded(const std::shared_ptr<C2ComponentInterface> &intf);
+
+ c2_status_t mInit;
+ std::shared_ptr<C2ComponentStore> mStore;
+ std::shared_ptr<C2ParamReflector> mParamReflector;
+
+ std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
+ std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
+ std::set<C2String> mLoadedInterfaces;
+ mutable std::mutex mStructDescriptorsMutex;
+
+ // ComponentStore keeps track of live Components.
+
+ struct ComponentStatus {
+ std::shared_ptr<C2Component> c2Component;
+ std::chrono::system_clock::time_point birthTime;
+ };
+
+ mutable std::mutex mComponentRosterMutex;
+ std::map<Component*, ComponentStatus> mComponentRoster;
+
+ // Called whenever Component is created.
+ void reportComponentBirth(Component* component);
+ // Called only from the destructor of Component.
+ void reportComponentDeath(Component* component);
+
+ friend Component;
+
+ // Helper functions for dumping.
+
+ std::ostream& dump(
+ std::ostream& out,
+ const std::shared_ptr<const C2Component::Traits>& comp);
+
+ std::ostream& dump(
+ std::ostream& out,
+ ComponentStatus& compStatus);
+
+};
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_COMPONENT_STORE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
new file mode 100644
index 0000000..fd9091b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/Configurable.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
+#define CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::ConfigurableC2Intf;
+using ::android::hardware::media::c2::V1_0::utils::ParameterCache;
+using ::android::hardware::media::c2::V1_0::utils::CachedConfigurable;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_CONFIGURABLE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
new file mode 100644
index 0000000..8e7a91b
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputBufferManager.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputBufferManager;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_BUFFER_MANAGER_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
new file mode 100644
index 0000000..59223b7
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
+
+#include <codec2/hidl/1.0/InputSurface.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurface;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
new file mode 100644
index 0000000..7f695ef
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/InputSurfaceConnection.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
+#define CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
+
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::InputSurfaceConnection;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_INPUT_SURFACE_CONNECTION_H
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
new file mode 100644
index 0000000..f77852d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
+#define CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
+
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
new file mode 100644
index 0000000..d0ba93d
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/types.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_1_UTILS_TYPES_H
+#define CODEC2_HIDL_V1_1_UTILS_TYPES_H
+
+#include <android/hardware/media/c2/1.1/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.1/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
+#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
+
+#include <codec2/hidl/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_1 {
+
+using ::android::hardware::media::c2::V1_0::BaseBlock;
+using ::android::hardware::media::c2::V1_0::Block;
+using ::android::hardware::media::c2::V1_0::Buffer;
+using ::android::hardware::media::c2::V1_0::FieldDescriptor;
+using ::android::hardware::media::c2::V1_0::FieldId;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValues;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQuery;
+using ::android::hardware::media::c2::V1_0::FieldSupportedValuesQueryResult;
+using ::android::hardware::media::c2::V1_0::FrameData;
+using ::android::hardware::media::c2::V1_0::InfoBuffer;
+using ::android::hardware::media::c2::V1_0::ParamDescriptor;
+using ::android::hardware::media::c2::V1_0::ParamField;
+using ::android::hardware::media::c2::V1_0::ParamFieldValues;
+using ::android::hardware::media::c2::V1_0::ParamIndex;
+using ::android::hardware::media::c2::V1_0::Params;
+using ::android::hardware::media::c2::V1_0::PrimitiveValue;
+using ::android::hardware::media::c2::V1_0::SettingResult;
+using ::android::hardware::media::c2::V1_0::Status;
+using ::android::hardware::media::c2::V1_0::StructDescriptor;
+using ::android::hardware::media::c2::V1_0::ValueRange;
+using ::android::hardware::media::c2::V1_0::Work;
+using ::android::hardware::media::c2::V1_0::WorkBundle;
+using ::android::hardware::media::c2::V1_0::WorkOrdinal;
+using ::android::hardware::media::c2::V1_0::Worklet;
+
+using ::android::hardware::media::c2::V1_0::IComponentInterface;
+using ::android::hardware::media::c2::V1_0::IComponentListener;
+using ::android::hardware::media::c2::V1_0::IConfigurable;
+using ::android::hardware::media::c2::V1_0::IInputSink;
+using ::android::hardware::media::c2::V1_0::IInputSurface;
+using ::android::hardware::media::c2::V1_0::IInputSurfaceConnection;
+
+namespace utils {
+
+using ::android::hardware::media::c2::V1_0::utils::toC2Status;
+
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Range;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RangeInfo;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_Rect;
+using ::android::hardware::media::c2::V1_0::utils::C2Hidl_RectInfo;
+
+using ::android::hardware::media::c2::V1_0::utils::objcpy;
+using ::android::hardware::media::c2::V1_0::utils::parseParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::createParamsBlob;
+using ::android::hardware::media::c2::V1_0::utils::copyParamsFromBlob;
+using ::android::hardware::media::c2::V1_0::utils::updateParamsFromBlob;
+
+using ::android::hardware::media::c2::V1_0::utils::BufferPoolSender;
+using ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender;
+
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::beginTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlock;
+using ::android::hardware::media::c2::V1_0::utils::endTransferBufferQueueBlocks;
+using ::android::hardware::media::c2::V1_0::utils::displayBufferQueueBlock;
+
+using ::android::hardware::media::c2::V1_0::utils::operator<<;
+
+} // namespace utils
+} // namespace V1_1
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_1_UTILS_TYPES_H
diff --git a/media/codec2/hidl/1.1/utils/types.cpp b/media/codec2/hidl/1.1/utils/types.cpp
new file mode 100644
index 0000000..8c09023
--- /dev/null
+++ b/media/codec2/hidl/1.1/utils/types.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <codec2/hidl/1.1/types.h>
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index 89c1c4a..3c37990 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -9,10 +9,12 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.media.bufferpool@2.0",
"android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
"libbase",
"libbinder",
"libcodec2",
"libcodec2_hidl_client@1.0",
+ "libcodec2_hidl_client@1.1",
"libcodec2_vndk",
"libcutils",
"libgui",
@@ -28,8 +30,11 @@
],
export_shared_lib_headers: [
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
"libcodec2",
"libcodec2_hidl_client@1.0",
+ "libcodec2_hidl_client@1.1",
"libcodec2_vndk",
],
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index c747190..199a99c 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -19,6 +19,29 @@
#include <android-base/logging.h>
#include <codec2/hidl/client.h>
+#include <C2Debug.h>
+#include <C2BufferPriv.h>
+#include <C2PlatformSupport.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android/hardware/media/c2/1.0/IComponentStore.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+
+#include <android-base/properties.h>
+#include <bufferpool/ClientManager.h>
+#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.1/OutputBufferQueue.h>
+#include <codec2/hidl/1.1/types.h>
+
+#include <cutils/native_handle.h>
+#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
+#include <hidl/HidlSupport.h>
#include <deque>
#include <iterator>
@@ -30,25 +53,6 @@
#include <type_traits>
#include <vector>
-#include <android-base/properties.h>
-#include <bufferpool/ClientManager.h>
-#include <cutils/native_handle.h>
-#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
-#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
-#include <hidl/HidlSupport.h>
-
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <android/hardware/media/c2/1.0/IComponent.h>
-#include <android/hardware/media/c2/1.0/IComponentInterface.h>
-#include <android/hardware/media/c2/1.0/IComponentListener.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/c2/1.0/IConfigurable.h>
-#include <android/hidl/manager/1.2/IServiceManager.h>
-
-#include <C2Debug.h>
-#include <C2BufferPriv.h>
-#include <C2PlatformSupport.h>
-
namespace android {
using ::android::hardware::hidl_vec;
@@ -56,8 +60,8 @@
using ::android::hardware::Return;
using ::android::hardware::Void;
-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;
using namespace ::android::hardware::media::bufferpool::V2_0;
using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
@@ -514,8 +518,24 @@
};
+// Codec2Client::Component::BufferPoolSender
+struct Codec2Client::Component::BufferPoolSender :
+ hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
+ BufferPoolSender()
+ : hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
+ }
+};
+
+// Codec2Client::Component::OutputBufferQueue
+struct Codec2Client::Component::OutputBufferQueue :
+ hardware::media::c2::V1_1::utils::OutputBufferQueue {
+ OutputBufferQueue()
+ : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
+ }
+};
+
// Codec2Client
-Codec2Client::Codec2Client(const sp<IComponentStore>& base,
+Codec2Client::Codec2Client(sp<Base> const& base,
size_t serviceIndex)
: Configurable{
[base]() -> sp<IConfigurable> {
@@ -526,7 +546,8 @@
nullptr;
}()
},
- mBase{base},
+ mBase1_0{base},
+ mBase1_1{Base1_1::castFrom(base)},
mServiceIndex{serviceIndex} {
Return<sp<IClientManager>> transResult = base->getPoolClientManager();
if (!transResult.isOk()) {
@@ -537,7 +558,15 @@
}
sp<Codec2Client::Base> const& Codec2Client::getBase() const {
- return mBase;
+ return mBase1_0;
+}
+
+sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
+ return mBase1_0;
+}
+
+sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
+ return mBase1_1;
}
std::string const& Codec2Client::getServiceName() const {
@@ -552,7 +581,8 @@
c2_status_t status;
sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
hidlListener->base = listener;
- Return<void> transStatus = mBase->createComponent(
+ Return<void> transStatus = mBase1_1 ?
+ mBase1_1->createComponent_1_1(
name,
hidlListener,
ClientManager::getInstance(),
@@ -565,6 +595,20 @@
}
*component = std::make_shared<Codec2Client::Component>(c);
hidlListener->component = *component;
+ }) :
+ mBase1_0->createComponent(
+ name,
+ hidlListener,
+ ClientManager::getInstance(),
+ [&status, component, hidlListener](
+ Status s,
+ const sp<hardware::media::c2::V1_0::IComponent>& c) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ return;
+ }
+ *component = std::make_shared<Codec2Client::Component>(c);
+ hidlListener->component = *component;
});
if (!transStatus.isOk()) {
LOG(ERROR) << "createComponent(" << name.c_str()
@@ -587,7 +631,7 @@
<< status << ".";
}
- (*component)->mBufferPoolSender.setReceiver(mHostPoolManager);
+ (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
return status;
}
@@ -595,7 +639,7 @@
const C2String& name,
std::shared_ptr<Codec2Client::Interface>* const interface) {
c2_status_t status;
- Return<void> transStatus = mBase->createInterface(
+ Return<void> transStatus = mBase1_0->createInterface(
name,
[&status, interface](
Status s,
@@ -622,7 +666,7 @@
c2_status_t Codec2Client::createInputSurface(
std::shared_ptr<InputSurface>* const inputSurface) {
c2_status_t status;
- Return<void> transStatus = mBase->createInputSurface(
+ Return<void> transStatus = mBase1_0->createInputSurface(
[&status, inputSurface](
Status s,
const sp<IInputSurface>& i) {
@@ -650,7 +694,7 @@
bool* success) const {
std::vector<C2Component::Traits> traits;
std::string const& serviceName = getServiceName();
- Return<void> transStatus = mBase->listComponents(
+ Return<void> transStatus = mBase1_0->listComponents(
[&traits, &serviceName](Status s,
const hidl_vec<IComponentStore::ComponentTraits>& t) {
if (s != Status::OK) {
@@ -734,7 +778,7 @@
sp<Base> mBase;
};
- return std::make_shared<SimpleParamReflector>(mBase);
+ return std::make_shared<SimpleParamReflector>(mBase1_0);
};
std::vector<std::string> const& Codec2Client::GetServiceNames() {
@@ -1053,8 +1097,32 @@
nullptr;
}()
},
- mBase{base},
- mBufferPoolSender{nullptr} {
+ mBase1_0{base},
+ mBase1_1{Base1_1::castFrom(base)},
+ mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const sp<Base1_1>& base)
+ : Configurable{
+ [base]() -> sp<IConfigurable> {
+ Return<sp<IComponentInterface>> transResult1 =
+ base->getInterface();
+ if (!transResult1.isOk()) {
+ return nullptr;
+ }
+ Return<sp<IConfigurable>> transResult2 =
+ static_cast<sp<IComponentInterface>>(transResult1)->
+ getConfigurable();
+ return transResult2.isOk() ?
+ static_cast<sp<IConfigurable>>(transResult2) :
+ nullptr;
+ }()
+ },
+ mBase1_0{base},
+ mBase1_1{base},
+ mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
Codec2Client::Component::~Component() {
@@ -1065,7 +1133,7 @@
C2BlockPool::local_id_t* blockPoolId,
std::shared_ptr<Codec2Client::Configurable>* configurable) {
c2_status_t status;
- Return<void> transStatus = mBase->createBlockPool(
+ Return<void> transStatus = mBase1_0->createBlockPool(
static_cast<uint32_t>(id),
[&status, blockPoolId, configurable](
Status s,
@@ -1090,7 +1158,7 @@
c2_status_t Codec2Client::Component::destroyBlockPool(
C2BlockPool::local_id_t localId) {
- Return<Status> transResult = mBase->destroyBlockPool(
+ Return<Status> transResult = mBase1_0->destroyBlockPool(
static_cast<uint64_t>(localId));
if (!transResult.isOk()) {
LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1102,17 +1170,17 @@
void Codec2Client::Component::handleOnWorkDone(
const std::list<std::unique_ptr<C2Work>> &workItems) {
// Output bufferqueue-based blocks' lifetime management
- mOutputBufferQueue.holdBufferQueueBlocks(workItems);
+ mOutputBufferQueue->holdBufferQueueBlocks(workItems);
}
c2_status_t Codec2Client::Component::queue(
std::list<std::unique_ptr<C2Work>>* const items) {
WorkBundle workBundle;
- if (!objcpy(&workBundle, *items, &mBufferPoolSender)) {
+ if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
LOG(ERROR) << "queue -- bad input.";
return C2_TRANSACTION_FAILED;
}
- Return<Status> transStatus = mBase->queue(workBundle);
+ Return<Status> transStatus = mBase1_0->queue(workBundle);
if (!transStatus.isOk()) {
LOG(ERROR) << "queue -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1130,7 +1198,7 @@
std::list<std::unique_ptr<C2Work>>* const flushedWork) {
(void)mode; // Flush mode isn't supported in HIDL yet.
c2_status_t status;
- Return<void> transStatus = mBase->flush(
+ Return<void> transStatus = mBase1_0->flush(
[&status, flushedWork](
Status s, const WorkBundle& wb) {
status = static_cast<c2_status_t>(s);
@@ -1165,13 +1233,13 @@
}
// Output bufferqueue-based blocks' lifetime management
- mOutputBufferQueue.holdBufferQueueBlocks(*flushedWork);
+ mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
return status;
}
c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
- Return<Status> transStatus = mBase->drain(
+ Return<Status> transStatus = mBase1_0->drain(
mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
if (!transStatus.isOk()) {
LOG(ERROR) << "drain -- transaction failed.";
@@ -1186,7 +1254,7 @@
}
c2_status_t Codec2Client::Component::start() {
- Return<Status> transStatus = mBase->start();
+ Return<Status> transStatus = mBase1_0->start();
if (!transStatus.isOk()) {
LOG(ERROR) << "start -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1200,7 +1268,7 @@
}
c2_status_t Codec2Client::Component::stop() {
- Return<Status> transStatus = mBase->stop();
+ Return<Status> transStatus = mBase1_0->stop();
if (!transStatus.isOk()) {
LOG(ERROR) << "stop -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1214,7 +1282,7 @@
}
c2_status_t Codec2Client::Component::reset() {
- Return<Status> transStatus = mBase->reset();
+ Return<Status> transStatus = mBase1_0->reset();
if (!transStatus.isOk()) {
LOG(ERROR) << "reset -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1228,7 +1296,7 @@
}
c2_status_t Codec2Client::Component::release() {
- Return<Status> transStatus = mBase->release();
+ Return<Status> transStatus = mBase1_0->release();
if (!transStatus.isOk()) {
LOG(ERROR) << "release -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1241,6 +1309,29 @@
return status;
}
+c2_status_t Codec2Client::Component::configureVideoTunnel(
+ uint32_t avSyncHwId,
+ native_handle_t** sidebandHandle) {
+ *sidebandHandle = nullptr;
+ if (!mBase1_1) {
+ return C2_OMITTED;
+ }
+ c2_status_t status{};
+ Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+ [&status, sidebandHandle](
+ Status s, hardware::hidl_handle const& h) {
+ status = static_cast<c2_status_t>(s);
+ if (h.getNativeHandle()) {
+ *sidebandHandle = native_handle_clone(h.getNativeHandle());
+ }
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "configureVideoTunnel -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ return status;
+}
+
c2_status_t Codec2Client::Component::setOutputSurface(
C2BlockPool::local_id_t blockPoolId,
const sp<IGraphicBufferProducer>& surface,
@@ -1256,18 +1347,18 @@
}
if (!surface) {
- mOutputBufferQueue.configure(nullIgbp, generation, 0);
+ mOutputBufferQueue->configure(nullIgbp, generation, 0);
} else if (surface->getUniqueId(&bqId) != OK) {
LOG(ERROR) << "setOutputSurface -- "
"cannot obtain bufferqueue id.";
bqId = 0;
- mOutputBufferQueue.configure(nullIgbp, generation, 0);
+ mOutputBufferQueue->configure(nullIgbp, generation, 0);
} else {
- mOutputBufferQueue.configure(surface, generation, bqId);
+ mOutputBufferQueue->configure(surface, generation, bqId);
}
ALOGD("generation remote change %u", generation);
- Return<Status> transStatus = mBase->setOutputSurface(
+ Return<Status> transStatus = mBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp);
if (!transStatus.isOk()) {
@@ -1286,14 +1377,14 @@
const C2ConstGraphicBlock& block,
const QueueBufferInput& input,
QueueBufferOutput* output) {
- return mOutputBufferQueue.outputBuffer(block, input, output);
+ return mOutputBufferQueue->outputBuffer(block, input, output);
}
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
c2_status_t status;
- Return<void> transStatus = mBase->connectToInputSurface(
+ Return<void> transStatus = mBase1_0->connectToInputSurface(
inputSurface->mBase,
[&status, connection](
Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1317,7 +1408,7 @@
const sp<HGraphicBufferSource>& source,
std::shared_ptr<InputSurfaceConnection>* connection) {
c2_status_t status;
- Return<void> transStatus = mBase->connectToOmxInputSurface(
+ Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
producer, source,
[&status, connection](
Status s, const sp<IInputSurfaceConnection>& c) {
@@ -1337,7 +1428,7 @@
}
c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
- Return<Status> transStatus = mBase->disconnectFromInputSurface();
+ Return<Status> transStatus = mBase1_0->disconnectFromInputSurface();
if (!transStatus.isOk()) {
LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1376,7 +1467,7 @@
deathRecipient->component = component;
component->mDeathRecipient = deathRecipient;
- Return<bool> transResult = component->mBase->linkToDeath(
+ Return<bool> transResult = component->mBase1_0->linkToDeath(
component->mDeathRecipient, 0);
if (!transResult.isOk()) {
LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index dca28f7..649dffd 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -17,14 +17,13 @@
#ifndef CODEC2_HIDL_CLIENT_H
#define CODEC2_HIDL_CLIENT_H
-#include <gui/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
#include <C2PlatformSupport.h>
#include <C2Component.h>
#include <C2Buffer.h>
#include <C2Param.h>
#include <C2.h>
+#include <gui/IGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
#include <utils/StrongPointer.h>
@@ -74,6 +73,11 @@
struct IInputSurfaceConnection;
} // namespace android::hardware::media::c2::V1_0
+namespace android::hardware::media::c2::V1_1 {
+struct IComponent;
+struct IComponentStore;
+} // namespace android::hardware::media::c2::V1_1
+
namespace android::hardware::media::bufferpool::V2_0 {
struct IClientManager;
} // namespace android::hardware::media::bufferpool::V2_0
@@ -82,6 +86,10 @@
struct IGraphicBufferProducer;
} // android::hardware::graphics::bufferqueue::V1_0
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+} // android::hardware::graphics::bufferqueue::V2_0
+
namespace android::hardware::media::omx::V1_0 {
struct IGraphicBufferSource;
} // namespace android::hardware::media::omx::V1_0
@@ -127,7 +135,9 @@
struct Codec2Client : public Codec2ConfigurableClient {
- typedef ::android::hardware::media::c2::V1_0::IComponentStore Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
+ typedef Base1_0 Base;
struct Listener;
@@ -144,6 +154,8 @@
typedef Codec2Client Store;
sp<Base> const& getBase() const;
+ sp<Base1_0> const& getBase1_0() const;
+ sp<Base1_1> const& getBase1_1() const;
std::string const& getServiceName() const;
@@ -206,7 +218,8 @@
Codec2Client(sp<Base> const& base, size_t serviceIndex);
protected:
- sp<Base> mBase;
+ sp<Base1_0> mBase1_0;
+ sp<Base1_1> mBase1_1;
// Finds the first store where the predicate returns C2_OK and returns the
// last predicate result. The predicate will be tried on all stores. The
@@ -295,7 +308,9 @@
struct Codec2Client::Component : public Codec2Client::Configurable {
- typedef ::android::hardware::media::c2::V1_0::IComponent Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
+ typedef Base1_0 Base;
c2_status_t createBlockPool(
C2Allocator::id_t id,
@@ -322,6 +337,17 @@
c2_status_t release();
+ /**
+ * Use tunneling.
+ *
+ * On success, @p sidebandHandle will be a newly allocated native handle.
+ * File descriptors in @p sidebandHandle must be closed and
+ * @p sidebandHandle itself must be deleted afterwards.
+ */
+ c2_status_t configureVideoTunnel(
+ uint32_t avSyncHwId,
+ native_handle_t** sidebandHandle);
+
typedef ::android::
IGraphicBufferProducer IGraphicBufferProducer;
typedef IGraphicBufferProducer::
@@ -378,17 +404,19 @@
// base cannot be null.
Component(const sp<Base>& base);
+ Component(const sp<Base1_1>& base);
~Component();
protected:
- sp<Base> mBase;
+ sp<Base1_0> mBase1_0;
+ sp<Base1_1> mBase1_1;
- ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
- mBufferPoolSender;
+ struct BufferPoolSender;
+ std::unique_ptr<BufferPoolSender> mBufferPoolSender;
- ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue
- mOutputBufferQueue;
+ struct OutputBufferQueue;
+ std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
static c2_status_t setDeathListener(
const std::shared_ptr<Component>& component,
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 0403a1f..46bea2e 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -1,37 +1,82 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This is an example of an empty Codec2.0 service.
+//
+// To use this, make a copy of this whole directory and rename modules
+// accordingly. The contents of "vendor.cpp" and files in the subdirectory
+// "seccomp_policy" may also need to be modified.
+
+// Binary file for the service.
+//
+// The init_rc file contains the absolute path to this binary on the device.
+// If the name of this module is modified, the content of the init_rc file has
+// to be modified accordingly.
+//
+// The seccomp_policy file name and its content can be modified, but note that
+// vendor.cpp also needs to be updated because it needs the absolute path to the
+// seccomp policy file on the device.
cc_binary {
- name: "android.hardware.media.c2@1.0-service",
- defaults: ["hidl_defaults"],
- soc_specific: true,
+ name: "android.hardware.media.c2@1.1-default-service",
+ vendor: true,
relative_install_path: "hw",
+
+ init_rc: ["android.hardware.media.c2@1.1-default-service.rc"],
+
+ defaults: ["libcodec2-hidl-defaults"],
srcs: [
"vendor.cpp",
],
- init_rc: ["android.hardware.media.c2@1.0-service.rc"],
-
+ // minijail is used to protect against unexpected system calls.
shared_libs: [
- "android.hardware.media.c2@1.0",
- "android.hardware.media.omx@1.0",
"libavservices_minijail_vendor",
"libbinder",
- "libcodec2_hidl@1.0",
- "libcodec2_vndk",
- "libhidlbase",
- "liblog",
- "libstagefright_omx",
- "libstagefright_xmlparser",
- "libutils",
],
+ required: ["android.hardware.media.c2@1.1-default-seccomp_policy"],
+}
+// seccomp policy file.
+//
+// This should be modified to suit the target device and architecture.
+//
+// Files in the "seccomp_policy" subdirectory are only provided as examples.
+// They may not work on some devices and/or architectures without modification.
+prebuilt_etc {
+ name: "android.hardware.media.c2@1.1-default-seccomp_policy",
+ vendor: true,
+ sub_dir: "seccomp_policy",
+
+ // If a specific architecture is targeted, multiple choices are not needed.
arch: {
arm: {
- required: ["codec2.vendor.base.policy"],
+ src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy",
+ },
+ arm64: {
+ src: "seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy",
},
x86: {
- required: ["codec2.vendor.base.policy"],
+ src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy",
+ },
+ x86_64: {
+ src: "seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy",
},
},
- compile_multilib: "32",
+ // This may be removed.
+ required: ["crash_dump.policy"],
}
diff --git a/media/codec2/hidl/services/Android.mk b/media/codec2/hidl/services/Android.mk
deleted file mode 100644
index d9b28e7..0000000
--- a/media/codec2/hidl/services/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# vendor service seccomp policy
-ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH), x86 x86_64 arm arm64))
-include $(CLEAR_VARS)
-LOCAL_MODULE := codec2.vendor.base.policy
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_REQUIRED_MODULES := crash_dump.policy
-ifdef TARGET_2ND_ARCH
- ifneq ($(TARGET_TRANSLATE_2ND_ARCH),true)
- LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_2ND_ARCH).policy
- else
- LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
- endif
-else
- LOCAL_SRC_FILES := seccomp_policy/codec2.vendor.base-$(TARGET_ARCH).policy
-endif
-include $(BUILD_PREBUILT)
-endif
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
deleted file mode 100644
index 8806bd1f..0000000
--- a/media/codec2/hidl/services/android.hardware.media.c2@1.0-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service android-hardware-media-c2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service
- class hal
- user mediacodec
- group camera mediadrm drmrpc
- ioprio rt 4
- writepid /dev/cpuset/foreground/tasks
-
diff --git a/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
new file mode 100644
index 0000000..44f2d8e
--- /dev/null
+++ b/media/codec2/hidl/services/android.hardware.media.c2@1.1-default-service.rc
@@ -0,0 +1,7 @@
+service android-hardware-media-c2-hal-1-1 /vendor/bin/hw/android.hardware.media.c2@1.1-default-service
+ class hal
+ user mediacodec
+ group camera mediadrm drmrpc
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
+
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
similarity index 70%
copy from media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
copy to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
index d5871d1..9042cd7 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# 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.
@@ -12,21 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Organized by frequency of systemcall - in descending order for
-# best performance.
futex: 1
+# ioctl calls are filtered via the selinux policy.
ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
+sched_yield: 1
close: 1
-writev: 1
dup: 1
ppoll: 1
-mmap2: 1
-getrandom: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap2: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
# parser support for '<' is in this needs to be modified to also prevent
@@ -36,38 +33,54 @@
# for more details.
mremap: arg3 == 3
munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
+prctl: 1
+getuid32: 1
+writev: 1
sigaltstack: 1
clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
lseek: 1
+rt_sigprocmask: 1
+openat: 1
+open: 1
+fstat64: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+readlink: 1
+read: 1
+pread64: 1
+fstatfs64: 1
+gettimeofday: 1
+faccessat: 1
_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
fstatat64: 1
ugetrlimit: 1
-getdents64: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
getrandom: 1
+madvise: 1
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
+# crash dump policy additions
+sigreturn: 1
+clock_gettime: 1
+futex: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
+#mprotect: arg2 in 0x1|0x2
+#mmap2: arg2 in 0x1|0x2
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
similarity index 71%
rename from media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
rename to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
index d5871d1..4faf8b2 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-arm.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-arm64.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# 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.
@@ -12,21 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Organized by frequency of systemcall - in descending order for
-# best performance.
futex: 1
+# ioctl calls are filtered via the selinux policy.
ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
+sched_yield: 1
close: 1
-writev: 1
dup: 1
ppoll: 1
-mmap2: 1
-getrandom: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+getuid: 1
+getrlimit: 1
+fstat: 1
+newfstatat: 1
+fstatfs: 1
+memfd_create: 1
+ftruncate: 1
# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
# parser support for '<' is in this needs to be modified to also prevent
@@ -36,38 +37,45 @@
# for more details.
mremap: arg3 == 3
munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
+prctl: 1
+writev: 1
sigaltstack: 1
clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
+rt_sigprocmask: 1
+openat: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
getdents64: 1
+readlinkat: 1
+read: 1
+pread64: 1
+gettimeofday: 1
+faccessat: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
getrandom: 1
+madvise: 1
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
+# crash dump policy additions
+clock_gettime: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#mprotect: arg2 in 0x1|0x2
+munmap: 1
+#mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
similarity index 81%
rename from media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
rename to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
index 20c7625..d9c4045 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,14 +16,22 @@
mprotect: 1
prctl: 1
openat: 1
+open: 1
getuid32: 1
+getuid: 1
+getrlimit: 1
writev: 1
ioctl: 1
close: 1
mmap2: 1
+mmap: 1
fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
madvise: 1
fstatat64: 1
+newfstatat: 1
futex: 1
munmap: 1
faccessat: 1
@@ -37,15 +45,22 @@
exit_group: 1
rt_sigreturn: 1
ugetrlimit: 1
+readlink: 1
readlinkat: 1
_llseek: 1
fstatfs64: 1
+fstatfs: 1
pread64: 1
mremap: 1
dup: 1
set_tid_address: 1
write: 1
nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
# Required by AddressSanitizer
gettid: 1
@@ -54,4 +69,3 @@
gettid: 1
@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
similarity index 81%
copy from media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
copy to media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
index 20c7625..d9c4045 100644
--- a/media/codec2/hidl/services/seccomp_policy/codec2.software.base-x86.policy
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.1-default-x86_64.policy
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 The Android Open Source Project
+# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,14 +16,22 @@
mprotect: 1
prctl: 1
openat: 1
+open: 1
getuid32: 1
+getuid: 1
+getrlimit: 1
writev: 1
ioctl: 1
close: 1
mmap2: 1
+mmap: 1
fstat64: 1
+fstat: 1
+stat64: 1
+statfs64: 1
madvise: 1
fstatat64: 1
+newfstatat: 1
futex: 1
munmap: 1
faccessat: 1
@@ -37,15 +45,22 @@
exit_group: 1
rt_sigreturn: 1
ugetrlimit: 1
+readlink: 1
readlinkat: 1
_llseek: 1
fstatfs64: 1
+fstatfs: 1
pread64: 1
mremap: 1
dup: 1
set_tid_address: 1
write: 1
nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+ftruncate64: 1
# Required by AddressSanitizer
gettid: 1
@@ -54,4 +69,3 @@
gettid: 1
@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
deleted file mode 100644
index d5871d1..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-arm.policy
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Organized by frequency of systemcall - in descending order for
-# best performance.
-futex: 1
-ioctl: 1
-write: 1
-prctl: 1
-clock_gettime: 1
-getpriority: 1
-read: 1
-close: 1
-writev: 1
-dup: 1
-ppoll: 1
-mmap2: 1
-getrandom: 1
-
-# mremap: Ensure |flags| are (MREMAP_MAYMOVE | MREMAP_FIXED) TODO: Once minijail
-# parser support for '<' is in this needs to be modified to also prevent
-# |old_address| and |new_address| from touching the exception vector page, which
-# on ARM is statically loaded at 0xffff 0000. See
-# http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211h/Babfeega.html
-# for more details.
-mremap: arg3 == 3
-munmap: 1
-mprotect: 1
-madvise: 1
-openat: 1
-sigaltstack: 1
-clone: 1
-setpriority: 1
-getuid32: 1
-fstat64: 1
-fstatfs64: 1
-pread64: 1
-faccessat: 1
-readlinkat: 1
-exit: 1
-rt_sigprocmask: 1
-set_tid_address: 1
-restart_syscall: 1
-exit_group: 1
-rt_sigreturn: 1
-pipe2: 1
-gettimeofday: 1
-sched_yield: 1
-nanosleep: 1
-lseek: 1
-_llseek: 1
-sched_get_priority_max: 1
-sched_get_priority_min: 1
-statfs64: 1
-sched_setscheduler: 1
-fstatat64: 1
-ugetrlimit: 1
-getdents64: 1
-getrandom: 1
-
-@include /system/etc/seccomp_policy/crash_dump.arm.policy
-
diff --git a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy b/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
deleted file mode 100644
index 20c7625..0000000
--- a/media/codec2/hidl/services/seccomp_policy/codec2.vendor.base-x86.policy
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-read: 1
-mprotect: 1
-prctl: 1
-openat: 1
-getuid32: 1
-writev: 1
-ioctl: 1
-close: 1
-mmap2: 1
-fstat64: 1
-madvise: 1
-fstatat64: 1
-futex: 1
-munmap: 1
-faccessat: 1
-_llseek: 1
-lseek: 1
-clone: 1
-sigaltstack: 1
-setpriority: 1
-restart_syscall: 1
-exit: 1
-exit_group: 1
-rt_sigreturn: 1
-ugetrlimit: 1
-readlinkat: 1
-_llseek: 1
-fstatfs64: 1
-pread64: 1
-mremap: 1
-dup: 1
-set_tid_address: 1
-write: 1
-nanosleep: 1
-
-# Required by AddressSanitizer
-gettid: 1
-sched_yield: 1
-getpid: 1
-gettid: 1
-
-@include /system/etc/seccomp_policy/crash_dump.x86.policy
-
diff --git a/media/codec2/hidl/services/vendor.cpp b/media/codec2/hidl/services/vendor.cpp
index ef2f98e..65bb6f7 100644
--- a/media/codec2/hidl/services/vendor.cpp
+++ b/media/codec2/hidl/services/vendor.cpp
@@ -15,25 +15,27 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "android.hardware.media.c2@1.0-service"
+#define LOG_TAG "android.hardware.media.c2@1.1-service"
-#include <codec2/hidl/1.0/ComponentStore.h>
-#include <hidl/HidlTransportSupport.h>
+#include <android-base/logging.h>
#include <binder/ProcessState.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
+#include <hidl/HidlTransportSupport.h>
#include <minijail.h>
#include <C2Component.h>
-// OmxStore is added for visibility by dumpstate.
-#include <media/stagefright/omx/1.0/OmxStore.h>
-
-// This is created by module "codec2.vendor.base.policy". This can be modified.
+// This is the absolute on-device path of the prebuild_etc module
+// "android.hardware.media.c2@1.1-default-seccomp_policy" in Android.bp.
static constexpr char kBaseSeccompPolicyPath[] =
- "/vendor/etc/seccomp_policy/codec2.vendor.base.policy";
+ "/vendor/etc/seccomp_policy/"
+ "android.hardware.media.c2@1.1-default-seccomp-policy";
-// Additional device-specific seccomp permissions can be added in this file.
+// Additional seccomp permissions can be added in this file.
+// This file does not exist by default.
static constexpr char kExtSeccompPolicyPath[] =
- "/vendor/etc/seccomp_policy/codec2.vendor.ext.policy";
+ "/vendor/etc/seccomp_policy/"
+ "android.hardware.media.c2@1.1-extended-seccomp-policy";
class DummyC2Store : public C2ComponentStore {
public:
@@ -97,54 +99,48 @@
};
int main(int /* argc */, char** /* argv */) {
- ALOGD("android.hardware.media.c2@1.0-service starting...");
+ using namespace ::android;
+ LOG(DEBUG) << "android.hardware.media.c2@1.1-service starting...";
+ // Set up minijail to limit system calls.
signal(SIGPIPE, SIG_IGN);
- android::SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
+ SetUpMinijail(kBaseSeccompPolicyPath, kExtSeccompPolicyPath);
- // vndbinder is needed by BufferQueue.
- android::ProcessState::initWithDriver("/dev/vndbinder");
- android::ProcessState::self()->startThreadPool();
+ // Enable vndbinder to allow vendor-to-vendor binder calls.
+ ProcessState::initWithDriver("/dev/vndbinder");
+ ProcessState::self()->startThreadPool();
// Extra threads may be needed to handle a stacked IPC sequence that
// contains alternating binder and hwbinder calls. (See b/35283480.)
- android::hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
+ hardware::configureRpcThreadpool(8, true /* callerWillJoin */);
// Create IComponentStore service.
{
- using namespace ::android::hardware::media::c2::V1_0;
- android::sp<IComponentStore> store;
+ using namespace ::android::hardware::media::c2::V1_1;
+ sp<IComponentStore> store;
- // Vendor's TODO: Replace this with
+ // TODO: Replace this with
// store = new utils::ComponentStore(
// /* implementation of C2ComponentStore */);
- ALOGD("Instantiating Codec2's dummy IComponentStore service...");
+ LOG(DEBUG) << "Instantiating Codec2's IComponentStore service...";
store = new utils::ComponentStore(
std::make_shared<DummyC2Store>());
if (store == nullptr) {
- ALOGE("Cannot create Codec2's IComponentStore service.");
+ LOG(ERROR) << "Cannot create Codec2's IComponentStore service.";
} else {
- if (store->registerAsService("default") != android::OK) {
- ALOGE("Cannot register Codec2's "
- "IComponentStore service.");
+ constexpr char const* serviceName = "default";
+ if (store->registerAsService(serviceName) != OK) {
+ LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
+ " with instance name << \""
+ << serviceName << "\".";
} else {
- ALOGI("Codec2's IComponentStore service created.");
+ LOG(DEBUG) << "Codec2's IComponentStore service registered. "
+ "Instance name: \"" << serviceName << "\".";
}
}
}
- // Register IOmxStore service.
- {
- using namespace ::android::hardware::media::omx::V1_0;
- android::sp<IOmxStore> omxStore = new implementation::OmxStore();
- if (omxStore == nullptr) {
- ALOGE("Cannot create IOmxStore HAL service.");
- } else if (omxStore->registerAsService() != android::OK) {
- ALOGE("Cannot register IOmxStore HAL service.");
- }
- }
-
- android::hardware::joinRpcThreadpool();
+ hardware::joinRpcThreadpool();
return 0;
}
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index e174751..59ac94b 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -27,6 +27,7 @@
shared_libs: [
"android.hardware.cas.native@1.0",
+ "android.hardware.drm@1.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
"libbase",
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 1cbbbb8..c78cdc1 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -27,6 +27,7 @@
#include <C2PlatformSupport.h>
#include <android/IOMXBufferSource.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android-base/stringprintf.h>
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index d61b751..39f3f35 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -27,10 +27,12 @@
#include <C2Debug.h>
#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
#include <android-base/stringprintf.h>
#include <binder/MemoryDealer.h>
#include <cutils/properties.h>
#include <gui/Surface.h>
+#include <hidlmemory/FrameworkUtils.h>
#include <media/openmax/OMX_Core.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ALookup.h>
@@ -52,10 +54,14 @@
using hardware::hidl_handle;
using hardware::hidl_string;
using hardware::hidl_vec;
+using hardware::fromHeap;
+using hardware::HidlMemory;
+
using namespace hardware::cas::V1_0;
using namespace hardware::cas::native::V1_0;
using CasStatus = hardware::cas::V1_0::Status;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
namespace {
@@ -431,15 +437,16 @@
ssize_t result = -1;
ssize_t codecDataOffset = 0;
if (mCrypto != nullptr) {
- ICrypto::DestinationBuffer destination;
+ hardware::drm::V1_0::DestinationBuffer destination;
if (secure) {
- destination.mType = ICrypto::kDestinationTypeNativeHandle;
- destination.mHandle = encryptedBuffer->handle();
+ destination.type = DrmBufferType::NATIVE_HANDLE;
+ destination.secureMemory = hidl_handle(encryptedBuffer->handle());
} else {
- destination.mType = ICrypto::kDestinationTypeSharedMemory;
- destination.mSharedMemory = mDecryptDestination;
+ destination.type = DrmBufferType::SHARED_MEMORY;
+ IMemoryToSharedBuffer(
+ mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
}
- ICrypto::SourceBuffer source;
+ hardware::drm::V1_0::SharedBuffer source;
encryptedBuffer->fillSourceBuffer(&source);
result = mCrypto->decrypt(
key, iv, mode, pattern, source, buffer->offset(),
@@ -447,7 +454,7 @@
if (result < 0) {
return result;
}
- if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+ if (destination.type == DrmBufferType::SHARED_MEMORY) {
encryptedBuffer->copyDecryptedContent(mDecryptDestination, result);
}
} else {
@@ -919,7 +926,8 @@
mDecryptDestination = mDealer->allocate((size_t)capacity);
}
if (mCrypto != nullptr && mHeapSeqNum < 0) {
- mHeapSeqNum = mCrypto->setHeap(mDealer->getMemoryHeap());
+ sp<HidlMemory> heap = fromHeap(mDealer->getMemoryHeap());
+ mHeapSeqNum = mCrypto->setHeap(heap);
} else {
mHeapSeqNum = -1;
}
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index b339a92..b6d18e2 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -20,6 +20,7 @@
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/CodecBase.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -779,9 +780,8 @@
}
void EncryptedLinearBlockBuffer::fillSourceBuffer(
- ICrypto::SourceBuffer *source) {
- source->mSharedMemory = mMemory;
- source->mHeapSeqNum = mHeapSeqNum;
+ hardware::drm::V1_0::SharedBuffer *source) {
+ BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
}
void EncryptedLinearBlockBuffer::fillSourceBuffer(
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 6f87101..9291c52 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -21,6 +21,7 @@
#include <C2Buffer.h>
#include <android/hardware/cas/native/1.0/types.h>
+#include <android/hardware/drm/1.0/types.h>
#include <binder/IMemory.h>
#include <media/hardware/VideoAPI.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -361,7 +362,8 @@
*
* \param source source buffer structure to fill.
*/
- void fillSourceBuffer(ICrypto::SourceBuffer *source);
+ void fillSourceBuffer(
+ hardware::drm::V1_0::SharedBuffer *source);
void fillSourceBuffer(
hardware::cas::native::V1_0::SharedBuffer *source);
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 4c529a6..e0b3939 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -16,6 +16,7 @@
vendor_available: true,
srcs: [
+ "C2AllocatorBlob.cpp",
"C2AllocatorIon.cpp",
"C2AllocatorGralloc.cpp",
"C2Buffer.cpp",
diff --git a/media/codec2/vndk/C2AllocatorBlob.cpp b/media/codec2/vndk/C2AllocatorBlob.cpp
new file mode 100644
index 0000000..50c9e59
--- /dev/null
+++ b/media/codec2/vndk/C2AllocatorBlob.cpp
@@ -0,0 +1,186 @@
+/*
+ * 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 "C2AllocatorBlob"
+
+#include <C2AllocatorBlob.h>
+#include <C2PlatformSupport.h>
+
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using ::android::hardware::graphics::common::V1_2::PixelFormat;
+
+constexpr uint32_t kLinearBufferHeight = 1u;
+constexpr uint32_t kLinearBufferFormat = static_cast<uint32_t>(PixelFormat::BLOB);
+
+namespace {
+
+c2_status_t GetCapacityFromHandle(const C2Handle* const grallocHandle, size_t* capacity) {
+ uint32_t width, height, format, stride, generation, igbp_slot;
+ uint64_t usage, igbp_id;
+ _UnwrapNativeCodec2GrallocMetadata(grallocHandle, &width, &height, &format, &usage, &stride,
+ &generation, &igbp_id, &igbp_slot);
+
+ if (height != kLinearBufferHeight || format != kLinearBufferFormat) {
+ return C2_BAD_VALUE;
+ }
+ *capacity = width;
+ return C2_OK;
+}
+
+} // namespace
+
+// C2AllocationBlob is a wrapper for C2AllocationGralloc allocated by C2AllocatorGralloc.
+// C2AllocationBlob::handle() delegates to the backed C2AllocationGralloc::handle().
+class C2AllocationBlob : public C2LinearAllocation {
+public:
+ C2AllocationBlob(std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+ C2Allocator::id_t allocatorId);
+ ~C2AllocationBlob() override;
+ c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence* fence,
+ void** addr /* nonnull */) override;
+ c2_status_t unmap(void* addr, size_t size, C2Fence* fenceFd) override;
+
+ id_t getAllocatorId() const override { return mAllocatorId; }
+ const C2Handle* handle() const override { return mGraphicAllocation->handle(); }
+ bool equals(const std::shared_ptr<C2LinearAllocation>& other) const override {
+ return other && other->handle() == handle();
+ }
+
+private:
+ const std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
+ const C2Allocator::id_t mAllocatorId;
+};
+
+C2AllocationBlob::C2AllocationBlob(
+ std::shared_ptr<C2GraphicAllocation> graphicAllocation, size_t capacity,
+ C2Allocator::id_t allocatorId)
+ : C2LinearAllocation(capacity),
+ mGraphicAllocation(std::move(graphicAllocation)),
+ mAllocatorId(allocatorId) {}
+
+C2AllocationBlob::~C2AllocationBlob() {}
+
+c2_status_t C2AllocationBlob::map(size_t offset, size_t size, C2MemoryUsage usage,
+ C2Fence* fence, void** addr /* nonnull */) {
+ C2PlanarLayout layout;
+ C2Rect rect = C2Rect(size, kLinearBufferHeight).at(offset, 0u);
+ return mGraphicAllocation->map(rect, usage, fence, &layout, reinterpret_cast<uint8_t**>(addr));
+}
+
+c2_status_t C2AllocationBlob::unmap(void* addr, size_t size, C2Fence* fenceFd) {
+ C2Rect rect(size, kLinearBufferHeight);
+ return mGraphicAllocation->unmap(reinterpret_cast<uint8_t**>(&addr), rect, fenceFd);
+}
+
+/* ====================================== BLOB ALLOCATOR ====================================== */
+C2AllocatorBlob::C2AllocatorBlob(id_t id) {
+ C2MemoryUsage minUsage = {0, 0};
+ C2MemoryUsage maxUsage = {C2MemoryUsage::CPU_READ | C2MemoryUsage::READ_PROTECTED,
+ C2MemoryUsage::CPU_WRITE};
+ Traits traits = {"android.allocator.blob", id, LINEAR, minUsage, maxUsage};
+ mTraits = std::make_shared<C2Allocator::Traits>(traits);
+ auto allocatorStore = GetCodec2PlatformAllocatorStore();
+ allocatorStore->fetchAllocator(C2PlatformAllocatorStore::GRALLOC, &mC2AllocatorGralloc);
+ if (!mC2AllocatorGralloc) {
+ ALOGE("Failed to obtain C2AllocatorGralloc as backed allocator");
+ }
+}
+
+C2AllocatorBlob::~C2AllocatorBlob() {}
+
+c2_status_t C2AllocatorBlob::newLinearAllocation(
+ uint32_t capacity, C2MemoryUsage usage, std::shared_ptr<C2LinearAllocation>* allocation) {
+ if (allocation == nullptr) {
+ return C2_BAD_VALUE;
+ }
+
+ allocation->reset();
+
+ if (!mC2AllocatorGralloc) {
+ return C2_CORRUPTED;
+ }
+
+ std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+ c2_status_t status = mC2AllocatorGralloc->newGraphicAllocation(
+ capacity, kLinearBufferHeight, kLinearBufferFormat, usage, &graphicAllocation);
+ if (status != C2_OK) {
+ ALOGE("Failed newGraphicAllocation");
+ return status;
+ }
+
+ allocation->reset(new C2AllocationBlob(std::move(graphicAllocation),
+ static_cast<size_t>(capacity), mTraits->id));
+ return C2_OK;
+}
+
+c2_status_t C2AllocatorBlob::priorLinearAllocation(
+ const C2Handle* handle, std::shared_ptr<C2LinearAllocation>* allocation) {
+ if (allocation == nullptr) {
+ return C2_BAD_VALUE;
+ }
+
+ allocation->reset();
+
+ if (!mC2AllocatorGralloc) {
+ return C2_CORRUPTED;
+ }
+
+ std::shared_ptr<C2GraphicAllocation> graphicAllocation;
+ c2_status_t status = mC2AllocatorGralloc->priorGraphicAllocation(handle, &graphicAllocation);
+ if (status != C2_OK) {
+ ALOGE("Failed priorGraphicAllocation");
+ return status;
+ }
+
+ const C2Handle* const grallocHandle = graphicAllocation->handle();
+ size_t capacity = 0;
+ status = GetCapacityFromHandle(grallocHandle, &capacity);
+ if (status != C2_OK) {
+ ALOGE("Failed to extract capacity from Handle");
+ return status;
+ }
+
+ allocation->reset(new C2AllocationBlob(std::move(graphicAllocation), capacity, mTraits->id));
+ return C2_OK;
+}
+
+id_t C2AllocatorBlob::getId() const {
+ return mTraits->id;
+}
+
+C2String C2AllocatorBlob::getName() const {
+ return mTraits->name;
+}
+
+std::shared_ptr<const C2Allocator::Traits> C2AllocatorBlob::getTraits() const {
+ return mTraits;
+}
+
+// static
+bool C2AllocatorBlob::isValid(const C2Handle* const o) {
+ size_t capacity;
+ // Distinguish C2Handle purely allocated by C2AllocatorGralloc, or one allocated through
+ // C2AllocatorBlob, by checking the handle's height is 1, and its format is
+ // PixelFormat::BLOB by GetCapacityFromHandle().
+ return C2AllocatorGralloc::isValid(o) && GetCapacityFromHandle(o, &capacity) == C2_OK;
+}
+
+} // namespace android
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 8fffa5e..78ac355 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -605,14 +605,11 @@
(int32_t)rect.width, (int32_t)rect.height },
// TODO: fence
hidl_handle(),
- [&err, &pointer](const auto &maperr, const auto &mapPointer,
- int32_t bytesPerPixel, int32_t bytesPerStride) {
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
err = maperr2error(maperr);
if (err == C2_OK) {
pointer = mapPointer;
}
- (void)bytesPerPixel;
- (void)bytesPerStride;
}).isOk()) {
ALOGE("failed transaction: lock(RGBA_1010102) (@4.0)");
return C2_CORRUPTED;
@@ -743,14 +740,11 @@
(int32_t)rect.width, (int32_t)rect.height },
// TODO: fence
hidl_handle(),
- [&err, &pointer](const auto &maperr, const auto &mapPointer,
- int32_t bytesPerPixel, int32_t bytesPerStride) {
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
err = maperr2error(maperr);
if (err == C2_OK) {
pointer = mapPointer;
}
- (void)bytesPerPixel;
- (void)bytesPerStride;
}).isOk()) {
ALOGE("failed transaction: lock(RGBA_8888) (@4.0)");
return C2_CORRUPTED;
@@ -816,6 +810,70 @@
break;
}
+ case PixelFormat4::BLOB: {
+ void* pointer = nullptr;
+ if (mMapper2) {
+ if (!mMapper2->lock(const_cast<native_handle_t*>(mBuffer), grallocUsage,
+ {(int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width,
+ (int32_t)rect.height},
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto& maperr, const auto& mapPointer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lock(BLOB)");
+ return C2_CORRUPTED;
+ }
+ } else if (mMapper3) {
+ if (!mMapper3->lock(
+ const_cast<native_handle_t*>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer,
+ int32_t bytesPerPixel, int32_t bytesPerStride) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ (void)bytesPerPixel;
+ (void)bytesPerStride;
+ }).isOk()) {
+ ALOGE("failed transaction: lock(BLOB) (@3.0)");
+ return C2_CORRUPTED;
+ }
+ } else {
+ if (!mMapper4->lock(
+ const_cast<native_handle_t *>(mBuffer),
+ grallocUsage,
+ { (int32_t)rect.left, (int32_t)rect.top,
+ (int32_t)rect.width, (int32_t)rect.height },
+ // TODO: fence
+ hidl_handle(),
+ [&err, &pointer](const auto &maperr, const auto &mapPointer) {
+ err = maperr2error(maperr);
+ if (err == C2_OK) {
+ pointer = mapPointer;
+ }
+ }).isOk()) {
+ ALOGE("failed transaction: lock(BLOB) (@4.0)");
+ return C2_CORRUPTED;
+ }
+ }
+ if (err != C2_OK) {
+ ALOGD("lock failed: %d", err);
+ return err;
+ }
+
+ *addr = static_cast<uint8_t*>(pointer);
+ break;
+ }
+
case PixelFormat4::YCBCR_420_888:
// fall-through
case PixelFormat4::YV12:
@@ -875,27 +933,14 @@
return C2_CORRUPTED;
}
} else {
- if (!mMapper4->lockYCbCr(
- const_cast<native_handle_t *>(mBuffer), grallocUsage,
- { (int32_t)rect.left, (int32_t)rect.top,
- (int32_t)rect.width, (int32_t)rect.height },
- // TODO: fence
- hidl_handle(),
- [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
- err = maperr2error(maperr);
- if (err == C2_OK) {
- ycbcrLayout = YCbCrLayout{
- mapLayout.y,
- mapLayout.cb,
- mapLayout.cr,
- mapLayout.yStride,
- mapLayout.cStride,
- mapLayout.chromaStep};
- }
- }).isOk()) {
- ALOGE("failed transaction: lockYCbCr (@4.0)");
- return C2_CORRUPTED;
- }
+ // No device currently supports IMapper 4.0 so it is safe to just return an error
+ // code here.
+ //
+ // This will be supported by a combination of lock and BufferMetadata getters.
+ // We are going to refactor all the IAllocator/IMapper versioning code into a
+ // shared library. We will then add the IMapper 4.0 lockYCbCr support then.
+ ALOGE("failed transaction: lockYCbCr (@4.0)");
+ return C2_CORRUPTED;
}
if (err != C2_OK) {
ALOGD("lockYCbCr failed: %d", err);
@@ -1232,6 +1277,7 @@
} else {
BufferDescriptorInfo4 info = {
{
+ "C2GrallocAllocation",
width,
height,
1u, // layerCount
diff --git a/media/codec2/vndk/include/C2AllocatorBlob.h b/media/codec2/vndk/include/C2AllocatorBlob.h
new file mode 100644
index 0000000..89ce949
--- /dev/null
+++ b/media/codec2/vndk/include/C2AllocatorBlob.h
@@ -0,0 +1,57 @@
+/*
+ * 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 STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+#define STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
+
+#include <functional>
+
+#include <C2AllocatorGralloc.h>
+#include <C2Buffer.h>
+
+namespace android {
+
+class C2AllocatorBlob : public C2Allocator {
+public:
+ virtual id_t getId() const override;
+
+ virtual C2String getName() const override;
+
+ virtual std::shared_ptr<const Traits> getTraits() const override;
+
+ virtual c2_status_t newLinearAllocation(
+ uint32_t capacity, C2MemoryUsage usage,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ virtual c2_status_t priorLinearAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *allocation) override;
+
+ C2AllocatorBlob(id_t id);
+
+ virtual ~C2AllocatorBlob() override;
+
+ static bool isValid(const C2Handle* const o);
+
+private:
+ std::shared_ptr<const Traits> mTraits;
+ // Design as C2AllocatorGralloc-backed to unify Gralloc implementations.
+ std::shared_ptr<C2Allocator> mC2AllocatorGralloc;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_CODEC2_ALLOCATOR_BLOB_H_
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 81e1b8c..6f85960 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1082,9 +1082,14 @@
const uint8_t *ptr = (const uint8_t *)data;
const uint8_t profile = ptr[2] >> 1;
const uint8_t bl_compatibility_id = (ptr[4]) >> 4;
+ bool create_two_tracks = false;
+
+ if (bl_compatibility_id && bl_compatibility_id != 15) {
+ create_two_tracks = true;
+ }
if (4 == profile || 7 == profile ||
- (profile >= 8 && profile < 11 && bl_compatibility_id)) {
+ (profile >= 8 && profile < 11 && create_two_tracks)) {
// we need a backward compatible track
ALOGV("Adding new backward compatible track");
Track *track_b = new Track;
@@ -2388,6 +2393,9 @@
}
case FOURCC("dvcC"):
case FOURCC("dvvC"): {
+
+ CHECK_EQ(chunk_data_size, 24);
+
auto buffer = heapbuffer<uint8_t>(chunk_data_size);
if (buffer.get() == NULL) {
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index 1d9e1e6..8638cdc 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -12,15 +12,10 @@
],
shared_libs: [
- "android.hardware.cas@1.0",
- "android.hardware.cas.native@1.0",
- "android.hidl.token@1.0-utils",
- "android.hidl.allocator@1.0",
- "libcrypto",
- "libhidlmemory",
- "libhidlbase",
- "liblog",
- "libmediandk",
+ "libcgrouprc#29",
+ "liblog#10000",
+ "libmediandk#29",
+ "libvndksupport#29",
],
header_libs: [
@@ -31,11 +26,24 @@
],
static_libs: [
+ "android.hardware.cas@1.0",
+ "android.hardware.cas.native@1.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "libbase",
+ "libbinderthreadstate",
+ "libcutils",
+ "libhidlbase",
+ "libhidlmemory",
+ "libjsoncpp",
+ "libprocessgroup",
+ "libstagefright_esds",
"libstagefright_foundation_without_imemory",
+ "libstagefright_mpeg2extractor",
"libstagefright_mpeg2support",
"libutils",
- "libstagefright_mpeg2extractor",
- "libstagefright_esds",
],
name: "libmpeg2extractor",
@@ -51,11 +59,16 @@
version_script: "exports.lds",
sanitize: {
- cfi: true,
+ // STOPSHIP: turn on cfi once b/139945549 is resolved.
+ cfi: false,
misc_undefined: [
"unsigned-integer-overflow",
"signed-integer-overflow",
],
},
+ apex_available: [
+ "com.android.media",
+ "test_com.android.media",
+ ],
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index ad79e9c..d1812e6 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -21,6 +21,7 @@
"AudioVolumeGroup.cpp",
],
shared_libs: [
+ "libaudiofoundation",
"libaudioutils",
"libbinder",
"libcutils",
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index 3cdf095..06fc23c 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -22,22 +22,6 @@
namespace android {
//
-// AudioDeviceTypeAddr implementation
-//
-status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
- mType = (audio_devices_t) parcel->readInt32();
- mAddress = parcel->readString8();
- return NO_ERROR;
-}
-
-status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
- parcel->writeInt32((int32_t) mType);
- parcel->writeString8(mAddress);
- return NO_ERROR;
-}
-
-
-//
// AudioMixMatchCriterion implementation
//
AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 02dc516..54184e0 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1392,6 +1392,12 @@
return af->getMicrophones(microphones);
}
+status_t AudioSystem::setAudioHalPids(const std::vector<pid_t>& pids) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) return PERMISSION_DENIED;
+ return af->setAudioHalPids(pids);
+}
+
status_t AudioSystem::getSurroundFormats(unsigned int *numSurroundFormats,
audio_format_t *surroundFormats,
bool *surroundFormatsEnabled,
@@ -1519,6 +1525,13 @@
return aps->setRttEnabled(enabled);
}
+bool AudioSystem::isCallScreenModeSupported()
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return false;
+ return aps->isCallScreenModeSupported();
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 6e9a7cf..04ef3dd 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -90,10 +90,12 @@
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
SET_EFFECT_SUSPENDED,
+ SET_AUDIO_HAL_PIDS
};
#define MAX_ITEMS_PER_LIST 1024
+
class BpAudioFlinger : public BpInterface<IAudioFlinger>
{
public:
@@ -900,6 +902,20 @@
status = reply.readParcelableVector(microphones);
return status;
}
+ virtual status_t setAudioHalPids(const std::vector<pid_t>& pids)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(pids.size());
+ for (auto pid : pids) {
+ data.writeInt32(pid);
+ }
+ status_t status = remote()->transact(SET_AUDIO_HAL_PIDS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -955,7 +971,8 @@
case SET_MODE:
case SET_MIC_MUTE:
case SET_LOW_RAM_DEVICE:
- case SYSTEM_READY: {
+ case SYSTEM_READY:
+ case SET_AUDIO_HAL_PIDS: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1544,6 +1561,31 @@
}
return NO_ERROR;
}
+ case SET_AUDIO_HAL_PIDS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ std::vector<pid_t> pids;
+ int32_t size;
+ status_t status = data.readInt32(&size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (size < 0) {
+ return BAD_VALUE;
+ }
+ if (size > MAX_ITEMS_PER_LIST) {
+ size = MAX_ITEMS_PER_LIST;
+ }
+ for (int32_t i = 0; i < size; i++) {
+ int32_t pid;
+ status = data.readInt32(&pid);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ pids.push_back(pid);
+ }
+ reply->writeInt32(setAudioHalPids(pids));
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 7cc95e5..f27e21a 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -104,7 +104,8 @@
GET_VOLUME_GROUP_FOR_ATTRIBUTES,
SET_ALLOWED_CAPTURE_POLICY,
MOVE_EFFECTS_TO_IO,
- SET_RTT_ENABLED
+ SET_RTT_ENABLED,
+ IS_CALL_SCREEN_MODE_SUPPORTED
};
#define MAX_ITEMS_PER_LIST 1024
@@ -1284,6 +1285,17 @@
}
return static_cast<status_t>(reply.readInt32());
}
+
+ virtual bool isCallScreenModeSupported()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ status_t status = remote()->transact(IS_CALL_SCREEN_MODE_SUPPORTED, data, &reply);
+ if (status != NO_ERROR) {
+ return false;
+ }
+ return reply.readBool();
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1346,7 +1358,8 @@
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
- case SET_RTT_ENABLED: {
+ case SET_RTT_ENABLED:
+ case IS_CALL_SCREEN_MODE_SUPPORTED: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -2237,7 +2250,6 @@
reply->writeBool(isSupported);
return NO_ERROR;
}
-
case SET_UID_DEVICE_AFFINITY: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
const uid_t uid = (uid_t) data.readInt32();
@@ -2369,6 +2381,13 @@
return NO_ERROR;
}
+ case IS_CALL_SCREEN_MODE_SUPPORTED: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ bool isAvailable = isCallScreenModeSupported();
+ reply->writeBool(isAvailable);
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index ef39fd1..0ab1c9d 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -18,9 +18,10 @@
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
+#include <binder/Parcel.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
#include <system/audio_policy.h>
-#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -60,19 +61,6 @@
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
-class AudioDeviceTypeAddr {
-public:
- AudioDeviceTypeAddr() {}
- AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
- mType(type), mAddress(address) {}
-
- status_t readFromParcel(Parcel *parcel);
- status_t writeToParcel(Parcel *parcel) const;
-
- audio_devices_t mType;
- String8 mAddress;
-};
-
class AudioMixMatchCriterion {
public:
AudioMixMatchCriterion() {}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 09e80b2..d7266b4 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -19,6 +19,7 @@
#include <sys/types.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
@@ -396,6 +397,14 @@
static status_t setRttEnabled(bool enabled);
+ static bool isCallScreenModeSupported();
+
+ /**
+ * Send audio HAL server process pids to native audioserver process for use
+ * when generating audio HAL servers tombstones
+ */
+ static status_t setAudioHalPids(const std::vector<pid_t>& pids);
+
// ----------------------------------------------------------------------------
class AudioVolumeGroupCallback : public RefBase
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 0a65857..308e9d3 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -523,6 +523,8 @@
/* List available microphones and their characteristics */
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+
+ virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
};
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 32275cf..14c1d40 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -23,6 +23,7 @@
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/IAudioPolicyServiceClient.h>
@@ -222,6 +223,8 @@
volume_group_t &volumeGroup) = 0;
virtual status_t setRttEnabled(bool enabled) = 0;
+
+ virtual bool isCallScreenModeSupported() = 0;
};
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index edc06d2..93bc4d9 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -19,6 +19,7 @@
srcs: [
"AudioContainers.cpp",
+ "AudioDeviceTypeAddr.cpp",
"AudioGain.cpp",
"AudioPort.cpp",
"AudioProfile.cpp",
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index adc5d40..31257d5 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -42,6 +42,13 @@
return audioDeviceOutAllScoSet;
}
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet() {
+ static const DeviceTypeSet audioDeviceOutAllUsbSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_OUT_ALL_USB_ARRAY),
+ std::end(AUDIO_DEVICE_OUT_ALL_USB_ARRAY));
+ return audioDeviceOutAllUsbSet;
+}
+
const DeviceTypeSet& getAudioDeviceInAllSet() {
static const DeviceTypeSet audioDeviceInAllSet = DeviceTypeSet(
std::begin(AUDIO_DEVICE_IN_ALL_ARRAY),
@@ -49,7 +56,18 @@
return audioDeviceInAllSet;
}
+const DeviceTypeSet& getAudioDeviceInAllUsbSet() {
+ static const DeviceTypeSet audioDeviceInAllUsbSet = DeviceTypeSet(
+ std::begin(AUDIO_DEVICE_IN_ALL_USB_ARRAY),
+ std::end(AUDIO_DEVICE_IN_ALL_USB_ARRAY));
+ return audioDeviceInAllUsbSet;
+}
+
bool deviceTypesToString(const DeviceTypeSet &deviceTypes, std::string &str) {
+ if (deviceTypes.empty()) {
+ str = "Empty device types";
+ return true;
+ }
bool ret = true;
for (auto it = deviceTypes.begin(); it != deviceTypes.end();) {
std::string deviceTypeStr;
@@ -83,4 +101,10 @@
return ret;
}
+std::string toString(const DeviceTypeSet& deviceTypes) {
+ std::string ret;
+ deviceTypesToString(deviceTypes, ret);
+ return ret;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/AudioDeviceTypeAddr.cpp b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
new file mode 100644
index 0000000..d390467
--- /dev/null
+++ b/media/libaudiofoundation/AudioDeviceTypeAddr.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/AudioDeviceTypeAddr.h>
+
+namespace android {
+
+const char* AudioDeviceTypeAddr::getAddress() const {
+ return mAddress.c_str();
+}
+
+bool AudioDeviceTypeAddr::equals(const AudioDeviceTypeAddr& other) const {
+ return mType == other.mType && mAddress == other.mAddress;
+}
+
+void AudioDeviceTypeAddr::reset() {
+ mType = AUDIO_DEVICE_NONE;
+ mAddress = "";
+}
+
+status_t AudioDeviceTypeAddr::readFromParcel(const Parcel *parcel) {
+ status_t status;
+ if ((status = parcel->readUint32(&mType)) != NO_ERROR) return status;
+ status = parcel->readUtf8FromUtf16(&mAddress);
+ return status;
+}
+
+status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
+ status_t status;
+ if ((status = parcel->writeUint32(mType)) != NO_ERROR) return status;
+ status = parcel->writeUtf8AsUtf16(mAddress);
+ return status;
+}
+
+
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs) {
+ DeviceTypeSet deviceTypes;
+ for (const auto& deviceTypeAddr : deviceTypeAddrs) {
+ deviceTypes.insert(deviceTypeAddr.mType);
+ }
+ return deviceTypes;
+}
+
+}
\ No newline at end of file
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index 18fd184..ef7576e 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -25,13 +25,23 @@
namespace android {
DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type) :
- AudioPort("", AUDIO_PORT_TYPE_DEVICE,
- audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
- AUDIO_PORT_ROLE_SOURCE),
- mDeviceType(type)
+ DeviceDescriptorBase(type, "")
{
- if (audio_is_remote_submix_device(type)) {
- mAddress = "0";
+}
+
+DeviceDescriptorBase::DeviceDescriptorBase(audio_devices_t type, const std::string& address) :
+ DeviceDescriptorBase(AudioDeviceTypeAddr(type, address))
+{
+}
+
+DeviceDescriptorBase::DeviceDescriptorBase(const AudioDeviceTypeAddr &deviceTypeAddr) :
+ AudioPort("", AUDIO_PORT_TYPE_DEVICE,
+ audio_is_output_device(deviceTypeAddr.mType) ? AUDIO_PORT_ROLE_SINK :
+ AUDIO_PORT_ROLE_SOURCE),
+ mDeviceTypeAddr(deviceTypeAddr)
+{
+ if (mDeviceTypeAddr.mAddress.empty() && audio_is_remote_submix_device(mDeviceTypeAddr.mType)) {
+ mDeviceTypeAddr.mAddress = "0";
}
}
@@ -55,22 +65,22 @@
AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
- dstConfig->role = audio_is_output_device(mDeviceType) ?
+ dstConfig->role = audio_is_output_device(mDeviceTypeAddr.mType) ?
AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
- dstConfig->ext.device.type = mDeviceType;
+ dstConfig->ext.device.type = mDeviceTypeAddr.mType;
- (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.c_str());
+ (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mDeviceTypeAddr.getAddress());
}
void DeviceDescriptorBase::toAudioPort(struct audio_port *port) const
{
- ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceType);
+ ALOGV("DeviceDescriptorBase::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
AudioPort::toAudioPort(port);
toAudioPortConfig(&port->active_config);
port->id = mId;
- port->ext.device.type = mDeviceType;
- (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.c_str());
+ port->ext.device.type = mDeviceTypeAddr.mType;
+ (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mDeviceTypeAddr.getAddress());
}
void DeviceDescriptorBase::dump(std::string *dst, int spaces, int index,
@@ -86,10 +96,11 @@
}
dst->append(base::StringPrintf("%*s- type: %-48s\n",
- spaces, "", ::android::toString(mDeviceType).c_str()));
+ spaces, "", ::android::toString(mDeviceTypeAddr.mType).c_str()));
- if (mAddress.size() != 0) {
- dst->append(base::StringPrintf("%*s- address: %-32s\n", spaces, "", mAddress.c_str()));
+ if (mDeviceTypeAddr.mAddress.size() != 0) {
+ dst->append(base::StringPrintf(
+ "%*s- address: %-32s\n", spaces, "", mDeviceTypeAddr.getAddress()));
}
AudioPort::dump(dst, spaces, verbose);
}
@@ -97,15 +108,15 @@
std::string DeviceDescriptorBase::toString() const
{
std::stringstream sstream;
- sstream << "type:0x" << std::hex << type() << ",@:" << mAddress;
+ sstream << "type:0x" << std::hex << type() << ",@:" << mDeviceTypeAddr.mAddress;
return sstream.str();
}
void DeviceDescriptorBase::log() const
{
- ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceType,
- ::android::toString(mDeviceType).c_str(),
- mAddress.c_str());
+ ALOGI("Device id:%d type:0x%08X:%s, addr:%s", mId, mDeviceTypeAddr.mType,
+ ::android::toString(mDeviceTypeAddr.mType).c_str(),
+ mDeviceTypeAddr.getAddress());
AudioPort::log(" ");
}
@@ -115,8 +126,7 @@
return other != nullptr &&
static_cast<const AudioPort*>(this)->equals(other) &&
static_cast<const AudioPortConfig*>(this)->equals(other) &&
- mAddress.compare(other->address()) == 0 &&
- mDeviceType == other->type();
+ mDeviceTypeAddr.equals(other->mDeviceTypeAddr);
}
status_t DeviceDescriptorBase::writeToParcel(Parcel *parcel) const
@@ -124,8 +134,7 @@
status_t status = NO_ERROR;
if ((status = AudioPort::writeToParcel(parcel)) != NO_ERROR) return status;
if ((status = AudioPortConfig::writeToParcel(parcel)) != NO_ERROR) return status;
- if ((status = parcel->writeUtf8AsUtf16(mAddress)) != NO_ERROR) return status;
- if ((status = parcel->writeUint32(mDeviceType)) != NO_ERROR) return status;
+ if ((status = parcel->writeParcelable(mDeviceTypeAddr)) != NO_ERROR) return status;
return status;
}
@@ -134,9 +143,29 @@
status_t status = NO_ERROR;
if ((status = AudioPort::readFromParcel(parcel)) != NO_ERROR) return status;
if ((status = AudioPortConfig::readFromParcel(parcel)) != NO_ERROR) return status;
- if ((status = parcel->readUtf8FromUtf16(&mAddress)) != NO_ERROR) return status;
- if ((status = parcel->readUint32(&mDeviceType)) != NO_ERROR) return status;
+ if ((status = parcel->readParcelable(&mDeviceTypeAddr)) != NO_ERROR) return status;
return status;
}
+std::string toString(const DeviceDescriptorBaseVector& devices)
+{
+ std::string ret;
+ for (const auto& device : devices) {
+ if (device != *devices.begin()) {
+ ret += ";";
+ }
+ ret += device->toString();
+ }
+ return ret;
+}
+
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices)
+{
+ AudioDeviceTypeAddrVector deviceTypeAddrs;
+ for (const auto& device : devices) {
+ deviceTypeAddrs.push_back(device->getDeviceTypeAddr());
+ }
+ return deviceTypeAddrs;
+}
+
} // namespace android
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index 05e68fa..72fda49 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -37,7 +37,9 @@
const DeviceTypeSet& getAudioDeviceOutAllSet();
const DeviceTypeSet& getAudioDeviceOutAllA2dpSet();
const DeviceTypeSet& getAudioDeviceOutAllScoSet();
+const DeviceTypeSet& getAudioDeviceOutAllUsbSet();
const DeviceTypeSet& getAudioDeviceInAllSet();
+const DeviceTypeSet& getAudioDeviceInAllUsbSet();
template<typename T>
static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
@@ -123,5 +125,10 @@
std::string dumpDeviceTypes(const DeviceTypeSet& deviceTypes);
+/**
+ * Return human readable string for device types.
+ */
+std::string toString(const DeviceTypeSet& deviceTypes);
+
} // namespace android
\ No newline at end of file
diff --git a/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
new file mode 100644
index 0000000..5e5e762
--- /dev/null
+++ b/media/libaudiofoundation/include/media/AudioDeviceTypeAddr.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <binder/Parcelable.h>
+#include <binder/Parcel.h>
+#include <media/AudioContainers.h>
+#include <system/audio.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct AudioDeviceTypeAddr : public Parcelable {
+ AudioDeviceTypeAddr() = default;
+
+ AudioDeviceTypeAddr(audio_devices_t type, const std::string& address) :
+ mType(type), mAddress(address) {}
+
+ const char* getAddress() const;
+
+ bool equals(const AudioDeviceTypeAddr& other) const;
+
+ void reset();
+
+ status_t readFromParcel(const Parcel *parcel) override;
+
+ status_t writeToParcel(Parcel *parcel) const override;
+
+ audio_devices_t mType = AUDIO_DEVICE_NONE;
+ std::string mAddress;
+};
+
+using AudioDeviceTypeAddrVector = std::vector<AudioDeviceTypeAddr>;
+
+/**
+ * Return a collection of audio device types from a collection of AudioDeviceTypeAddr
+ */
+DeviceTypeSet getAudioDeviceTypes(const AudioDeviceTypeAddrVector& deviceTypeAddrs);
+
+}
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 6a34b4d..4c03667 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -16,9 +16,13 @@
#pragma once
+#include <vector>
+
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
+#include <media/AudioContainers.h>
#include <media/AudioPort.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <utils/Errors.h>
#include <cutils/config_utils.h>
#include <system/audio.h>
@@ -31,12 +35,15 @@
public:
// Note that empty name refers by convention to a generic device.
explicit DeviceDescriptorBase(audio_devices_t type);
+ DeviceDescriptorBase(audio_devices_t type, const std::string& address);
+ explicit DeviceDescriptorBase(const AudioDeviceTypeAddr& deviceTypeAddr);
virtual ~DeviceDescriptorBase() {}
- audio_devices_t type() const { return mDeviceType; }
- std::string address() const { return mAddress; }
- void setAddress(const std::string &address) { mAddress = address; }
+ audio_devices_t type() const { return mDeviceTypeAddr.mType; }
+ std::string address() const { return mDeviceTypeAddr.mAddress; }
+ void setAddress(const std::string &address) { mDeviceTypeAddr.mAddress = address; }
+ const AudioDeviceTypeAddr& getDeviceTypeAddr() const { return mDeviceTypeAddr; }
// AudioPortConfig
virtual sp<AudioPort> getAudioPort() const {
@@ -59,8 +66,20 @@
status_t readFromParcel(const Parcel* parcel) override;
protected:
- std::string mAddress{""};
- audio_devices_t mDeviceType;
+ AudioDeviceTypeAddr mDeviceTypeAddr;
};
+using DeviceDescriptorBaseVector = std::vector<sp<DeviceDescriptorBase>>;
+
+/**
+ * Return human readable string for collection of DeviceDescriptorBase.
+ * For a DeviceDescriptorBase, it contains port id, audio device type and address.
+ */
+std::string toString(const DeviceDescriptorBaseVector& devices);
+
+/**
+ * Return a set of device types and addresses from collection of DeviceDescriptorBase.
+ */
+AudioDeviceTypeAddrVector deviceTypeAddrsFromDescriptors(const DeviceDescriptorBaseVector& devices);
+
} // namespace android
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 8669e2a..e96a68c 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -27,6 +27,7 @@
"android.hardware.audio.common-util",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libaudiofoundation",
"libaudiohal_deathhandler",
"libaudioutils",
"libbase",
diff --git a/media/libaudiohal/impl/ConversionHelperHidl.cpp b/media/libaudiohal/impl/ConversionHelperHidl.cpp
index 9f8a520..f29b0f3 100644
--- a/media/libaudiohal/impl/ConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperHidl.cpp
@@ -17,6 +17,7 @@
#include <string.h>
#define LOG_TAG "HalHidl"
+#include <media/AudioContainers.h>
#include <media/AudioParameter.h>
#include <utils/Log.h>
@@ -109,26 +110,22 @@
char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
memset(halAddress, 0, sizeof(halAddress));
audio_devices_t halDevice = static_cast<audio_devices_t>(address.device);
- const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
- if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
- if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
- (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+ if (getAudioDeviceOutAllA2dpSet().count(halDevice) > 0 ||
+ halDevice == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
address.address.mac[0], address.address.mac[1], address.address.mac[2],
address.address.mac[3], address.address.mac[4], address.address.mac[5]);
- } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
- (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
+ } else if (halDevice == AUDIO_DEVICE_OUT_IP || halDevice == AUDIO_DEVICE_IN_IP) {
snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
- } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
- (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
+ } else if (getAudioDeviceOutAllUsbSet().count(halDevice) > 0 ||
+ getAudioDeviceInAllUsbSet().count(halDevice) > 0) {
snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
address.address.alsa.device);
- } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
- (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+ } else if (halDevice == AUDIO_DEVICE_OUT_BUS || halDevice == AUDIO_DEVICE_IN_BUS) {
snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
- } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
- (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+ } else if (halDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ||
+ halDevice == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
} else {
snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 3d3a5eb..d52416c 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -22,6 +22,7 @@
#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
#include <cutils/native_handle.h>
#include <hwbinder/IPCThreadState.h>
+#include <media/AudioContainers.h>
#include <utils/Log.h>
#include <common/all-versions/VersionUtils.h>
@@ -51,42 +52,32 @@
if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
return OK;
}
- const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
- if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
- if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
- || (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+ if (getAudioDeviceOutAllA2dpSet().count(device) > 0
+ || device == AUDIO_DEVICE_IN_BLUETOOTH_A2DP) {
int status = sscanf(halAddress,
"%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
&address->address.mac[0], &address->address.mac[1], &address->address.mac[2],
&address->address.mac[3], &address->address.mac[4], &address->address.mac[5]);
return status == 6 ? OK : BAD_VALUE;
- } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0)
- || (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+ } else if (device == AUDIO_DEVICE_OUT_IP || device == AUDIO_DEVICE_IN_IP) {
int status = sscanf(halAddress,
"%hhu.%hhu.%hhu.%hhu",
&address->address.ipv4[0], &address->address.ipv4[1],
&address->address.ipv4[2], &address->address.ipv4[3]);
return status == 4 ? OK : BAD_VALUE;
- } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0
- || (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+ } else if (getAudioDeviceOutAllUsbSet().count(device) > 0
+ || getAudioDeviceInAllUsbSet().count(device) > 0) {
int status = sscanf(halAddress,
"card=%d;device=%d",
&address->address.alsa.card, &address->address.alsa.device);
return status == 2 ? OK : BAD_VALUE;
- } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0)
- || (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
- if (halAddress != NULL) {
- address->busAddress = halAddress;
- return OK;
- }
- return BAD_VALUE;
- } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
- || (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
- if (halAddress != NULL) {
- address->rSubmixAddress = halAddress;
- return OK;
- }
- return BAD_VALUE;
+ } else if (device == AUDIO_DEVICE_OUT_BUS || device == AUDIO_DEVICE_IN_BUS) {
+ address->busAddress = halAddress;
+ return OK;
+ } else if (device == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+ || device == AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
+ address->rSubmixAddress = halAddress;
+ return OK;
}
return OK;
}
@@ -100,8 +91,12 @@
DeviceHalHidl::~DeviceHalHidl() {
if (mDevice != 0) {
+#if MAJOR_VERSION <= 5
mDevice.clear();
hardware::IPCThreadState::self()->flushCommands();
+#elif MAJOR_VERSION >= 6
+ mDevice->close();
+#endif
}
}
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 1335a0c..c30da3c 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -20,6 +20,7 @@
#define LOG_TAG "DevicesFactoryHalHidl"
//#define LOG_NDEBUG 0
+#include "android/hidl/manager/1.0/IServiceManager.h"
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include <media/audiohal/hidl/HalDeathHandler.h>
#include <utils/Log.h>
@@ -28,6 +29,8 @@
#include "DeviceHalHidl.h"
#include "DevicesFactoryHalHidl.h"
+#include <set>
+
using ::android::hardware::audio::CPP_VERSION::IDevice;
using ::android::hardware::audio::CPP_VERSION::Result;
using ::android::hardware::Return;
@@ -108,5 +111,29 @@
return BAD_VALUE;
}
+status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
+ std::set<pid_t> pidsSet;
+
+ for (const auto& factory : mDeviceFactories) {
+ using ::android::hidl::base::V1_0::DebugInfo;
+ using android::hidl::manager::V1_0::IServiceManager;
+
+ DebugInfo debugInfo;
+ auto ret = factory->getDebugInfo([&] (const auto &info) {
+ debugInfo = info;
+ });
+ if (!ret.isOk()) {
+ return INVALID_OPERATION;
+ }
+ if (debugInfo.pid == (int)IServiceManager::PidConstant::NO_PID) {
+ continue;
+ }
+ pidsSet.insert(debugInfo.pid);
+ }
+
+ *pids = {pidsSet.begin(), pidsSet.end()};
+ return NO_ERROR;
+}
+
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 8775e7b..52185c8 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -37,6 +37,9 @@
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+
+ status_t getHalPids(std::vector<pid_t> *pids) override;
+
private:
std::vector<sp<IDevicesFactory>> mDeviceFactories;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
index 0e1f1bb..a5aef1b 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
@@ -37,6 +37,14 @@
}
return mLocalFactory->openDevice(name, device);
}
+
+status_t DevicesFactoryHalHybrid::getHalPids(std::vector<pid_t> *pids) {
+ if (mHidlFactory != 0) {
+ return mHidlFactory->getHalPids(pids);
+ }
+ return INVALID_OPERATION;
+}
+
} // namespace CPP_VERSION
template <>
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
index 545bb70..2189b36 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
@@ -36,6 +36,8 @@
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+ status_t getHalPids(std::vector<pid_t> *pids) override;
+
private:
sp<DevicesFactoryHalInterface> mLocalFactory;
sp<DevicesFactoryHalInterface> mHidlFactory;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalLocal.h b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
index 5d108dd..2b011f4 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalLocal.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
@@ -33,6 +33,10 @@
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+ status_t getHalPids(std::vector<pid_t> *pids __unused) override {
+ return INVALID_OPERATION;
+ }
+
private:
friend class DevicesFactoryHalHybrid;
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 14af384..e9ac1ce 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -20,6 +20,7 @@
#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <vector>
namespace android {
@@ -30,6 +31,8 @@
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
+ virtual status_t getHalPids(std::vector<pid_t> *pids) = 0;
+
static sp<DevicesFactoryHalInterface> create();
protected:
diff --git a/media/libdatasource/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
index 7f5ae61..6d63ffb 100644
--- a/media/libdatasource/NuCachedSource2.cpp
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -689,10 +689,6 @@
restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
}
-sp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) {
- return mSource->DrmInitialization(mime);
-}
-
String8 NuCachedSource2::getUri() {
return mSource->getUri();
}
diff --git a/media/libdatasource/include/datasource/NuCachedSource2.h b/media/libdatasource/include/datasource/NuCachedSource2.h
index 596efb8..4c253ad 100644
--- a/media/libdatasource/include/datasource/NuCachedSource2.h
+++ b/media/libdatasource/include/datasource/NuCachedSource2.h
@@ -44,7 +44,6 @@
virtual status_t getSize(off64_t *size);
virtual uint32_t flags();
- virtual sp<DecryptHandle> DrmInitialization(const char* mime);
virtual String8 getUri();
virtual String8 getMIMEType() const;
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 33ea1ca..b80f4b4 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -83,9 +83,6 @@
void close() {}
uint32_t getFlags() override { return 0; }
String8 toString() override { return String8("HeifDataSource"); }
- sp<DecryptHandle> DrmInitialization(const char*) override {
- return nullptr;
- }
private:
enum {
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index ac88448..b064f08 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -34,7 +34,6 @@
"aidl/android/media/MediaResourceParcel.aidl",
"aidl/android/media/MediaResourcePolicyParcel.aidl",
],
- api_dir: "api/resourcemanager",
versions: ["1"],
}
diff --git a/media/libmedia/IDataSource.cpp b/media/libmedia/IDataSource.cpp
index 31c85af..61f0a68 100644
--- a/media/libmedia/IDataSource.cpp
+++ b/media/libmedia/IDataSource.cpp
@@ -23,7 +23,6 @@
#include <binder/IMemory.h>
#include <binder/Parcel.h>
-#include <drm/drm_framework_common.h>
#include <media/stagefright/foundation/ADebug.h>
namespace android {
@@ -35,7 +34,6 @@
CLOSE,
GET_FLAGS,
TO_STRING,
- DRM_INITIALIZATION,
};
struct BpDataSource : public BpInterface<IDataSource> {
@@ -95,47 +93,6 @@
remote()->transact(TO_STRING, data, &reply);
return reply.readString8();
}
-
- virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
- Parcel data, reply;
- data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
- if (mime == NULL) {
- data.writeInt32(0);
- } else {
- data.writeInt32(1);
- data.writeCString(mime);
- }
- remote()->transact(DRM_INITIALIZATION, data, &reply);
- sp<DecryptHandle> handle;
- if (reply.dataAvail() != 0) {
- handle = new DecryptHandle();
- handle->decryptId = reply.readInt32();
- handle->mimeType = reply.readString8();
- handle->decryptApiType = reply.readInt32();
- handle->status = reply.readInt32();
-
- const int bufferLength = data.readInt32();
- if (bufferLength != -1) {
- handle->decryptInfo = new DecryptInfo();
- handle->decryptInfo->decryptBufferLength = bufferLength;
- }
-
- size_t size = data.readInt32();
- for (size_t i = 0; i < size; ++i) {
- DrmCopyControl key = (DrmCopyControl)data.readInt32();
- int value = data.readInt32();
- handle->copyControlVector.add(key, value);
- }
-
- size = data.readInt32();
- for (size_t i = 0; i < size; ++i) {
- String8 key = data.readString8();
- String8 value = data.readString8();
- handle->extendedData.add(key, value);
- }
- }
- return handle;
- }
};
IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
@@ -178,42 +135,6 @@
reply->writeString8(toString());
return NO_ERROR;
} break;
- case DRM_INITIALIZATION: {
- CHECK_INTERFACE(IDataSource, data, reply);
- const char *mime = NULL;
- const int32_t flag = data.readInt32();
- if (flag != 0) {
- mime = data.readCString();
- }
- sp<DecryptHandle> handle = DrmInitialization(mime);
- if (handle != NULL) {
- reply->writeInt32(handle->decryptId);
- reply->writeString8(handle->mimeType);
- reply->writeInt32(handle->decryptApiType);
- reply->writeInt32(handle->status);
-
- if (handle->decryptInfo != NULL) {
- reply->writeInt32(handle->decryptInfo->decryptBufferLength);
- } else {
- reply->writeInt32(-1);
- }
-
- size_t size = handle->copyControlVector.size();
- reply->writeInt32(size);
- for (size_t i = 0; i < size; ++i) {
- reply->writeInt32(handle->copyControlVector.keyAt(i));
- reply->writeInt32(handle->copyControlVector.valueAt(i));
- }
-
- size = handle->extendedData.size();
- reply->writeInt32(size);
- for (size_t i = 0; i < size; ++i) {
- reply->writeString8(handle->extendedData.keyAt(i));
- reply->writeString8(handle->extendedData.valueAt(i));
- }
- }
- return NO_ERROR;
- } break;
default:
return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/libmedia/api/resourcemanager/1/.hash b/media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/.hash
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/.hash
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerClient.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerClient.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/IResourceManagerService.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/IResourceManagerService.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourcePolicyParcel.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourcePolicyParcel.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceSubType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceSubType.aidl
diff --git a/media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl b/media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
similarity index 100%
rename from media/libmedia/api/resourcemanager/1/android/media/MediaResourceType.aidl
rename to media/libmedia/aidl_api/resourcemanager_aidl_interface/1/android/media/MediaResourceType.aidl
diff --git a/media/libmedia/include/media/IDataSource.h b/media/libmedia/include/media/IDataSource.h
index 3858f78..43e2b50 100644
--- a/media/libmedia/include/media/IDataSource.h
+++ b/media/libmedia/include/media/IDataSource.h
@@ -50,8 +50,6 @@
virtual uint32_t getFlags() = 0;
// get a description of the source, e.g. the url or filename it is based on
virtual String8 toString() = 0;
- // Initialize DRM and return a DecryptHandle.
- virtual sp<DecryptHandle> DrmInitialization(const char *mime) = 0;
private:
DISALLOW_EVIL_CONSTRUCTORS(IDataSource);
diff --git a/media/libmedia/include/media/PluginMetricsReporting.h b/media/libmedia/include/media/PluginMetricsReporting.h
index e00bd43..f71c52d 100644
--- a/media/libmedia/include/media/PluginMetricsReporting.h
+++ b/media/libmedia/include/media/PluginMetricsReporting.h
@@ -18,6 +18,7 @@
#define PLUGIN_METRICS_REPORTING_H_
+#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -26,7 +27,7 @@
status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
const String8& vendorName,
const String8& description,
- const String8& appPackageName);
+ uid_t appUid);
} // namespace android
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
index 5be78d1..817aadf 100644
--- a/media/libmediahelper/TypeConverter.cpp
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -325,6 +325,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_MODE_RINGTONE),
MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_CALL),
MAKE_STRING_FROM_ENUM(AUDIO_MODE_IN_COMMUNICATION),
+ MAKE_STRING_FROM_ENUM(AUDIO_MODE_CALL_SCREEN),
TERMINATOR
};
diff --git a/media/libmediametrics/TEST_MAPPING b/media/libmediametrics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/media/libmediametrics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "mediametrics_tests"
+ },
+ {
+ "name": "CtsNativeMediaMetricsTestCases"
+ }
+ ]
+}
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 5301f5c..762ed19 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -39,6 +39,7 @@
"libpowermanager",
"libstagefright",
"libstagefright_foundation",
+ "libstagefright_framecapture_utils",
"libstagefright_httplive",
"libutils",
],
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 81ffcbc..f2a38dd 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -58,6 +58,7 @@
#include <media/Metadata.h>
#include <media/AudioTrack.h>
#include <media/MemoryLeakTrackUtil.h>
+#include <media/stagefright/FrameCaptureProcessor.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/MediaCodecList.h>
@@ -447,6 +448,8 @@
mNextConnId = 1;
MediaPlayerFactory::registerBuiltinFactories();
+ // initialize the frame capture utilities
+ (void)FrameCaptureProcessor::getInstance();
}
MediaPlayerService::~MediaPlayerService()
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
index 1580891..bb4ba75 100644
--- a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -31,6 +31,7 @@
mDrmBufOffset(0),
mDrmBufSize(0),
mDrmBuf(NULL){
+ (void) DrmInitialization(nullptr);
}
PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
@@ -40,6 +41,7 @@
mDrmBufOffset(0),
mDrmBufSize(0),
mDrmBuf(NULL) {
+ (void) DrmInitialization(nullptr);
}
PlayerServiceFileSource::~PlayerServiceFileSource() {
@@ -87,7 +89,9 @@
}
sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
- if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
+ if (getuid() == AID_MEDIA_EX) {
+ return NULL; // no DRM in media extractor
+ }
if (mDrmManagerClient == NULL) {
mDrmManagerClient = new DrmManagerClient();
}
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
index 0124720..f99a861 100644
--- a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
+++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
@@ -32,6 +32,7 @@
PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
: MediaHTTP(conn),
mDrmManagerClient(NULL) {
+ (void) DrmInitialization(nullptr);
}
PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
@@ -40,7 +41,7 @@
// DRM...
-sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char* mime) {
+sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char *mime) {
if (mDrmManagerClient == NULL) {
mDrmManagerClient = new DrmManagerClient();
}
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
index 08a013e..7ae8dda 100644
--- a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
@@ -37,8 +37,6 @@
virtual ssize_t readAt(off64_t offset, void *data, size_t size);
- virtual sp<DecryptHandle> DrmInitialization(const char *mime);
-
static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
protected:
@@ -52,6 +50,7 @@
ssize_t mDrmBufSize;
unsigned char *mDrmBuf;
+ sp<DecryptHandle> DrmInitialization(const char *mime);
ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
PlayerServiceFileSource(const PlayerServiceFileSource &);
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
index 0032cd7..b5124dc 100644
--- a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
@@ -33,12 +33,11 @@
protected:
virtual ~PlayerServiceMediaHTTP();
- virtual sp<DecryptHandle> DrmInitialization(const char* mime);
-
private:
sp<DecryptHandle> mDecryptHandle;
DrmManagerClient *mDrmManagerClient;
+ sp<DecryptHandle> DrmInitialization(const char *mime);
void clearDRMState_l();
DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 2d0c9e0..6788b56 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -19,8 +19,7 @@
#include "NuPlayerDrm.h"
-#include <binder/IServiceManager.h>
-#include <mediadrm/IMediaDrmService.h>
+#include <mediadrm/DrmUtils.h>
#include <utils/Log.h>
@@ -30,60 +29,13 @@
sp<IDrm> NuPlayerDrm::CreateDrm(status_t *pstatus)
{
- status_t &status = *pstatus;
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- ALOGV("CreateDrm binder %p", (binder != NULL ? binder.get() : 0));
-
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- ALOGE("CreateDrm failed at IMediaDrmService");
- return NULL;
- }
-
- sp<IDrm> drm = service->makeDrm();
- if (drm == NULL) {
- ALOGE("CreateDrm failed at makeDrm");
- return NULL;
- }
-
- // this is before plugin creation so NO_INIT is fine
- status = drm->initCheck();
- if (status != OK && status != NO_INIT) {
- ALOGE("CreateDrm failed drm->initCheck(): %d", status);
- return NULL;
- }
- return drm;
+ return DrmUtils::MakeDrm(pstatus);
}
sp<ICrypto> NuPlayerDrm::createCrypto(status_t *pstatus)
{
- status_t &status = *pstatus;
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- status = UNKNOWN_ERROR;
- ALOGE("CreateCrypto failed at IMediaDrmService");
- return NULL;
- }
-
- sp<ICrypto> crypto = service->makeCrypto();
- if (crypto == NULL) {
- status = UNKNOWN_ERROR;
- ALOGE("createCrypto failed");
- return NULL;
- }
-
- // this is before plugin creation so NO_INIT is fine
- status = crypto->initCheck();
- if (status != OK && status != NO_INIT) {
- ALOGE("createCrypto failed crypto->initCheck(): %d", status);
- return NULL;
- }
-
- return crypto;
+ return DrmUtils::MakeCrypto(pstatus);
}
Vector<DrmUUID> NuPlayerDrm::parsePSSH(const void *pssh, size_t psshsize)
diff --git a/media/libmediaplayerservice/tests/Android.bp b/media/libmediaplayerservice/tests/Android.bp
index 8357925..e845c33 100644
--- a/media/libmediaplayerservice/tests/Android.bp
+++ b/media/libmediaplayerservice/tests/Android.bp
@@ -7,6 +7,7 @@
shared_libs: [
"liblog",
"libbinder",
+ "libbinder_ndk",
"libmedia",
"libmediaplayerservice",
"libmediadrm",
@@ -17,6 +18,10 @@
"android.hardware.drm@1.2",
],
+ static_libs: [
+ "resourcemanager_aidl_interface-ndk_platform",
+ ],
+
include_dirs: [
"frameworks/av/include",
"frameworks/av/services/mediaresourcemanager",
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index 262fe32..9a8ed8d 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -16,19 +16,21 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmSessionManager_test"
+#include <android/binder_auto_utils.h>
#include <utils/Log.h>
#include <gtest/gtest.h>
+#include <aidl/android/media/BnResourceManagerClient.h>
+#include <aidl/android/media/BnResourceManagerService.h>
#include <android/media/BnResourceManagerClient.h>
-#include <android/media/IResourceManagerService.h>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/ProcessInfoInterface.h>
-#include <mediadrm/DrmHal.h>
-#include <mediadrm/DrmSessionClientInterface.h>
#include <mediadrm/DrmSessionManager.h>
#include <algorithm>
+#include <iostream>
#include <vector>
#include "ResourceManagerService.h"
@@ -36,8 +38,109 @@
namespace android {
using ::android::binder::Status;
-using ::android::media::BnResourceManagerClient;
using ::android::media::ResourceManagerService;
+using ::ndk::ScopedAStatus;
+
+using NdkBnResourceManagerClient = ::aidl::android::media::BnResourceManagerClient;
+using NdkBnResourceManagerService = ::aidl::android::media::BnResourceManagerService;
+using NdkMediaResource = ::aidl::android::media::MediaResourceParcel;
+using NdkResourceManagerClient = ::aidl::android::media::IResourceManagerClient;
+
+using FwkBnResourceManagerClient = ::android::media::BnResourceManagerClient;
+using FwkMediaResource = ::android::media::MediaResourceParcel;
+
+namespace {
+
+struct FwkResourceManagerClientImpl : public FwkBnResourceManagerClient {
+ FwkResourceManagerClientImpl(const std::shared_ptr<NdkResourceManagerClient> &client)
+ : mClient(client) {
+ }
+
+ Status reclaimResource(bool* _aidl_return) override {
+ mClient->reclaimResource(_aidl_return);
+ return Status::ok();
+ }
+
+ Status getName(std::string* _aidl_return) override {
+ mClient->getName(_aidl_return);
+ return Status::ok();
+ }
+
+private:
+ std::shared_ptr<NdkResourceManagerClient> mClient;
+};
+
+FwkMediaResource NdkToFwkMediaResource(const NdkMediaResource &in) {
+ FwkMediaResource out{};
+ out.type = static_cast<decltype(out.type)>(in.type);
+ out.subType = static_cast<decltype(out.subType)>(in.subType);
+ auto v(reinterpret_cast<const uint8_t *>(in.id.data()));
+ out.id.assign(v, v + in.id.size());
+ out.value = in.value;
+ return out;
+}
+
+std::vector<FwkMediaResource> NdkToFwkMediaResourceVec(const std::vector<NdkMediaResource> &in) {
+ std::vector<FwkMediaResource> out;
+ for (auto e : in) {
+ out.push_back(NdkToFwkMediaResource(e));
+ }
+ return out;
+}
+
+ScopedAStatus FwkToNdkStatus(Status err) {
+ return ScopedAStatus(AStatus_fromExceptionCode(err.serviceSpecificErrorCode()));
+}
+
+struct NdkResourceManagerServiceImpl : public NdkBnResourceManagerService {
+ using NdkMediaResourcePolicy = ::aidl::android::media::MediaResourcePolicyParcel;
+
+ NdkResourceManagerServiceImpl(const sp<ResourceManagerService> &service)
+ : mService(service) {}
+
+ ScopedAStatus config(const std::vector<NdkMediaResourcePolicy>& in_policies) override {
+ (void)in_policies;
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus addResource(int32_t in_pid, int32_t in_uid, int64_t in_clientId,
+ const std::shared_ptr<NdkResourceManagerClient>& in_client,
+ const std::vector<NdkMediaResource>& in_resources) override {
+ sp<FwkBnResourceManagerClient> client(new FwkResourceManagerClientImpl(in_client));
+ std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+ auto err = mService->addResource(in_pid, in_uid, in_clientId, client, resources);
+ return FwkToNdkStatus(err);
+ }
+
+ ScopedAStatus removeResource(int32_t in_pid, int64_t in_clientId,
+ const std::vector<NdkMediaResource>& in_resources) override {
+ std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+ auto err = mService->removeResource(in_pid, in_clientId, resources);
+ return FwkToNdkStatus(err);
+ }
+
+ ScopedAStatus removeClient(int32_t in_pid, int64_t in_clientId) override{
+ auto err = mService->removeClient(in_pid, in_clientId);
+ return FwkToNdkStatus(err);
+ }
+
+ ScopedAStatus reclaimResource(int32_t in_callingPid,
+ const std::vector<NdkMediaResource>& in_resources, bool* _aidl_return) override {
+ std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
+ auto err = mService->reclaimResource(in_callingPid, resources, _aidl_return);
+ return FwkToNdkStatus(err);
+ }
+
+private:
+ sp<ResourceManagerService> mService;
+};
+
+template <typename Impl>
+std::shared_ptr<NdkResourceManagerClient> NdkImplToIface(const Impl &impl) {
+ return std::static_pointer_cast<NdkResourceManagerClient>(impl);
+}
+
+}
static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
Vector<uint8_t> aVec;
@@ -66,29 +169,27 @@
DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
};
-struct FakeDrm : public BnResourceManagerClient {
+struct FakeDrm : public NdkBnResourceManagerClient {
FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
: mSessionId(toAndroidVector(sessionId)),
mReclaimed(false),
mDrmSessionManager(manager) {}
- virtual ~FakeDrm() {}
-
- Status reclaimResource(bool* _aidl_return) {
+ ScopedAStatus reclaimResource(bool* _aidl_return) {
mReclaimed = true;
mDrmSessionManager->removeSession(mSessionId);
*_aidl_return = true;
- return Status::ok();
+ return ScopedAStatus::ok();
}
- Status getName(::std::string* _aidl_return) {
+ ScopedAStatus getName(::std::string* _aidl_return) {
String8 name("FakeDrm[");
for (size_t i = 0; i < mSessionId.size(); ++i) {
name.appendFormat("%02x", mSessionId[i]);
}
name.append("]");
*_aidl_return = name;
- return Status::ok();
+ return ScopedAStatus::ok();
}
bool isReclaimed() const {
@@ -137,27 +238,24 @@
public:
DrmSessionManagerTest()
: mService(new ResourceManagerService(new FakeProcessInfo(), new FakeSystemCallback())),
- mDrmSessionManager(new DrmSessionManager(mService)),
+ mDrmSessionManager(new DrmSessionManager(std::shared_ptr<NdkBnResourceManagerService>(new NdkResourceManagerServiceImpl(mService)))),
mTestDrm1(new FakeDrm(kTestSessionId1, mDrmSessionManager)),
mTestDrm2(new FakeDrm(kTestSessionId2, mDrmSessionManager)),
mTestDrm3(new FakeDrm(kTestSessionId3, mDrmSessionManager)) {
- DrmSessionManager *ptr = new DrmSessionManager(mService);
- EXPECT_NE(ptr, nullptr);
- /* mDrmSessionManager = ptr; */
}
protected:
void addSession() {
- mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+ mDrmSessionManager->addSession(kTestPid1, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
}
- sp<IResourceManagerService> mService;
+ sp<ResourceManagerService> mService;
sp<DrmSessionManager> mDrmSessionManager;
- sp<FakeDrm> mTestDrm1;
- sp<FakeDrm> mTestDrm2;
- sp<FakeDrm> mTestDrm3;
+ std::shared_ptr<FakeDrm> mTestDrm1;
+ std::shared_ptr<FakeDrm> mTestDrm2;
+ std::shared_ptr<FakeDrm> mTestDrm3;
};
TEST_F(DrmSessionManagerTest, addSession) {
@@ -204,8 +302,8 @@
// add a session from a higher priority process.
const std::vector<uint8_t> sid{1, 3, 5};
- sp<FakeDrm> drm = new FakeDrm(sid, mDrmSessionManager);
- mDrmSessionManager->addSession(15, drm, drm->mSessionId);
+ std::shared_ptr<FakeDrm> drm(new FakeDrm(sid, mDrmSessionManager));
+ mDrmSessionManager->addSession(15, NdkImplToIface(drm), drm->mSessionId);
// make sure mTestDrm2 is reclaimed next instead of mTestDrm3
mDrmSessionManager->useSession(mTestDrm3->mSessionId);
@@ -225,9 +323,9 @@
EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
// add sessions from same pid
- mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
- mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
+ mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
// use some but not all sessions
mDrmSessionManager->useSession(mTestDrm1->mSessionId);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 965e5a6..ef9d253 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2436,7 +2436,7 @@
}
rate = (OMX_U32)(rateFloat * 65536.0f + 0.5f);
} else {
- if (rateFloat > UINT_MAX) {
+ if (rateFloat > (float)UINT_MAX) {
return BAD_VALUE;
}
rate = (OMX_U32)(rateFloat);
@@ -3342,6 +3342,7 @@
{ MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
{ MEDIA_MIMETYPE_VIDEO_DOLBY_VISION, OMX_VIDEO_CodingDolbyVision },
{ MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC, OMX_VIDEO_CodingImageHEIC },
+ { MEDIA_MIMETYPE_VIDEO_AV1, OMX_VIDEO_CodingAV1 },
};
static status_t GetVideoCodingTypeFromMime(
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index dd6f7b4..aa4c22a 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -21,6 +21,7 @@
#include <numeric>
#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
#include <binder/MemoryDealer.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/openmax/OMX_Core.h>
@@ -41,6 +42,7 @@
using hardware::hidl_vec;
using namespace hardware::cas::V1_0;
using namespace hardware::cas::native::V1_0;
+using DrmBufferType = hardware::drm::V1_0::BufferType;
using BufferInfo = ACodecBufferChannel::BufferInfo;
using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
@@ -131,18 +133,18 @@
ssize_t result = -1;
ssize_t codecDataOffset = 0;
if (mCrypto != NULL) {
- ICrypto::DestinationBuffer destination;
+ hardware::drm::V1_0::DestinationBuffer destination;
if (secure) {
- destination.mType = ICrypto::kDestinationTypeNativeHandle;
- destination.mHandle = secureHandle;
+ destination.type = DrmBufferType::NATIVE_HANDLE;
+ destination.secureMemory = hidl_handle(secureHandle);
} else {
- destination.mType = ICrypto::kDestinationTypeSharedMemory;
- destination.mSharedMemory = mDecryptDestination;
+ destination.type = DrmBufferType::SHARED_MEMORY;
+ IMemoryToSharedBuffer(
+ mDecryptDestination, mHeapSeqNum, &destination.nonsecureMemory);
}
- ICrypto::SourceBuffer source;
- source.mSharedMemory = it->mSharedEncryptedBuffer;
- source.mHeapSeqNum = mHeapSeqNum;
+ hardware::drm::V1_0::SharedBuffer source;
+ IMemoryToSharedBuffer(it->mSharedEncryptedBuffer, mHeapSeqNum, &source);
result = mCrypto->decrypt(key, iv, mode, pattern,
source, it->mClientBuffer->offset(),
@@ -152,9 +154,8 @@
return result;
}
- if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
- memcpy(it->mCodecBuffer->base(),
- destination.mSharedMemory->unsecurePointer(), result);
+ if (destination.type == DrmBufferType::SHARED_MEMORY) {
+ memcpy(it->mCodecBuffer->base(), mDecryptDestination->unsecurePointer(), result);
}
} else {
// Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
@@ -315,7 +316,8 @@
}
dealer = new MemoryDealer(heapSize, "ACodecBufferChannel");
if (mCrypto != nullptr) {
- int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
+ sp<HidlMemory> hHeap = fromHeap(dealer->getMemoryHeap());
+ int32_t seqNum = mCrypto->setHeap(hHeap);
if (seqNum >= 0) {
mHeapSeqNum = seqNum;
ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index a48faca..76eadf7 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -66,12 +66,14 @@
shared_libs: [
"libgui",
+ "libhidlallocatorutils",
"liblog",
"libmedia_codeclist",
"libstagefright_foundation",
"libui",
"libutils",
"android.hardware.cas.native@1.0",
+ "android.hardware.drm@1.0",
],
sanitize: {
@@ -250,6 +252,7 @@
"libhidlmemory",
"android.hidl.allocator@1.0",
"android.hardware.cas.native@1.0",
+ "android.hardware.drm@1.0",
"android.hardware.media.omx@1.0",
],
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 2f8e6af..dea83d4 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -114,10 +114,6 @@
}
}
-sp<DecryptHandle> CallbackDataSource::DrmInitialization(const char *mime) {
- return mIDataSource->DrmInitialization(mime);
-}
-
sp<IDataSource> CallbackDataSource::getIDataSource() const {
return mIDataSource;
}
@@ -191,14 +187,6 @@
return mSource->flags();
}
-sp<DecryptHandle> TinyCacheSource::DrmInitialization(const char *mime) {
- // flush cache when DrmInitialization occurs since decrypted
- // data may differ from what is in cache.
- mCachedOffset = 0;
- mCachedSize = 0;
- return mSource->DrmInitialization(mime);
-}
-
sp<IDataSource> TinyCacheSource::getIDataSource() const {
return mSource->getIDataSource();
}
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
index 97f38f8..5765883 100644
--- a/media/libstagefright/CodecBase.cpp
+++ b/media/libstagefright/CodecBase.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "CodecBase"
#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <android/hardware/drm/1.0/types.h>
+#include <hidlmemory/FrameworkUtils.h>
#include <mediadrm/ICrypto.h>
#include <media/stagefright/CodecBase.h>
#include <utils/Log.h>
@@ -32,4 +34,18 @@
mDescrambler = descrambler;
}
+void BufferChannelBase::IMemoryToSharedBuffer(
+ const sp<IMemory> &memory,
+ int32_t heapSeqNum,
+ hardware::drm::V1_0::SharedBuffer *buf) {
+ ssize_t offset;
+ size_t size;
+
+ sp<hardware::HidlMemory> hidlMemory;
+ hidlMemory = hardware::fromHeap(memory->getMemory(&offset, &size));
+ buf->bufferId = static_cast<uint32_t>(heapSeqNum);
+ buf->offset = offset >= 0 ? offset : 0;
+ buf->size = size;
+}
+
} // namespace android
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 4f9bc6d..24608a7 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -281,7 +281,7 @@
it = mTimers.erase(it);
} else {
if (mPlaybackRate != 0.0
- && (double)diffMediaUs < INT64_MAX * (double)mPlaybackRate) {
+ && (double)diffMediaUs < (double)INT64_MAX * (double)mPlaybackRate) {
int64_t targetRealUs = diffMediaUs / (double)mPlaybackRate;
if (targetRealUs < nextLapseRealUs) {
nextLapseRealUs = targetRealUs;
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 4c8be1f..120f354 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -71,9 +71,6 @@
ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
- // initialize source decryption if needed
- source->DrmInitialization(nullptr /* mime */);
-
void *meta = nullptr;
void *creator = NULL;
FreeMetaFunc freeMeta = nullptr;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index ac4d087..a1e4d43 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -751,6 +751,7 @@
{ "temporal-layer-id", kKeyTemporalLayerId },
{ "thumbnail-width", kKeyThumbnailWidth },
{ "thumbnail-height", kKeyThumbnailHeight },
+ { "track-id", kKeyTrackID },
{ "valid-samples", kKeyValidSamples },
}
};
@@ -958,12 +959,6 @@
msg->setInt32("is-sync-frame", 1);
}
- // this only needs to be translated from meta to message as it is an extractor key
- int32_t trackID;
- if (meta->findInt32(kKeyTrackID, &trackID)) {
- msg->setInt32("track-id", trackID);
- }
-
const char *lang;
if (meta->findCString(kKeyMediaLanguage, &lang)) {
msg->setString("language", lang);
@@ -1874,7 +1869,7 @@
if (msg->findInt32("frame-rate", &fps) && fps > 0) {
meta->setInt32(kKeyFrameRate, fps);
} else if (msg->findFloat("frame-rate", &fpsFloat)
- && fpsFloat >= 1 && fpsFloat <= INT32_MAX) {
+ && fpsFloat >= 1 && fpsFloat <= (float)INT32_MAX) {
// truncate values to distinguish between e.g. 24 vs 23.976 fps
meta->setInt32(kKeyFrameRate, (int32_t)fpsFloat);
}
@@ -1909,25 +1904,24 @@
meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_VIDEO_DOLBY_VISION) {
if (msg->findBuffer("csd-2", &csd2)) {
- meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
-
- size_t dvcc_size = 1024;
- uint8_t dvcc[dvcc_size];
- memcpy(dvcc, csd2->data(), dvcc_size);
- const uint8_t profile = dvcc[2] >> 1;
-
- if (profile > 1 && profile < 9) {
- std::vector<uint8_t> hvcc(csd0size + 1024);
- size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
- meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
- } else if (DolbyVisionProfileDvav110 == profile) {
- meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
- } else {
- sp<ABuffer> csd1;
- if (msg->findBuffer("csd-1", &csd1)) {
- std::vector<char> avcc(csd0size + csd1->size() + 1024);
- size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
- meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ //dvcc should be 24
+ if (csd2->size() == 24) {
+ meta->setData(kKeyDVCC, kTypeDVCC, csd2->data(), csd2->size());
+ uint8_t *dvcc = csd2->data();
+ const uint8_t profile = dvcc[2] >> 1;
+ if (profile > 1 && profile < 9) {
+ std::vector<uint8_t> hvcc(csd0size + 1024);
+ size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
+ meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
+ } else if (DolbyVisionProfileDvav110 == profile) {
+ meta->setData(kKeyAV1C, 0, csd0->data(), csd0->size());
+ } else {
+ sp<ABuffer> csd1;
+ if (msg->findBuffer("csd-1", &csd1)) {
+ std::vector<char> avcc(csd0size + csd1->size() + 1024);
+ size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
+ }
}
}
} else {
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
index adb0dd4..f9d91b1 100644
--- a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
@@ -44,7 +44,7 @@
#endif
#include "pvmp3_audio_type_defs.h"
-#define Qfmt_31(a) (Int32)((float)(a)*0x7FFFFFFF)
+#define Qfmt_31(a) (Int32)((float)(a)*(float)0x7FFFFFFF)
#define Qfmt15(x) (Int16)((x)*((Int32)1<<15) + ((x)>=0?0.5F:-0.5F))
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
index af738ba..6c8102b 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
@@ -169,7 +169,7 @@
int32 i, j;
- *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)(0x7FFFFFFF / (float)18 - 1.0f)) >> 15;
+ *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)((float)0x7FFFFFFF / (float)18 - 1.0f)) >> 15;
if (gr_info->window_switching_flag && gr_info->block_type == 2)
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
index bbb247d..9cd0e91 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
@@ -77,7 +77,7 @@
; Include all pre-processor statements here. Include conditional
; compile variables also.
----------------------------------------------------------------------------*/
-#define Qfmt31(a) (int32)((a)*(0x7FFFFFFF))
+#define Qfmt31(a) (int32)((a)*((float)0x7FFFFFFF))
#define cos_pi_9 Qfmt31( 0.93969262078591f)
#define cos_2pi_9 Qfmt31( 0.76604444311898f)
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/libstagefright/foundation/TEST_MAPPING
new file mode 100644
index 0000000..3301c4b
--- /dev/null
+++ b/media/libstagefright/foundation/TEST_MAPPING
@@ -0,0 +1,5 @@
+{
+ "presubmit": [
+ { "name": "sf_foundation_test" }
+ ]
+}
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/libstagefright/foundation/tests/Android.bp
new file mode 100644
index 0000000..f2157c9
--- /dev/null
+++ b/media/libstagefright/foundation/tests/Android.bp
@@ -0,0 +1,27 @@
+cc_test {
+ name: "sf_foundation_test",
+ test_suites: ["device-tests"],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ include_dirs: [
+ "frameworks/av/include",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libstagefright_foundation",
+ "libutils",
+ ],
+
+ srcs: [
+ "AData_test.cpp",
+ "Base64_test.cpp",
+ "Flagged_test.cpp",
+ "TypeTraits_test.cpp",
+ "Utils_test.cpp",
+ ],
+}
diff --git a/media/libstagefright/foundation/tests/Android.mk b/media/libstagefright/foundation/tests/Android.mk
deleted file mode 100644
index a9e3c76..0000000
--- a/media/libstagefright/foundation/tests/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := sf_foundation_test
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
- AData_test.cpp \
- Base64_test.cpp \
- Flagged_test.cpp \
- TypeTraits_test.cpp \
- Utils_test.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- liblog \
- libstagefright_foundation \
- libutils \
-
-LOCAL_C_INCLUDES := \
- frameworks/av/include \
-
-LOCAL_CFLAGS += -Werror -Wall
-LOCAL_CLANG := true
-
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..e428494 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -41,7 +41,6 @@
virtual String8 toString() {
return mName;
}
- virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
virtual sp<IDataSource> getIDataSource() const;
private:
@@ -70,7 +69,6 @@
virtual String8 toString() {
return mName;
}
- virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
virtual sp<IDataSource> getIDataSource() const;
private:
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
index 71e62f7..5ae0653 100644
--- a/media/libstagefright/include/ThrottledSource.h
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -54,10 +54,6 @@
return mSource->reconnectAtOffset(offset);
}
- virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL) {
- return mSource->DrmInitialization(mime);
- }
-
virtual String8 getMIMEType() const {
return mSource->getMIMEType();
}
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index ad60f46..e728c00 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -42,12 +42,20 @@
struct RenderedFrameInfo;
class Surface;
struct ICrypto;
+class IMemory;
+
namespace hardware {
namespace cas {
namespace native {
namespace V1_0 {
struct IDescrambler;
-}}}}
+}}}
+namespace drm {
+namespace V1_0 {
+struct SharedBuffer;
+}}
+}
+
using hardware::cas::native::V1_0::IDescrambler;
struct CodecBase : public AHandler, /* static */ ColorUtils {
@@ -314,6 +322,18 @@
*/
virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) = 0;
+ /**
+ * Convert binder IMemory to drm SharedBuffer
+ *
+ * \param memory IMemory object to store encrypted content.
+ * \param heapSeqNum Heap sequence number from ICrypto; -1 if N/A
+ * \param buf SharedBuffer structure to fill.
+ */
+ static void IMemoryToSharedBuffer(
+ const sp<IMemory> &memory,
+ int32_t heapSeqNum,
+ hardware::drm::V1_0::SharedBuffer *buf);
+
protected:
std::unique_ptr<CodecBase::BufferCallback> mCallback;
sp<ICrypto> mCrypto;
diff --git a/media/libstagefright/include/media/stagefright/DataSource.h b/media/libstagefright/include/media/stagefright/DataSource.h
index 1f7a473..83d3e5d 100644
--- a/media/libstagefright/include/media/stagefright/DataSource.h
+++ b/media/libstagefright/include/media/stagefright/DataSource.h
@@ -52,11 +52,6 @@
////////////////////////////////////////////////////////////////////////////
- // for DRM
- virtual sp<DecryptHandle> DrmInitialization(const char * /*mime*/ = NULL) {
- return NULL;
- }
-
virtual String8 getUri() {
return String8();
}
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index b634505..83273cb 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -66,9 +66,6 @@
virtual String8 toString() {
return mName;
}
- virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
- return mSource->DrmInitialization(mime);
- }
private:
enum {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 5af7b23..657144c 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -36,6 +36,10 @@
#include <inttypes.h>
#include <netinet/in.h>
+#ifndef __ANDROID_APEX__
+#include "HlsSampleDecryptor.h"
+#endif
+
namespace android {
ElementaryStreamQueue::ElementaryStreamQueue(Mode mode, uint32_t flags)
@@ -50,7 +54,13 @@
// Create the decryptor anyway since we don't know the use-case unless key is provided
// Won't decrypt if key info not available (e.g., scanner/extractor just parsing ts files)
- mSampleDecryptor = isSampleEncrypted() ? new HlsSampleDecryptor : NULL;
+ mSampleDecryptor = isSampleEncrypted() ?
+#ifdef __ANDROID_APEX__
+ new SampleDecryptor
+#else
+ new HlsSampleDecryptor
+#endif
+ : NULL;
}
sp<MetaData> ElementaryStreamQueue::getFormat() {
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 3227f47..a06bd6a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -25,7 +25,7 @@
#include <utils/RefBase.h>
#include <vector>
-#include "HlsSampleDecryptor.h"
+#include "SampleDecryptor.h"
namespace android {
@@ -109,7 +109,7 @@
sp<MetaData> mFormat;
- sp<HlsSampleDecryptor> mSampleDecryptor;
+ sp<SampleDecryptor> mSampleDecryptor;
int mAUIndex;
bool isSampleEncrypted() const {
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
index 2c76620..63b4d7b 100644
--- a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
+++ b/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef SAMPLE_AES_PROCESSOR_H_
+#ifndef HLS_SAMPLE_AES_PROCESSOR_H_
-#define SAMPLE_AES_PROCESSOR_H_
+#define HLS_SAMPLE_AES_PROCESSOR_H_
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AString.h>
@@ -28,18 +28,20 @@
#include <utils/RefBase.h>
#include <utils/Vector.h>
+#include "SampleDecryptor.h"
+
namespace android {
-struct HlsSampleDecryptor : RefBase {
+struct HlsSampleDecryptor : SampleDecryptor {
HlsSampleDecryptor();
explicit HlsSampleDecryptor(const sp<AMessage> &sampleAesKeyItem);
- void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
+ virtual void signalNewSampleAesKey(const sp<AMessage> &sampleAesKeyItem);
- size_t processNal(uint8_t *nalData, size_t nalSize);
- void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
- void processAC3(uint8_t *data, size_t size);
+ virtual size_t processNal(uint8_t *nalData, size_t nalSize);
+ virtual void processAAC(size_t adtsHdrSize, uint8_t *data, size_t size);
+ virtual void processAC3(uint8_t *data, size_t size);
static AString aesBlockToStr(uint8_t block[AES_BLOCK_SIZE]);
@@ -60,4 +62,4 @@
} // namespace android
-#endif // SAMPLE_AES_PROCESSOR_H_
+#endif // HLS_SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/mpeg2ts/SampleDecryptor.h b/media/libstagefright/mpeg2ts/SampleDecryptor.h
new file mode 100644
index 0000000..6bc4ac8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/SampleDecryptor.h
@@ -0,0 +1,44 @@
+/*
+ * 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 SAMPLE_AES_PROCESSOR_H_
+
+#define SAMPLE_AES_PROCESSOR_H_
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Base class of HlsSampleDecryptor which has dummy default implementation.
+struct SampleDecryptor : RefBase {
+
+ SampleDecryptor() { };
+
+ virtual void signalNewSampleAesKey(const sp<AMessage> &) { };
+
+ virtual size_t processNal(uint8_t *, size_t) { return -1; };
+ virtual void processAAC(size_t, uint8_t *, size_t) { };
+ virtual void processAC3(uint8_t *, size_t) { };
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(SampleDecryptor);
+};
+
+} // namespace android
+
+#endif // SAMPLE_AES_PROCESSOR_H_
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index cac1af9..bb66f4c 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -954,7 +954,7 @@
CHECK_GE(space2, 0);
method->setTo(request, 0, space1);
- url->setTo(request, space1 + 1, space2 - space1);
+ url->setTo(request, space1 + 1, space2 - space1 - 1);
}
void ARTSPConnection::addAuthentication(AString *request) {
diff --git a/media/libstagefright/tests/writer/Android.bp b/media/libstagefright/tests/writer/Android.bp
new file mode 100644
index 0000000..7e169cb
--- /dev/null
+++ b/media/libstagefright/tests/writer/Android.bp
@@ -0,0 +1,58 @@
+/*
+ * 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: "writerTest",
+ gtest: true,
+
+ srcs: [
+ "WriterUtility.cpp",
+ "WriterTest.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libstagefright_webm",
+ "libdatasource",
+ "libstagefright",
+ "libstagefright_foundation",
+ "libstagefright_esds",
+ "libogg",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/libstagefright",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
diff --git a/media/libstagefright/tests/writer/README.md b/media/libstagefright/tests/writer/README.md
new file mode 100644
index 0000000..52db6f0
--- /dev/null
+++ b/media/libstagefright/tests/writer/README.md
@@ -0,0 +1,30 @@
+## Media Testing ##
+---
+#### Writer :
+The Writer Test Suite validates the writers available in libstagefright.
+
+Run the following steps to build the test suite:
+```
+mmm frameworks/av/media/libstagefright/tests/writer/
+```
+
+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/writerTest/writerTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+
+adb push ${OUT}/data/nativetest/writerTest/writerTest /data/local/tmp/
+
+The resource file for the tests is taken from Codec2 VTS resource folder. Push these files into device for testing.
+```
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/codec2/hidl/1.0/vts/functional/res /sdcard/
+```
+
+usage: writerTest -P \<path_to_res_folder\>
+```
+adb shell /data/local/tmp/writerTest -P /sdcard/res/
+```
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
new file mode 100644
index 0000000..d68438c
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -0,0 +1,400 @@
+/*
+ * 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 "WriterTest"
+#include <utils/Log.h>
+
+#include <fstream>
+#include <iostream>
+
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include <media/mediarecorder.h>
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/OggWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <webm/WebmWriter.h>
+
+#include "WriterTestEnvironment.h"
+#include "WriterUtility.h"
+
+#define OUTPUT_FILE_NAME "/data/local/tmp/writer.out"
+
+static WriterTestEnvironment *gEnv = nullptr;
+
+struct configFormat {
+ char mime[128];
+ int32_t width;
+ int32_t height;
+ int32_t sampleRate;
+ int32_t channelCount;
+};
+
+// LookUpTable of clips and metadata for component testing
+static const struct InputData {
+ const char *mime;
+ string inputFile;
+ string info;
+ int32_t firstParam;
+ int32_t secondParam;
+ bool isAudio;
+} kInputData[] = {
+ {MEDIA_MIMETYPE_AUDIO_OPUS, "bbb_opus_stereo_128kbps_48000hz.opus",
+ "bbb_opus_stereo_128kbps_48000hz.info", 48000, 2, true},
+ {MEDIA_MIMETYPE_AUDIO_AAC, "bbb_aac_stereo_128kbps_48000hz.aac",
+ "bbb_aac_stereo_128kbps_48000hz.info", 48000, 2, true},
+ {MEDIA_MIMETYPE_AUDIO_AAC_ADTS, "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.adts",
+ "Mps_2_c2_fr1_Sc1_Dc2_0x03_raw.info", 48000, 2, true},
+ {MEDIA_MIMETYPE_AUDIO_AMR_NB, "sine_amrnb_1ch_12kbps_8000hz.amrnb",
+ "sine_amrnb_1ch_12kbps_8000hz.info", 8000, 1, true},
+ {MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+ "bbb_amrwb_1ch_14kbps_16000hz.info", 16000, 1, true},
+ {MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
+ "bbb_vorbis_stereo_128kbps_48000hz.info", 48000, 2, true},
+ {MEDIA_MIMETYPE_AUDIO_FLAC, "bbb_flac_stereo_680kbps_48000hz.flac",
+ "bbb_flac_stereo_680kbps_48000hz.info", 48000, 2, true},
+ {MEDIA_MIMETYPE_VIDEO_VP9, "bbb_vp9_176x144_285kbps_60fps.vp9",
+ "bbb_vp9_176x144_285kbps_60fps.info", 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_VP8, "bbb_vp8_176x144_240kbps_60fps.vp8",
+ "bbb_vp8_176x144_240kbps_60fps.info", 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_AVC, "bbb_avc_176x144_300kbps_60fps.h264",
+ "bbb_avc_176x144_300kbps_60fps.info", 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_HEVC, "bbb_hevc_176x144_176kbps_60fps.hevc",
+ "bbb_hevc_176x144_176kbps_60fps.info", 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_AV1, "bbb_av1_176_144.av1", "bbb_av1_176_144.info", 176, 144, false},
+ {MEDIA_MIMETYPE_VIDEO_H263, "bbb_h263_352x288_300kbps_12fps.h263",
+ "bbb_h263_352x288_300kbps_12fps.info", 352, 288, false},
+ {MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_mpeg4_352x288_512kbps_30fps.m4v",
+ "bbb_mpeg4_352x288_512kbps_30fps.info", 352, 288, false},
+};
+
+class WriterTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+ public:
+ virtual void SetUp() override {
+ mNumCsds = 0;
+ mInputFrameId = 0;
+ mWriterName = unknown_comp;
+ mDisableTest = false;
+
+ std::map<std::string, standardWriters> mapWriter = {
+ {"ogg", OGG}, {"aac", AAC}, {"aac_adts", AAC_ADTS}, {"webm", WEBM},
+ {"mpeg4", MPEG4}, {"amrnb", AMR_NB}, {"amrwb", AMR_WB}, {"mpeg2Ts", MPEG2TS}};
+ // Find the component type
+ string writerFormat = GetParam().first;
+ if (mapWriter.find(writerFormat) != mapWriter.end()) {
+ mWriterName = mapWriter[writerFormat];
+ }
+ if (mWriterName == standardWriters::unknown_comp) {
+ cout << "[ WARN ] Test Skipped. No specific writer mentioned\n";
+ mDisableTest = true;
+ }
+ }
+
+ virtual void TearDown() override {
+ mWriter.clear();
+ mFileMeta.clear();
+ mBufferInfo.clear();
+ if (mInputStream) mInputStream.close();
+ }
+
+ void getInputBufferInfo(string inputFileName, string inputInfo);
+
+ int32_t createWriter(int32_t fd);
+
+ int32_t addWriterSource(bool isAudio, configFormat params);
+
+ enum standardWriters {
+ OGG,
+ AAC,
+ AAC_ADTS,
+ WEBM,
+ MPEG4,
+ AMR_NB,
+ AMR_WB,
+ MPEG2TS,
+ unknown_comp,
+ };
+
+ standardWriters mWriterName;
+ sp<MediaWriter> mWriter;
+ sp<MetaData> mFileMeta;
+ sp<MediaAdapter> mCurrentTrack;
+
+ bool mDisableTest;
+ int32_t mNumCsds;
+ int32_t mInputFrameId;
+ ifstream mInputStream;
+ vector<BufferInfo> mBufferInfo;
+};
+
+void WriterTest::getInputBufferInfo(string inputFileName, string inputInfo) {
+ std::ifstream eleInfo;
+ eleInfo.open(inputInfo.c_str());
+ CHECK_EQ(eleInfo.is_open(), true);
+ int32_t bytesCount = 0;
+ uint32_t flags = 0;
+ int64_t timestamp = 0;
+ while (1) {
+ if (!(eleInfo >> bytesCount)) break;
+ eleInfo >> flags;
+ eleInfo >> timestamp;
+ mBufferInfo.push_back({bytesCount, flags, timestamp});
+ if (flags == CODEC_CONFIG_FLAG) mNumCsds++;
+ }
+ eleInfo.close();
+ mInputStream.open(inputFileName.c_str(), std::ifstream::binary);
+ CHECK_EQ(mInputStream.is_open(), true);
+}
+
+int32_t WriterTest::createWriter(int32_t fd) {
+ mFileMeta = new MetaData;
+ switch (mWriterName) {
+ case OGG:
+ mWriter = new OggWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_OGG);
+ break;
+ case AAC:
+ mWriter = new AACWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADIF);
+ break;
+ case AAC_ADTS:
+ mWriter = new AACWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AAC_ADTS);
+ break;
+ case WEBM:
+ mWriter = new WebmWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_WEBM);
+ break;
+ case MPEG4:
+ mWriter = new MPEG4Writer(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG_4);
+ break;
+ case AMR_NB:
+ mWriter = new AMRWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_NB);
+ break;
+ case AMR_WB:
+ mWriter = new AMRWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_AMR_WB);
+ break;
+ case MPEG2TS:
+ mWriter = new MPEG2TSWriter(fd);
+ mFileMeta->setInt32(kKeyFileType, output_format::OUTPUT_FORMAT_MPEG2TS);
+ break;
+ default:
+ return -1;
+ }
+ if (mWriter == nullptr) return -1;
+ mFileMeta->setInt32(kKeyRealTimeRecording, false);
+ return 0;
+}
+
+int32_t WriterTest::addWriterSource(bool isAudio, configFormat params) {
+ if (mInputFrameId) return -1;
+ sp<AMessage> format = new AMessage;
+ if (mInputStream.is_open()) {
+ format->setString("mime", params.mime);
+ if (isAudio) {
+ format->setInt32("channel-count", params.channelCount);
+ format->setInt32("sample-rate", params.sampleRate);
+ } else {
+ format->setInt32("width", params.width);
+ format->setInt32("height", params.height);
+ }
+
+ int32_t status =
+ writeHeaderBuffers(mInputStream, mBufferInfo, mInputFrameId, format, mNumCsds);
+ if (status != 0) return -1;
+ }
+ sp<MetaData> trackMeta = new MetaData;
+ convertMessageToMetaData(format, trackMeta);
+ mCurrentTrack = new MediaAdapter(trackMeta);
+ status_t result = mWriter->addSource(mCurrentTrack);
+ return result;
+}
+
+void getFileDetails(string &inputFilePath, string &info, configFormat ¶ms, bool &isAudio,
+ int32_t streamIndex = 0) {
+ if (streamIndex >= sizeof(kInputData) / sizeof(kInputData[0])) {
+ return;
+ }
+ inputFilePath += kInputData[streamIndex].inputFile;
+ info += kInputData[streamIndex].info;
+ strcpy(params.mime, kInputData[streamIndex].mime);
+ isAudio = kInputData[streamIndex].isAudio;
+ if (isAudio) {
+ params.sampleRate = kInputData[streamIndex].firstParam;
+ params.channelCount = kInputData[streamIndex].secondParam;
+ } else {
+ params.width = kInputData[streamIndex].firstParam;
+ params.height = kInputData[streamIndex].secondParam;
+ }
+ return;
+}
+
+TEST_P(WriterTest, CreateWriterTest) {
+ if (mDisableTest) return;
+ ALOGV("Tests the creation of writers");
+
+ string outputFile = OUTPUT_FILE_NAME;
+ int32_t fd =
+ open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd < 0) return;
+
+ // Creating writer within a test scope. Destructor should be called when the test ends
+ int32_t status = createWriter(fd);
+ if (status) {
+ cout << "Failed to create writer for output format:" << GetParam().first << "\n";
+ ASSERT_TRUE(false);
+ }
+}
+
+TEST_P(WriterTest, WriterTest) {
+ if (mDisableTest) return;
+ ALOGV("Checks if for a given input, a valid muxed file has been created or not");
+
+ string writerFormat = GetParam().first;
+ string outputFile = OUTPUT_FILE_NAME;
+ int32_t fd =
+ open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd < 0) return;
+ int32_t status = createWriter(fd);
+ if (status) {
+ cout << "Failed to create writer for output format:" << writerFormat << "\n";
+ ASSERT_TRUE(false);
+ }
+ string inputFile = gEnv->getRes();
+ string inputInfo = gEnv->getRes();
+ configFormat param;
+ bool isAudio;
+ int32_t inputFileIdx = GetParam().second;
+ getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+ if (!inputFile.compare(gEnv->getRes())) {
+ ALOGV("No input file specified");
+ return;
+ }
+ getInputBufferInfo(inputFile, inputInfo);
+ status = addWriterSource(isAudio, param);
+ if (status) {
+ cout << "Failed to add source for " << writerFormat << "Writer \n";
+ ASSERT_TRUE(false);
+ }
+ CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+ status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+ mBufferInfo.size());
+ mCurrentTrack->stop();
+ if (status) {
+ cout << writerFormat << " writer failed \n";
+ mWriter->stop();
+ ASSERT_TRUE(false);
+ }
+ CHECK_EQ((status_t)OK, mWriter->stop());
+ close(fd);
+}
+
+TEST_P(WriterTest, PauseWriterTest) {
+ if (mDisableTest) return;
+ ALOGV("Validates the pause() api of writers");
+
+ string writerFormat = GetParam().first;
+ string outputFile = OUTPUT_FILE_NAME;
+ int32_t fd =
+ open(outputFile.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ if (fd < 0) return;
+ int32_t status = createWriter(fd);
+ if (status) {
+ cout << "Failed to create writer for output format:" << writerFormat << "\n";
+ ASSERT_TRUE(false);
+ }
+ string inputFile = gEnv->getRes();
+ string inputInfo = gEnv->getRes();
+ configFormat param;
+ bool isAudio;
+ int32_t inputFileIdx = GetParam().second;
+ getFileDetails(inputFile, inputInfo, param, isAudio, inputFileIdx);
+ if (!inputFile.compare(gEnv->getRes())) {
+ ALOGV("No input file specified");
+ return;
+ }
+ getInputBufferInfo(inputFile, inputInfo);
+ status = addWriterSource(isAudio, param);
+ if (status) {
+ cout << "Failed to add source for " << writerFormat << "Writer \n";
+ ASSERT_TRUE(false);
+ }
+ CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+ status = sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack, 0,
+ mBufferInfo.size() / 4);
+ if (status) {
+ cout << writerFormat << " writer failed \n";
+ mCurrentTrack->stop();
+ mWriter->stop();
+ ASSERT_TRUE(false);
+ }
+
+ bool isPaused = false;
+ if ((mWriterName != standardWriters::MPEG2TS) && (mWriterName != standardWriters::MPEG4)) {
+ CHECK_EQ((status_t)OK, mWriter->pause());
+ isPaused = true;
+ }
+ // In the pause state, writers shouldn't write anything. Testing the writers for the same
+ int32_t numFramesPaused = mBufferInfo.size() / 4;
+ status |= sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+ mInputFrameId, numFramesPaused, isPaused);
+ if (isPaused) {
+ CHECK_EQ((status_t)OK, mWriter->start(mFileMeta.get()));
+ }
+ status |= sendBuffersToWriter(mInputStream, mBufferInfo, mInputFrameId, mCurrentTrack,
+ mInputFrameId, mBufferInfo.size());
+ mCurrentTrack->stop();
+ if (status) {
+ cout << writerFormat << " writer failed \n";
+ mWriter->stop();
+ ASSERT_TRUE(false);
+ }
+ CHECK_EQ((status_t)OK, mWriter->stop());
+ close(fd);
+}
+
+// TODO: (b/144476164)
+// Add AAC_ADTS, FLAC, AV1 input
+INSTANTIATE_TEST_SUITE_P(WriterTestAll, WriterTest,
+ ::testing::Values(make_pair("ogg", 0), make_pair("webm", 0),
+ make_pair("aac", 1), make_pair("mpeg4", 1),
+ make_pair("amrnb", 3), make_pair("amrwb", 4),
+ make_pair("webm", 5), make_pair("webm", 7),
+ make_pair("webm", 8), make_pair("mpeg4", 9),
+ make_pair("mpeg4", 10), make_pair("mpeg4", 12),
+ make_pair("mpeg4", 13), make_pair("mpeg2Ts", 1),
+ make_pair("mpeg2Ts", 9)));
+
+int main(int argc, char **argv) {
+ gEnv = new WriterTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/libstagefright/tests/writer/WriterTestEnvironment.h b/media/libstagefright/tests/writer/WriterTestEnvironment.h
new file mode 100644
index 0000000..34c2baa
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterTestEnvironment.h
@@ -0,0 +1,72 @@
+/*
+ * 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 __WRITER_TEST_ENVIRONMENT_H__
+#define __WRITER_TEST_ENVIRONMENT_H__
+
+#include <gtest/gtest.h>
+
+#include <getopt.h>
+
+using namespace std;
+
+class WriterTestEnvironment : public ::testing::Environment {
+ public:
+ WriterTestEnvironment() : res("/sdcard/media/") {}
+
+ // 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 WriterTestEnvironment::initFromOptions(int argc, char **argv) {
+ static struct option options[] = {{"res", 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 // __WRITER_TEST_ENVIRONMENT_H__
diff --git a/media/libstagefright/tests/writer/WriterUtility.cpp b/media/libstagefright/tests/writer/WriterUtility.cpp
new file mode 100644
index 0000000..2ba90a0
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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 "WriterUtility"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaBuffer.h>
+
+#include "WriterUtility.h"
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+ int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset,
+ int32_t range, bool isPaused) {
+ while (1) {
+ if (inputFrameId == (int)bufferInfo.size() || inputFrameId >= (offset + range)) break;
+ int32_t size = bufferInfo[inputFrameId].size;
+ char *data = (char *)malloc(size);
+ if (!data) {
+ ALOGE("Insufficient memeory to read input");
+ return -1;
+ }
+
+ inputStream.read(data, size);
+ CHECK_EQ(inputStream.gcount(), size);
+
+ sp<ABuffer> buffer = new ABuffer((void *)data, size);
+ if (buffer.get() == nullptr) {
+ ALOGE("sendBuffersToWriter() got a nullptr buffer.");
+ return -1;
+ }
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+ // Released in MediaAdapter::signalBufferReturned().
+ mediaBuffer->add_ref();
+ mediaBuffer->set_range(buffer->offset(), buffer->size());
+
+ MetaDataBase &sampleMetaData = mediaBuffer->meta_data();
+ sampleMetaData.setInt64(kKeyTime, bufferInfo[inputFrameId].timeUs);
+ // Just set the kKeyDecodingTime as the presentation time for now.
+ sampleMetaData.setInt64(kKeyDecodingTime, bufferInfo[inputFrameId].timeUs);
+
+ if (bufferInfo[inputFrameId].flags == 1) {
+ sampleMetaData.setInt32(kKeyIsSyncFrame, true);
+ }
+
+ // This pushBuffer will wait until the mediaBuffer is consumed.
+ int status = currentTrack->pushBuffer(mediaBuffer);
+ free(data);
+ inputFrameId++;
+
+ if (OK != status) {
+ if (!isPaused) return status;
+ else {
+ ALOGD("Writer is in paused state. Input buffers won't get consumed");
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+ int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds) {
+ char csdName[kMaxCSDStrlen];
+ for (int csdId = 0; csdId < numCsds; csdId++) {
+ int32_t flags = bufferInfo[inputFrameId].flags;
+ if (flags == CODEC_CONFIG_FLAG) {
+ int32_t size = bufferInfo[inputFrameId].size;
+ char *data = (char *)malloc(size);
+ if (!data) {
+ ALOGE("Insufficient memeory to read input");
+ return -1;
+ }
+ inputStream.read(data, size);
+ CHECK_EQ(inputStream.gcount(), size);
+
+ sp<ABuffer> csdBuffer = ABuffer::CreateAsCopy((void *)data, size);
+ if (csdBuffer.get() == nullptr || csdBuffer->base() == nullptr) {
+ return -1;
+ }
+ snprintf(csdName, sizeof(csdName), "csd-%d", csdId);
+ format->setBuffer(csdName, csdBuffer);
+ inputFrameId++;
+ free(data);
+ }
+ }
+ return 0;
+}
diff --git a/media/libstagefright/tests/writer/WriterUtility.h b/media/libstagefright/tests/writer/WriterUtility.h
new file mode 100644
index 0000000..d402798
--- /dev/null
+++ b/media/libstagefright/tests/writer/WriterUtility.h
@@ -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.
+ */
+
+#ifndef WRITER_UTILITY_H_
+#define WRITER_UTILITY_H_
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <media/stagefright/MediaAdapter.h>
+
+using namespace android;
+using namespace std;
+
+#define CODEC_CONFIG_FLAG 32
+
+constexpr uint32_t kMaxCSDStrlen = 16;
+
+struct BufferInfo {
+ int32_t size;
+ uint32_t flags;
+ int64_t timeUs;
+};
+
+int32_t sendBuffersToWriter(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+ int32_t &inputFrameId, sp<MediaAdapter> ¤tTrack, int32_t offset,
+ int32_t range, bool isPaused = false);
+
+int32_t writeHeaderBuffers(ifstream &inputStream, vector<BufferInfo> &bufferInfo,
+ int32_t &inputFrameId, sp<AMessage> &format, int32_t numCsds);
+
+#endif // WRITER_UTILITY_H_
diff --git a/media/mediaserver/manifest_media_c2_software.xml b/media/mediaserver/manifest_media_c2_software.xml
index 5196336..f23ed44 100644
--- a/media/mediaserver/manifest_media_c2_software.xml
+++ b/media/mediaserver/manifest_media_c2_software.xml
@@ -2,7 +2,7 @@
<hal>
<name>android.hardware.media.c2</name>
<transport>hwbinder</transport>
- <version>1.0</version>
+ <version>1.1</version>
<interface>
<name>IComponentStore</name>
<instance>software</instance>
diff --git a/media/mediaserver/mediaserver.rc b/media/mediaserver/mediaserver.rc
index f6c325c..ecb75a9 100644
--- a/media/mediaserver/mediaserver.rc
+++ b/media/mediaserver/mediaserver.rc
@@ -1,3 +1,6 @@
+on property:init.svc.media=*
+ setprop init.svc.mediadrm ${init.svc.media}
+
service media /system/bin/mediaserver
class main
user media
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 032c5e2..0eb46f4 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -42,6 +42,7 @@
name: "libmediandk",
srcs: [
+ "NdkJavaVMHelper.cpp",
"NdkMediaCodec.cpp",
"NdkMediaCrypto.cpp",
"NdkMediaDataSource.cpp",
@@ -94,6 +95,7 @@
"libgui",
"libui",
"libmediandk_utils",
+ "libnativehelper",
],
export_include_dirs: ["include"],
diff --git a/media/ndk/NdkJavaVMHelper.cpp b/media/ndk/NdkJavaVMHelper.cpp
new file mode 100644
index 0000000..baf2744
--- /dev/null
+++ b/media/ndk/NdkJavaVMHelper.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "NdkJavaVMHelper"
+
+#include <media/NdkJavaVMHelper.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+JNIEnv *NdkJavaVMHelper::getJNIEnv() {
+ JNIEnv *env;
+ jsize nVMs;
+ JavaVM *vm;
+
+ int status = JNI_GetCreatedJavaVMs(&vm, 1, &nVMs);
+ if (status != JNI_OK || nVMs == 0 || vm == NULL) {
+ ALOGE("Failed to get JVM instance");
+ return NULL;
+ } else if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("Failed to get JNIEnv for JavaVM: %p", vm);
+ return NULL;
+ }
+
+ return env;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/media/ndk/NdkMediaCrypto.cpp b/media/ndk/NdkMediaCrypto.cpp
index 792fc00..741e58b 100644
--- a/media/ndk/NdkMediaCrypto.cpp
+++ b/media/ndk/NdkMediaCrypto.cpp
@@ -26,9 +26,8 @@
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
-#include <binder/IServiceManager.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/ICrypto.h>
-#include <mediadrm/IMediaDrmService.h>
#include <android_util_Binder.h>
#include <jni.h>
@@ -36,19 +35,7 @@
using namespace android;
static sp<ICrypto> makeCrypto() {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.drm"));
-
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<ICrypto> crypto = service->makeCrypto();
- if (crypto == NULL || (crypto->initCheck() != OK && crypto->initCheck() != NO_INIT)) {
- return NULL;
- }
- return crypto;
+ return DrmUtils::MakeCrypto();
}
struct AMediaCrypto {
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index c1d4686..98ccd6c 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -30,6 +30,7 @@
#include <datasource/HTTPBase.h>
#include <datasource/NuCachedSource2.h>
#include <media/IMediaHTTPService.h>
+#include <media/NdkJavaVMHelper.h>
#include <media/NdkMediaError.h>
#include <media/NdkMediaDataSource.h>
#include <media/stagefright/InterfaceUtils.h>
@@ -167,7 +168,8 @@
JNIEnv *env;
const char *clazz, *method, *signature;
- env = AndroidRuntime::getJNIEnv();
+ env = NdkJavaVMHelper::getJNIEnv();
+
clazz = "android/media/MediaHTTPService";
method = "createHttpServiceBinderIfNecessary";
signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 842216c..8a95982 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -29,19 +29,19 @@
#include <android-base/properties.h>
#include <binder/PermissionController.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrm.h>
#include <mediadrm/IDrmClient.h>
#include <media/stagefright/MediaErrors.h>
#include <binder/IServiceManager.h>
#include <media/NdkMediaCrypto.h>
-#include <mediadrm/IMediaDrmService.h>
using namespace android;
typedef Vector<uint8_t> idvec_t;
-struct DrmListener: virtual public BnDrmClient
+struct DrmListener: virtual public IDrmClient
{
private:
AMediaDrm *mObj;
@@ -71,12 +71,27 @@
mKeysChangeListener = listener;
}
- void notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj);
+ void sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) override;
+
+ void sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) override;
+
+ void sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) override;
+
+ void sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &) override {}
+
};
struct AMediaDrm {
sp<IDrm> mDrm;
- sp<IDrmClient> mDrmClient;
List<idvec_t> mIds;
KeyedVector<String8, String8> mQueryResults;
Vector<uint8_t> mKeyRequest;
@@ -88,71 +103,52 @@
sp<DrmListener> mListener;
};
-void DrmListener::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj) {
- if (!mEventListener || !mExpirationUpdateListener || !mKeysChangeListener) {
- ALOGE("No listeners are specified");
+void DrmListener::sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) {
+ if (!mExpirationUpdateListener) {
+ ALOGE("No ExpirationUpdateListener specified");
return;
}
- obj->setDataPosition(0);
+ if (expiryTimeInMS >= 0) {
+ AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+ (*mExpirationUpdateListener)(mObj, &asid, expiryTimeInMS);
+ } else {
+ ALOGE("expiry time negative, status=%" PRId64 "", expiryTimeInMS);
+ }
+}
- AMediaDrmSessionId sessionId = {NULL, 0};
- int32_t sessionIdSize = obj->readInt32();
- if (sessionIdSize <= 0) {
- ALOGE("Invalid session id size");
+void DrmListener::sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) {
+ if (!mKeysChangeListener) {
+ ALOGE("No KeysChangeListener specified");
return;
}
- std::unique_ptr<uint8_t[]> sessionIdData(new uint8_t[sessionIdSize]);
- sessionId.ptr = sessionIdData.get();
- sessionId.length = sessionIdSize;
- status_t err = obj->read(sessionIdData.get(), sessionId.length);
- if (err != OK) {
- ALOGE("Failed to read session id, error=%d", err);
- return;
- }
-
- if (DrmPlugin::kDrmPluginEventExpirationUpdate == eventType) {
- int64_t expiryTimeInMS = obj->readInt64();
- if (expiryTimeInMS >= 0) {
- (*mExpirationUpdateListener)(mObj, &sessionId, expiryTimeInMS);
- } else {
- ALOGE("Failed to read expiry time, status=%" PRId64 "", expiryTimeInMS);
- }
- return;
- } else if (DrmPlugin::kDrmPluginEventKeysChange == eventType) {
- int32_t numKeys = 0;
- err = obj->readInt32(&numKeys);
- if (err != OK) {
- ALOGE("Failed to read number of keys status, error=%d", err);
- return;
- }
-
- Vector<AMediaDrmKeyStatus> keysStatus;
- std::vector<std::unique_ptr<uint8_t[]> > dataPointers;
+ Vector<AMediaDrmKeyStatus> keysStatus;
+ for (const auto &drmKeyStatus : keyStatusList) {
AMediaDrmKeyStatus keyStatus;
+ keyStatus.keyId.ptr = drmKeyStatus.keyId.data();
+ keyStatus.keyId.length = drmKeyStatus.keyId.size();
+ keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(drmKeyStatus.type);
+ keysStatus.push(keyStatus);
+ }
- for (size_t i = 0; i < numKeys; ++i) {
- keyStatus.keyId.ptr = nullptr;
- keyStatus.keyId.length = 0;
- int32_t idSize = obj->readInt32();
- if (idSize > 0) {
- std::unique_ptr<uint8_t[]> data(new uint8_t[idSize]);
- err = obj->read(data.get(), idSize);
- if (err != OK) {
- ALOGE("Failed to read key data, error=%d", err);
- return;
- }
- keyStatus.keyId.ptr = data.get();
- keyStatus.keyId.length = idSize;
- dataPointers.push_back(std::move(data));
- }
- keyStatus.keyType = static_cast<AMediaDrmKeyStatusType>(obj->readInt32());
- keysStatus.push(keyStatus);
- }
+ AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+ int32_t numKeys = keyStatusList.size();
+ (*mKeysChangeListener)(mObj, &asid, keysStatus.array(), numKeys, hasNewUsableKey);
+ return;
+}
- bool hasNewUsableKey = obj->readInt32();
- (*mKeysChangeListener)(mObj, &sessionId, keysStatus.array(), numKeys, hasNewUsableKey);
+void DrmListener::sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) {
+ if (!mEventListener) {
+ ALOGE("No EventListener specified");
return;
}
@@ -176,23 +172,17 @@
ndkEventType = EVENT_SESSION_RECLAIMED;
break;
default:
- ALOGE("Invalid event DrmPlugin::EventType %d, ignored", (int)eventType);
+ ALOGE("Invalid event DrmPlugin::EventType %d, ignored", eventType);
return;
}
- int32_t dataSize = obj->readInt32();
- uint8_t *data = NULL;
+ AMediaDrmSessionId asid = {sessionId.data(), sessionId.size()};
+ int32_t dataSize = data.size();
+ const uint8_t *dataPtr = data.data();
if (dataSize > 0) {
- data = new uint8_t[dataSize];
- err = obj->read(data, dataSize);
- if (err == OK) {
- (*mEventListener)(mObj, &sessionId, ndkEventType, extra, data, dataSize);
- } else {
- ALOGE("Failed to read event data, error=%d", err);
- }
- delete [] data;
+ (*mEventListener)(mObj, &asid, ndkEventType, 0, dataPtr, dataSize);
} else {
- ALOGE("Error reading parcel: invalid event data size=%d", dataSize);
+ ALOGE("invalid event data size=%d", dataSize);
}
}
@@ -268,19 +258,7 @@
}
static sp<IDrm> CreateDrm() {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("media.drm"));
-
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<IDrm> drm = service->makeDrm();
- if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
- return NULL;
- }
- return drm;
+ return DrmUtils::MakeDrm();
}
diff --git a/media/ndk/include/media/NdkJavaVMHelper.h b/media/ndk/include/media/NdkJavaVMHelper.h
new file mode 100644
index 0000000..1c20275
--- /dev/null
+++ b/media/ndk/include/media/NdkJavaVMHelper.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NDK_JAVA_VM_HELPER_H_
+
+#define NDK_JAVA_VM_HELPER_H_
+
+#include "jni.h"
+
+namespace android {
+
+struct NdkJavaVMHelper {
+ static JNIEnv *getJNIEnv();
+};
+
+} // namespace android
+
+#endif // NDK_JAVA_VM_HELPER_H_
\ No newline at end of file
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index f666ad0..7531578 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -4,7 +4,7 @@
AImageReader_acquireLatestImageAsync; # introduced=26
AImageReader_acquireNextImage; # introduced=24
AImageReader_acquireNextImageAsync; # introduced=26
- AImageReader_getWindowNativeHandle; #vndk
+ AImageReader_getWindowNativeHandle; # llndk
AImageReader_delete; # introduced=24
AImageReader_getFormat; # introduced=24
AImageReader_getHeight; # introduced=24
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
index 487ddb8..520a2cf 100644
--- a/media/tests/benchmark/README.md
+++ b/media/tests/benchmark/README.md
@@ -118,5 +118,30 @@
The test encodes input stream and benchmarks the encoders available in SDK.
```
adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+# Codec2
+To run the test suite for measuring performance of the codec2 layer, follow the following steps:
+
+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/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest64/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To test 32-bit binary push binaries from nativetest.
+adb push $(OUT)/data/nativetest/* /data/local/tmp/
+Eg. adb push $(OUT)/data/nativetest/C2DecoderTest/C2DecoderTest /data/local/tmp/
+
+To get the resource files for the test follow instructions given in [NDK](#NDK)
+
+## C2 Decoder
+
+The test decodes input stream and benchmarks the codec2 decoders available in device.
+
+Setup steps are same as [extractor](#extractor).
+
+```
+adb shell /data/local/tmp/C2DecoderTest -P /data/local/tmp/MediaBenchmark/res/
```
diff --git a/media/tests/benchmark/src/native/common/Android.bp b/media/tests/benchmark/src/native/common/Android.bp
index 1da0102..babc329 100644
--- a/media/tests/benchmark/src/native/common/Android.bp
+++ b/media/tests/benchmark/src/native/common/Android.bp
@@ -24,6 +24,7 @@
srcs: [
"BenchmarkCommon.cpp",
"Stats.cpp",
+ "utils/Timers.cpp",
],
export_include_dirs: ["."],
@@ -49,7 +50,6 @@
shared_libs: [
"libmediandk",
"liblog",
- "libutils",
],
cflags: [
@@ -58,6 +58,39 @@
]
}
+cc_library_static {
+ name: "libmediabenchmark_codec2_common",
+ defaults: [
+ "libmediabenchmark_codec2_common-defaults",
+ ],
+
+ srcs: [
+ "BenchmarkC2Common.cpp",
+ ],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
+
+cc_defaults {
+ name: "libmediabenchmark_codec2_common-defaults",
+
+ defaults: [
+ "libmediabenchmark_common-defaults",
+ "libcodec2-hidl-client-defaults",
+ "libmediabenchmark_soft_sanitize_all-defaults",
+ ],
+
+ include_dirs: [
+ "frameworks/av/media/codec2/hidl/client/include",
+ ],
+
+ shared_libs: [
+ "libcodec2_client",
+ ]
+}
+
// public dependency for native implementation
// to be used by code under media/benchmark/* only
cc_defaults {
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
new file mode 100644
index 0000000..622a0e1
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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 "BenchmarkC2Common"
+
+#include "BenchmarkC2Common.h"
+
+int32_t BenchmarkC2Common::setupCodec2() {
+ ALOGV("In %s", __func__);
+ mClient = android::Codec2Client::CreateFromService("default");
+ if (!mClient) return -1;
+
+ std::shared_ptr<C2AllocatorStore> store = android::GetCodec2PlatformAllocatorStore();
+ if (!store) return -1;
+
+ c2_status_t status = store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mLinearAllocator);
+ if (status != C2_OK) return status;
+
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
+ if (!mLinearPool) return -1;
+
+ status = store->fetchAllocator(C2AllocatorStore::DEFAULT_GRAPHIC, &mGraphicAllocator);
+ if (status != C2_OK) return status;
+
+ mGraphicPool = std::make_shared<C2PooledBlockPool>(mGraphicAllocator, mBlockPoolId++);
+ if (!mGraphicPool) return -1;
+
+ for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
+ mWorkQueue.emplace_back(new C2Work);
+ }
+ if (!mStats) mStats = new Stats();
+
+ return status;
+}
+
+vector<string> BenchmarkC2Common::getSupportedComponentList(bool isEncoder) {
+ // Get List of components from all known services
+ vector<string> codecList;
+ const std::vector<C2Component::Traits> listTraits = mClient->ListComponents();
+ if (listTraits.size() == 0)
+ ALOGE("ComponentInfo list empty.");
+ else {
+ for (size_t i = 0; i < listTraits.size(); i++) {
+ if (isEncoder && C2Component::KIND_ENCODER == listTraits[i].kind) {
+ codecList.push_back(listTraits[i].name);
+ } else if (!isEncoder && C2Component::KIND_DECODER == listTraits[i].kind) {
+ codecList.push_back(listTraits[i].name);
+ }
+ }
+ }
+ return codecList;
+}
+
+void BenchmarkC2Common::waitOnInputConsumption() {
+ typedef std::unique_lock<std::mutex> ULock;
+ uint32_t queueSize;
+ uint32_t maxRetry = 0;
+ {
+ ULock l(mQueueLock);
+ queueSize = mWorkQueue.size();
+ }
+ while ((maxRetry < MAX_RETRY) && (queueSize < MAX_INPUT_BUFFERS)) {
+ ULock l(mQueueLock);
+ if (queueSize != mWorkQueue.size()) {
+ queueSize = mWorkQueue.size();
+ maxRetry = 0;
+ } else {
+ mQueueCondition.wait_for(l, TIME_OUT);
+ maxRetry++;
+ }
+ }
+}
+
+void BenchmarkC2Common::handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems) {
+ ALOGV("In %s", __func__);
+ mStats->addOutputTime();
+ for (std::unique_ptr<C2Work> &work : workItems) {
+ if (!work->worklets.empty()) {
+ if (work->worklets.front()->output.flags != C2FrameData::FLAG_INCOMPLETE) {
+ mEos = (work->worklets.front()->output.flags & C2FrameData::FLAG_END_OF_STREAM) !=
+ 0;
+ ALOGV("WorkDone: frameID received %d , mEos : %d",
+ (int)work->worklets.front()->output.ordinal.frameIndex.peeku(), mEos);
+ work->input.buffers.clear();
+ work->worklets.clear();
+ {
+ typedef std::unique_lock<std::mutex> ULock;
+ ULock l(mQueueLock);
+ mWorkQueue.push_back(std::move(work));
+ mQueueCondition.notify_all();
+ }
+ }
+ }
+ }
+}
+
diff --git a/media/tests/benchmark/src/native/common/BenchmarkC2Common.h b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
new file mode 100644
index 0000000..d67758a
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/BenchmarkC2Common.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BENCHMARK_C2_COMMON_H__
+#define __BENCHMARK_C2_COMMON_H__
+
+#include "codec2/hidl/client.h"
+
+#include <C2Component.h>
+#include <C2Config.h>
+
+#include <hidl/HidlSupport.h>
+
+#include <C2AllocatorIon.h>
+#include <C2Buffer.h>
+#include <C2BufferPriv.h>
+
+#include "BenchmarkCommon.h"
+
+#define MAX_RETRY 20
+#define TIME_OUT 400ms
+#define MAX_INPUT_BUFFERS 8
+
+using android::C2AllocatorIon;
+
+class LinearBuffer : public C2Buffer {
+ public:
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block)
+ : C2Buffer({block->share(block->offset(), block->size(), ::C2Fence())}) {}
+
+ explicit LinearBuffer(const std::shared_ptr<C2LinearBlock> &block, size_t size)
+ : C2Buffer({block->share(block->offset(), size, ::C2Fence())}) {}
+};
+
+class GraphicBuffer : public C2Buffer {
+ public:
+ explicit GraphicBuffer(const std::shared_ptr<C2GraphicBlock> &block)
+ : C2Buffer({block->share(C2Rect(block->width(), block->height()), ::C2Fence())}) {}
+};
+
+/**
+ * Handle Callback functions onWorkDone(), onTripped(),
+ * onError(), onDeath(), onFramesRendered() for C2 Components
+ */
+struct CodecListener : public android::Codec2Client::Listener {
+ public:
+ CodecListener(
+ const std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> fn = nullptr)
+ : callBack(fn) {}
+ virtual void onWorkDone(const std::weak_ptr<android::Codec2Client::Component> &comp,
+ std::list<std::unique_ptr<C2Work>> &workItems) override {
+ ALOGV("onWorkDone called");
+ (void)comp;
+ if (callBack) callBack(workItems);
+ }
+
+ virtual void onTripped(
+ const std::weak_ptr<android::Codec2Client::Component> &comp,
+ const std::vector<std::shared_ptr<C2SettingResult>> &settingResults) override {
+ (void)comp;
+ (void)settingResults;
+ }
+
+ virtual void onError(const std::weak_ptr<android::Codec2Client::Component> &comp,
+ uint32_t errorCode) override {
+ (void)comp;
+ ALOGV("onError called");
+ if (errorCode != 0) ALOGE("Error : %u", errorCode);
+ }
+
+ virtual void onDeath(const std::weak_ptr<android::Codec2Client::Component> &comp) override {
+ (void)comp;
+ }
+
+ virtual void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex) override {
+ (void)frameIndex;
+ (void)arrayIndex;
+ }
+
+ virtual void onFrameRendered(uint64_t bufferQueueId, int32_t slotId,
+ int64_t timestampNs) override {
+ (void)bufferQueueId;
+ (void)slotId;
+ (void)timestampNs;
+ }
+
+ std::function<void(std::list<std::unique_ptr<C2Work>> &workItems)> callBack;
+};
+
+class BenchmarkC2Common {
+ public:
+ BenchmarkC2Common()
+ : mEos(false),
+ mStats(nullptr),
+ mClient(nullptr),
+ mBlockPoolId(0),
+ mLinearPool(nullptr),
+ mGraphicPool(nullptr),
+ mLinearAllocator(nullptr),
+ mGraphicAllocator(nullptr) {}
+
+ int32_t setupCodec2();
+
+ vector<string> getSupportedComponentList(bool isEncoder);
+
+ void waitOnInputConsumption();
+
+ // callback function to process onWorkDone received by Listener
+ void handleWorkDone(std::list<std::unique_ptr<C2Work>> &workItems);
+
+ bool mEos;
+ protected:
+ Stats *mStats;
+
+ std::shared_ptr<android::Codec2Client> mClient;
+
+ C2BlockPool::local_id_t mBlockPoolId;
+ std::shared_ptr<C2BlockPool> mLinearPool;
+ std::shared_ptr<C2BlockPool> mGraphicPool;
+ std::shared_ptr<C2Allocator> mLinearAllocator;
+ std::shared_ptr<C2Allocator> mGraphicAllocator;
+
+ std::mutex mQueueLock;
+ std::condition_variable mQueueCondition;
+ std::list<std::unique_ptr<C2Work>> mWorkQueue;
+};
+
+#endif // __BENCHMARK_C2_COMMON_H__
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
index 5bdb48a..ab74508 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.cpp
@@ -56,10 +56,10 @@
void OnErrorCB(AMediaCodec *codec, void *userdata, media_status_t err, int32_t actionCode,
const char *detail) {
- (void)codec;
- ALOGV("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
+ ALOGE("OnErrorCB: err(%d), actionCode(%d), detail(%s)", err, actionCode, detail);
CallBackHandle *self = (CallBackHandle *)userdata;
self->mSawError = true;
+ self->mIOQueue.push([self, codec, err]() { self->onError(codec, err); });
}
AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index df16baf..8153a86 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.h
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -17,8 +17,6 @@
#ifndef __BENCHMARK_COMMON_H__
#define __BENCHMARK_COMMON_H__
-#include <utils/Log.h>
-
#include <inttypes.h>
#include <mutex>
#include <queue>
@@ -89,6 +87,10 @@
(void)codec;
(void)format;
}
+ virtual void onError(AMediaCodec *codec, media_status_t err) {
+ (void)codec;
+ (void)err;
+ }
virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
AMediaCodecBufferInfo *bufferInfo) {
(void)codec;
diff --git a/media/tests/benchmark/src/native/common/Stats.cpp b/media/tests/benchmark/src/native/common/Stats.cpp
index 6bcd3ce..2d9bb31 100644
--- a/media/tests/benchmark/src/native/common/Stats.cpp
+++ b/media/tests/benchmark/src/native/common/Stats.cpp
@@ -19,7 +19,6 @@
#include <iostream>
#include <stdint.h>
-#include <utils/Log.h>
#include "Stats.h"
diff --git a/media/tests/benchmark/src/native/common/Stats.h b/media/tests/benchmark/src/native/common/Stats.h
index 024319a..2f556ee 100644
--- a/media/tests/benchmark/src/native/common/Stats.h
+++ b/media/tests/benchmark/src/native/common/Stats.h
@@ -17,11 +17,28 @@
#ifndef __STATS_H__
#define __STATS_H__
+#include <android/log.h>
+
+#ifndef ALOG
+#define ALOG(priority, tag, ...) ((void)__android_log_print(ANDROID_##priority, tag, __VA_ARGS__))
+
+#define ALOGI(...) ALOG(LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define ALOGE(...) ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__)
+#define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#if LOG_NDEBUG
+#define ALOGV(cond, ...) ((void)0)
+#else
+#define ALOGV(...) ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
+#endif
+#endif // ALOG
+
#include <sys/time.h>
#include <algorithm>
#include <numeric>
#include <vector>
-#include <utils/Timers.h>
+
+// Include local copy of Timers taken from system/core/libutils
+#include "utils/Timers.h"
using namespace std;
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.cpp b/media/tests/benchmark/src/native/common/utils/Timers.cpp
new file mode 100644
index 0000000..1acbdb3
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#define LOG_TAG "Timers"
+
+#include <limits.h>
+#include <time.h>
+
+#include "Timers.h"
+
+#if defined(__ANDROID__)
+nsecs_t systemTime(int clock) {
+ static const clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
+ CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME};
+ struct timespec t;
+ t.tv_sec = t.tv_nsec = 0;
+ clock_gettime(clocks[clock], &t);
+ return nsecs_t(t.tv_sec) * 1000000000LL + t.tv_nsec;
+}
+#else
+nsecs_t systemTime(int /*clock*/) {
+ // Clock support varies widely across hosts. Mac OS doesn't support
+ // posix clocks, older glibcs don't support CLOCK_BOOTTIME and Windows
+ // is windows.
+ struct timeval t;
+ t.tv_sec = t.tv_usec = 0;
+ gettimeofday(&t, NULL);
+ return nsecs_t(t.tv_sec) * 1000000000LL + nsecs_t(t.tv_usec) * 1000LL;
+}
+#endif
+
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime) {
+ nsecs_t timeoutDelayMillis;
+ if (timeoutTime > referenceTime) {
+ uint64_t timeoutDelay = uint64_t(timeoutTime - referenceTime);
+ if (timeoutDelay > uint64_t((INT_MAX - 1) * 1000000LL)) {
+ timeoutDelayMillis = -1;
+ } else {
+ timeoutDelayMillis = (timeoutDelay + 999999LL) / 1000000LL;
+ }
+ } else {
+ timeoutDelayMillis = 0;
+ }
+ return (int)timeoutDelayMillis;
+}
diff --git a/media/tests/benchmark/src/native/common/utils/Timers.h b/media/tests/benchmark/src/native/common/utils/Timers.h
new file mode 100644
index 0000000..d643dcd
--- /dev/null
+++ b/media/tests/benchmark/src/native/common/utils/Timers.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+//
+// Timer functions.
+//
+
+#ifndef _LIBS_UTILS_TIMERS_H
+#define _LIBS_UTILS_TIMERS_H
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+// ------------------------------------------------------------------
+// C API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int64_t nsecs_t; // nano-seconds
+
+static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs) {
+ return secs * 1000000000;
+}
+
+static inline nsecs_t milliseconds_to_nanoseconds(nsecs_t secs) {
+ return secs * 1000000;
+}
+
+static inline nsecs_t microseconds_to_nanoseconds(nsecs_t secs) {
+ return secs * 1000;
+}
+
+static inline nsecs_t nanoseconds_to_seconds(nsecs_t secs) {
+ return secs / 1000000000;
+}
+
+static inline nsecs_t nanoseconds_to_milliseconds(nsecs_t secs) {
+ return secs / 1000000;
+}
+
+static inline nsecs_t nanoseconds_to_microseconds(nsecs_t secs) {
+ return secs / 1000;
+}
+
+static inline nsecs_t s2ns(nsecs_t v) {
+ return seconds_to_nanoseconds(v);
+}
+static inline nsecs_t ms2ns(nsecs_t v) {
+ return milliseconds_to_nanoseconds(v);
+}
+static inline nsecs_t us2ns(nsecs_t v) {
+ return microseconds_to_nanoseconds(v);
+}
+static inline nsecs_t ns2s(nsecs_t v) {
+ return nanoseconds_to_seconds(v);
+}
+static inline nsecs_t ns2ms(nsecs_t v) {
+ return nanoseconds_to_milliseconds(v);
+}
+static inline nsecs_t ns2us(nsecs_t v) {
+ return nanoseconds_to_microseconds(v);
+}
+
+static inline nsecs_t seconds(nsecs_t v) {
+ return s2ns(v);
+}
+static inline nsecs_t milliseconds(nsecs_t v) {
+ return ms2ns(v);
+}
+static inline nsecs_t microseconds(nsecs_t v) {
+ return us2ns(v);
+}
+
+enum {
+ SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
+ SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
+ SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
+ SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock
+ SYSTEM_TIME_BOOTTIME = 4 // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+};
+
+// return the system-time according to the specified clock
+#ifdef __cplusplus
+nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+#else
+nsecs_t systemTime(int clock);
+#endif // def __cplusplus
+
+/**
+ * Returns the number of milliseconds to wait between the reference time and the timeout time.
+ * If the timeout is in the past relative to the reference time, returns 0.
+ * If the timeout is more than INT_MAX milliseconds in the future relative to the reference time,
+ * such as when timeoutTime == LLONG_MAX, returns -1 to indicate an infinite timeout delay.
+ * Otherwise, returns the difference between the reference time and timeout time
+ * rounded up to the next millisecond.
+ */
+int toMillisecondTimeoutDelay(nsecs_t referenceTime, nsecs_t timeoutTime);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _LIBS_UTILS_TIMERS_H
diff --git a/media/tests/benchmark/src/native/decoder/Android.bp b/media/tests/benchmark/src/native/decoder/Android.bp
index b6286d4..b5072ab 100644
--- a/media/tests/benchmark/src/native/decoder/Android.bp
+++ b/media/tests/benchmark/src/native/decoder/Android.bp
@@ -29,3 +29,22 @@
ldflags: ["-Wl,-Bsymbolic"]
}
+
+cc_library_static {
+ name: "libmediabenchmark_codec2_decoder",
+ defaults: [
+ "libmediabenchmark_common-defaults",
+ "libmediabenchmark_codec2_common-defaults",
+ ],
+
+ srcs: ["C2Decoder.cpp"],
+
+ static_libs: [
+ "libmediabenchmark_codec2_common",
+ "libmediabenchmark_extractor",
+ ],
+
+ export_include_dirs: ["."],
+
+ ldflags: ["-Wl,-Bsymbolic"]
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.cpp b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
new file mode 100644
index 0000000..20a1468
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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 "C2Decoder"
+#include <log/log.h>
+
+#include "C2Decoder.h"
+#include <iostream>
+
+int32_t C2Decoder::createCodec2Component(string compName, AMediaFormat *format) {
+ ALOGV("In %s", __func__);
+ mListener.reset(new CodecListener(
+ [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
+ if (!mListener) return -1;
+
+ const char *mime = nullptr;
+ AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
+ if (!mime) {
+ ALOGE("Error in AMediaFormat_getString");
+ return -1;
+ }
+ // Configure the plugin with Input properties
+ std::vector<C2Param *> configParam;
+ if (!strncmp(mime, "audio/", 6)) {
+ int32_t sampleRate, numChannels;
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels);
+ C2StreamSampleRateInfo::output sampleRateInfo(0u, sampleRate);
+ C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
+ configParam.push_back(&sampleRateInfo);
+ configParam.push_back(&channelCountInfo);
+
+ } else {
+ int32_t width, height;
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
+ AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
+ C2StreamPictureSizeInfo::input inputSize(0u, width, height);
+ configParam.push_back(&inputSize);
+ }
+
+ int64_t sTime = mStats->getCurTime();
+ mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
+ if (mComponent == nullptr) {
+ ALOGE("Create component failed for %s", compName.c_str());
+ return -1;
+ }
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
+ if (failures.size() != 0) {
+ ALOGE("Invalid Configuration");
+ return -1;
+ }
+
+ status |= mComponent->start();
+ int64_t eTime = mStats->getCurTime();
+ int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+ mStats->setInitTime(timeTaken);
+ return status;
+}
+
+int32_t C2Decoder::decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo) {
+ ALOGV("In %s", __func__);
+ typedef std::unique_lock<std::mutex> ULock;
+ c2_status_t status = C2_OK;
+ mStats->setStartTime();
+ while (1) {
+ if (mNumInputFrame == frameInfo.size()) break;
+ std::unique_ptr<C2Work> work;
+ // Prepare C2Work
+ {
+ ULock l(mQueueLock);
+ if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
+ if (!mWorkQueue.empty()) {
+ mStats->addInputTime();
+ work.swap(mWorkQueue.front());
+ mWorkQueue.pop_front();
+ } else {
+ std::cout << "Wait for generating C2Work exceeded timeout" << std::endl;
+ return -1;
+ }
+ }
+
+ uint32_t flags = frameInfo[mNumInputFrame].flags;
+ if (flags == AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
+ flags = C2FrameData::FLAG_CODEC_CONFIG;
+ }
+ if (mNumInputFrame == (frameInfo.size() - 1)) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
+ }
+ work->input.flags = (C2FrameData::flags_t)flags;
+ work->input.ordinal.timestamp = frameInfo[mNumInputFrame].presentationTimeUs;
+ work->input.ordinal.frameIndex = mNumInputFrame;
+ work->input.buffers.clear();
+ int size = frameInfo[mNumInputFrame].size;
+ int alignedSize = ALIGN(size, PAGE_SIZE);
+ if (size) {
+ std::shared_ptr<C2LinearBlock> block;
+ status = mLinearPool->fetchLinearBlock(
+ alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
+ if (status != C2_OK || block == nullptr) {
+ std::cout << "C2LinearBlock::map() failed : " << status << std::endl;
+ return status;
+ }
+
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ std::cout << "C2LinearBlock::map() failed : " << view.error() << std::endl;
+ return view.error();
+ }
+ memcpy(view.base(), inputBuffer + mOffset, size);
+ work->input.buffers.emplace_back(new LinearBuffer(block, size));
+ mStats->addFrameSize(size);
+ }
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+ // queue() invokes process() function of C2 Plugin.
+ status = mComponent->queue(&items);
+ if (status != C2_OK) {
+ ALOGE("queue failed");
+ return status;
+ }
+ ALOGV("Frame #%d size = %d queued", mNumInputFrame, size);
+ mNumInputFrame++;
+ mOffset += size;
+ }
+ return status;
+}
+
+void C2Decoder::deInitCodec() {
+ ALOGV("In %s", __func__);
+ if (!mComponent) return;
+
+ int64_t sTime = mStats->getCurTime();
+ mComponent->stop();
+ mComponent->release();
+ mComponent = nullptr;
+ int64_t eTime = mStats->getCurTime();
+ int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
+ mStats->setDeInitTime(timeTaken);
+}
+
+void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs) {
+ string operation = "c2decode";
+ mStats->dumpStatistics(operation, inputReference, durationUs);
+}
+
+void C2Decoder::resetDecoder() {
+ mOffset = 0;
+ mNumInputFrame = 0;
+ if (mStats) mStats->reset();
+}
diff --git a/media/tests/benchmark/src/native/decoder/C2Decoder.h b/media/tests/benchmark/src/native/decoder/C2Decoder.h
new file mode 100644
index 0000000..4a3eb96
--- /dev/null
+++ b/media/tests/benchmark/src/native/decoder/C2Decoder.h
@@ -0,0 +1,47 @@
+/*
+ * 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 __C2_DECODER_H__
+#define __C2_DECODER_H__
+
+#include "BenchmarkC2Common.h"
+
+#define ALIGN(_sz, _align) (((_sz) + ((_align) - 1)) & ~((_align) - 1))
+
+class C2Decoder : public BenchmarkC2Common {
+ public:
+ C2Decoder() : mOffset(0), mNumInputFrame(0), mComponent(nullptr) {}
+
+ int32_t createCodec2Component(string codecName, AMediaFormat *format);
+
+ int32_t decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo);
+
+ void deInitCodec();
+
+ void dumpStatistics(string inputReference, int64_t durationUs);
+
+ void resetDecoder();
+
+ private:
+ int32_t mOffset;
+ int32_t mNumInputFrame;
+ vector<AMediaCodecBufferInfo> mFrameMetaData;
+
+ std::shared_ptr<android::Codec2Client::Listener> mListener;
+ std::shared_ptr<android::Codec2Client::Component> mComponent;
+};
+
+#endif // __C2_DECODER_H__
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.cpp b/media/tests/benchmark/src/native/decoder/Decoder.cpp
index ef84537..ac0d525 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.cpp
+++ b/media/tests/benchmark/src/native/decoder/Decoder.cpp
@@ -32,8 +32,8 @@
int64_t timestamp = frameInfo[frameID].presentationTimeUs;
ssize_t bytesCount = frameInfo[frameID].size;
if (bufSize < bytesCount) {
- ALOGE("Error : insufficient resource");
- return make_tuple(0, AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE, 0);
+ ALOGE("Error : Buffer size is insufficient to read sample");
+ return make_tuple(0, AMEDIA_ERROR_MALFORMED, 0);
}
memcpy(buf, inputBuffer + offset, bytesCount);
@@ -54,6 +54,7 @@
size_t bufSize;
uint8_t *buf = AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
if (!buf) {
+ mErrorCode = AMEDIA_ERROR_IO;
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
@@ -64,7 +65,8 @@
int64_t presentationTimeUs = 0;
tie(bytesRead, flag, presentationTimeUs) = readSampleData(
mInputBuffer, mOffset, mFrameMetaData, buf, mNumInputFrame, bufSize);
- if (flag == AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE) {
+ if (flag == AMEDIA_ERROR_MALFORMED) {
+ mErrorCode = (media_status_t)flag;
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
@@ -74,9 +76,10 @@
ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRId64 " mSawInputEOS : %s", __FUNCTION__,
bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
- int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
- presentationTimeUs, flag);
+ media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+ bytesRead, presentationTimeUs, flag);
if (AMEDIA_OK != status) {
+ mErrorCode = status;
mSignalledError = true;
mDecoderDoneCondition.notify_one();
return;
@@ -127,6 +130,16 @@
}
}
+void Decoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ ALOGE("Received Error %d", err);
+ mErrorCode = err;
+ mSignalledError = true;
+ mDecoderDoneCondition.notify_one();
+ }
+}
+
void Decoder::setupDecoder() {
if (!mFormat) mFormat = mExtractor->getFormat();
}
@@ -168,7 +181,8 @@
ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
- return AMEDIA_ERROR_IO;
+ mErrorCode = (media_status_t)inIdx;
+ return mErrorCode;
} else if (inIdx >= 0) {
mStats->addInputTime();
onInputAvailable(mCodec, inIdx);
@@ -188,13 +202,18 @@
} else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
- return AMEDIA_ERROR_IO;
+ mErrorCode = (media_status_t)outIdx;
+ return mErrorCode;
}
}
} else {
unique_lock<mutex> lock(mMutex);
mDecoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
}
+ if (mSignalledError) {
+ ALOGE("Received Error while Decoding");
+ return mErrorCode;
+ }
if (codecName.empty()) {
char *decName;
diff --git a/media/tests/benchmark/src/native/decoder/Decoder.h b/media/tests/benchmark/src/native/decoder/Decoder.h
index 7630e7b..aeda080 100644
--- a/media/tests/benchmark/src/native/decoder/Decoder.h
+++ b/media/tests/benchmark/src/native/decoder/Decoder.h
@@ -38,6 +38,7 @@
mSawInputEOS(false),
mSawOutputEOS(false),
mSignalledError(false),
+ mErrorCode(AMEDIA_OK),
mInputBuffer(nullptr),
mOutFp(nullptr) {
mExtractor = new Extractor();
@@ -61,6 +62,8 @@
void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+ void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
void onOutputAvailable(AMediaCodec *codec, int32_t index,
AMediaCodecBufferInfo *bufferInfo) override;
@@ -82,6 +85,7 @@
bool mSawInputEOS;
bool mSawOutputEOS;
bool mSignalledError;
+ media_status_t mErrorCode;
int32_t mOffset;
uint8_t *mInputBuffer;
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.cpp b/media/tests/benchmark/src/native/encoder/Encoder.cpp
index 5fdf9e3..a5605de 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/Encoder.cpp
@@ -34,6 +34,7 @@
size_t bufSize = 0;
char *buf = (char *)AMediaCodec_getInputBuffer(mCodec, bufIdx, &bufSize);
if (!buf) {
+ mErrorCode = AMEDIA_ERROR_IO;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -41,6 +42,7 @@
if (mInputBufferSize < mOffset) {
ALOGE("Out of bound access of input buffer\n");
+ mErrorCode = AMEDIA_ERROR_MALFORMED;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -51,6 +53,7 @@
}
if (bufSize < bytesRead) {
ALOGE("bytes to read %zu bufSize %zu \n", bytesRead, bufSize);
+ mErrorCode = AMEDIA_ERROR_MALFORMED;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -58,6 +61,7 @@
if (bytesRead < mParams.frameSize && mNumInputFrame < mParams.numFrames - 1) {
ALOGE("Partial frame at frameID %d bytesRead %zu frameSize %d total numFrames %d\n",
mNumInputFrame, bytesRead, mParams.frameSize, mParams.numFrames);
+ mErrorCode = AMEDIA_ERROR_MALFORMED;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -66,6 +70,7 @@
size_t bytesgcount = mEleStream->gcount();
if (bytesgcount != bytesRead) {
ALOGE("bytes to read %zu actual bytes read %zu \n", bytesRead, bytesgcount);
+ mErrorCode = AMEDIA_ERROR_MALFORMED;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -89,9 +94,10 @@
ALOGV("%s bytesRead : %zd presentationTimeUs : %" PRIu64 " mSawInputEOS : %s", __FUNCTION__,
bytesRead, presentationTimeUs, mSawInputEOS ? "TRUE" : "FALSE");
- int status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */, bytesRead,
- presentationTimeUs, flag);
+ media_status_t status = AMediaCodec_queueInputBuffer(mCodec, bufIdx, 0 /* offset */,
+ bytesRead, presentationTimeUs, flag);
if (AMEDIA_OK != status) {
+ mErrorCode = status;
mSignalledError = true;
mEncoderDoneCondition.notify_one();
return;
@@ -133,6 +139,16 @@
}
}
+void Encoder::onError(AMediaCodec *mediaCodec, media_status_t err) {
+ ALOGV("In %s", __func__);
+ if (mediaCodec == mCodec && mediaCodec) {
+ ALOGE("Received Error %d", err);
+ mErrorCode = err;
+ mSignalledError = true;
+ mEncoderDoneCondition.notify_one();
+ }
+}
+
void Encoder::setupEncoder() {
if (!mFormat) mFormat = AMediaFormat_new();
}
@@ -235,7 +251,8 @@
ssize_t inIdx = AMediaCodec_dequeueInputBuffer(mCodec, kQueueDequeueTimeoutUs);
if (inIdx < 0 && inIdx != AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
ALOGE("AMediaCodec_dequeueInputBuffer returned invalid index %zd\n", inIdx);
- return AMEDIA_ERROR_IO;
+ mErrorCode = (media_status_t)inIdx;
+ return mErrorCode;
} else if (inIdx >= 0) {
mStats->addInputTime();
onInputAvailable(mCodec, inIdx);
@@ -255,13 +272,18 @@
} else if (!(outIdx == AMEDIACODEC_INFO_TRY_AGAIN_LATER ||
outIdx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)) {
ALOGE("AMediaCodec_dequeueOutputBuffer returned invalid index %zd\n", outIdx);
- return AMEDIA_ERROR_IO;
+ mErrorCode = (media_status_t)outIdx;
+ return mErrorCode;
}
}
} else {
unique_lock<mutex> lock(mMutex);
mEncoderDoneCondition.wait(lock, [this]() { return (mSawOutputEOS || mSignalledError); });
}
+ if (mSignalledError) {
+ ALOGE("Received Error while Encoding");
+ return mErrorCode;
+ }
if (codecName.empty()) {
char *encName;
diff --git a/media/tests/benchmark/src/native/encoder/Encoder.h b/media/tests/benchmark/src/native/encoder/Encoder.h
index 75d9941..6059c4a 100644
--- a/media/tests/benchmark/src/native/encoder/Encoder.h
+++ b/media/tests/benchmark/src/native/encoder/Encoder.h
@@ -49,7 +49,8 @@
mNumOutputFrame(0),
mSawInputEOS(false),
mSawOutputEOS(false),
- mSignalledError(false) {}
+ mSignalledError(false),
+ mErrorCode(AMEDIA_OK) {}
virtual ~Encoder() {}
@@ -65,6 +66,8 @@
void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) override;
+ void onError(AMediaCodec *mediaCodec, media_status_t err) override;
+
void onOutputAvailable(AMediaCodec *codec, int32_t index,
AMediaCodecBufferInfo *bufferInfo) override;
@@ -83,6 +86,7 @@
bool mSawInputEOS;
bool mSawOutputEOS;
bool mSignalledError;
+ media_status_t mErrorCode;
char *mMime;
int32_t mOffset;
diff --git a/media/tests/benchmark/tests/Android.bp b/media/tests/benchmark/tests/Android.bp
index 24fd68c..128d055 100644
--- a/media/tests/benchmark/tests/Android.bp
+++ b/media/tests/benchmark/tests/Android.bp
@@ -75,3 +75,20 @@
"libmediabenchmark_encoder",
],
}
+
+cc_test {
+ name: "C2DecoderTest",
+ gtest: true,
+ defaults: [
+ "libmediabenchmark_codec2_common-defaults",
+ "libmediabenchmark_soft_sanitize_all-defaults",
+ ],
+
+ srcs: ["C2DecoderTest.cpp"],
+
+ static_libs: [
+ "libmediabenchmark_extractor",
+ "libmediabenchmark_codec2_common",
+ "libmediabenchmark_codec2_decoder",
+ ],
+}
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
new file mode 100644
index 0000000..3531d8a
--- /dev/null
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -0,0 +1,213 @@
+/*
+ * 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 "C2DecoderTest"
+
+#include <fstream>
+#include <iostream>
+#include <limits>
+
+#include "BenchmarkTestEnvironment.h"
+#include "C2Decoder.h"
+#include "Extractor.h"
+
+static BenchmarkTestEnvironment *gEnv = nullptr;
+
+class C2DecoderTest : public ::testing::TestWithParam<pair<string, string>> {
+ public:
+ C2DecoderTest() : mDecoder(nullptr), disableTest(false) { setupC2DecoderTest(); }
+
+ void setupC2DecoderTest();
+
+ vector<string> mCodecList;
+ C2Decoder *mDecoder;
+ bool disableTest;
+};
+
+void C2DecoderTest::setupC2DecoderTest() {
+ mDecoder = new C2Decoder();
+ if (!mDecoder) {
+ cout << "[ WARN ] Test Skipped. C2Decoder creation failed\n";
+ disableTest = true;
+ return;
+ }
+ int32_t status = mDecoder->setupCodec2();
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Codec2 setup failed \n";
+ disableTest = true;
+ return;
+ }
+ mCodecList = mDecoder->getSupportedComponentList(false /* isEncoder*/);
+ if (!mCodecList.size()) {
+ cout << "[ WARN ] Test Skipped. Codec2 client didn't recognise any component \n";
+ disableTest = true;
+ return;
+ }
+}
+
+TEST_P(C2DecoderTest, Codec2Decode) {
+ if (disableTest) return;
+
+ ALOGV("Decode the samples given by extractor using codec2");
+ string inputFile = gEnv->getRes() + GetParam().first;
+ FILE *inputFp = fopen(inputFile.c_str(), "rb");
+ if (!inputFp) {
+ cout << "[ WARN ] Test Skipped. Unable to open input file" << inputFile
+ << " for reading \n";
+ return;
+ }
+
+ Extractor *extractor = new Extractor();
+ if (!extractor) {
+ cout << "[ WARN ] Test Skipped. Extractor creation failed \n";
+ return;
+ }
+
+ // Read file properties
+ fseek(inputFp, 0, SEEK_END);
+ size_t fileSize = ftell(inputFp);
+ fseek(inputFp, 0, SEEK_SET);
+ int32_t fd = fileno(inputFp);
+
+ if (fileSize > kMaxBufferSize) {
+ cout << "[ WARN ] Test Skipped. Input file size is greater than the threshold memory "
+ "dedicated to the test \n";
+ }
+
+ int32_t trackCount = extractor->initExtractor(fd, fileSize);
+ if (trackCount <= 0) {
+ cout << "[ WARN ] Test Skipped. initExtractor failed\n";
+ return;
+ }
+ for (int32_t curTrack = 0; curTrack < trackCount; curTrack++) {
+ int32_t status = extractor->setupTrackFormat(curTrack);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Track Format invalid \n";
+ return;
+ }
+
+ uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+ if (!inputBuffer) {
+ cout << "[ WARN ] Test Skipped. Insufficient memory \n";
+ return;
+ }
+
+ vector<AMediaCodecBufferInfo> frameInfo;
+ AMediaCodecBufferInfo info;
+ uint32_t inputBufferOffset = 0;
+ int32_t idx = 0;
+
+ // Get CSD data
+ while (1) {
+ void *csdBuffer = extractor->getCSDSample(info, idx);
+ if (!csdBuffer || !info.size) break;
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > fileSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ idx++;
+ }
+
+ // Get frame data
+ while (1) {
+ status = extractor->getFrameSample(info);
+ if (status || !info.size) break;
+ // copy the meta data and buffer to be passed to decoder
+ if (inputBufferOffset + info.size > fileSize) {
+ cout << "[ WARN ] Test Skipped. Memory allocated not sufficient\n";
+ free(inputBuffer);
+ return;
+ }
+ memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+ frameInfo.push_back(info);
+ inputBufferOffset += info.size;
+ }
+
+ AMediaFormat *format = extractor->getFormat();
+ // Decode the given input stream for all C2 codecs supported by device
+ for (string codecName : mCodecList) {
+ if (codecName.find(GetParam().second) != string::npos &&
+ codecName.find("secure") == string::npos) {
+ status = mDecoder->createCodec2Component(codecName, format);
+ if (status != 0) {
+ cout << "[ WARN ] Test Skipped. Create component failed for " << codecName
+ << "\n";
+ continue;
+ }
+
+ // Send the inputs to C2 Decoder and wait till all buffers are returned.
+ mDecoder->decodeFrames(inputBuffer, frameInfo);
+ mDecoder->waitOnInputConsumption();
+ if (!mDecoder->mEos) {
+ cout << "[ WARN ] Test Failed. Didn't receive EOS \n";
+ }
+ mDecoder->deInitCodec();
+ int64_t durationUs = extractor->getClipDuration();
+ cout << "codec: " << codecName << endl;
+ mDecoder->dumpStatistics(GetParam().first, durationUs);
+ mDecoder->resetDecoder();
+ }
+ }
+ free(inputBuffer);
+ fclose(inputFp);
+ extractor->deInitExtractor();
+ delete extractor;
+ delete mDecoder;
+ }
+}
+
+// TODO: (b/140549596)
+// Add wav files
+INSTANTIATE_TEST_SUITE_P(
+ AudioDecoderTest, C2DecoderTest,
+ ::testing::Values(
+ make_pair("bbb_44100hz_2ch_128kbps_aac_30sec.mp4", "aac"),
+ make_pair("bbb_44100hz_2ch_128kbps_mp3_30sec.mp3", "mp3"),
+ make_pair("bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp", "amrnb"),
+ make_pair("bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp", "amrnb"),
+ make_pair("bbb_44100hz_2ch_80kbps_vorbis_30sec.mp4", "vorbis"),
+ make_pair("bbb_44100hz_2ch_600kbps_flac_30sec.mp4", "flac"),
+ make_pair("bbb_48000hz_2ch_100kbps_opus_30sec.webm", "opus")));
+
+INSTANTIATE_TEST_SUITE_P(
+ VideoDecoderTest, C2DecoderTest,
+ ::testing::Values(
+ make_pair("crowd_1920x1080_25fps_4000kbps_vp9.webm", "vp9"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_vp8.webm", "vp8"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_av1.webm", "av1"),
+ make_pair("crowd_1920x1080_25fps_7300kbps_mpeg2.mp4", "mpeg2"),
+ make_pair("crowd_1920x1080_25fps_6000kbps_mpeg4.mp4", "mpeg4"),
+ make_pair("crowd_352x288_25fps_6000kbps_h263.3gp", "h263"),
+ make_pair("crowd_1920x1080_25fps_6700kbps_h264.ts", "avc"),
+ make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
+
+int main(int argc, char **argv) {
+ gEnv = new BenchmarkTestEnvironment();
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = gEnv->initFromOptions(argc, argv);
+ if (status == 0) {
+ status = RUN_ALL_TESTS();
+ ALOGV("C2 Decoder Test result = %d\n", status);
+ }
+ return status;
+}
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 242178f..fa37435 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -93,7 +93,7 @@
decoder->setupDecoder();
status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
if (status != AMEDIA_OK) {
- cout << "[ WARN ] Test Skipped. Decode returned error \n";
+ cout << "[ WARN ] Test Failed. Decode returned error " << status << endl;
free(inputBuffer);
return;
}
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index 9f42c64..c3963f8 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -143,7 +143,11 @@
string codecName = get<1>(params);
bool asyncMode = get<2>(params);
status = encoder->encode(codecName, eleStream, eleSize, asyncMode, encParams, (char *)mime);
- ASSERT_EQ(status, 0);
+ if (status != AMEDIA_OK) {
+ cout << "[ WARN ] Test Failed. Encode returned error " << status << endl;
+ free(inputBuffer);
+ return;
+ }
encoder->deInitCodec();
cout << "codec : " << codecName << endl;
string inputReference = get<0>(params);
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 8a9039c..5047b19 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -51,6 +51,10 @@
"libmedia_headers",
],
+ include_dirs: [
+ // For DEBUGGER_SIGNAL
+ "system/core/debuggerd/include",
+ ],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
}
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 971ae9f..b132782 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -167,9 +167,16 @@
}
bool modifyAudioRoutingAllowed() {
+ return modifyAudioRoutingAllowed(
+ IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
+}
+
+bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid) {
+ if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
- bool ok = PermissionCache::checkCallingPermission(sModifyAudioRouting);
- if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING");
+ bool ok = PermissionCache::checkPermission(sModifyAudioRouting, pid, uid);
+ if (!ok) ALOGE("%s(): android.permission.MODIFY_AUDIO_ROUTING denied for uid %d",
+ __func__, uid);
return ok;
}
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 96f7802..4a3e470 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -14,13 +14,50 @@
* limitations under the License.
*/
+#define LOG_TAG "TimeCheck"
#include <utils/Log.h>
#include <mediautils/TimeCheck.h>
#include <mediautils/EventLog.h>
+#include "debuggerd/handler.h"
namespace android {
+// Audio HAL server pids vector used to generate audio HAL processes tombstone
+// when audioserver watchdog triggers.
+// We use a lockless storage to avoid potential deadlocks in the context of watchdog
+// trigger.
+// Protection again simultaneous writes is not needed given one update takes place
+// during AudioFlinger construction and other comes necessarily later once the IAudioFlinger
+// interface is available.
+// The use of an atomic index just guaranties that current vector is fully initialized
+// when read.
+/* static */
+void TimeCheck::accessAudioHalPids(std::vector<pid_t>* pids, bool update) {
+ static constexpr int kNumAudioHalPidsVectors = 3;
+ static std::vector<pid_t> audioHalPids[kNumAudioHalPidsVectors];
+ static std::atomic<int> curAudioHalPids = 0;
+
+ if (update) {
+ audioHalPids[(curAudioHalPids + 1) % kNumAudioHalPidsVectors] = *pids;
+ curAudioHalPids++;
+ } else {
+ *pids = audioHalPids[curAudioHalPids];
+ }
+}
+
+/* static */
+void TimeCheck::setAudioHalPids(const std::vector<pid_t>& pids) {
+ accessAudioHalPids(&(const_cast<std::vector<pid_t>&>(pids)), true);
+}
+
+/* static */
+std::vector<pid_t> TimeCheck::getAudioHalPids() {
+ std::vector<pid_t> pids;
+ accessAudioHalPids(&pids, false);
+ return pids;
+}
+
/* static */
sp<TimeCheck::TimeCheckThread> TimeCheck::getTimeCheckThread()
{
@@ -83,6 +120,18 @@
status = mCond.waitRelative(mMutex, waitTimeNs);
}
if (status != NO_ERROR) {
+ // Generate audio HAL processes tombstones and allow time to complete
+ // before forcing restart
+ std::vector<pid_t> pids = getAudioHalPids();
+ if (pids.size() != 0) {
+ for (const auto& pid : pids) {
+ ALOGI("requesting tombstone for pid: %d", pid);
+ sigqueue(pid, DEBUGGER_SIGNAL, {.sival_int = 0});
+ }
+ sleep(1);
+ } else {
+ ALOGI("No HAL process pid available, skipping tombstones");
+ }
LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag);
LOG_ALWAYS_FATAL("TimeCheck timeout for %s", tag);
}
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 2595761..9e852fd 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -85,6 +85,7 @@
bool captureHotwordAllowed(const String16& opPackageName, pid_t pid, uid_t uid);
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
+bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid);
bool modifyDefaultAudioEffectsAllowed();
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index 6c5f656..5ba6d7c 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -20,7 +20,7 @@
#include <utils/KeyedVector.h>
#include <utils/Thread.h>
-
+#include <vector>
namespace android {
@@ -35,6 +35,8 @@
TimeCheck(const char *tag, uint32_t timeoutMs = kDefaultTimeOutMs);
~TimeCheck();
+ static void setAudioHalPids(const std::vector<pid_t>& pids);
+ static std::vector<pid_t> getAudioHalPids();
private:
@@ -63,6 +65,7 @@
};
static sp<TimeCheckThread> getTimeCheckThread();
+ static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
const nsecs_t mEndTimeNs;
};
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index eba0b20..9756abb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -70,6 +70,7 @@
#include <media/nbaio/PipeReader.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
#include <private/android_filesystem_config.h>
//#define BUFLOG_NDEBUG 0
@@ -193,6 +194,9 @@
mEffectsFactoryHal = EffectsFactoryHalInterface::create();
mMediaLogNotifier->run("MediaLogNotifier");
+ std::vector<pid_t> halPids;
+ mDevicesFactoryHal->getHalPids(&halPids);
+ TimeCheck::setAudioHalPids(halPids);
}
void AudioFlinger::onFirstRef()
@@ -218,6 +222,11 @@
gAudioFlinger = this;
}
+status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
+ TimeCheck::setAudioHalPids(pids);
+ return NO_ERROR;
+}
+
AudioFlinger::~AudioFlinger()
{
while (!mRecordThreads.isEmpty()) {
@@ -1357,6 +1366,13 @@
}
}
+void AudioFlinger::updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+{
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ mRecordThreads.valueAt(i)->updateOutDevices(devices);
+ }
+}
+
// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
@@ -1573,7 +1589,7 @@
proposed.format = format;
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
- size_t frames;
+ size_t frames = 0;
for (;;) {
// Note: config is currently a const parameter for get_input_buffer_size()
// but we use a copy from proposed in case config changes from the call.
@@ -2361,8 +2377,7 @@
if (status == NO_ERROR) {
if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
sp<MmapPlaybackThread> thread =
- new MmapPlaybackThread(this, *output, outHwDev, outputStream,
- deviceType, AUDIO_DEVICE_NONE, mSystemReady);
+ new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
mMmapThreads.add(*output, thread);
ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
*output, thread.get());
@@ -2370,18 +2385,17 @@
} else {
sp<PlaybackThread> thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output, deviceType, mSystemReady);
+ thread = new OffloadThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created offload output: ID %d thread %p",
*output, thread.get());
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask)) {
- thread = new DirectOutputThread(
- this, outputStream, *output, deviceType, mSystemReady);
+ thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created direct output: ID %d thread %p",
*output, thread.get());
} else {
- thread = new MixerThread(this, outputStream, *output, deviceType, mSystemReady);
+ thread = new MixerThread(this, outputStream, *output, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p",
*output, thread.get());
}
@@ -2689,9 +2703,7 @@
AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
sp<MmapCaptureThread> thread =
- new MmapCaptureThread(this, *input,
- inHwDev, inputStream,
- primaryOutputDevice_l(), devices, mSystemReady);
+ new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady);
mMmapThreads.add(*input, thread);
ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
thread.get());
@@ -2700,13 +2712,7 @@
// Start record thread
// RecordThread requires both input and output device indication to forward to audio
// pre processing modules
- sp<RecordThread> thread = new RecordThread(this,
- inputStream,
- *input,
- primaryOutputDevice_l(),
- devices,
- mSystemReady
- );
+ sp<RecordThread> thread = new RecordThread(this, inputStream, *input, mSystemReady);
mRecordThreads.add(*input, thread);
ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
return thread;
@@ -3122,15 +3128,15 @@
return NULL;
}
-audio_devices_t AudioFlinger::primaryOutputDevice_l() const
+DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
{
PlaybackThread *thread = primaryPlaybackThread_l();
if (thread == NULL) {
- return 0;
+ return DeviceTypeSet();
}
- return thread->outDevice();
+ return thread->outDeviceTypes();
}
AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 65be06d..3b6bbdb 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -65,7 +65,10 @@
#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
#include <media/AudioBufferProvider.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioMixer.h>
+#include <media/DeviceDescriptorBase.h>
#include <media/ExtendedAudioBufferProvider.h>
#include <media/VolumeShaper.h>
@@ -278,6 +281,8 @@
virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+ virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
@@ -716,7 +721,7 @@
// return thread associated with primary hardware device, or NULL
PlaybackThread *primaryPlaybackThread_l() const;
- audio_devices_t primaryOutputDevice_l() const;
+ DeviceTypeSet primaryOutputDevice_l() const;
// return the playback thread with smallest HAL buffer size, and prefer fast
PlaybackThread *fastPlaybackThread_l() const;
@@ -750,6 +755,7 @@
std::vector< sp<EffectModule> > purgeStaleEffects_l();
void broacastParametersToRecordThreads_l(const String8& keyValuePairs);
+ void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index d54ab42..1355b1b 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -29,7 +29,9 @@
#include <system/audio_effects/effect_visualizer.h>
#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
+#include <media/AudioContainers.h>
#include <media/AudioEffect.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <mediautils/ServiceUtilities.h>
@@ -1229,9 +1231,11 @@
}
}
-status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
+status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+ const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
{
- if (device == AUDIO_DEVICE_NONE) {
+ audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
+ if (deviceType == AUDIO_DEVICE_NONE) {
return NO_ERROR;
}
@@ -1243,17 +1247,26 @@
if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
status_t cmdStatus;
uint32_t size = sizeof(status_t);
- uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
- EFFECT_CMD_SET_INPUT_DEVICE;
- status = mEffectInterface->command(cmd,
+ // FIXME: use audio device types and addresses when the hal interface is ready.
+ status = mEffectInterface->command(cmdCode,
sizeof(uint32_t),
- &device,
+ &deviceType,
&size,
&cmdStatus);
}
return status;
}
+status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+{
+ return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
+}
+
+status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+{
+ return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
+}
+
status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
{
Mutex::Autolock _l(mLock);
@@ -2288,12 +2301,21 @@
return mEffects.size();
}
-// setDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevice_l(audio_devices_t device)
+// setDevices_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
{
size_t size = mEffects.size();
for (size_t i = 0; i < size; i++) {
- mEffects[i]->setDevice(device);
+ mEffects[i]->setDevices(devices);
+ }
+}
+
+// setInputDevice_l() must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+{
+ size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->setInputDevice(device);
}
}
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 220874d..dbf63c8 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -109,7 +109,8 @@
const effect_descriptor_t& desc() const { return mDescriptor; }
wp<EffectChain>& chain() { return mChain; }
- status_t setDevice(audio_devices_t device);
+ status_t setDevices(const AudioDeviceTypeAddrVector &devices);
+ status_t setInputDevice(const AudioDeviceTypeAddr &device);
status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
status_t setMode(audio_mode_t mode);
status_t setAudioSource(audio_source_t source);
@@ -158,6 +159,7 @@
status_t start_l();
status_t stop_l();
status_t remove_effect_from_hal_l();
+ status_t sendSetAudioDevicesCommand(const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode);
mutable Mutex mLock; // mutex for process, commands and handles list protection
wp<ThreadBase> mThread; // parent thread
@@ -350,7 +352,8 @@
// FIXME use float to improve the dynamic range
bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
void resetVolume_l();
- void setDevice_l(audio_devices_t device);
+ void setDevices_l(const AudioDeviceTypeAddrVector &devices);
+ void setInputDevice_l(const AudioDeviceTypeAddr &device);
void setMode_l(audio_mode_t mode);
void setAudioSource_l(audio_source_t source);
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 18cb53b..53e2dd5 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -25,6 +25,7 @@
#include "AudioFlinger.h"
#include <media/AudioParameter.h>
+#include <media/DeviceDescriptorBase.h>
#include <media/PatchBuilder.h>
#include <mediautils/ServiceUtilities.h>
@@ -167,6 +168,7 @@
if (hwDevice != 0) {
hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
}
+ halHandle = removedPatch.mHalHandle;
}
mPatches.erase(iter);
removeSoftwarePatchFromInsertedModules(*handle);
@@ -351,7 +353,7 @@
goto exit;
}
// limit to connections between devices and output streams
- audio_devices_t type = AUDIO_DEVICE_NONE;
+ DeviceDescriptorBaseVector devices;
for (unsigned int i = 0; i < patch->num_sinks; i++) {
if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
ALOGW("%s() invalid sink type %d for mix source",
@@ -364,7 +366,11 @@
status = BAD_VALUE;
goto exit;
}
- type |= patch->sinks[i].ext.device.type;
+ sp<DeviceDescriptorBase> device = new DeviceDescriptorBase(
+ patch->sinks[i].ext.device.type);
+ device->setAddress(patch->sinks[i].ext.device.address);
+ device->applyAudioPortConfig(&patch->sinks[i]);
+ devices.push_back(device);
}
sp<ThreadBase> thread =
mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
@@ -378,10 +384,7 @@
}
}
if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
- AudioParameter param = AudioParameter();
- param.addInt(String8(AudioParameter::keyRouting), (int)type);
-
- mAudioFlinger.broacastParametersToRecordThreads_l(param.toString());
+ mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
}
status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8704d16..4be21b1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -29,6 +29,8 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <cutils/properties.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioParameter.h>
#include <media/AudioResamplerPublic.h>
#include <media/RecordBufferConverter.h>
@@ -460,7 +462,7 @@
}
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- audio_devices_t outDevice, audio_devices_t inDevice, type_t type, bool systemReady)
+ type_t type, bool systemReady)
: Thread(false /*canCallJava*/),
mType(type),
mAudioFlinger(audioFlinger),
@@ -468,8 +470,7 @@
// are set by PlaybackThread::readOutputParameters_l() or
// RecordThread::readInputParameters_l()
//FIXME: mStandby should be true here. Is this some kind of hack?
- mStandby(false), mOutDevice(outDevice), mInDevice(inDevice),
- mPrevOutDevice(AUDIO_DEVICE_NONE), mPrevInDevice(AUDIO_DEVICE_NONE),
+ mStandby(false),
mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id),
// mName will be set by concrete (non-virtual) subclass
mDeathRecipient(new PMDeathRecipient(this)),
@@ -646,6 +647,18 @@
return sendConfigEvent_l(configEvent);
}
+status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+ const DeviceDescriptorBaseVector& outDevices)
+{
+ if (type() != RECORD) {
+ // The update out device operation is only for record thread.
+ return INVALID_OPERATION;
+ }
+ Mutex::Autolock _l(mLock);
+ sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
+ return sendConfigEvent_l(configEvent);
+}
+
// post condition: mConfigEvents.isEmpty()
void AudioFlinger::ThreadBase::processConfigEvents_l()
@@ -680,24 +693,29 @@
}
} break;
case CFG_EVENT_CREATE_AUDIO_PATCH: {
- const audio_devices_t oldDevice = getDevice();
+ const DeviceTypeSet oldDevices = getDeviceTypes();
CreateAudioPatchConfigEventData *data =
(CreateAudioPatchConfigEventData *)event->mData.get();
event->mStatus = createAudioPatch_l(&data->mPatch, &data->mHandle);
- const audio_devices_t newDevice = getDevice();
- mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, toString(oldDevice).c_str(),
- (unsigned)newDevice, toString(newDevice).c_str());
+ const DeviceTypeSet newDevices = getDeviceTypes();
+ mLocalLog.log("CFG_EVENT_CREATE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+ dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+ dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
} break;
case CFG_EVENT_RELEASE_AUDIO_PATCH: {
- const audio_devices_t oldDevice = getDevice();
+ const DeviceTypeSet oldDevices = getDeviceTypes();
ReleaseAudioPatchConfigEventData *data =
(ReleaseAudioPatchConfigEventData *)event->mData.get();
event->mStatus = releaseAudioPatch_l(data->mHandle);
- const audio_devices_t newDevice = getDevice();
- mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %#x (%s) new device %#x (%s)",
- (unsigned)oldDevice, toString(oldDevice).c_str(),
- (unsigned)newDevice, toString(newDevice).c_str());
+ const DeviceTypeSet newDevices = getDeviceTypes();
+ mLocalLog.log("CFG_EVENT_RELEASE_AUDIO_PATCH: old device %s (%s) new device %s (%s)",
+ dumpDeviceTypes(oldDevices).c_str(), toString(oldDevices).c_str(),
+ dumpDeviceTypes(newDevices).c_str(), toString(newDevices).c_str());
+ } break;
+ case CFG_EVENT_UPDATE_OUT_DEVICE: {
+ UpdateOutDevicesConfigEventData *data =
+ (UpdateOutDevicesConfigEventData *)event->mData.get();
+ updateOutDevices(data->mOutDevices);
} break;
default:
ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
@@ -840,8 +858,10 @@
dprintf(fd, " none\n");
}
// Note: output device may be used by capture threads for effects such as AEC.
- dprintf(fd, " Output device: %#x (%s)\n", mOutDevice, toString(mOutDevice).c_str());
- dprintf(fd, " Input device: %#x (%s)\n", mInDevice, toString(mInDevice).c_str());
+ dprintf(fd, " Output devices: %s (%s)\n",
+ dumpDeviceTypes(outDeviceTypes()).c_str(), toString(outDeviceTypes()).c_str());
+ dprintf(fd, " Input device: %#x (%s)\n",
+ inDeviceType(), toString(inDeviceType()).c_str());
dprintf(fd, " Audio source: %d (%s)\n", mAudioSource, toString(mAudioSource).c_str());
// Dump timestamp statistics for the Thread types that support it.
@@ -1011,6 +1031,12 @@
mPowerManager.clear();
}
+void AudioFlinger::ThreadBase::updateOutDevices(
+ const DeviceDescriptorBaseVector& outDevices __unused)
+{
+ ALOGE("%s should only be called in RecordThread", __func__);
+}
+
void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
{
sp<ThreadBase> thread = mThread.promote();
@@ -1351,8 +1377,9 @@
}
effectCreated = true;
- effect->setDevice(mOutDevice);
- effect->setDevice(mInDevice);
+ // FIXME: use vector of device and address when effect interface is ready.
+ effect->setDevices(outDeviceTypeAddrs());
+ effect->setInputDevice(inDeviceTypeAddr());
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
}
@@ -1468,8 +1495,8 @@
return status;
}
- effect->setDevice(mOutDevice);
- effect->setDevice(mInDevice);
+ effect->setDevices(outDeviceTypeAddrs());
+ effect->setInputDevice(inDeviceTypeAddr());
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
@@ -1702,8 +1729,8 @@
item->setInt64(MM_PREFIX "channelMask", (int64_t)mChannelMask);
item->setCString(MM_PREFIX "encoding", toString(mFormat).c_str());
item->setInt32(MM_PREFIX "frameCount", (int32_t)mFrameCount);
- item->setCString(MM_PREFIX "outDevice", toString(mOutDevice).c_str());
- item->setCString(MM_PREFIX "inDevice", toString(mInDevice).c_str());
+ item->setCString(MM_PREFIX "outDevice", toString(outDeviceTypes()).c_str());
+ item->setCString(MM_PREFIX "inDevice", toString(inDeviceType()).c_str());
// thread statistics
if (mIoJitterMs.getN() > 0) {
@@ -1734,10 +1761,9 @@
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
audio_io_handle_t id,
- audio_devices_t device,
type_t type,
bool systemReady)
- : ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
+ : ThreadBase(audioFlinger, id, type, systemReady),
mNormalFrameCount(0), mSinkBuffer(NULL),
mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
mMixerBuffer(NULL),
@@ -1800,8 +1826,9 @@
// TODO: We may also match on address as well as device type for
// AUDIO_DEVICE_OUT_BUS, AUDIO_DEVICE_OUT_ALL_A2DP, AUDIO_DEVICE_OUT_REMOTE_SUBMIX
if (type == MIXER || type == DIRECT) {
- mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
- "audio.timestamp.corrected_output_devices",
+ // TODO: This property should be ensure that only contains one single device type.
+ mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_output_device",
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
}
@@ -2891,7 +2918,7 @@
{
if (!mMasterMute) {
char value[PROPERTY_VALUE_MAX];
- if (mOutDevice == AUDIO_DEVICE_OUT_REMOTE_SUBMIX) {
+ if (isSingleDeviceType(outDeviceTypes(), AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) {
ALOGD("ro.audio.silent will be ignored for threads on AUDIO_DEVICE_OUT_REMOTE_SUBMIX");
return;
}
@@ -3035,7 +3062,7 @@
// make sure standby delay is not too short when connected to an A2DP sink to avoid
// truncating audio when going to standby.
mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs;
- if ((mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) {
+ if (!Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty()) {
if (mStandbyDelayNs < kDefaultStandbyTimeInNsecs) {
mStandbyDelayNs = kDefaultStandbyTimeInNsecs;
}
@@ -3283,8 +3310,8 @@
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
- // Note: we access outDevice() outside of mLock.
- if (isMsdDevice() && (outDevice() & AUDIO_DEVICE_OUT_BUS) != 0) {
+ // Note: we access outDeviceTypes() outside of mLock.
+ if (isMsdDevice() && outDeviceTypes().count(AUDIO_DEVICE_OUT_BUS) != 0) {
// Here, we try for the AF lock, but do not block on it as the latency
// is more informational.
if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
@@ -3820,8 +3847,10 @@
if (diff > 0) {
// notify of throttle end on debug log
// but prevent spamming for bluetooth
- ALOGD_IF(!audio_is_a2dp_out_device(outDevice()) &&
- !audio_is_hearing_aid_out_device(outDevice()),
+ ALOGD_IF(!isSingleDeviceType(
+ outDeviceTypes(), audio_is_a2dp_out_device) &&
+ !isSingleDeviceType(
+ outDeviceTypes(), audio_is_hearing_aid_out_device),
"mixer(%p) throttle end: throttle time(%u)", this, diff);
mThreadThrottleEndMs = mThreadThrottleTimeMs;
}
@@ -4006,25 +4035,31 @@
// store new device and send to effects
audio_devices_t type = AUDIO_DEVICE_NONE;
+ AudioDeviceTypeAddrVector deviceTypeAddrs;
for (unsigned int i = 0; i < patch->num_sinks; i++) {
+ LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+ && !mOutput->audioHwDev->supportsAudioPatches(),
+ "Enumerated device type(%#x) must not be used "
+ "as it does not support audio patches",
+ patch->sinks[i].ext.device.type);
type |= patch->sinks[i].ext.device.type;
+ deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address));
}
audio_port_handle_t sinkPortId = patch->sinks[0].id;
#ifdef ADD_BATTERY_DATA
// when changing the audio output device, call addBatteryData to notify
// the change
- if (mOutDevice != type) {
+ if (outDeviceTypes() != deviceTypes) {
uint32_t params = 0;
// check whether speaker is on
- if (type & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (deviceTypes.count(AUDIO_DEVICE_OUT_SPEAKER) > 0) {
params |= IMediaPlayerService::kBatteryDataSpeakerOn;
}
- audio_devices_t deviceWithoutSpeaker
- = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
// check if any other device (except speaker) is on
- if (type & deviceWithoutSpeaker) {
+ if (!isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_SPEAKER)) {
params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
}
@@ -4035,14 +4070,15 @@
#endif
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(type);
+ mEffectChains[i]->setDevices_l(deviceTypeAddrs);
}
- // mPrevOutDevice is the latest device set by createAudioPatch_l(). It is not set when
- // the thread is created so that the first patch creation triggers an ioConfigChanged callback
- bool configChanged = (mPrevOutDevice != type) || (mDeviceId != sinkPortId);
- mOutDevice = type;
+ // mPatch.num_sinks is not set when the thread is created so that
+ // the first patch creation triggers an ioConfigChanged callback
+ bool configChanged = (mPatch.num_sinks == 0) ||
+ (mPatch.sinks[0].id != sinkPortId);
mPatch = *patch;
+ mOutDeviceTypeAddrs = deviceTypeAddrs;
if (mOutput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4068,8 +4104,6 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
if (configChanged) {
- mPrevOutDevice = type;
- mDeviceId = sinkPortId;
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
return status;
@@ -4093,7 +4127,8 @@
{
status_t status = NO_ERROR;
- mOutDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mOutDeviceTypeAddrs.clear();
if (mOutput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mOutput->audioHwDev->hwDevice();
@@ -4133,8 +4168,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, bool systemReady, type_t type)
- : PlaybackThread(audioFlinger, output, id, device, type, systemReady),
+ audio_io_handle_t id, bool systemReady, type_t type)
+ : PlaybackThread(audioFlinger, output, id, type, systemReady),
// mAudioMixer below
// mFastMixer below
mFastMixerFutex(0),
@@ -4144,7 +4179,7 @@
// mNormalSink below
{
setMasterBalance(audioFlinger->getMasterBalance_l());
- ALOGV("MixerThread() id=%d device=%#x type=%d", id, device, type);
+ ALOGV("MixerThread() id=%d type=%d", id, type);
ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
"mFrameCount=%zu, mNormalFrameCount=%zu",
mSampleRate, mChannelMask, mChannelCount, mFormat, mFrameSize, mFrameCount,
@@ -4186,7 +4221,7 @@
// scheduled reliably with CFS. However, the BT A2DP HAL is
// bursty (does not pull at a regular rate) and so cannot operate with FastMixer.
initFastMixer = mFrameCount < mNormalFrameCount
- && (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) == 0;
+ && Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty();
break;
}
ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
@@ -5357,39 +5392,7 @@
}
}
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
-#ifdef ADD_BATTERY_DATA
- // when changing the audio output device, call addBatteryData to notify
- // the change
- if (mOutDevice != value) {
- uint32_t params = 0;
- // check whether speaker is on
- if (value & AUDIO_DEVICE_OUT_SPEAKER) {
- params |= IMediaPlayerService::kBatteryDataSpeakerOn;
- }
-
- audio_devices_t deviceWithoutSpeaker
- = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
- // check if any other device (except speaker) is on
- if (value & deviceWithoutSpeaker) {
- params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
- }
-
- if (params != 0) {
- addBatteryData(params);
- }
- }
-#endif
-
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (value != AUDIO_DEVICE_NONE) {
- a2dpDeviceChanged =
- (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
- mOutDevice = value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mOutDevice);
- }
- }
+ LOG_FATAL("Should not set routing device in MixerThread");
}
if (status == NO_ERROR) {
@@ -5490,9 +5493,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device,
- ThreadBase::type_t type, bool systemReady)
- : PlaybackThread(audioFlinger, output, id, device, type, systemReady)
+ AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady)
+ : PlaybackThread(audioFlinger, output, id, type, systemReady)
{
setMasterBalance(audioFlinger->getMasterBalance_l());
}
@@ -5894,16 +5896,7 @@
AudioParameter param = AudioParameter(keyValuePair);
int value;
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (value != AUDIO_DEVICE_NONE) {
- a2dpDeviceChanged =
- (mOutDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != (value & AUDIO_DEVICE_OUT_ALL_A2DP);
- mOutDevice = value;
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mOutDevice);
- }
- }
+ LOG_FATAL("Should not set routing device in DirectOutputThread");
}
if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
// do not accept frame count changes if tracks are open as the track buffer
@@ -6115,8 +6108,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
+ AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
+ : DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
mOffloadUnderrunPosition(~0LL)
{
@@ -6441,7 +6434,7 @@
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
- : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->outDevice(),
+ : MixerThread(audioFlinger, mainThread->getOutput(), id,
systemReady, DUPLICATING),
mWaitTimeMs(UINT_MAX)
{
@@ -6673,11 +6666,9 @@
AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input,
audio_io_handle_t id,
- audio_devices_t outDevice,
- audio_devices_t inDevice,
bool systemReady
) :
- ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady),
+ ThreadBase(audioFlinger, id, RECORD, systemReady),
mInput(input),
mSource(mInput),
mActiveTracks(&this->mLocalLog),
@@ -6709,8 +6700,9 @@
// TODO: We may also match on address as well as device type for
// AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_IN_REMOTE_SUBMIX
- mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
- "audio.timestamp.corrected_input_devices",
+ // TODO: This property should be ensure that only contains one single device type.
+ mTimestampCorrectedDevice = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_input_device",
(int64_t)(mIsMsdDevice ? AUDIO_DEVICE_IN_BUS // turn on by default for MSD
: AUDIO_DEVICE_NONE));
@@ -8054,7 +8046,7 @@
{
// disable AEC and NS if the device is a BT SCO headset supporting those
// pre processings
- bool suspend = audio_is_bluetooth_sco_device(mInDevice) &&
+ bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
mAudioFlinger->btNrecIsOff();
if (mBtNrecSuspended.exchange(suspend) != suspend) {
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -8119,34 +8111,11 @@
}
}
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(value);
- }
-
- // store input device and output device but do not forward output device to audio HAL.
- // Note that status is ignored by the caller for output device
- // (see AudioFlinger::setParameters()
- if (audio_is_output_devices(value)) {
- mOutDevice = value;
- status = BAD_VALUE;
- } else {
- mInDevice = value;
- if (value != AUDIO_DEVICE_NONE) {
- mPrevInDevice = value;
- }
- checkBtNrec_l();
- }
+ LOG_FATAL("Should not set routing device in RecordThread");
}
if (param.getInt(String8(AudioParameter::keyInputSource), value) == NO_ERROR &&
mAudioSource != (audio_source_t)value) {
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setAudioSource_l((audio_source_t)value);
- }
- mAudioSource = (audio_source_t)value;
+ LOG_FATAL("Should not set audio source in RecordThread");
}
if (status == NO_ERROR) {
@@ -8348,11 +8317,11 @@
status_t status = NO_ERROR;
// store new device and send to effects
- mInDevice = patch->sources[0].ext.device.type;
+ mInDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+ mInDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
audio_port_handle_t deviceId = patch->sources[0].id;
- mPatch = *patch;
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(mInDevice);
+ mEffectChains[i]->setInputDevice_l(inDeviceTypeAddr());
}
checkBtNrec_l();
@@ -8391,10 +8360,9 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if ((mInDevice != mPrevInDevice) || (mDeviceId != deviceId)) {
+ if ((mPatch.num_sources == 0) || (mPatch.sources[0].id != deviceId)) {
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
- mPrevInDevice = mInDevice;
- mDeviceId = deviceId;
+ mPatch = *patch;
}
return status;
@@ -8404,7 +8372,8 @@
{
status_t status = NO_ERROR;
- mInDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mInDeviceTypeAddr.reset();
if (mInput->audioHwDev->supportsAudioPatches()) {
sp<DeviceHalInterface> hwDevice = mInput->audioHwDev->hwDevice();
@@ -8417,6 +8386,15 @@
return status;
}
+void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+{
+ mOutDevices = outDevices;
+ mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->setDevices_l(outDeviceTypeAddrs());
+ }
+}
+
void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
{
Mutex::Autolock _l(mLock);
@@ -8493,9 +8471,8 @@
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : ThreadBase(audioFlinger, id, outDevice, inDevice, MMAP, systemReady),
+ AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady)
+ : ThreadBase(audioFlinger, id, MMAP, systemReady),
mSessionId(AUDIO_SESSION_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE),
mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
@@ -8861,26 +8838,7 @@
int value;
bool sendToHal = true;
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
- audio_devices_t device = (audio_devices_t)value;
- // forward device change to effects that have requested to be
- // aware of attached audio device.
- if (device != AUDIO_DEVICE_NONE) {
- for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(device);
- }
- }
- if (audio_is_output_devices(device)) {
- mOutDevice = device;
- if (!isOutput()) {
- sendToHal = false;
- }
- } else {
- mInDevice = device;
- if (device != AUDIO_DEVICE_NONE) {
- mPrevInDevice = value;
- }
- // TODO: implement and call checkBtNrec_l();
- }
+ LOG_FATAL("Should not happen set routing device in MmapThread");
}
if (sendToHal) {
status = mHalStream->setParameters(keyValuePair);
@@ -8939,24 +8897,39 @@
// store new device and send to effects
audio_devices_t type = AUDIO_DEVICE_NONE;
audio_port_handle_t deviceId;
+ AudioDeviceTypeAddrVector sinkDeviceTypeAddrs;
+ AudioDeviceTypeAddr sourceDeviceTypeAddr;
+ uint32_t numDevices = 0;
if (isOutput()) {
for (unsigned int i = 0; i < patch->num_sinks; i++) {
+ LOG_ALWAYS_FATAL_IF(popcount(patch->sinks[i].ext.device.type) > 1
+ && !mAudioHwDev->supportsAudioPatches(),
+ "Enumerated device type(%#x) must not be used "
+ "as it does not support audio patches",
+ patch->sinks[i].ext.device.type);
type |= patch->sinks[i].ext.device.type;
+ sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address));
}
deviceId = patch->sinks[0].id;
+ numDevices = mPatch.num_sinks;
} else {
type = patch->sources[0].ext.device.type;
deviceId = patch->sources[0].id;
+ numDevices = mPatch.num_sources;
+ sourceDeviceTypeAddr.mType = patch->sources[0].ext.device.type;
+ sourceDeviceTypeAddr.mAddress = patch->sources[0].ext.device.address;
}
for (size_t i = 0; i < mEffectChains.size(); i++) {
- mEffectChains[i]->setDevice_l(type);
+ if (isOutput()) {
+ mEffectChains[i]->setDevices_l(sinkDeviceTypeAddrs);
+ } else {
+ mEffectChains[i]->setInputDevice_l(sourceDeviceTypeAddr);
+ }
}
- if (isOutput()) {
- mOutDevice = type;
- } else {
- mInDevice = type;
+ if (!isOutput()) {
// store new source and send to effects
if (mAudioSource != patch->sinks[0].ext.mix.usecase.source) {
mAudioSource = patch->sinks[0].ext.mix.usecase.source;
@@ -8993,26 +8966,21 @@
*handle = AUDIO_PATCH_HANDLE_NONE;
}
- if (isOutput() && (mPrevOutDevice != mOutDevice || mDeviceId != deviceId)) {
- mPrevOutDevice = type;
- sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+ if (numDevices == 0 || mDeviceId != deviceId) {
+ if (isOutput()) {
+ sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
+ mOutDeviceTypeAddrs = sinkDeviceTypeAddrs;
+ } else {
+ sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
+ mInDeviceTypeAddr = sourceDeviceTypeAddr;
+ }
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
mLock.unlock();
callback->onRoutingChanged(deviceId);
mLock.lock();
}
- mDeviceId = deviceId;
- }
- if (!isOutput() && (mPrevInDevice != mInDevice || mDeviceId != deviceId)) {
- mPrevInDevice = type;
- sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
- sp<MmapStreamCallback> callback = mCallback.promote();
- if (mDeviceId != deviceId && callback != 0) {
- mLock.unlock();
- callback->onRoutingChanged(deviceId);
- mLock.lock();
- }
+ mPatch = *patch;
mDeviceId = deviceId;
}
return status;
@@ -9022,7 +8990,9 @@
{
status_t status = NO_ERROR;
- mInDevice = AUDIO_DEVICE_NONE;
+ mPatch = audio_patch{};
+ mOutDeviceTypeAddrs.clear();
+ mInDeviceTypeAddr.reset();
bool supportsAudioPatches = mHalDevice->supportsAudioPatches(&supportsAudioPatches) == OK ?
supportsAudioPatches : false;
@@ -9198,9 +9168,8 @@
AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamOut *output,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, output->stream, outDevice, inDevice, systemReady),
+ AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady)
+ : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady),
mStreamType(AUDIO_STREAM_MUSIC),
mStreamVolume(1.0),
mStreamMute(false),
@@ -9410,9 +9379,8 @@
AudioFlinger::MmapCaptureThread::MmapCaptureThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamIn *input,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady)
- : MmapThread(audioFlinger, id, hwDev, input->stream, outDevice, inDevice, systemReady),
+ AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady)
+ : MmapThread(audioFlinger, id, hwDev, input->stream, systemReady),
mInput(input)
{
snprintf(mThreadName, kThreadNameLength, "AudioMmapIn_%X", id);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 34a3f34..ef7eb6e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -37,8 +37,7 @@
static const char *threadTypeToString(type_t type);
ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- audio_devices_t outDevice, audio_devices_t inDevice, type_t type,
- bool systemReady);
+ type_t type, bool systemReady);
virtual ~ThreadBase();
virtual status_t readyToRun();
@@ -52,6 +51,7 @@
CFG_EVENT_SET_PARAMETER,
CFG_EVENT_CREATE_AUDIO_PATCH,
CFG_EVENT_RELEASE_AUDIO_PATCH,
+ CFG_EVENT_UPDATE_OUT_DEVICE,
};
class ConfigEventData: public RefBase {
@@ -219,6 +219,28 @@
virtual ~ReleaseAudioPatchConfigEvent() {}
};
+ class UpdateOutDevicesConfigEventData : public ConfigEventData {
+ public:
+ explicit UpdateOutDevicesConfigEventData(const DeviceDescriptorBaseVector& outDevices) :
+ mOutDevices(outDevices) {}
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "Devices: %s", android::toString(mOutDevices).c_str());
+ }
+
+ DeviceDescriptorBaseVector mOutDevices;
+ };
+
+ class UpdateOutDevicesConfigEvent : public ConfigEvent {
+ public:
+ explicit UpdateOutDevicesConfigEvent(const DeviceDescriptorBaseVector& outDevices) :
+ ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
+ mData = new UpdateOutDevicesConfigEventData(outDevices);
+ }
+
+ virtual ~UpdateOutDevicesConfigEvent();
+ };
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
explicit PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -278,19 +300,33 @@
status_t sendCreateAudioPatchConfigEvent(const struct audio_patch *patch,
audio_patch_handle_t *handle);
status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle);
+ status_t sendUpdateOutDeviceConfigEvent(
+ const DeviceDescriptorBaseVector& outDevices);
void processConfigEvents_l();
virtual void cacheParameters_l() = 0;
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle) = 0;
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle) = 0;
+ virtual void updateOutDevices(const DeviceDescriptorBaseVector& outDevices);
virtual void toAudioPortConfig(struct audio_port_config *config) = 0;
// see note at declaration of mStandby, mOutDevice and mInDevice
bool standby() const { return mStandby; }
- audio_devices_t outDevice() const { return mOutDevice; }
- audio_devices_t inDevice() const { return mInDevice; }
- audio_devices_t getDevice() const { return isOutput() ? mOutDevice : mInDevice; }
+ const DeviceTypeSet outDeviceTypes() const {
+ return getAudioDeviceTypes(mOutDeviceTypeAddrs);
+ }
+ audio_devices_t inDeviceType() const { return mInDeviceTypeAddr.mType; }
+ DeviceTypeSet getDeviceTypes() const {
+ return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+ }
+
+ const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const {
+ return mOutDeviceTypeAddrs;
+ }
+ const AudioDeviceTypeAddr& inDeviceTypeAddr() const {
+ return mInDeviceTypeAddr;
+ }
virtual bool isOutput() const = 0;
@@ -502,26 +538,21 @@
// HAL format if Fastmixer is used.
audio_format_t mHALFormat;
size_t mBufferSize; // HAL buffer size for read() or write()
-
+ AudioDeviceTypeAddrVector mOutDeviceTypeAddrs; // output device types and addresses
+ AudioDeviceTypeAddr mInDeviceTypeAddr; // input device type and address
Vector< sp<ConfigEvent> > mConfigEvents;
Vector< sp<ConfigEvent> > mPendingConfigEvents; // events awaiting system ready
// These fields are written and read by thread itself without lock or barrier,
- // and read by other threads without lock or barrier via standby(), outDevice()
- // and inDevice().
+ // and read by other threads without lock or barrier via standby(), outDeviceTypes()
+ // and inDeviceType().
// Because of the absence of a lock or barrier, any other thread that reads
// these fields must use the information in isolation, or be prepared to deal
// with possibility that it might be inconsistent with other information.
bool mStandby; // Whether thread is currently in standby.
- audio_devices_t mOutDevice; // output device
- audio_devices_t mInDevice; // input device
- audio_devices_t mPrevOutDevice; // previous output device
- audio_devices_t mPrevInDevice; // previous input device
+
struct audio_patch mPatch;
- /**
- * @brief mDeviceId current device port unique identifier
- */
- audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
audio_source_t mAudioSource;
const audio_io_handle_t mId;
@@ -544,7 +575,8 @@
ExtendedTimestamp mTimestamp;
TimestampVerifier< // For timestamp statistics.
int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
- audio_devices_t mTimestampCorrectedDevices = AUDIO_DEVICE_NONE;
+ // Timestamp corrected device should be a single device.
+ audio_devices_t mTimestampCorrectedDevice = AUDIO_DEVICE_NONE;
// ThreadLoop statistics per iteration.
int64_t mLastIoBeginNs = -1;
@@ -719,7 +751,7 @@
static const nsecs_t kMaxNextBufferDelayNs = 100000000;
PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
+ audio_io_handle_t id, type_t type, bool systemReady);
virtual ~PlaybackThread();
// Thread virtuals
@@ -886,10 +918,10 @@
}
bool isTimestampCorrectionEnabled() const override {
- const audio_devices_t device =
- mOutDevice & mTimestampCorrectedDevices;
- return audio_is_output_devices(device) && popcount(device) > 0;
+ return audio_is_output_devices(mTimestampCorrectedDevice)
+ && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
}
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1171,7 +1203,6 @@
MixerThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output,
audio_io_handle_t id,
- audio_devices_t device,
bool systemReady,
type_t type = MIXER);
virtual ~MixerThread();
@@ -1269,8 +1300,8 @@
public:
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, bool systemReady)
- : DirectOutputThread(audioFlinger, output, id, device, DIRECT, systemReady) { }
+ audio_io_handle_t id, bool systemReady)
+ : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady) { }
virtual ~DirectOutputThread();
@@ -1305,8 +1336,7 @@
bool mVolumeShaperActive = false;
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, ThreadBase::type_t type,
- bool systemReady);
+ audio_io_handle_t id, ThreadBase::type_t type, bool systemReady);
void processVolume_l(Track *track, bool lastTrack);
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -1345,7 +1375,7 @@
public:
OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, uint32_t device, bool systemReady);
+ audio_io_handle_t id, bool systemReady);
virtual ~OffloadThread() {};
virtual void flushHw_l();
@@ -1516,8 +1546,6 @@
RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input,
audio_io_handle_t id,
- audio_devices_t outDevice,
- audio_devices_t inDevice,
bool systemReady
);
virtual ~RecordThread();
@@ -1577,6 +1605,7 @@
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
+ void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
void addPatchTrack(const sp<PatchRecord>& record);
void deletePatchTrack(const sp<PatchRecord>& record);
@@ -1629,8 +1658,8 @@
bool isTimestampCorrectionEnabled() const override {
// checks popcount for exactly one device.
- return audio_is_input_device(
- mInDevice & mTimestampCorrectedDevices);
+ return audio_is_input_device(mTimestampCorrectedDevice)
+ && inDeviceType() == mTimestampCorrectedDevice;
}
protected:
@@ -1709,6 +1738,8 @@
std::atomic_bool mBtNrecSuspended;
int64_t mFramesRead = 0; // continuous running counter.
+
+ DeviceDescriptorBaseVector mOutDevices;
};
class MmapThread : public ThreadBase
@@ -1718,8 +1749,7 @@
#include "MmapTracks.h"
MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady);
virtual ~MmapThread();
virtual void configure(const audio_attributes_t *attr,
@@ -1793,6 +1823,11 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
void dumpTracks_l(int fd, const Vector<String16>& args) override;
+ /**
+ * @brief mDeviceId current device port unique identifier
+ */
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+
audio_attributes_t mAttr;
audio_session_t mSessionId;
audio_port_handle_t mPortId;
@@ -1813,8 +1848,7 @@
public:
MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamOut *output,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady);
virtual ~MmapPlaybackThread() {}
virtual void configure(const audio_attributes_t *attr,
@@ -1863,8 +1897,7 @@
public:
MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, AudioStreamIn *input,
- audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady);
+ AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady);
virtual ~MmapCaptureThread() {}
AudioStreamIn* clearInput();
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 0d3e614..92d8c83 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_AUDIOPOLICY_INTERFACE_H
#define ANDROID_AUDIOPOLICY_INTERFACE_H
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/DeviceDescriptorBase.h>
@@ -68,6 +69,14 @@
API_INPUT_TELEPHONY_RX, // used for capture from telephony RX path
} input_type_t;
+ typedef enum {
+ API_OUTPUT_INVALID = -1,
+ API_OUTPUT_LEGACY = 0,// e.g. audio playing to speaker
+ API_OUT_MIX_PLAYBACK, // used for "remote submix" playback of audio from remote source
+ // to local capture
+ API_OUTPUT_TELEPHONY_TX, // used for playback to telephony TX path
+ } output_type_t;
+
public:
virtual ~AudioPolicyInterface() {}
//
@@ -114,7 +123,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
- std::vector<audio_io_handle_t> *secondaryOutputs) = 0;
+ std::vector<audio_io_handle_t> *secondaryOutputs,
+ output_type_t *outputType) = 0;
// indicates to the audio policy manager that the output starts being used by corresponding stream.
virtual status_t startOutput(audio_port_handle_t portId) = 0;
// indicates to the audio policy manager that the output stops being used by corresponding stream.
@@ -270,6 +280,8 @@
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup) = 0;
+
+ virtual bool isCallScreenModeSupported() = 0;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 56596f5..e59386f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -45,7 +45,8 @@
mAvailableOutputDevices(availableOutputDevices),
mAvailableInputDevices(availableInputDevices),
mDefaultOutputDevice(defaultOutputDevice),
- mIsSpeakerDrcEnabled(false)
+ mIsSpeakerDrcEnabled(false),
+ mIsCallScreenModeSupported(false)
{}
const std::string& getSource() const {
@@ -95,6 +96,14 @@
mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
}
+ bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
+
+ void setCallScreenModeSupported(bool isCallScreenModeSupported)
+ {
+ mIsCallScreenModeSupported = isCallScreenModeSupported;
+ }
+
+
const HwModuleCollection getHwModules() const { return mHwModules; }
const DeviceVector &getAvailableInputDevices() const
@@ -189,6 +198,7 @@
// DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
// Note: remove also speaker_drc_enabled from global configuration of XML config file.
bool mIsSpeakerDrcEnabled;
+ bool mIsCallScreenModeSupported;
SurroundFormats mSurroundFormats;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 094f506..fc79ab1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -18,6 +18,7 @@
#include "DeviceDescriptor.h"
#include <utils/RefBase.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
#include <utils/Vector.h>
#include <system/audio.h>
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 7faf90e..a6562d7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -33,9 +33,13 @@
{
public:
// Note that empty name refers by convention to a generic device.
- explicit DeviceDescriptor(audio_devices_t type, const std::string &tagName = "");
- DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
- const std::string &tagName = "");
+ explicit DeviceDescriptor(audio_devices_t type);
+ DeviceDescriptor(audio_devices_t type, const std::string &tagName,
+ const FormatVector &encodedFormats = FormatVector{});
+ DeviceDescriptor(audio_devices_t type, const std::string &tagName,
+ const std::string &address, const FormatVector &encodedFormats = FormatVector{});
+ DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr, const std::string &tagName = "",
+ const FormatVector &encodedFormats = FormatVector{});
virtual ~DeviceDescriptor() {}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 6f8ea36..20c0a24 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -455,9 +455,9 @@
}
// check if this mix goes to a device in the list of devices
bool deviceMatch = false;
+ const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
for (size_t j = 0; j < devices.size(); j++) {
- if (devices[j].mType == mix->mDeviceType
- && devices[j].mAddress == mix->mDeviceAddress) {
+ if (mixDevice.equals(devices[j])) {
deviceMatch = true;
break;
}
@@ -522,7 +522,7 @@
}
}
if (ruleAllowsUid) {
- devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress));
+ devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
}
}
return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 0587041..86dbba8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -26,14 +26,30 @@
namespace android {
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const std::string &tagName) :
- DeviceDescriptor(type, FormatVector{}, tagName)
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type) :
+ DeviceDescriptor(type, "" /*tagName*/)
{
}
-DeviceDescriptor::DeviceDescriptor(audio_devices_t type, const FormatVector &encodedFormats,
- const std::string &tagName) :
- DeviceDescriptorBase(type), mTagName(tagName), mEncodedFormats(encodedFormats)
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
+ const std::string &tagName,
+ const FormatVector &encodedFormats) :
+ DeviceDescriptor(type, tagName, "" /*address*/, encodedFormats)
+{
+}
+
+DeviceDescriptor::DeviceDescriptor(audio_devices_t type,
+ const std::string &tagName,
+ const std::string &address,
+ const FormatVector &encodedFormats) :
+ DeviceDescriptor(AudioDeviceTypeAddr(type, address), tagName, encodedFormats)
+{
+}
+
+DeviceDescriptor::DeviceDescriptor(const AudioDeviceTypeAddr &deviceTypeAddr,
+ const std::string &tagName,
+ const FormatVector &encodedFormats) :
+ DeviceDescriptorBase(deviceTypeAddr), mTagName(tagName), mEncodedFormats(encodedFormats)
{
mCurrentEncodedFormat = AUDIO_FORMAT_DEFAULT;
/* If framework runs against a pre 5.0 Audio HAL, encoded formats are absent from the config.
@@ -41,7 +57,7 @@
* For now, the workaround to remove AC3 and IEC61937 support on HDMI is to declare
* something like 'encodedFormats="AUDIO_FORMAT_PCM_16_BIT"' on the HDMI devicePort.
*/
- if (type == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.empty()) {
+ if (mDeviceTypeAddr.mType == AUDIO_DEVICE_OUT_HDMI && mEncodedFormats.empty()) {
mEncodedFormats.push_back(AUDIO_FORMAT_AC3);
mEncodedFormats.push_back(AUDIO_FORMAT_IEC61937);
}
@@ -76,7 +92,7 @@
return false;
}
- return (mDeviceType == other->mDeviceType) && (mAddress == other->mAddress) &&
+ return mDeviceTypeAddr.equals(other->mDeviceTypeAddr) &&
checkEqual(mEncodedFormats, other->mEncodedFormats);
}
@@ -135,7 +151,7 @@
void DeviceDescriptor::toAudioPort(struct audio_port *port) const
{
- ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceType);
+ ALOGV("DeviceDescriptor::toAudioPort() handle %d type %08x", mId, mDeviceTypeAddr.mType);
DeviceDescriptorBase::toAudioPort(port);
port->ext.device.hw_module = getModuleHandle();
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 0b4d3d4..886e4c9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -49,8 +49,7 @@
profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
config->sample_rate));
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
- devDesc->setAddress(address.string());
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@@ -117,8 +116,7 @@
profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
config->sample_rate));
- sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
- devDesc->setAddress(address.string());
+ sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device, "" /*tagName*/, address.string());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@@ -360,9 +358,9 @@
address);
return nullptr;
}
- sp<DeviceDescriptor> device = new DeviceDescriptor(type, name);
+
+ sp<DeviceDescriptor> device = new DeviceDescriptor(type, name, address);
device->setName(name);
- device->setAddress(address);
device->setEncodedFormat(encodedFormat);
// Add the device to the list of dynamic devices
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 3b27cf6..4376802 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -199,6 +199,7 @@
struct Attributes
{
static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
+ static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
};
static status_t deserialize(const xmlNode *root, AudioPolicyConfig *config);
@@ -511,13 +512,8 @@
if (!encodedFormatsLiteral.empty()) {
encodedFormats = formatsFromString(encodedFormatsLiteral, " ");
}
- Element deviceDesc = new DeviceDescriptor(type, encodedFormats, name);
-
std::string address = getXmlAttribute(cur, Attributes::address);
- if (!address.empty()) {
- ALOGV("%s: address=%s for %s", __func__, address.c_str(), name.c_str());
- deviceDesc->setAddress(address);
- }
+ Element deviceDesc = new DeviceDescriptor(type, name, address, encodedFormats);
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
@@ -685,14 +681,17 @@
{
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(tag))) {
- std::string speakerDrcEnabled =
- getXmlAttribute(cur, Attributes::speakerDrcEnabled);
- bool isSpeakerDrcEnabled;
- if (!speakerDrcEnabled.empty() &&
- convertTo<std::string, bool>(speakerDrcEnabled, isSpeakerDrcEnabled)) {
- config->setSpeakerDrcEnabled(isSpeakerDrcEnabled);
+ bool value;
+ std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
+ if (!attr.empty() &&
+ convertTo<std::string, bool>(attr, value)) {
+ config->setSpeakerDrcEnabled(value);
}
- return NO_ERROR;
+ attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
+ if (!attr.empty() &&
+ convertTo<std::string, bool>(attr, value)) {
+ config->setCallScreenModeSupported(value);
+ }
}
}
return NO_ERROR;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 3223530..355e4f0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -682,8 +682,8 @@
* Switching to or from incall state or switching between telephony and VoIP lead to force
* routing command.
*/
- bool force = ((is_state_in_call(oldState) != is_state_in_call(state))
- || (is_state_in_call(state) && (state != oldState)));
+ bool force = ((isStateInCall(oldState) != isStateInCall(state))
+ || (isStateInCall(state) && (state != oldState)));
// check for device and output changes triggered by new phone state
checkForDeviceAndOutputChanges();
@@ -945,7 +945,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs)
+ std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs,
+ output_type_t *outputType)
{
DeviceVector outputDevices;
const audio_port_handle_t requestedPortId = *selectedDeviceId;
@@ -953,6 +954,7 @@
const sp<DeviceDescriptor> requestedDevice =
mAvailableOutputDevices.getDeviceFromId(requestedPortId);
+ *outputType = API_OUTPUT_INVALID;
status_t status = getAudioAttributes(resultAttr, attr, *stream);
if (status != NO_ERROR) {
return status;
@@ -991,7 +993,13 @@
mix->mDeviceAddress,
AUDIO_FORMAT_DEFAULT);
*selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
+
ALOGV("getOutputForAttr() returns output %d", *output);
+ if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
+ *outputType = API_OUT_MIX_PLAYBACK;
+ } else {
+ *outputType = API_OUTPUT_LEGACY;
+ }
return NO_ERROR;
}
// Virtual sources must always be dynamicaly or explicitly routed
@@ -1015,7 +1023,7 @@
if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX) &&
(*stream == AUDIO_STREAM_MUSIC || resultAttr->usage == AUDIO_USAGE_VOICE_COMMUNICATION) &&
audio_is_linear_pcm(config->format) &&
- isInCall()) {
+ isCallAudioAccessible()) {
if (requestedPortId != AUDIO_PORT_HANDLE_NONE) {
*flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
*isRequestedDeviceForExclusiveUse = true;
@@ -1048,6 +1056,12 @@
*selectedDeviceId = getFirstDeviceId(outputDevices);
+ if (outputDevices.onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+ *outputType = API_OUTPUT_TELEPHONY_TX;
+ } else {
+ *outputType = API_OUTPUT_LEGACY;
+ }
+
ALOGV("%s returns output %d selectedDeviceId %d", __func__, *output, *selectedDeviceId);
return NO_ERROR;
@@ -1062,7 +1076,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
- std::vector<audio_io_handle_t> *secondaryOutputs)
+ std::vector<audio_io_handle_t> *secondaryOutputs,
+ output_type_t *outputType)
{
// The supplied portId must be AUDIO_PORT_HANDLE_NONE
if (*portId != AUDIO_PORT_HANDLE_NONE) {
@@ -1082,7 +1097,7 @@
status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputDescs);
+ &secondaryOutputDescs, outputType);
if (status != NO_ERROR) {
return status;
}
@@ -3058,13 +3073,13 @@
// reevaluate outputs for all given devices
for (size_t i = 0; i < devices.size(); i++) {
sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress, String8(),
+ devices[i].mType, devices[i].mAddress.c_str(), String8(),
AUDIO_FORMAT_DEFAULT);
SortedVector<audio_io_handle_t> outputs;
if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
outputs) != NO_ERROR) {
ALOGE("setUidDeviceAffinities() error in checkOutputsForDevice for device=%08x"
- " addr=%s", devices[i].mType, devices[i].mAddress.string());
+ " addr=%s", devices[i].mType, devices[i].mAddress.c_str());
return INVALID_OPERATION;
}
}
@@ -3909,10 +3924,11 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
bool isRequestedDeviceForExclusiveUse = false;
std::vector<sp<SwAudioOutputDescriptor>> secondaryOutputs;
+ output_type_t outputType;
getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE,
&attributes, &stream, sourceDesc->uid(), &config, &flags,
&selectedDeviceId, &isRequestedDeviceForExclusiveUse,
- &secondaryOutputs);
+ &secondaryOutputs, &outputType);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %s",
__FUNCTION__, dumpDeviceTypes(sinkDevices.types()).c_str());
@@ -4207,6 +4223,12 @@
return false;
}
+bool AudioPolicyManager::isCallScreenModeSupported()
+{
+ return getConfig().isCallScreenModeSupported();
+}
+
+
status_t AudioPolicyManager::disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
{
ALOGV("%s port Id %d", __FUNCTION__, sourceDesc->portId());
@@ -6062,6 +6084,14 @@
return is_state_in_call(state);
}
+bool AudioPolicyManager::isCallAudioAccessible()
+{
+ audio_mode_t mode = mEngine->getPhoneState();
+ return (mode == AUDIO_MODE_IN_CALL)
+ || (mode == AUDIO_MODE_IN_COMMUNICATION)
+ || (mode == AUDIO_MODE_CALL_SCREEN);
+}
+
void AudioPolicyManager::cleanUpForDevice(const sp<DeviceDescriptor>& deviceDesc)
{
for (ssize_t i = (ssize_t)mAudioSources.size() - 1; i >= 0; i--) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 707e4b0..322c188 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -121,7 +121,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
- std::vector<audio_io_handle_t> *secondaryOutputs) override;
+ std::vector<audio_io_handle_t> *secondaryOutputs,
+ output_type_t *outputType) override;
virtual status_t startOutput(audio_port_handle_t portId);
virtual status_t stopOutput(audio_port_handle_t portId);
virtual void releaseOutput(audio_port_handle_t portId);
@@ -306,6 +307,8 @@
return volumeGroup != VOLUME_GROUP_NONE ? NO_ERROR : BAD_VALUE;
}
+ bool isCallScreenModeSupported() override;
+
status_t initialize();
protected:
@@ -476,6 +479,8 @@
virtual bool isInCall();
// true if given state represents a device in a telephony or VoIP call
virtual bool isStateInCall(int state);
+ // true if playback to call TX or capture from call RX is possible
+ bool isCallAudioAccessible();
// when a device is connected, checks if an open output can be routed
// to this device. If none is open, tries to open one of the available outputs.
@@ -805,7 +810,8 @@
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse,
- std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs);
+ std::vector<sp<SwAudioOutputDescriptor>> *secondaryDescs,
+ output_type_t *outputType);
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevices(
const DeviceVector &devices,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 875f51d..feb930e 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -181,13 +181,13 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- ALOGV("getOutputForAttr()");
+ ALOGV("%s()", __func__);
Mutex::Autolock _l(mLock);
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!isAudioServerOrMediaServerUid(callingUid) || uid == (uid_t)-1) {
ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
- "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, uid);
+ "%s uid %d tried to pass itself off as %d", __func__, callingUid, uid);
uid = callingUid;
}
if (!mPackageManager.allowPlaybackCapture(uid)) {
@@ -197,27 +197,39 @@
&& !bypassInterruptionPolicyAllowed(pid, uid)) {
attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
}
- audio_output_flags_t originalFlags = flags;
AutoCallerClear acc;
+ AudioPolicyInterface::output_type_t outputType;
status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
&flags, selectedDeviceId, portId,
- secondaryOutputs);
+ secondaryOutputs,
+ &outputType);
// FIXME: Introduce a way to check for the the telephony device before opening the output
- if ((result == NO_ERROR) &&
- (flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) &&
- !modifyPhoneStateAllowed(pid, uid)) {
- // If the app tries to play music through the telephony device and doesn't have permission
- // the fallback to the default output device.
- mAudioPolicyManager->releaseOutput(*portId);
- flags = originalFlags;
- *selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- *portId = AUDIO_PORT_HANDLE_NONE;
- secondaryOutputs->clear();
- result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, config,
- &flags, selectedDeviceId, portId,
- secondaryOutputs);
+ if (result == NO_ERROR) {
+ // enforce permission (if any) required for each type of input
+ switch (outputType) {
+ case AudioPolicyInterface::API_OUTPUT_LEGACY:
+ break;
+ case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
+ if (!modifyPhoneStateAllowed(pid, uid)) {
+ ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
+ __func__, uid);
+ result = PERMISSION_DENIED;
+ }
+ break;
+ case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
+ if (!modifyAudioRoutingAllowed(pid, uid)) {
+ ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
+ __func__, uid);
+ result = PERMISSION_DENIED;
+ }
+ break;
+ case AudioPolicyInterface::API_OUTPUT_INVALID:
+ default:
+ LOG_ALWAYS_FATAL("%s() encountered an invalid output type %d",
+ __func__, (int)outputType);
+ }
}
if (result == NO_ERROR) {
@@ -434,7 +446,7 @@
}
break;
case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
- if (!modifyAudioRoutingAllowed()) {
+ if (!modifyAudioRoutingAllowed(pid, uid)) {
ALOGE("getInputForAttr() permission denied: modify audio routing not allowed");
status = PERMISSION_DENIED;
}
@@ -1329,4 +1341,15 @@
return NO_ERROR;
}
+bool AudioPolicyService::isCallScreenModeSupported()
+{
+ if (mAudioPolicyManager == NULL) {
+ ALOGW("%s, mAudioPolicyManager == NULL", __func__);
+ return false;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->isCallScreenModeSupported();
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 17e0437..2bd02c8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -259,6 +259,8 @@
virtual status_t setRttEnabled(bool enabled);
+ bool isCallScreenModeSupported() override;
+
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 1ee1eea..e4a19ea 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -179,9 +179,10 @@
audio_port_handle_t localPortId;
if (!portId) portId = &localPortId;
*portId = AUDIO_PORT_HANDLE_NONE;
+ AudioPolicyInterface::output_type_t outputType;
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, AUDIO_SESSION_NONE, &stream, 0 /*uid*/, &config, &flags,
- selectedDeviceId, portId, {}));
+ selectedDeviceId, portId, {}, &outputType));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c10adbb..b704573 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -732,9 +732,10 @@
}
Status CameraService::makeClient(const sp<CameraService>& cameraService,
- const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
- int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
- int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+ const sp<IInterface>& cameraCb, const String16& packageName,
+ const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+ int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+ int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client) {
if (halVersion < 0 || halVersion == deviceVersion) {
@@ -744,7 +745,7 @@
case CAMERA_DEVICE_API_VERSION_1_0:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
- *client = new CameraClient(cameraService, tmp, packageName,
+ *client = new CameraClient(cameraService, tmp, packageName, featureId,
api1CameraId, facing, clientPid, clientUid,
getpid());
} else { // Camera2 API route
@@ -762,15 +763,15 @@
case CAMERA_DEVICE_API_VERSION_3_5:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
- *client = new Camera2Client(cameraService, tmp, packageName,
+ *client = new Camera2Client(cameraService, tmp, packageName, featureId,
cameraId, api1CameraId,
facing, clientPid, clientUid,
servicePid);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
- *client = new CameraDeviceClient(cameraService, tmp, packageName, cameraId,
- facing, clientPid, clientUid, servicePid);
+ *client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
+ cameraId, facing, clientPid, clientUid, servicePid);
}
break;
default:
@@ -787,7 +788,7 @@
halVersion == CAMERA_DEVICE_API_VERSION_1_0) {
// Only support higher HAL version device opened as HAL1.0 device.
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
- *client = new CameraClient(cameraService, tmp, packageName,
+ *client = new CameraClient(cameraService, tmp, packageName, featureId,
api1CameraId, facing, clientPid, clientUid,
servicePid);
} else {
@@ -887,7 +888,7 @@
if (!(ret = connectHelper<ICameraClient,Client>(
sp<ICameraClient>{nullptr}, id, cameraId,
static_cast<int>(CAMERA_HAL_API_VERSION_UNSPECIFIED),
- internalPackageName, uid, USE_CALLING_PID,
+ internalPackageName, std::unique_ptr<String16>(), uid, USE_CALLING_PID,
API_1, /*shimUpdateOnly*/ true, /*out*/ tmp)
).isOk()) {
ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
@@ -1400,8 +1401,8 @@
String8 id = cameraIdIntToStr(api1CameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1,
- /*shimUpdateOnly*/ false, /*out*/client);
+ CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, std::unique_ptr<String16>(),
+ clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*out*/client);
if(!ret.isOk()) {
logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1427,8 +1428,8 @@
Status ret = Status::ok();
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId, halVersion,
- clientPackageName, clientUid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ false,
- /*out*/client);
+ clientPackageName, std::unique_ptr<String16>(), clientUid, USE_CALLING_PID, API_1,
+ /*shimUpdateOnly*/ false, /*out*/client);
if(!ret.isOk()) {
logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1502,6 +1503,7 @@
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
const String16& cameraId,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
int clientUid,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
@@ -1511,6 +1513,7 @@
String8 id = String8(cameraId);
sp<CameraDeviceClient> client = nullptr;
String16 clientPackageNameAdj = clientPackageName;
+
if (hardware::IPCThreadState::self()->isServingCall()) {
std::string vendorClient =
StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
@@ -1518,7 +1521,7 @@
}
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj,
+ CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageNameAdj, clientFeatureId,
clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, /*out*/client);
if(!ret.isOk()) {
@@ -1533,8 +1536,9 @@
template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
- int api1CameraId, int halVersion, const String16& clientPackageName, int clientUid,
- int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
+ int api1CameraId, int halVersion, const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+ apiLevel effectiveApiLevel, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
@@ -1617,7 +1621,7 @@
}
sp<BasicClient> tmp = nullptr;
- if(!(ret = makeClient(this, cameraCb, clientPackageName,
+ if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
cameraId, api1CameraId, facing,
clientPid, clientUid, getpid(),
halVersion, deviceVersion, effectiveApiLevel,
@@ -2459,13 +2463,14 @@
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraIdStr,
int api1CameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService,
IInterface::asBinder(cameraClient),
- clientPackageName,
+ clientPackageName, clientFeatureId,
cameraIdStr, cameraFacing,
clientPid, clientUid,
servicePid),
@@ -2495,17 +2500,24 @@
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
- const String16& clientPackageName,
+ const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraIdStr, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
mCameraIdStr(cameraIdStr), mCameraFacing(cameraFacing),
- mClientPackageName(clientPackageName), mClientPid(clientPid), mClientUid(clientUid),
+ mClientPackageName(clientPackageName),
+ mClientPid(clientPid), mClientUid(clientUid),
mServicePid(servicePid),
mDisconnected(false),
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE),
mRemoteBinder(remoteCallback)
{
+ if (clientFeatureId) {
+ mClientFeatureId = std::unique_ptr<String16>(new String16(*clientFeatureId));
+ } else {
+ mClientFeatureId = std::unique_ptr<String16>();
+ }
+
if (sCameraService == nullptr) {
sCameraService = cameraService;
}
@@ -2649,8 +2661,9 @@
int32_t res;
mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
mClientPackageName, mOpsCallback);
- res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
- mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+ res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
+ mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
+ String16("start camera ") + String16(mCameraIdStr));
if (res == AppOpsManager::MODE_ERRORED) {
ALOGI("Camera %s: Access for \"%s\" has been revoked",
@@ -2692,7 +2705,7 @@
// Notify app ops that the camera is available again
if (mAppOpsManager != nullptr) {
mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
- mClientPackageName);
+ mClientPackageName, mClientFeatureId);
mOpsActive = false;
}
// This function is called when a client disconnects. This should
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 829a3ee..1f40fc3 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -134,7 +134,8 @@
virtual binder::Status connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
- const String16& clientPackageName, int32_t clientUid,
+ const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
+ int32_t clientUid,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -275,6 +276,7 @@
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraIdStr,
int cameraFacing,
int clientPid,
@@ -294,6 +296,7 @@
const String8 mCameraIdStr;
const int mCameraFacing;
String16 mClientPackageName;
+ std::unique_ptr<String16> mClientFeatureId;
pid_t mClientPid;
const uid_t mClientUid;
const pid_t mServicePid;
@@ -365,6 +368,7 @@
Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraIdStr,
int api1CameraId,
int cameraFacing,
@@ -688,8 +692,8 @@
template<class CALLBACK, class CLIENT>
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, int halVersion, const String16& clientPackageName,
- int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly,
- /*out*/sp<CLIENT>& device);
+ const std::unique_ptr<String16>& clientFeatureId, int clientUid, int clientPid,
+ apiLevel effectiveApiLevel, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
// Lock guarding camera service state
Mutex mServiceLock;
@@ -985,9 +989,10 @@
static String8 getFormattedCurrentTime();
static binder::Status makeClient(const sp<CameraService>& cameraService,
- const sp<IInterface>& cameraCb, const String16& packageName, const String8& cameraId,
- int api1CameraId, int facing, int clientPid, uid_t clientUid, int servicePid,
- int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
+ const sp<IInterface>& cameraCb, const String16& packageName,
+ const std::unique_ptr<String16>& featureId, const String8& cameraId, int api1CameraId,
+ int facing, int clientPid, uid_t clientUid, int servicePid, int halVersion,
+ int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client);
status_t checkCameraAccess(const String16& opPackageName);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index c273881..5dbbc0b 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -50,13 +50,14 @@
Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraDeviceId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
- Camera2ClientBase(cameraService, cameraClient, clientPackageName,
+ Camera2ClientBase(cameraService, cameraClient, clientPackageName, clientFeatureId,
cameraDeviceId, api1CameraId, cameraFacing,
clientPid, clientUid, servicePid),
mParameters(api1CameraId, cameraFacing)
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 8a17b17..8034ab4 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -93,6 +93,7 @@
Camera2Client(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraDeviceId,
int api1CameraId,
int cameraFacing,
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 388a5dc..83da880 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -34,11 +34,11 @@
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
- const String16& clientPackageName,
+ const String16& clientPackageName, const std::unique_ptr<String16>& clientFeatureId,
int cameraId, int cameraFacing,
int clientPid, int clientUid,
int servicePid):
- Client(cameraService, cameraClient, clientPackageName,
+ Client(cameraService, cameraClient, clientPackageName, clientFeatureId,
String8::format("%d", cameraId), cameraId, cameraFacing, clientPid,
clientUid, servicePid)
{
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index b26b612..501ad18 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -66,6 +66,7 @@
CameraClient(const sp<CameraService>& cameraService,
const sp<hardware::ICameraClient>& cameraClient,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
int cameraId,
int cameraFacing,
int clientPid,
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index 88799f9..0c01a91 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -265,7 +265,7 @@
Mutex::Autolock l(mInputMutex);
while (!mStartCapture) {
res = mStartCaptureSignal.waitRelative(mInputMutex,
- kWaitDuration);
+ kIdleWaitDuration);
if (res == TIMED_OUT) break;
}
if (mStartCapture) {
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
index 727dd53..9475a39 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
@@ -111,6 +111,7 @@
* Internal to CaptureSequencer
*/
static const nsecs_t kWaitDuration = 100000000; // 100 ms
+ static const nsecs_t kIdleWaitDuration = 10000000; // 10 ms
static const int kMaxTimeoutsForPrecaptureStart = 10; // 1 sec
static const int kMaxTimeoutsForPrecaptureEnd = 20; // 2 sec
static const int kMaxTimeoutsForCaptureEnd = 40; // 4 sec
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 08fb153..27bebde 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -54,6 +54,7 @@
const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
@@ -63,6 +64,7 @@
BasicClient(cameraService,
IInterface::asBinder(remoteCallback),
clientPackageName,
+ clientFeatureId,
cameraId,
cameraFacing,
clientPid,
@@ -78,12 +80,13 @@
CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid) :
- Camera2ClientBase(cameraService, remoteCallback, clientPackageName,
+ Camera2ClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
cameraId, /*API1 camera ID*/ -1,
cameraFacing, clientPid, clientUid, servicePid),
mInputStream(),
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index fe25010..7efc5ab 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -47,6 +47,7 @@
CameraDeviceClientBase(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
@@ -163,6 +164,7 @@
CameraDeviceClient(const sp<CameraService>& cameraService,
const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int cameraFacing,
int clientPid,
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 26459f9..bf4d1c8 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -597,7 +597,8 @@
// to look up timestamp.
int64_t bufferTime = -1;
if (mCodecOutputBufferTimestamps.empty()) {
- ALOGE("%s: Failed to find buffer timestamp for codec output buffer!", __FUNCTION__);
+ ALOGV("%s: Failed to find buffer timestamp for codec output buffer!", __FUNCTION__);
+ break;
} else {
// Direct mapping between camera timestamp (in ns) and codec timestamp (in us).
bufferTime = mCodecOutputBufferTimestamps.front();
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 78feb3e..8792f9a 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -44,13 +44,14 @@
const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
int clientPid,
uid_t clientUid,
int servicePid):
- TClientBase(cameraService, remoteCallback, clientPackageName,
+ TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
cameraId, api1CameraId, cameraFacing, clientPid, clientUid, servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 6693847..12cba0b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -48,6 +48,7 @@
Camera2ClientBase(const sp<CameraService>& cameraService,
const sp<TCamCallbacks>& remoteCallback,
const String16& clientPackageName,
+ const std::unique_ptr<String16>& clientFeatureId,
const String8& cameraId,
int api1CameraId,
int cameraFacing,
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 80df7db..5c6c518 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -139,7 +139,9 @@
mOutputSlots.clear();
mConsumerBufferCount.clear();
- mConsumer->consumerDisconnect();
+ if (mConsumer.get() != nullptr) {
+ mConsumer->consumerDisconnect();
+ }
if (mBuffers.size() > 0) {
SP_LOGW("%zu buffers still being tracked", mBuffers.size());
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 1daa035..97ba9c4 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -103,7 +103,7 @@
}
sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
binder::Status serviceRet = mAidlICameraService->connectDevice(
- callbacks, String16(cameraId.c_str()), String16(""),
+ callbacks, String16(cameraId.c_str()), String16(""), std::unique_ptr<String16>(),
hardware::ICameraService::USE_CALLING_UID, /*out*/&deviceRemote);
HStatus status = HStatus::NO_ERROR;
if (!serviceRet.isOk()) {
diff --git a/services/mediaanalytics/TEST_MAPPING b/services/mediaanalytics/TEST_MAPPING
new file mode 100644
index 0000000..01e9e46
--- /dev/null
+++ b/services/mediaanalytics/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "mediametrics_tests"
+ },
+ {
+ "name": "CtsNativeMediaMetricsTestCases"
+ }
+ ]
+}
diff --git a/services/mediaanalytics/tests/Android.bp b/services/mediaanalytics/tests/Android.bp
index 7bca1c4..a8a330c 100644
--- a/services/mediaanalytics/tests/Android.bp
+++ b/services/mediaanalytics/tests/Android.bp
@@ -1,5 +1,6 @@
cc_test {
name: "mediametrics_tests",
+ test_suites: ["device-tests"],
cflags: [
"-Wall",
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 36042a4..3141c31 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -62,5 +62,8 @@
src: "seccomp_policy/mediacodec-x86.policy",
},
},
- required: ["crash_dump.policy"],
+ required: [
+ "crash_dump.policy",
+ "code_coverage.policy",
+ ],
}
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index d878d72..1cf0534 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -70,7 +70,7 @@
LOCAL_MODULE := mediacodec.policy
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/seccomp_policy
-LOCAL_REQUIRED_MODULES := crash_dump.policy
+LOCAL_REQUIRED_MODULES := crash_dump.policy code_coverage.policy
# mediacodec runs in 32-bit combatibility mode. For 64 bit architectures,
# use the 32 bit policy
ifdef TARGET_2ND_ARCH
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
index fa5bc4a..ad03e68 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/services/mediacodec/registrant/Android.bp
@@ -9,12 +9,11 @@
"libmedia_headers",
],
+ defaults: [
+ "libcodec2-hidl-defaults",
+ ],
shared_libs: [
- "android.hardware.media.c2@1.0",
"libbase",
- "libcodec2_hidl@1.0",
- "libcodec2_vndk",
- "libutils",
],
// Codecs
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
index 706ebee..58db801e 100644
--- a/services/mediacodec/registrant/CodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -20,11 +20,11 @@
#include <android-base/logging.h>
#include <C2PlatformSupport.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.1/ComponentStore.h>
#include <media/CodecServiceRegistrant.h>
extern "C" void RegisterCodecServices() {
- using namespace ::android::hardware::media::c2::V1_0;
+ using namespace ::android::hardware::media::c2::V1_1;
LOG(INFO) << "Creating software Codec2 service...";
android::sp<IComponentStore> store =
new utils::ComponentStore(
diff --git a/services/mediacodec/seccomp_policy/mediacodec-arm.policy b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
index 3870a11..835f8bb 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-arm.policy
@@ -59,3 +59,5 @@
getrandom: 1
@include /system/etc/seccomp_policy/crash_dump.arm.policy
+
+@include /system/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediacodec/seccomp_policy/mediacodec-x86.policy b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
index d9c4045..a9d32d6 100644
--- a/services/mediacodec/seccomp_policy/mediacodec-x86.policy
+++ b/services/mediacodec/seccomp_policy/mediacodec-x86.policy
@@ -69,3 +69,4 @@
gettid: 1
@include /system/etc/seccomp_policy/crash_dump.x86.policy
+@include /system/etc/seccomp_policy/code_coverage.x86.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
index 9042cd7..93b4852 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
@@ -84,3 +84,5 @@
getgid32: 1
getegid32: 1
getgroups32: 1
+
+@include /system/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
index 4faf8b2..bb05770 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm64.policy
@@ -79,3 +79,4 @@
getegid: 1
getgroups: 1
+@include /system/etc/seccomp_policy/code_coverage.arm64.policy
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
deleted file mode 100644
index 72d42ae..0000000
--- a/services/mediadrm/Android.mk
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2014 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- MediaDrmService.cpp \
- main_mediadrmserver.cpp
-
-LOCAL_HEADER_LIBRARIES:= \
- libmedia_headers \
- libmediadrm_headers
-
-LOCAL_SHARED_LIBRARIES:= \
- libbinder \
- liblog \
- libmedia \
- libmediadrm \
- libutils \
- libhidlbase \
- libhidlmemory \
- android.hardware.drm@1.0 \
- android.hardware.drm@1.1 \
- android.hardware.drm@1.2
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-LOCAL_MODULE:= mediadrmserver
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-LOCAL_INIT_RC := mediadrmserver.rc
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
deleted file mode 100644
index 5afd079..0000000
--- a/services/mediadrm/MediaDrmService.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-**
-** Copyright 2008, 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.
-*/
-
-// Proxy for media player implementations
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaDrmService"
-
-#include "MediaDrmService.h"
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-
-#include <mediadrm/CryptoHal.h>
-#include <mediadrm/DrmHal.h>
-
-namespace android {
-
-void MediaDrmService::instantiate() {
- defaultServiceManager()->addService(
- String16("media.drm"), new MediaDrmService());
-}
-
-sp<ICrypto> MediaDrmService::makeCrypto() {
- return new CryptoHal;
-}
-
-sp<IDrm> MediaDrmService::makeDrm() {
- return new DrmHal;
-}
-
-} // namespace android
diff --git a/services/mediadrm/MediaDrmService.h b/services/mediadrm/MediaDrmService.h
deleted file mode 100644
index 3607201..0000000
--- a/services/mediadrm/MediaDrmService.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_MEDIADRMSERVICE_H
-#define ANDROID_MEDIADRMSERVICE_H
-
-#include <arpa/inet.h>
-
-#include <utils/threads.h>
-
-#include <media/Metadata.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <mediadrm/IMediaDrmService.h>
-
-namespace android {
-
-class MediaDrmService : public BnMediaDrmService
-{
-public:
- static void instantiate();
-
- // IMediaDrmService interface
- virtual sp<ICrypto> makeCrypto();
- virtual sp<IDrm> makeDrm();
-private:
- MediaDrmService() {}
- virtual ~MediaDrmService() {}
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_MEDIADRMSERVICE_H
diff --git a/services/mediadrm/OWNERS b/services/mediadrm/OWNERS
deleted file mode 100644
index 6d3b533..0000000
--- a/services/mediadrm/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jtinker@google.com
-marcone@google.com
diff --git a/services/mediadrm/main_mediadrmserver.cpp b/services/mediadrm/main_mediadrmserver.cpp
deleted file mode 100644
index b767b8c..0000000
--- a/services/mediadrm/main_mediadrmserver.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "mediaserver"
-//#define LOG_NDEBUG 0
-
-#include <fcntl.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include "MediaDrmService.h"
-
-using namespace android;
-
-int main()
-{
- signal(SIGPIPE, SIG_IGN);
-
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- ALOGI("ServiceManager: %p", sm.get());
- MediaDrmService::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
-}
diff --git a/services/mediadrm/mediadrmserver.rc b/services/mediadrm/mediadrmserver.rc
deleted file mode 100644
index 359c2cf..0000000
--- a/services/mediadrm/mediadrmserver.rc
+++ /dev/null
@@ -1,6 +0,0 @@
-service mediadrm /system/bin/mediadrmserver
- class main
- user media
- group mediadrm drmrpc
- ioprio rt 4
- writepid /dev/cpuset/foreground/tasks
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 828e89a..816a6b1 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -68,6 +68,9 @@
src: "seccomp_policy/mediaextractor-x86_64.policy",
},
},
- required: ["crash_dump.policy"],
+ required: [
+ "crash_dump.policy",
+ "code_coverage.policy",
+ ],
}
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
index 964acf4..38f9be6 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm.policy
@@ -50,3 +50,4 @@
_llseek: 1
@include /system/etc/seccomp_policy/crash_dump.arm.policy
+@include /system/etc/seccomp_policy/code_coverage.arm.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
index e6c676c..8fd8787 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-arm64.policy
@@ -44,3 +44,4 @@
sched_yield: 1
@include /system/etc/seccomp_policy/crash_dump.arm64.policy
+@include /system/etc/seccomp_policy/code_coverage.arm64.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
index 56ad8df..05915d1 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86.policy
@@ -57,3 +57,4 @@
gettid: 1
@include /system/etc/seccomp_policy/crash_dump.x86.policy
+@include /system/etc/seccomp_policy/code_coverage.x86.policy
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
index 607a03e..e6a55d0 100644
--- a/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-x86_64.policy
@@ -51,3 +51,4 @@
gettid: 1
@include /system/etc/seccomp_policy/crash_dump.x86_64.policy
+@include /system/etc/seccomp_policy/code_coverage.x86_64.policy
diff --git a/tools/OWNERS b/tools/OWNERS
deleted file mode 100644
index f9cb567..0000000
--- a/tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-gkasten@google.com
diff --git a/tools/resampler_tools/Android.bp b/tools/resampler_tools/Android.bp
deleted file mode 100644
index 7549359..0000000
--- a/tools/resampler_tools/Android.bp
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2005 The Android Open Source Project
-//
-// Android.mk for resampler_tools
-//
-
-cc_binary_host {
- name: "fir",
-
- srcs: ["fir.cpp"],
-
- cflags: [
- "-Werror",
- "-Wall",
- ],
-}
diff --git a/tools/resampler_tools/OWNERS b/tools/resampler_tools/OWNERS
deleted file mode 100644
index b4a6798..0000000
--- a/tools/resampler_tools/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-hunga@google.com
diff --git a/tools/resampler_tools/fir.cpp b/tools/resampler_tools/fir.cpp
deleted file mode 100644
index fe4d212..0000000
--- a/tools/resampler_tools/fir.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-static inline double sinc(double x) {
- if (fabs(x) == 0.0f) return 1.0f;
- return sin(x) / x;
-}
-
-static inline double sqr(double x) {
- return x*x;
-}
-
-static inline int64_t toint(double x, int64_t maxval) {
- int64_t v;
-
- v = static_cast<int64_t>(floor(x * maxval + 0.5));
- if (v >= maxval) {
- return maxval - 1; // error!
- }
- return v;
-}
-
-static double I0(double x) {
- // from the Numerical Recipes in C p. 237
- double ax,ans,y;
- ax=fabs(x);
- if (ax < 3.75) {
- y=x/3.75;
- y*=y;
- ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
- +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
- } else {
- y=3.75/ax;
- ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1
- +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2
- +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
- +y*0.392377e-2))))))));
- }
- return ans;
-}
-
-static double kaiser(int k, int N, double beta) {
- if (k < 0 || k > N)
- return 0;
- return I0(beta * sqrt(1.0 - sqr((2.0*k)/N - 1.0))) / I0(beta);
-}
-
-static void usage(char* name) {
- fprintf(stderr,
- "usage: %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
- " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] [-l lerp]\n"
- " %s [-h] [-d] [-D] [-s sample_rate] [-c cut-off_frequency] [-n half_zero_crossings]"
- " [-f {float|fixed|fixed16}] [-b beta] [-v dBFS] -p M/N\n"
- " -h this help message\n"
- " -d debug, print comma-separated coefficient table\n"
- " -D generate extra declarations\n"
- " -p generate poly-phase filter coefficients, with sample increment M/N\n"
- " -s sample rate (48000)\n"
- " -c cut-off frequency (20478)\n"
- " -n number of zero-crossings on one side (8)\n"
- " -l number of lerping bits (4)\n"
- " -m number of polyphases (related to -l, default 16)\n"
- " -f output format, can be fixed, fixed16, or float (fixed)\n"
- " -b kaiser window parameter beta (7.865 [-80dB])\n"
- " -v attenuation in dBFS (0)\n",
- name, name
- );
- exit(0);
-}
-
-int main(int argc, char** argv)
-{
- // nc is the number of bits to store the coefficients
- int nc = 32;
- bool polyphase = false;
- unsigned int polyM = 160;
- unsigned int polyN = 147;
- bool debug = false;
- double Fs = 48000;
- double Fc = 20478;
- double atten = 1;
- int format = 0; // 0=fixed, 1=float
- bool declarations = false;
-
- // in order to keep the errors associated with the linear
- // interpolation of the coefficients below the quantization error
- // we must satisfy:
- // 2^nz >= 2^(nc/2)
- //
- // for 16 bit coefficients that would be 256
- //
- // note that increasing nz only increases memory requirements,
- // but doesn't increase the amount of computation to do.
- //
- //
- // see:
- // Smith, J.O. Digital Audio Resampling Home Page
- // https://ccrma.stanford.edu/~jos/resample/, 2011-03-29
- //
-
- // | 0.1102*(A - 8.7) A > 50
- // beta = | 0.5842*(A - 21)^0.4 + 0.07886*(A - 21) 21 <= A <= 50
- // | 0 A < 21
- // with A is the desired stop-band attenuation in dBFS
- //
- // for eg:
- //
- // 30 dB 2.210
- // 40 dB 3.384
- // 50 dB 4.538
- // 60 dB 5.658
- // 70 dB 6.764
- // 80 dB 7.865
- // 90 dB 8.960
- // 100 dB 10.056
- double beta = 7.865;
-
- // 2*nzc = (A - 8) / (2.285 * dw)
- // with dw the transition width = 2*pi*dF/Fs
- //
- int nzc = 8;
-
- /*
- * Example:
- * 44.1 KHz to 48 KHz resampling
- * 100 dB rejection above 28 KHz
- * (the spectrum will fold around 24 KHz and we want 100 dB rejection
- * at the point where the folding reaches 20 KHz)
- * ...___|_____
- * | \|
- * | ____/|\____
- * |/alias| \
- * ------/------+------\---------> KHz
- * 20 24 28
- *
- * Transition band 8 KHz, or dw = 1.0472
- *
- * beta = 10.056
- * nzc = 20
- */
-
- int M = 1 << 4; // number of phases for interpolation
- int ch;
- while ((ch = getopt(argc, argv, ":hds:c:n:f:l:m:b:p:v:z:D")) != -1) {
- switch (ch) {
- case 'd':
- debug = true;
- break;
- case 'D':
- declarations = true;
- break;
- case 'p':
- if (sscanf(optarg, "%u/%u", &polyM, &polyN) != 2) {
- usage(argv[0]);
- }
- polyphase = true;
- break;
- case 's':
- Fs = atof(optarg);
- break;
- case 'c':
- Fc = atof(optarg);
- break;
- case 'n':
- nzc = atoi(optarg);
- break;
- case 'm':
- M = atoi(optarg);
- break;
- case 'l':
- M = 1 << atoi(optarg);
- break;
- case 'f':
- if (!strcmp(optarg, "fixed")) {
- format = 0;
- }
- else if (!strcmp(optarg, "fixed16")) {
- format = 0;
- nc = 16;
- }
- else if (!strcmp(optarg, "float")) {
- format = 1;
- }
- else {
- usage(argv[0]);
- }
- break;
- case 'b':
- beta = atof(optarg);
- break;
- case 'v':
- atten = pow(10, -fabs(atof(optarg))*0.05 );
- break;
- case 'h':
- default:
- usage(argv[0]);
- break;
- }
- }
-
- // cut off frequency ratio Fc/Fs
- double Fcr = Fc / Fs;
-
- // total number of coefficients (one side)
-
- const int N = M * nzc;
-
- // lerp (which is most useful if M is a power of 2)
-
- int nz = 0; // recalculate nz as the bits needed to represent M
- for (int i = M-1 ; i; i>>=1, nz++);
- // generate the right half of the filter
- if (!debug) {
- printf("// cmd-line:");
- for (int i=0 ; i<argc ; i++) {
- printf(" %s", argv[i]);
- }
- printf("\n");
- if (declarations) {
- if (!polyphase) {
- printf("const int32_t RESAMPLE_FIR_SIZE = %d;\n", N);
- printf("const int32_t RESAMPLE_FIR_INT_PHASES = %d;\n", M);
- printf("const int32_t RESAMPLE_FIR_NUM_COEF = %d;\n", nzc);
- } else {
- printf("const int32_t RESAMPLE_FIR_SIZE = %d;\n", 2*nzc*polyN);
- printf("const int32_t RESAMPLE_FIR_NUM_COEF = %d;\n", 2*nzc);
- }
- if (!format) {
- printf("const int32_t RESAMPLE_FIR_COEF_BITS = %d;\n", nc);
- }
- printf("\n");
- printf("static %s resampleFIR[] = {", !format ? "int32_t" : "float");
- }
- }
-
- if (!polyphase) {
- for (int i=0 ; i<=M ; i++) { // an extra set of coefs for interpolation
- for (int j=0 ; j<nzc ; j++) {
- int ix = j*M + i;
- double x = (2.0 * M_PI * ix * Fcr) / M;
- double y = kaiser(ix+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;
- y *= atten;
-
- if (!debug) {
- if (j == 0)
- printf("\n ");
- }
- if (!format) {
- int64_t yi = toint(y, 1ULL<<(nc-1));
- if (nc > 16) {
- printf("0x%08x,", int32_t(yi));
- } else {
- printf("0x%04x,", int32_t(yi)&0xffff);
- }
- } else {
- printf("%.9g%s", y, debug ? "," : "f,");
- }
- if (j != nzc-1) {
- printf(" ");
- }
- }
- }
- } else {
- for (unsigned int j=0 ; j<polyN ; j++) {
- // calculate the phase
- double p = ((polyM*j) % polyN) / double(polyN);
- if (!debug) printf("\n ");
- else printf("\n");
- // generate a FIR per phase
- for (int i=-nzc ; i<nzc ; i++) {
- double x = 2.0 * M_PI * Fcr * (i + p);
- double y = kaiser(i+N, 2*N, beta) * sinc(x) * 2.0 * Fcr;;
- y *= atten;
- if (!format) {
- int64_t yi = toint(y, 1ULL<<(nc-1));
- if (nc > 16) {
- printf("0x%08x,", int32_t(yi));
- } else {
- printf("0x%04x,", int32_t(yi)&0xffff);
- }
- } else {
- printf("%.9g%s", y, debug ? "," : "f,");
- }
-
- if (i != nzc-1) {
- printf(" ");
- }
- }
- }
- }
-
- if (!debug && declarations) {
- printf("\n};");
- }
- printf("\n");
- return 0;
-}
-
-// http://www.csee.umbc.edu/help/sound/AFsp-V2R1/html/audio/ResampAudio.html