Merge "CameraService: Increase watchdog timer" into main
diff --git a/camera/Android.bp b/camera/Android.bp
index a3fd7f9..e5ae954 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -43,6 +43,22 @@
],
}
+aconfig_declarations {
+ name: "camera_platform_flags",
+ package: "com.android.internal.camera.flags",
+ srcs: ["camera_platform.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "camera_platform_flags_c_lib",
+ aconfig_declarations: "camera_platform_flags",
+}
+
+java_aconfig_library {
+ name: "camera_platform_flags_java_lib",
+ aconfig_declarations: "camera_platform_flags",
+}
+
cc_library_headers {
name: "camera_headers",
export_include_dirs: ["include"],
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 2a102d0..6759f3b 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -180,7 +180,7 @@
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera %d: %s", cameraId,
- (cs == nullptr) ? "Service not available" : ret.toString8().string());
+ (cs == nullptr) ? "Service not available" : ret.toString8().c_str());
c.clear();
}
return c;
@@ -265,7 +265,7 @@
&count);
if (!res.isOk()) {
ALOGE("Error reading number of cameras: %s",
- res.toString8().string());
+ res.toString8().c_str());
count = 0;
}
return count;
diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp
index a4ae71b..2e808d1 100644
--- a/camera/CameraMetadata.cpp
+++ b/camera/CameraMetadata.cpp
@@ -289,7 +289,7 @@
return res;
}
// string.size() doesn't count the null termination character.
- return updateImpl(tag, (const void*)string.string(), string.size() + 1);
+ return updateImpl(tag, (const void*)string.c_str(), string.size() + 1);
}
status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
@@ -809,7 +809,7 @@
for (size_t i = 0; i < totalSectionCount; ++i) {
const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
- (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
+ (*vendorSections)[i - ANDROID_SECTION_COUNT].c_str();
ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index e95c91c..272b113 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -205,7 +205,7 @@
void CameraParameters::unflatten(const String8 ¶ms)
{
- const char *a = params.string();
+ const char *a = params.c_str();
const char *b;
mMap.clear();
@@ -271,7 +271,7 @@
String8 v = mMap.valueFor(String8(key));
if (v.length() == 0)
return 0;
- return v.string();
+ return v.c_str();
}
int CameraParameters::getInt(const char *key) const
@@ -463,7 +463,7 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- ALOGD("%s: %s\n", k.string(), v.string());
+ ALOGD("%s: %s\n", k.c_str(), v.c_str());
}
}
@@ -478,10 +478,10 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+ snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
result.append(buffer);
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/camera/CameraParameters2.cpp b/camera/CameraParameters2.cpp
index a1cf355..1ccad08 100644
--- a/camera/CameraParameters2.cpp
+++ b/camera/CameraParameters2.cpp
@@ -52,14 +52,14 @@
flattened += ";";
}
- ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.string());
+ ALOGV("%s: Flattened params = %s", __FUNCTION__, flattened.c_str());
return flattened;
}
void CameraParameters2::unflatten(const String8 ¶ms)
{
- const char *a = params.string();
+ const char *a = params.c_str();
const char *b;
mMap.clear();
@@ -128,7 +128,7 @@
if (idx < 0) {
return NULL;
} else {
- return mMap.valueAt(idx).string();
+ return mMap.valueAt(idx).c_str();
}
}
@@ -305,7 +305,7 @@
void CameraParameters2::setPreviewFpsRange(int min_fps, int max_fps)
{
String8 str = String8::format("%d,%d", min_fps, max_fps);
- set(CameraParameters::KEY_PREVIEW_FPS_RANGE, str.string());
+ set(CameraParameters::KEY_PREVIEW_FPS_RANGE, str.c_str());
}
void CameraParameters2::setPreviewFormat(const char *format)
@@ -357,7 +357,7 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- ALOGD("%s: %s\n", k.string(), v.string());
+ ALOGD("%s: %s\n", k.c_str(), v.c_str());
}
}
@@ -373,10 +373,10 @@
String8 k, v;
k = mMap.keyAt(i);
v = mMap.valueAt(i);
- snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+ snprintf(buffer, 255, "\t%s: %s\n", k.c_str(), v.c_str());
result.append(buffer);
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/camera/VendorTagDescriptor.cpp b/camera/VendorTagDescriptor.cpp
index 151b653..fb26f83 100644
--- a/camera/VendorTagDescriptor.cpp
+++ b/camera/VendorTagDescriptor.cpp
@@ -152,7 +152,7 @@
break;
}
String8 tagName = parcel->readString8();
- if (tagName.isEmpty()) {
+ if (tagName.empty()) {
ALOGE("%s: parcel tag name was NULL for tag %d.", __FUNCTION__, tag);
res = NOT_ENOUGH_DATA;
break;
@@ -190,7 +190,7 @@
"Vector capacity must be positive");
for (size_t i = 0; i < sectionCount; ++i) {
String8 sectionName = parcel->readString8();
- if (sectionName.isEmpty()) {
+ if (sectionName.empty()) {
ALOGE("%s: parcel section name was NULL for section %zu.",
__FUNCTION__, i);
return NOT_ENOUGH_DATA;
@@ -237,7 +237,7 @@
if (index < 0) {
return VENDOR_SECTION_NAME_ERR;
}
- return mSections[mTagToSectionMap.valueAt(index)].string();
+ return mSections[mTagToSectionMap.valueAt(index)].c_str();
}
const char* VendorTagDescriptor::getTagName(uint32_t tag) const {
@@ -245,7 +245,7 @@
if (index < 0) {
return VENDOR_TAG_NAME_ERR;
}
- return mTagToNameMap.valueAt(index).string();
+ return mTagToNameMap.valueAt(index).c_str();
}
int VendorTagDescriptor::getTagType(uint32_t tag) const {
@@ -299,13 +299,13 @@
status_t VendorTagDescriptor::lookupTag(const String8& name, const String8& section, /*out*/uint32_t* tag) const {
ssize_t index = mReverseMapping.indexOfKey(section);
if (index < 0) {
- ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.string());
+ ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.c_str());
return BAD_VALUE;
}
ssize_t nameIndex = mReverseMapping[index]->indexOfKey(name);
if (nameIndex < 0) {
- ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.string());
+ ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.c_str());
return BAD_VALUE;
}
@@ -344,7 +344,7 @@
const char* typeName = (type >= 0 && type < NUM_TYPES) ?
camera_metadata_type_names[type] : "UNKNOWN";
dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2,
- "", tag, name.string(), type, typeName, sectionName.string());
+ "", tag, name.c_str(), type, typeName, sectionName.c_str());
}
}
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 33220ce..73b153c 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -249,7 +249,7 @@
for (auto& surface : surfaceShims) {
ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
surface.graphicBufferProducer.get(),
- toString8(surface.name).string());
+ toString8(surface.name).c_str());
mGbps.push_back(surface.graphicBufferProducer);
}
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
new file mode 100644
index 0000000..fc11518
--- /dev/null
+++ b/camera/camera_platform.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.internal.camera.flags"
+
+flag {
+ namespace: "camera_platform"
+ name: "initial_test_flag"
+ description: "Flag infrastructure test flag"
+ bug: "292631208"
+}
diff --git a/camera/include/camera/StringUtils.h b/camera/include/camera/StringUtils.h
index b9dfbfc..80c419f 100644
--- a/camera/include/camera/StringUtils.h
+++ b/camera/include/camera/StringUtils.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_SERVERS_CAMERA_STRINGUTILS_H
#define ANDROID_SERVERS_CAMERA_STRINGUTILS_H
-#include <codecvt>
-#include <locale>
#include <memory>
#include <optional>
#include <string>
@@ -61,12 +59,12 @@
}
inline std::string toStdString(const String8 &str) {
- return std::string(str.string());
+ return std::string(str.c_str());
}
inline std::string toStdString(const String16 &str) {
- std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
- return convert.to_bytes(str.string());
+ String8 str8(str);
+ return std::string(str8.c_str());
}
/**
@@ -74,8 +72,9 @@
* len is the number of characters.
*/
inline std::string toStdString(const char16_t *str, size_t len) {
- std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
- return convert.to_bytes(str, str + len);
+ String16 str16(str, len);
+ String8 str8(str16);
+ return std::string(str8.c_str());
}
} // namespace android
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 8bdb6d4..97d65b0 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -163,7 +163,7 @@
templateId);
return ACAMERA_ERROR_INVALID_PARAMETER;
} else if (!remoteRet.isOk()) {
- ALOGE("Create capture request failed: %s", remoteRet.toString8().string());
+ ALOGE("Create capture request failed: %s", remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
ACaptureRequest* outReq = new ACaptureRequest();
@@ -317,22 +317,22 @@
switch (remoteRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_INVALID_OPERATION:
ALOGE("Camera device %s invalid operation: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_INVALID_OPERATION;
break;
case hardware::ICameraService::ERROR_ALREADY_EXISTS:
ALOGE("Camera device %s output surface already exists: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_INVALID_PARAMETER;
break;
case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
ALOGE("Camera device %s invalid input argument: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_INVALID_PARAMETER;
break;
default:
ALOGE("Camera device %s failed to add shared output: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
}
@@ -368,24 +368,24 @@
// ndk as well.
if (remoteRet.exceptionCode() != EX_SERVICE_SPECIFIC) {
ALOGE("Camera device %s failed to prepare output window %p: %s", getId(), window,
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
switch (remoteRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_INVALID_OPERATION:
ALOGE("Camera device %s invalid operation: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_INVALID_OPERATION;
break;
case hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT:
ALOGE("Camera device %s invalid input argument: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_INVALID_PARAMETER;
break;
default:
ALOGE("Camera device %s failed to prepare output window %p: %s", getId(), window,
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
}
@@ -546,7 +546,7 @@
ALOGV("Repeating request is already stopped.");
return ACAMERA_OK;
} else if (!remoteRet.isOk()) {
- ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().string());
+ ALOGE("Stop repeating request fails in remote: %s", remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
@@ -598,7 +598,7 @@
int64_t lastFrameNumber;
binder::Status remoteRet = mRemote->flush(&lastFrameNumber);
if (!remoteRet.isOk()) {
- ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().string());
+ ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
if (mRepeatingSequenceId != REQUEST_ID_NONE) {
@@ -622,7 +622,7 @@
binder::Status remoteRet = mRemote->waitUntilIdle();
if (!remoteRet.isOk()) {
- ALOGE("Camera device %s waitUntilIdle failed: %s", getId(), remoteRet.toString8().string());
+ ALOGE("Camera device %s waitUntilIdle failed: %s", getId(), remoteRet.toString8().c_str());
// TODO: define a function to convert status_t -> camera_status_t
return ACAMERA_ERROR_UNKNOWN;
}
@@ -732,7 +732,7 @@
binder::Status remoteRet = mRemote->beginConfigure();
if (!remoteRet.isOk()) {
- ALOGE("Camera device %s begin configure failed: %s", getId(), remoteRet.toString8().string());
+ ALOGE("Camera device %s begin configure failed: %s", getId(), remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
@@ -741,7 +741,7 @@
remoteRet = mRemote->deleteStream(streamId);
if (!remoteRet.isOk()) {
ALOGE("Camera device %s failed to remove stream %d: %s", getId(), streamId,
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
mConfiguredOutputs.erase(streamId);
@@ -753,7 +753,7 @@
remoteRet = mRemote->createStream(outputPair.second, &streamId);
if (!remoteRet.isOk()) {
ALOGE("Camera device %s failed to create stream: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
@@ -768,10 +768,10 @@
ns2ms(startTimeNs), &offlineStreamIds);
if (remoteRet.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_ILLEGAL_ARGUMENT) {
ALOGE("Camera device %s cannnot support app output configuration: %s", getId(),
- remoteRet.toString8().string());
+ remoteRet.toString8().c_str());
return ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
} else if (!remoteRet.isOk()) {
- ALOGE("Camera device %s end configure failed: %s", getId(), remoteRet.toString8().string());
+ ALOGE("Camera device %s end configure failed: %s", getId(), remoteRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN;
}
@@ -918,7 +918,7 @@
if (cbh.mIsLogicalCameraCallback) {
if (resultExtras.errorPhysicalCameraId.size() > 0) {
String8 cameraId = toString8(resultExtras.errorPhysicalCameraId);
- msg->setString(kFailingPhysicalCameraId, cameraId.string(), cameraId.size());
+ msg->setString(kFailingPhysicalCameraId, cameraId.c_str(), cameraId.size());
}
msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
} else {
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 382d6ce..4658d18 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -66,7 +66,7 @@
ACameraDevice* wrapper);
~CameraDevice();
- inline const char* getId() const { return mCameraId.string(); }
+ inline const char* getId() const { return mCameraId.c_str(); }
camera_status_t createCaptureRequest(
ACameraDevice_request_template templateId,
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 299ffc0..5d3b65b 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -166,7 +166,7 @@
} else {
VendorTagDescriptorCache::clearGlobalVendorTagCache();
ALOGE("%s: Failed to setup vendor tag cache: %s",
- __FUNCTION__, res.toString8().string());
+ __FUNCTION__, res.toString8().c_str());
}
}
} else if (ret.serviceSpecificErrorCode() ==
@@ -176,7 +176,7 @@
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
} else {
ALOGE("%s: Failed to get vendor tag descriptors: %s",
- __FUNCTION__, ret.toString8().string());
+ __FUNCTION__, ret.toString8().c_str());
}
}
ALOGE_IF(mCameraService == nullptr, "no CameraService!?");
@@ -707,7 +707,7 @@
return ACAMERA_ERROR_INVALID_PARAMETER;
default:
ALOGE("Get camera characteristics from camera service failed: %s",
- serviceRet.toString8().string());
+ serviceRet.toString8().c_str());
return ACAMERA_ERROR_UNKNOWN; // should not reach here
}
}
@@ -751,7 +751,7 @@
targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
if (!serviceRet.isOk()) {
- ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
+ ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().c_str());
// Convert serviceRet to camera_status_t
switch(serviceRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_DISCONNECTED:
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 1fd4a86..61c7551 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -142,7 +142,7 @@
if (ids[i] == '\0') {
if (start != i) {
mStaticPhysicalCameraIdValues.push_back(String8((const char *)ids+start));
- mStaticPhysicalCameraIds.push_back(mStaticPhysicalCameraIdValues.back().string());
+ mStaticPhysicalCameraIds.push_back(mStaticPhysicalCameraIdValues.back().c_str());
}
start = i+1;
}
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index af00e55..4a589bc 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -584,6 +584,13 @@
* <p>Only constrains auto-exposure (AE) algorithm, not
* manual control of ACAMERA_SENSOR_EXPOSURE_TIME and
* ACAMERA_SENSOR_FRAME_DURATION.</p>
+ * <p>To start a CaptureSession with a target FPS range different from the
+ * capture request template's default value, the application
+ * is strongly recommended to call
+ * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+ * with the target fps range before creating the capture session. The aeTargetFpsRange is
+ * typically a session parameter. Specifying it at session creation time helps avoid
+ * session reconfiguration delays in cases like 60fps or high speed recording.</p>
*
* @see ACAMERA_SENSOR_EXPOSURE_TIME
* @see ACAMERA_SENSOR_FRAME_DURATION
@@ -1128,6 +1135,12 @@
* ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE field will return
* OFF if the recording output is not stabilized, or if there are no output
* Surface types that can be stabilized.</p>
+ * <p>The application is strongly recommended to call
+ * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+ * with the desired video stabilization mode before creating the capture session.
+ * Video stabilization mode is a session parameter on many devices. Specifying
+ * it at session creation time helps avoid reconfiguration delay caused by difference
+ * between the default value and the first CaptureRequest.</p>
* <p>If a camera device supports both this mode and OIS
* (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may
* produce undesirable interaction, so it is recommended not to enable
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 01f73e0..cd27bb5 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -153,7 +153,7 @@
// just convert to char* -- but String8 doesn't document what it does
// with values outside 0-255. So just convert to char* and use strlen()
// to see what we get.
- const char* str = str8.string();
+ const char* str = str8.c_str();
return computeScaledStringWidth(str, strlen(str));
}
@@ -180,13 +180,13 @@
void TextRenderer::drawString(const Program& program, const float* texMatrix,
float x, float y, const String8& str8) const {
- ALOGV("drawString %.3f,%.3f '%s' (scale=%.3f)", x, y, str8.string(),mScale);
+ ALOGV("drawString %.3f,%.3f '%s' (scale=%.3f)", x, y, str8.c_str(),mScale);
initOnce();
// We want to draw the entire string with a single GLES call. We
// generate two arrays, one with screen coordinates, one with texture
// coordinates. Need two triangles per character.
- const char* str = str8.string();
+ const char* str = str8.c_str();
size_t len = strlen(str); // again, unsure about String8 handling
const size_t quadCoords =
@@ -252,7 +252,7 @@
float TextRenderer::drawWrappedString(const Program& texRender,
float xpos, float ypos, const String8& str) {
- ALOGV("drawWrappedString %.3f,%.3f '%s'", xpos, ypos, str.string());
+ ALOGV("drawWrappedString %.3f,%.3f '%s'", xpos, ypos, str.c_str());
initOnce();
if (mScreenWidth == 0 || mScreenHeight == 0) {
@@ -283,7 +283,7 @@
} else {
// We need to break the string into pieces, ideally at whitespace
// boundaries.
- char* mangle = strdup(str.string());
+ char* mangle = strdup(str.c_str());
char* start = mangle;
while (start != NULL) {
float xposAdj = (start == mangle) ? xpos : xpos + indentWidth;
diff --git a/cmds/screenrecord/screenrecord.cpp b/cmds/screenrecord/screenrecord.cpp
index f53fc0a..55bfbd8 100644
--- a/cmds/screenrecord/screenrecord.cpp
+++ b/cmds/screenrecord/screenrecord.cpp
@@ -1096,7 +1096,7 @@
"-a",
"android.intent.action.MEDIA_SCANNER_SCAN_FILE",
"-d",
- fileUrl.string(),
+ fileUrl.c_str(),
NULL
};
if (gVerbose) {
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 379f244..f26e3a8 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -155,7 +155,7 @@
}
static void dumpSource(const sp<MediaSource> &source, const String8 &filename) {
- FILE *out = fopen(filename.string(), "wb");
+ FILE *out = fopen(filename.c_str(), "wb");
CHECK_EQ((status_t)OK, source->start());
@@ -212,8 +212,8 @@
}
rawSource = SimpleDecodingSource::Create(
source, flags, gSurface,
- gComponentNameOverride.isEmpty() ? nullptr : gComponentNameOverride.c_str(),
- !gComponentNameOverride.isEmpty());
+ gComponentNameOverride.empty() ? nullptr : gComponentNameOverride.c_str(),
+ !gComponentNameOverride.empty());
if (rawSource == NULL) {
return;
}
@@ -538,9 +538,9 @@
Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
#if 0
sp<MPEG4Writer> writer =
- new MPEG4Writer(gWriteMP4Filename.string());
+ new MPEG4Writer(gWriteMP4Filename.c_str());
#else
- int fd = open(gWriteMP4Filename.string(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ int fd = open(gWriteMP4Filename.c_str(), O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf(stderr, "couldn't open file");
return;
@@ -834,7 +834,7 @@
case 'd':
{
dumpStream = true;
- dumpStreamFilename.setTo(optarg);
+ dumpStreamFilename = optarg;
break;
}
@@ -842,13 +842,13 @@
{
dumpPCMStream = true;
audioOnly = true;
- dumpStreamFilename.setTo(optarg);
+ dumpStreamFilename = optarg;
break;
}
case 'N':
{
- gComponentNameOverride.setTo(optarg);
+ gComponentNameOverride = optarg;
break;
}
@@ -886,7 +886,7 @@
case 'w':
{
gWriteMP4 = true;
- gWriteMP4Filename.setTo(optarg);
+ gWriteMP4Filename = optarg;
break;
}
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
index 584c6a6..6294f50 100644
--- a/drm/common/DrmSupportInfo.cpp
+++ b/drm/common/DrmSupportInfo.cpp
@@ -50,7 +50,7 @@
for (size_t i = 0; i < mMimeTypeVector.size(); i++) {
const String8 item = mMimeTypeVector.itemAt(i);
- if (!strcasecmp(item.string(), mimeType.string())) {
+ if (!strcasecmp(item.c_str(), mimeType.c_str())) {
return true;
}
}
@@ -61,7 +61,7 @@
for (size_t i = 0; i < mFileSuffixVector.size(); i++) {
const String8 item = mFileSuffixVector.itemAt(i);
- if (!strcasecmp(item.string(), fileType.string())) {
+ if (!strcasecmp(item.c_str(), fileType.c_str())) {
return true;
}
}
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index a6d33b0..1b49be1 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -303,8 +303,8 @@
const String8 value = drmInforequest->get(key);
if (key == String8("FileDescriptorKey")) {
int fd = -1;
- if (sscanf(value.string(), "FileDescriptor[%d]", &fd) != 1) {
- sscanf(value.string(), "%d", &fd);
+ if (sscanf(value.c_str(), "FileDescriptor[%d]", &fd) != 1) {
+ sscanf(value.c_str(), "%d", &fd);
}
data.writeFileDescriptor(fd);
} else {
@@ -1330,7 +1330,7 @@
const String8 mime = data.readString8();
sp<DecryptHandle> handle
- = openDecryptSession(uniqueId, fd, offset, length, mime.string());
+ = openDecryptSession(uniqueId, fd, offset, length, mime.c_str());
if (NULL != handle.get()) {
writeDecryptHandleToParcelData(handle.get(), reply);
@@ -1349,7 +1349,7 @@
const String8 uri = data.readString8();
const String8 mime = data.readString8();
- sp<DecryptHandle> handle = openDecryptSession(uniqueId, uri.string(), mime.string());
+ sp<DecryptHandle> handle = openDecryptSession(uniqueId, uri.c_str(), mime.c_str());
if (NULL != handle.get()) {
writeDecryptHandleToParcelData(handle.get(), reply);
diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp
index 16b5b34..97c3716 100644
--- a/drm/common/ReadWriteUtils.cpp
+++ b/drm/common/ReadWriteUtils.cpp
@@ -34,7 +34,7 @@
String8 ReadWriteUtils::readBytes(const String8& filePath) {
FILE* file = NULL;
- file = fopen(filePath.string(), "r");
+ file = fopen(filePath.c_str(), "r");
String8 string("");
if (NULL != file) {
@@ -56,7 +56,7 @@
int ReadWriteUtils::readBytes(const String8& filePath, char** buffer) {
FILE* file = NULL;
- file = fopen(filePath.string(), "r");
+ file = fopen(filePath.c_str(), "r");
off64_t length = 0;
if (NULL != file) {
@@ -77,15 +77,15 @@
void ReadWriteUtils::writeToFile(const String8& filePath, const String8& data) {
FILE* file = NULL;
- file = fopen(filePath.string(), "w+");
+ file = fopen(filePath.c_str(), "w+");
if (NULL != file) {
int fd = fileno(file);
int size = data.size();
if (FAILURE != ftruncate(fd, size)) {
- if (size != write(fd, data.string(), size)) {
- ALOGE("Failed to write the data to: %s", filePath.string());
+ if (size != write(fd, data.c_str(), size)) {
+ ALOGE("Failed to write the data to: %s", filePath.c_str());
}
}
fclose(file);
@@ -94,14 +94,14 @@
void ReadWriteUtils::appendToFile(const String8& filePath, const String8& data) {
FILE* file = NULL;
- file = fopen(filePath.string(), "a+");
+ file = fopen(filePath.c_str(), "a+");
if (NULL != file) {
int fd = fileno(file);
int size = data.size();
- if (size != write(fd, data.string(), size)) {
- ALOGE("Failed to write the data to: %s", filePath.string());
+ if (size != write(fd, data.c_str(), size)) {
+ ALOGE("Failed to write the data to: %s", filePath.c_str());
}
fclose(file);
}
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index cee44b9..81c2003 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -78,6 +78,9 @@
"libselinux",
"libstagefright_foundation",
],
+ whole_static_libs: [
+ "libc++fs",
+ ],
cflags: [
"-Wall",
@@ -124,6 +127,7 @@
],
static_libs: [
+ "libc++fs",
"libmediautils",
"liblog",
"libdrmframeworkcommon",
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index f7989bd..d32228b 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -39,6 +39,7 @@
#include "ReadWriteUtils.h"
#include <algorithm>
+#include <filesystem>
#define DECRYPT_FILE_ERROR (-1)
@@ -114,7 +115,7 @@
std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
+ std::string plugInId = std::filesystem::path(plugInId8.c_str()).stem();
ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
Mutex::Autolock _l(mMetricsLock);
@@ -127,7 +128,7 @@
}
}
- if (!mimeType.isEmpty()) {
+ if (!mimeType.empty()) {
metrics.mMimeTypes.insert(mimeType.c_str());
} else if (NULL != info) {
DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
@@ -316,8 +317,8 @@
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
result = rDrmEngine.canHandle(uniqueId, path);
} else {
- String8 extension = path.getPathExtension();
- if (String8("") != extension) {
+ const auto extension = std::filesystem::path(path.c_str()).extension();
+ if (!extension.empty()) {
result = canHandle(uniqueId, path);
}
}
@@ -395,7 +396,7 @@
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
}
- if (!mimeType.isEmpty()) {
+ if (!mimeType.empty()) {
recordEngineMetrics(__func__, plugInId, mimeType);
}
return mimeType;
@@ -745,7 +746,7 @@
String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
String8 plugInId("");
- const String8 fileSuffix = path.getPathExtension();
+ const String8 fileSuffix(std::filesystem::path(path.c_str()).extension().c_str());
for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index c830c6e..98eba2a 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -373,7 +373,7 @@
(void)args;
#endif
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/drm/drmserver/PlugInManager.h b/drm/drmserver/PlugInManager.h
index 466844d..8a60b78 100644
--- a/drm/drmserver/PlugInManager.h
+++ b/drm/drmserver/PlugInManager.h
@@ -25,6 +25,8 @@
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
+#include <filesystem>
+
namespace android {
const char* const PLUGIN_MANAGER_CREATE = "create";
@@ -137,7 +139,7 @@
PlugInContainer* pPlugInContainer = new PlugInContainer();
- pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
+ pPlugInContainer->hHandle = dlopen(rsPlugInPath.c_str(), RTLD_LAZY);
if (NULL == pPlugInContainer->hHandle) {
delete pPlugInContainer;
@@ -201,7 +203,7 @@
*/
Vector<String8> getPlugInPathList(const String8& rsDirPath) {
Vector<String8> fileList;
- DIR* pDir = opendir(rsDirPath.string());
+ DIR* pDir = opendir(rsDirPath.c_str());
struct dirent* pEntry;
while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
@@ -227,10 +229,9 @@
* True if the input name denotes plug-in
*/
bool isPlugIn(const struct dirent* pEntry) const {
- String8 sName(pEntry->d_name);
- String8 extension(sName.getPathExtension());
+ const auto extension = std::filesystem::path(pEntry->d_name).extension();
// Note that the plug-in extension must exactly match case
- return extension == String8(PLUGIN_EXTENSION);
+ return extension.string() == PLUGIN_EXTENSION;
}
/**
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
index 3b1566f..d47a9d9 100644
--- a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -128,7 +128,7 @@
struct MimeGroup* pGroup;
struct MimeTypeList* pMimeItem;
int len;
- pMimeType = mimeType.string();
+ pMimeType = mimeType.c_str();
if (NULL != pMimeType) {
if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
(0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
@@ -159,7 +159,7 @@
result = String8(mime_type_unsupported);
}
LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
- pMimeType, result.string());
+ pMimeType, result.c_str());
}
return result;
}
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index 6e55a16..16ea15e 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -64,6 +64,10 @@
"libfwdlock-decoder",
],
+ whole_static_libs: [
+ "libc++fs",
+ ],
+
local_include_dirs: ["include"],
relative_install_path: "drm",
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index 769de0c..1ade2f7 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -37,6 +37,8 @@
#include "FwdLockGlue.h"
#include "MimeTypeUtil.h"
+#include <filesystem>
+
#undef LOG_TAG
#define LOG_TAG "FwdLockEngine"
@@ -227,7 +229,7 @@
bool FwdLockEngine::onCanHandle(int /* uniqueId */, const String8& path) {
bool result = false;
- String8 extString = path.getPathExtension();
+ String8 extString(std::filesystem::path(path.c_str()).extension().c_str());
return IsFileSuffixSupported(extString);
}
@@ -544,7 +546,7 @@
String8 uriTag = String8(uri);
uriTag.toLower();
- if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
+ if (0 == strncmp(uriTag.c_str(), fileTag, sizeof(fileTag) - 1)) {
const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
int fd = open(filePath, O_RDONLY);
diff --git a/drm/libdrmframework/plugins/passthru/Android.bp b/drm/libdrmframework/plugins/passthru/Android.bp
index 6dffd49..0a6cd47 100644
--- a/drm/libdrmframework/plugins/passthru/Android.bp
+++ b/drm/libdrmframework/plugins/passthru/Android.bp
@@ -39,11 +39,15 @@
srcs: ["src/DrmPassthruPlugIn.cpp"],
shared_libs: [
+ "libbase",
"libutils",
"liblog",
"libdl",
"libdrmframeworkcommon",
],
+ whole_static_libs: [
+ "libc++fs",
+ ],
local_include_dirs: ["include"],
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
index 0fa3478..55b4b08 100644
--- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "DrmPassthruPlugIn"
#include <utils/Log.h>
+#include <android-base/strings.h>
#include <drm/DrmRights.h>
#include <drm/DrmConstraints.h>
#include <drm/DrmMetadata.h>
@@ -29,6 +30,8 @@
#include <drm/DrmSupportInfo.h>
#include <DrmPassthruPlugIn.h>
+#include <filesystem>
+
using namespace android;
@@ -64,7 +67,7 @@
String8 value("dummy_available_time");
char* charValue = NULL;
charValue = new char[value.length() + 1];
- strncpy(charValue, value.string(), value.length());
+ strncpy(charValue, value.c_str(), value.length());
charValue[value.length()] = '\0';
//Just add dummy available time for verification
@@ -95,7 +98,7 @@
const int bufferSize = licenseString.size();
char* data = NULL;
data = new char[bufferSize];
- memcpy(data, licenseString.string(), bufferSize);
+ memcpy(data, licenseString.c_str(), bufferSize);
const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType());
@@ -150,7 +153,7 @@
int length = dataString.length();
char* data = NULL;
data = new char[length];
- memcpy(data, dataString.string(), length);
+ memcpy(data, dataString.c_str(), length);
drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
DrmBuffer(data, length), drmInfoRequest->getMimeType());
}
@@ -158,10 +161,9 @@
}
bool DrmPassthruPlugIn::onCanHandle(int /*uniqueId*/, const String8& path) {
- ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string());
- String8 extension = path.getPathExtension();
- extension.toLower();
- return (String8(".passthru") == extension);
+ ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.c_str());
+ const auto extension = std::filesystem::path(path.c_str()).extension();
+ return base::EqualsIgnoreCase(extension.string(), ".passthru");
}
String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId,
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index 5ec7337..7106d66 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -117,7 +117,7 @@
}
static std::string toStdString(const String8& string8) {
- return std::string(string8.string());
+ return std::string(string8.c_str());
}
static std::vector<KeyValue> toKeyValueVector(const KeyedVector<String8, String8>& keyedVector) {
@@ -375,7 +375,7 @@
sp<DrmHalAidl> drm = mDrm.promote();
if (drm == NULL) {
name.append("<deleted>");
- } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.empty()) {
name.append("<Get vendor failed or is empty>");
}
name.append("[");
@@ -415,7 +415,7 @@
*isSupported = false;
Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
SecurityLevel levelAidl = toAidlSecurityLevel(level);
- std::string mimeTypeStr = mimeType.string();
+ std::string mimeTypeStr = mimeType.c_str();
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
CryptoSchemes schemes{};
@@ -947,12 +947,12 @@
String8 vendor;
String8 description;
- if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.empty()) {
ALOGE("Get vendor failed or is empty");
vendor = "NONE";
}
if (getPropertyStringInternal(String8("description"), description) != OK ||
- description.isEmpty()) {
+ description.empty()) {
ALOGE("Get description failed or is empty.");
description = "NONE";
}
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index 00ea004..c8c6e8e 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -121,7 +121,7 @@
}
static hidl_string toHidlString(const String8& string) {
- return hidl_string(string.string());
+ return hidl_string(string.c_str());
}
static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
@@ -273,7 +273,7 @@
sp<DrmHalHidl> drm = mDrm.promote();
if (drm == NULL) {
name.append("<deleted>");
- } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) {
+ } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.empty()) {
name.append("<Get vendor failed or is empty>");
}
name.append("[");
@@ -353,7 +353,7 @@
sp<IDrmPlugin> plugin;
Return<void> hResult = factory->createPlugin(
- uuid, appPackageName.string(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
+ uuid, appPackageName.c_str(), [&](Status status, const sp<IDrmPlugin>& hPlugin) {
if (status != Status::OK) {
DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
return;
@@ -517,7 +517,7 @@
return DrmStatus(OK);
}
// isCryptoSchemeSupported(uuid, mimeType)
- auto hResult = factory->isContentTypeSupported(mimeType.string());
+ auto hResult = factory->isContentTypeSupported(mimeType.c_str());
if (!hResult.isOk()) {
return DrmStatus(DEAD_OBJECT);
}
@@ -531,7 +531,7 @@
if (factoryV1_2 == NULL) {
return DrmStatus(ERROR_UNSUPPORTED);
} else {
- auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
+ auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.c_str(),
toHidlSecurityLevel(level));
if (!hResult.isOk()) {
return DrmStatus(DEAD_OBJECT);
@@ -1261,12 +1261,12 @@
if (mPluginV1_1 != NULL) {
String8 vendor;
String8 description;
- if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.isEmpty()) {
+ if (getPropertyStringInternal(String8("vendor"), vendor) != OK || vendor.empty()) {
ALOGE("Get vendor failed or is empty");
vendor = "NONE";
}
if (getPropertyStringInternal(String8("description"), description) != OK ||
- description.isEmpty()) {
+ description.empty()) {
ALOGE("Get description failed or is empty.");
description = "NONE";
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index ce4d730..7d600cb 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -151,7 +151,7 @@
if (status == OK) {
String8 version8;
if (getPropertyString(String8("version"), version8) == OK) {
- mVersion = version8.string();
+ mVersion = version8.c_str();
}
reportMediaDrmCreated();
} else {
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index 6744e25..989a597 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -172,7 +172,7 @@
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());
+ GetSessionIdString(sessionId).c_str());
Mutex::Autolock lock(mLock);
if (mService == NULL) {
@@ -188,7 +188,7 @@
}
void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
- ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
+ ALOGV("useSession(%s)", GetSessionIdString(sessionId).c_str());
Mutex::Autolock lock(mLock);
auto it = mSessionMap.find(toStdVec(sessionId));
@@ -205,7 +205,7 @@
}
void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
- ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
+ ALOGV("removeSession(%s)", GetSessionIdString(sessionId).c_str());
Mutex::Autolock lock(mLock);
auto it = mSessionMap.find(toStdVec(sessionId));
diff --git a/drm/libmediadrm/SharedLibrary.cpp b/drm/libmediadrm/SharedLibrary.cpp
index b2d635d..97d5653 100644
--- a/drm/libmediadrm/SharedLibrary.cpp
+++ b/drm/libmediadrm/SharedLibrary.cpp
@@ -25,7 +25,7 @@
namespace android {
SharedLibrary::SharedLibrary(const String8 &path) {
- mLibHandle = dlopen(path.string(), RTLD_NOW);
+ mLibHandle = dlopen(path.c_str(), RTLD_NOW);
}
SharedLibrary::~SharedLibrary() {
diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
index af7c367..c364bbb 100644
--- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
+++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp
@@ -131,7 +131,7 @@
for (size_t i = 0; i < array.size(); i++) {
result.appendFormat("%02x ", array[i]);
}
- if (result.isEmpty()) {
+ if (result.empty()) {
result.append("(null)");
}
return result;
@@ -157,7 +157,7 @@
}
status_t ClearKeyCasPlugin::closeSession(const CasSessionId &sessionId) {
- ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).string());
+ ALOGV("closeSession: sessionId=%s", sessionIdToString(sessionId).c_str());
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
@@ -171,7 +171,7 @@
status_t ClearKeyCasPlugin::setSessionPrivateData(
const CasSessionId &sessionId, const CasData & /*data*/) {
ALOGV("setSessionPrivateData: sessionId=%s",
- sessionIdToString(sessionId).string());
+ sessionIdToString(sessionId).c_str());
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
@@ -182,7 +182,7 @@
status_t ClearKeyCasPlugin::processEcm(
const CasSessionId &sessionId, const CasEcm& ecm) {
- ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).string());
+ ALOGV("processEcm: sessionId=%s", sessionIdToString(sessionId).c_str());
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
if (session.get() == nullptr) {
@@ -220,7 +220,7 @@
const CasSessionId &sessionId, int32_t event,
int arg, const CasData &eventData) {
ALOGV("sendSessionEvent: sessionId=%s, event=%d, arg=%d",
- sessionIdToString(sessionId).string(), event, arg);
+ sessionIdToString(sessionId).c_str(), event, arg);
// Echo the received event to the callback.
// Clear key plugin doesn't use any event, echo'ing for testing only.
if (mCallbackExt != NULL) {
@@ -232,12 +232,12 @@
}
status_t ClearKeyCasPlugin::provision(const String8 &str) {
- ALOGV("provision: provisionString=%s", str.string());
+ ALOGV("provision: provisionString=%s", str.c_str());
Mutex::Autolock lock(mKeyFetcherLock);
std::unique_ptr<ClearKeyLicenseFetcher> license_fetcher;
license_fetcher.reset(new ClearKeyLicenseFetcher());
- status_t err = license_fetcher->Init(str.string());
+ status_t err = license_fetcher->Init(str.c_str());
if (err != OK) {
ALOGE("provision: failed to init ClearKeyLicenseFetcher (err=%d)", err);
return err;
@@ -475,7 +475,7 @@
status_t ClearKeyDescramblerPlugin::setMediaCasSession(
const CasSessionId &sessionId) {
- ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).string());
+ ALOGV("setMediaCasSession: sessionId=%s", sessionIdToString(sessionId).c_str());
std::shared_ptr<ClearKeyCasSession> session =
ClearKeySessionLibrary::get()->findSession(sessionId);
@@ -503,7 +503,7 @@
ALOGV("descramble: secure=%d, sctrl=%d, subSamples=%s, "
"srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d",
(int)secure, (int)scramblingControl,
- subSamplesToString(subSamples, numSubSamples).string(),
+ subSamplesToString(subSamples, numSubSamples).c_str(),
srcPtr, dstPtr, srcOffset, dstOffset);
std::shared_ptr<ClearKeyCasSession> session = std::atomic_load(&mCASSession);
diff --git a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
index ee8dba3..07de1d2 100644
--- a/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
+++ b/drm/mediacas/plugins/clearkey/JsonAssetLoader.cpp
@@ -80,7 +80,7 @@
}
}
- return decodeBase64(AString(paddedText.string()));
+ return decodeBase64(AString(paddedText.c_str()));
}
bool JsonAssetLoader::findKey(const String8& jsonObject, Asset *asset) {
@@ -91,30 +91,30 @@
return false;
}
findValue(kIdTag, &value);
- ALOGV("found %s=%s", kIdTag.string(), value.string());
- asset->set_id(atoi(value.string()));
+ ALOGV("found %s=%s", kIdTag.c_str(), value.c_str());
+ asset->set_id(atoi(value.c_str()));
if (jsonObject.find(kNameTag) < 0) {
return false;
}
findValue(kNameTag, &value);
- ALOGV("found %s=%s", kNameTag.string(), value.string());
- asset->set_name(value.string());
+ ALOGV("found %s=%s", kNameTag.c_str(), value.c_str());
+ asset->set_name(value.c_str());
if (jsonObject.find(kLowerCaseOgranizationNameTag) < 0) {
return false;
}
findValue(kLowerCaseOgranizationNameTag, &value);
- ALOGV("found %s=%s", kLowerCaseOgranizationNameTag.string(), value.string());
- asset->set_lowercase_organization_name(value.string());
+ ALOGV("found %s=%s", kLowerCaseOgranizationNameTag.c_str(), value.c_str());
+ asset->set_lowercase_organization_name(value.c_str());
if (jsonObject.find(kCasTypeTag) < 0) {
return false;
}
findValue(kCasTypeTag, &value);
- ALOGV("found %s=%s", kCasTypeTag.string(), value.string());
+ ALOGV("found %s=%s", kCasTypeTag.c_str(), value.c_str());
// Asset_CasType_CLEARKEY_CAS = 1
- asset->set_cas_type((Asset_CasType)atoi(value.string()));
+ asset->set_cas_type((Asset_CasType)atoi(value.c_str()));
return true;
}
@@ -127,8 +127,8 @@
if (0 == (*nextToken).compare(key)) {
if (nextToken + 1 == mTokens.end())
break;
- valueToken = (*(nextToken + 1)).string();
- value->setTo(valueToken);
+ valueToken = (*(nextToken + 1)).c_str();
+ *value = valueToken;
nextToken++;
break;
}
@@ -146,7 +146,7 @@
jsmn_init(&parser);
int numTokens = jsmn_parse(&parser,
- jsonObject.string(), jsonObject.size(), NULL, 0);
+ jsonObject.c_str(), jsonObject.size(), NULL, 0);
if (numTokens < 0) {
ALOGE("Parser returns error code=%d", numTokens);
return false;
@@ -157,7 +157,7 @@
mJsmnTokens.setCapacity(jsmnTokensSize);
jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonObject.string(),
+ int status = jsmn_parse(&parser, jsonObject.c_str(),
jsonObject.size(), mJsmnTokens.editArray(), numTokens);
if (status < 0) {
ALOGE("Parser returns error code=%d", status);
@@ -169,12 +169,12 @@
const char *pjs;
ALOGV("numTokens: %d", numTokens);
for (int j = 0; j < numTokens; ++j) {
- pjs = jsonObject.string() + mJsmnTokens[j].start;
+ pjs = jsonObject.c_str() + mJsmnTokens[j].start;
if (mJsmnTokens[j].type == JSMN_STRING ||
mJsmnTokens[j].type == JSMN_PRIMITIVE) {
- token.setTo(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+ token = String8(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
tokens->add(token);
- ALOGV("add token: %s", token.string());
+ ALOGV("add token: %s", token.c_str());
}
}
return true;
@@ -187,7 +187,7 @@
*/
bool JsonAssetLoader::parseJsonAssetString(const String8& jsonAsset,
Vector<String8>* jsonObjects) {
- if (jsonAsset.isEmpty()) {
+ if (jsonAsset.empty()) {
ALOGE("Empty JSON Web Key");
return false;
}
@@ -199,7 +199,7 @@
// the original string.
jsmn_init(&parser);
int numTokens = jsmn_parse(&parser,
- jsonAsset.string(), jsonAsset.size(), NULL, 0);
+ jsonAsset.c_str(), jsonAsset.size(), NULL, 0);
if (numTokens < 0) {
ALOGE("Parser returns error code=%d", numTokens);
return false;
@@ -209,7 +209,7 @@
mJsmnTokens.setCapacity(jsmnTokensSize);
jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonAsset.string(),
+ int status = jsmn_parse(&parser, jsonAsset.c_str(),
jsonAsset.size(), mJsmnTokens.editArray(), numTokens);
if (status < 0) {
ALOGE("Parser returns error code=%d", status);
@@ -219,9 +219,9 @@
String8 token;
const char *pjs;
for (int i = 0; i < numTokens; ++i) {
- pjs = jsonAsset.string() + mJsmnTokens[i].start;
+ pjs = jsonAsset.c_str() + mJsmnTokens[i].start;
if (mJsmnTokens[i].type == JSMN_OBJECT) {
- token.setTo(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+ token = String8(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
jsonObjects->add(token);
}
}
diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
index f8bab0a..cbff6cb 100644
--- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp
+++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp
@@ -96,7 +96,7 @@
for (size_t i = 0; i < array.size(); i++) {
result.appendFormat("%02x ", array[i]);
}
- if (result.isEmpty()) {
+ if (result.empty()) {
result.append("(null)");
}
return result;
@@ -135,7 +135,7 @@
}
status_t MockCasPlugin::closeSession(const CasSessionId &sessionId) {
- ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).string());
+ ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).c_str());
Mutex::Autolock lock(mLock);
sp<MockCasSession> session =
@@ -151,7 +151,7 @@
status_t MockCasPlugin::setSessionPrivateData(
const CasSessionId &sessionId, const CasData& /*data*/) {
ALOGV("setSessionPrivateData: sessionId=%s",
- arrayToString(sessionId).string());
+ arrayToString(sessionId).c_str());
Mutex::Autolock lock(mLock);
sp<MockCasSession> session =
@@ -164,7 +164,7 @@
status_t MockCasPlugin::processEcm(
const CasSessionId &sessionId, const CasEcm& ecm) {
- ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).string());
+ ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).c_str());
Mutex::Autolock lock(mLock);
sp<MockCasSession> session =
@@ -173,7 +173,7 @@
return BAD_VALUE;
}
ALOGV("ECM: size=%zu", ecm.size());
- ALOGV("ECM: data=%s", arrayToString(ecm).string());
+ ALOGV("ECM: data=%s", arrayToString(ecm).c_str());
return OK;
}
@@ -183,7 +183,7 @@
Mutex::Autolock lock(mLock);
ALOGV("EMM: size=%zu", emm.size());
- ALOGV("EMM: data=%s", arrayToString(emm).string());
+ ALOGV("EMM: data=%s", arrayToString(emm).c_str());
return OK;
}
@@ -200,14 +200,14 @@
const CasSessionId &sessionId, int32_t event,
int /*arg*/, const CasData& /*eventData*/) {
ALOGV("sendSessionEvent: sessionId=%s, event=%d",
- arrayToString(sessionId).string(), event);
+ arrayToString(sessionId).c_str(), event);
Mutex::Autolock lock(mLock);
return OK;
}
status_t MockCasPlugin::provision(const String8 &str) {
- ALOGV("provision: provisionString=%s", str.string());
+ ALOGV("provision: provisionString=%s", str.c_str());
Mutex::Autolock lock(mLock);
return OK;
@@ -215,7 +215,7 @@
status_t MockCasPlugin::refreshEntitlements(
int32_t /*refreshType*/, const CasData &refreshData) {
- ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
+ ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).c_str());
Mutex::Autolock lock(mLock);
return OK;
@@ -256,7 +256,7 @@
ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
"subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
(int)secure, (int)scramblingControl,
- subSamplesToString(subSamples, numSubSamples).string(),
+ subSamplesToString(subSamples, numSubSamples).c_str(),
srcPtr, dstPtr, srcOffset, dstOffset);
return 0;
diff --git a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
index 089eb1c..7ee8d3d 100644
--- a/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/DrmPlugin.cpp
@@ -142,7 +142,7 @@
const String8& name, Vector<uint8_t>& value) const {
ssize_t index = mByteArrayProperties.indexOfKey(name);
if (index < 0) {
- ALOGE("App requested unknown property: %s", name.string());
+ ALOGE("App requested unknown property: %s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
value = mByteArrayProperties.valueAt(index);
@@ -154,12 +154,12 @@
{
UNUSED(value);
if (0 == name.compare(kDeviceIdKey)) {
- ALOGD("Cannot set immutable property: %s", name.string());
+ ALOGD("Cannot set immutable property: %s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
// Setting of undefined properties is not supported
- ALOGE("Failed to set property byte array, key=%s", name.string());
+ ALOGE("Failed to set property byte array, key=%s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
@@ -167,7 +167,7 @@
const String8& name, String8& value) const {
ssize_t index = mStringProperties.indexOfKey(name);
if (index < 0) {
- ALOGE("App requested unknown property: %s", name.string());
+ ALOGE("App requested unknown property: %s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
value = mStringProperties.valueAt(index);
@@ -178,21 +178,21 @@
const String8& name, const String8& value) {
String8 immutableKeys;
immutableKeys.appendFormat("%s,%s,%s,%s",
- kAlgorithmsKey.string(), kPluginDescriptionKey.string(),
- kVendorKey.string(), kVersionKey.string());
- if (immutableKeys.contains(name.string())) {
- ALOGD("Cannot set immutable property: %s", name.string());
+ kAlgorithmsKey.c_str(), kPluginDescriptionKey.c_str(),
+ kVendorKey.c_str(), kVersionKey.c_str());
+ if (immutableKeys.contains(name.c_str())) {
+ ALOGD("Cannot set immutable property: %s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
ssize_t index = mStringProperties.indexOfKey(name);
if (index < 0) {
- ALOGE("Cannot set undefined property string, key=%s", name.string());
+ ALOGE("Cannot set undefined property string, key=%s", name.c_str());
return android::ERROR_DRM_CANNOT_HANDLE;
}
if (mStringProperties.add(name, value) < 0) {
- ALOGE("Failed to set property string, key=%s", name.string());
+ ALOGE("Failed to set property string, key=%s", name.c_str());
return android::ERROR_DRM_UNKNOWN;
}
return android::OK;
diff --git a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
index 121a4e2..ca697a2 100644
--- a/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/InitDataParser.cpp
@@ -69,7 +69,7 @@
String8 requestJson = generateRequest(keyIds);
licenseRequest->clear();
licenseRequest->appendArray(
- reinterpret_cast<const uint8_t*>(requestJson.string()),
+ reinterpret_cast<const uint8_t*>(requestJson.c_str()),
requestJson.size());
return android::OK;
}
diff --git a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
index a2d506d..6db70c1 100644
--- a/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/JsonWebKey.cpp
@@ -77,18 +77,18 @@
return false;
if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
- if (encodedKeyId.isEmpty() || encodedKey.isEmpty()) {
+ if (encodedKeyId.empty() || encodedKey.empty()) {
ALOGE("Must have both key id and key in the JsonWebKey set.");
continue;
}
if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
- ALOGE("Failed to decode key id(%s)", encodedKeyId.string());
+ ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
continue;
}
if (!decodeBase64String(encodedKey, &decodedKey)) {
- ALOGE("Failed to decode key(%s)", encodedKey.string());
+ ALOGE("Failed to decode key(%s)", encodedKey.c_str());
continue;
}
@@ -119,7 +119,7 @@
}
android::sp<ABuffer> buffer =
- android::decodeBase64(AString(paddedText.string()));
+ android::decodeBase64(AString(paddedText.c_str()));
if (buffer == NULL) {
ALOGE("Malformed base64 encoded content found.");
return false;
@@ -159,8 +159,8 @@
if (0 == (*nextToken).compare(key)) {
if (nextToken + 1 == mTokens.end())
break;
- valueToken = (*(nextToken + 1)).string();
- value->setTo(valueToken);
+ valueToken = (*(nextToken + 1)).c_str();
+ *value = valueToken;
nextToken++;
break;
}
@@ -186,7 +186,7 @@
jsmn_init(&parser);
int numTokens = jsmn_parse(&parser,
- jsonObject.string(), jsonObject.size(), NULL, 0);
+ jsonObject.c_str(), jsonObject.size(), NULL, 0);
if (numTokens < 0) {
ALOGE("Parser returns error code=%d", numTokens);
return false;
@@ -197,7 +197,7 @@
mJsmnTokens.setCapacity(jsmnTokensSize);
jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonObject.string(),
+ int status = jsmn_parse(&parser, jsonObject.c_str(),
jsonObject.size(), mJsmnTokens.editArray(), numTokens);
if (status < 0) {
ALOGE("Parser returns error code=%d", status);
@@ -208,10 +208,10 @@
String8 token;
const char *pjs;
for (int j = 0; j < numTokens; ++j) {
- pjs = jsonObject.string() + mJsmnTokens[j].start;
+ pjs = jsonObject.c_str() + mJsmnTokens[j].start;
if (mJsmnTokens[j].type == JSMN_STRING ||
mJsmnTokens[j].type == JSMN_PRIMITIVE) {
- token.setTo(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
+ token = String8(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
tokens->add(token);
}
}
@@ -225,7 +225,7 @@
*/
bool JsonWebKey::parseJsonWebKeySet(const String8& jsonWebKeySet,
Vector<String8>* jsonObjects) {
- if (jsonWebKeySet.isEmpty()) {
+ if (jsonWebKeySet.empty()) {
ALOGE("Empty JSON Web Key");
return false;
}
@@ -237,7 +237,7 @@
// the original string.
jsmn_init(&parser);
int numTokens = jsmn_parse(&parser,
- jsonWebKeySet.string(), jsonWebKeySet.size(), NULL, 0);
+ jsonWebKeySet.c_str(), jsonWebKeySet.size(), NULL, 0);
if (numTokens < 0) {
ALOGE("Parser returns error code=%d", numTokens);
return false;
@@ -247,7 +247,7 @@
mJsmnTokens.setCapacity(jsmnTokensSize);
jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonWebKeySet.string(),
+ int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
jsonWebKeySet.size(), mJsmnTokens.editArray(), numTokens);
if (status < 0) {
ALOGE("Parser returns error code=%d", status);
@@ -257,9 +257,9 @@
String8 token;
const char *pjs;
for (int i = 0; i < numTokens; ++i) {
- pjs = jsonWebKeySet.string() + mJsmnTokens[i].start;
+ pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
if (mJsmnTokens[i].type == JSMN_OBJECT) {
- token.setTo(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
+ token = String8(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
jsonObjects->add(token);
}
}
diff --git a/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
index 529230e..058f8ce 100644
--- a/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
+++ b/drm/mediadrm/plugins/clearkey/default/SessionLibrary.cpp
@@ -50,7 +50,7 @@
mNextSessionId += 1;
Vector<uint8_t> sessionId;
sessionId.appendArray(
- reinterpret_cast<const uint8_t*>(sessionIdString.string()),
+ reinterpret_cast<const uint8_t*>(sessionIdString.c_str()),
sessionIdString.size());
mSessions.add(sessionId, new Session(sessionId));
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 3b4145f..db98a80 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -91,14 +91,14 @@
}
mSessions.add(sessionId);
- ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
+ ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).c_str());
return OK;
}
status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
{
Mutex::Autolock lock(mLock);
- ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
+ ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
ALOGD("Invalid sessionId");
@@ -119,8 +119,8 @@
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
", keyType=%d, optionalParameters=%s))",
- vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
- keyType, stringMapToString(optionalParameters).string());
+ vectorToString(sessionId).c_str(), vectorToString(initData).c_str(), mimeType.c_str(),
+ keyType, stringMapToString(optionalParameters).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -144,8 +144,8 @@
String8 params;
for (size_t i = 0; i < optionalParameters.size(); i++) {
params.appendFormat("%s{%s,%s}", i ? "," : "",
- optionalParameters.keyAt(i).string(),
- optionalParameters.valueAt(i).string());
+ optionalParameters.keyAt(i).c_str(),
+ optionalParameters.valueAt(i).c_str());
}
mStringProperties.add(String8("mock-optparams"), params);
@@ -176,7 +176,7 @@
return BAD_VALUE;
} else {
*keyRequestType = static_cast<KeyRequestType>(
- atoi(mStringProperties.valueAt(index).string()));
+ atoi(mStringProperties.valueAt(index).c_str()));
}
return OK;
@@ -188,7 +188,7 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
- vectorToString(sessionId).string(), vectorToString(response).string());
+ vectorToString(sessionId).c_str(), vectorToString(response).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
ALOGD("Invalid sessionId");
@@ -217,7 +217,7 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
- vectorToString(keySetId).string());
+ vectorToString(keySetId).c_str());
ssize_t index = findKeySet(keySetId);
if (index == kNotFound) {
@@ -234,8 +234,8 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
- vectorToString(sessionId).string(),
- vectorToString(keySetId).string());
+ vectorToString(sessionId).c_str(),
+ vectorToString(keySetId).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
ALOGD("Invalid sessionId");
@@ -255,7 +255,7 @@
KeyedVector<String8, String8> &infoMap) const
{
ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
- vectorToString(sessionId).string());
+ vectorToString(sessionId).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -304,7 +304,7 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
- vectorToString(response).string());
+ vectorToString(response).c_str());
// Properties used in mock test, set by mock plugin and verifed cts test app
// byte[] response -> mock-response
@@ -367,7 +367,7 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
- vectorToString(ssRelease).string());
+ vectorToString(ssRelease).c_str());
// Properties used in mock test, set by mock plugin and verifed cts test app
// byte[] secure-stop-release -> mock-ssrelease
@@ -385,10 +385,10 @@
status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
{
- ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
+ ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.c_str());
ssize_t index = mStringProperties.indexOfKey(name);
if (index < 0) {
- ALOGD("no property for '%s'", name.string());
+ ALOGD("no property for '%s'", name.c_str());
return BAD_VALUE;
}
value = mStringProperties.valueAt(index);
@@ -398,10 +398,10 @@
status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
Vector<uint8_t> &value) const
{
- ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
+ ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.c_str());
ssize_t index = mByteArrayProperties.indexOfKey(name);
if (index < 0) {
- ALOGD("no property for '%s'", name.string());
+ ALOGD("no property for '%s'", name.c_str());
return BAD_VALUE;
}
value = mByteArrayProperties.valueAt(index);
@@ -413,11 +413,11 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
- name.string(), value.string());
+ name.c_str(), value.c_str());
if (name == "mock-send-event") {
unsigned code, extra;
- sscanf(value.string(), "%d %d", &code, &extra);
+ sscanf(value.c_str(), "%d %d", &code, &extra);
DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
Vector<uint8_t> const *pSessionId = NULL;
@@ -438,7 +438,7 @@
sendEvent(eventType, extra, pSessionId, pData);
} else if (name == "mock-send-expiration-update") {
int64_t expiryTimeMS;
- sscanf(value.string(), "%jd", &expiryTimeMS);
+ sscanf(value.c_str(), "%jd", &expiryTimeMS);
Vector<uint8_t> const *pSessionId = NULL;
ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
@@ -504,7 +504,7 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
- name.string(), vectorToString(value).string());
+ name.c_str(), vectorToString(value).c_str());
mByteArrayProperties.add(name, value);
return OK;
}
@@ -515,7 +515,7 @@
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
- vectorToString(sessionId).string(), algorithm.string());
+ vectorToString(sessionId).c_str(), algorithm.c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -535,7 +535,7 @@
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
- vectorToString(sessionId).string(), algorithm.string());
+ vectorToString(sessionId).c_str(), algorithm.c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -557,10 +557,10 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
- vectorToString(sessionId).string(),
- vectorToString(keyId).string(),
- vectorToString(input).string(),
- vectorToString(iv).string());
+ vectorToString(sessionId).c_str(),
+ vectorToString(keyId).c_str(),
+ vectorToString(input).c_str(),
+ vectorToString(iv).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -596,10 +596,10 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
- vectorToString(sessionId).string(),
- vectorToString(keyId).string(),
- vectorToString(input).string(),
- vectorToString(iv).string());
+ vectorToString(sessionId).c_str(),
+ vectorToString(keyId).c_str(),
+ vectorToString(input).c_str(),
+ vectorToString(iv).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -634,9 +634,9 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
- vectorToString(sessionId).string(),
- vectorToString(keyId).string(),
- vectorToString(message).string());
+ vectorToString(sessionId).c_str(),
+ vectorToString(keyId).c_str(),
+ vectorToString(message).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -670,10 +670,10 @@
{
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
- vectorToString(sessionId).string(),
- vectorToString(keyId).string(),
- vectorToString(message).string(),
- vectorToString(signature).string());
+ vectorToString(sessionId).c_str(),
+ vectorToString(keyId).c_str(),
+ vectorToString(message).c_str(),
+ vectorToString(signature).c_str());
ssize_t index = findSession(sessionId);
if (index == kNotFound) {
@@ -696,7 +696,7 @@
ALOGD("Missing 'mock-request' parameter for mock");
return BAD_VALUE;
} else {
- match = atol(mStringProperties.valueAt(index).string());
+ match = atol(mStringProperties.valueAt(index).c_str());
}
return OK;
}
@@ -710,11 +710,11 @@
Mutex::Autolock lock(mLock);
ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
"message=%s, signature=%s)",
- vectorToString(sessionId).string(),
- algorithm.string(),
- vectorToString(message).string(),
- vectorToString(wrappedKey).string(),
- vectorToString(signature).string());
+ vectorToString(sessionId).c_str(),
+ algorithm.c_str(),
+ vectorToString(message).c_str(),
+ vectorToString(wrappedKey).c_str(),
+ vectorToString(signature).c_str());
// Properties used in mock test, set by mock plugin and verifed cts test app
// byte[] wrappedKey -> mock-wrappedkey
@@ -772,7 +772,7 @@
String8 result("{ ");
for (size_t i = 0; i < map.size(); i++) {
result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
- map.keyAt(i).string(), map.valueAt(i).string());
+ map.keyAt(i).c_str(), map.valueAt(i).c_str());
}
return result + " }";
}
@@ -802,10 +802,10 @@
"pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, "
"subSamples=%s, dst=%p)",
(int)secure,
- arrayToString(key, DECRYPT_KEY_SIZE).string(),
- arrayToString(iv, DECRYPT_KEY_SIZE).string(),
+ arrayToString(key, DECRYPT_KEY_SIZE).c_str(),
+ arrayToString(iv, DECRYPT_KEY_SIZE).c_str(),
(int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr,
- subSamplesToString(subSamples, numSubSamples).string(),
+ subSamplesToString(subSamples, numSubSamples).c_str(),
dstPtr);
return OK;
}
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
index 11e1704..ec99fac 100644
--- a/include/private/media/VideoFrame.h
+++ b/include/private/media/VideoFrame.h
@@ -37,10 +37,12 @@
// will calculate frame buffer size if |hasData| is set to true.
VideoFrame(uint32_t width, uint32_t height,
uint32_t displayWidth, uint32_t displayHeight,
+ uint32_t displayLeft, uint32_t displayTop,
uint32_t tileWidth, uint32_t tileHeight,
uint32_t angle, uint32_t bpp, uint32_t bitDepth, bool hasData, size_t iccSize):
mWidth(width), mHeight(height),
mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
+ mDisplayLeft(displayLeft), mDisplayTop(displayTop),
mTileWidth(tileWidth), mTileHeight(tileHeight), mDurationUs(0),
mRotationAngle(angle), mBytesPerPixel(bpp), mIccSize(iccSize),
mBitDepth(bitDepth) {
@@ -82,6 +84,8 @@
uint32_t mHeight; // Decoded image height before rotation
uint32_t mDisplayWidth; // Display width before rotation
uint32_t mDisplayHeight; // Display height before rotation
+ uint32_t mDisplayLeft; // Display left (column coordinate) before rotation
+ uint32_t mDisplayTop; // Display top (row coordinate) before rotation
uint32_t mTileWidth; // Tile width (0 if image doesn't have grid)
uint32_t mTileHeight; // Tile height (0 if image doesn't have grid)
int64_t mDurationUs; // Frame duration in microseconds
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 4d3f9bd..7ea51ff 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -508,15 +508,6 @@
{
AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
AudioDeviceType::IN_ECHO_REFERENCE)
- },
- {
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, make_AudioDeviceDescription(
- AudioDeviceType::IN_SUBMIX)
- },
- {
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, make_AudioDeviceDescription(
- AudioDeviceType::OUT_SUBMIX,
- GET_DEVICE_DESC_CONNECTION(VIRTUAL))
}
}};
append_AudioDeviceDescription(pairs,
@@ -592,6 +583,11 @@
AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
GET_DEVICE_DESC_CONNECTION(BT_LE));
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX,
+ GET_DEVICE_DESC_CONNECTION(VIRTUAL));
+
return pairs;
}();
return pairs;
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index 216bc12..203ed2f 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,8 +1,12 @@
{
"presubmit": [
{
- "name": "audio_aidl_conversion_tests",
- "name": "audio_aidl_ndk_conversion_tests",
+ "name": "audio_aidl_conversion_tests"
+ },
+ {
+ "name": "audio_aidl_ndk_conversion_tests"
+ },
+ {
"name": "audio_aidl_ndk_cpp_conversion_tests"
}
]
diff --git a/media/codec2/hal/aidl/Android.bp b/media/codec2/hal/aidl/Android.bp
index 01cd354..b19f78c 100644
--- a/media/codec2/hal/aidl/Android.bp
+++ b/media/codec2/hal/aidl/Android.bp
@@ -8,28 +8,36 @@
name: "libcodec2_aidl_client",
srcs: [
+ "BufferTypes.cpp",
"ParamTypes.cpp",
],
header_libs: [
- "libcodec2_hal_common",
"libcodec2_internal", // private
"libgui_headers",
],
shared_libs: [
+ "android.hardware.common-V2-ndk",
"android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.bufferpool2-V1-ndk",
"android.hardware.media.c2-V1-ndk",
"libbinder_ndk",
"libbase",
"libcodec2",
+ "libcodec2_hal_common",
"libcodec2_vndk",
"libcutils",
"liblog",
"libnativewindow",
+ "libstagefright_aidl_bufferpool2",
"libutils",
],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+
export_include_dirs: [
"include",
],
@@ -37,6 +45,7 @@
export_shared_lib_headers: [
"android.hardware.media.c2-V1-ndk",
"libcodec2",
+ "libcodec2_hal_common",
],
}
diff --git a/media/codec2/hal/aidl/BufferTypes.cpp b/media/codec2/hal/aidl/BufferTypes.cpp
index 319ba62..1cd3555 100644
--- a/media/codec2/hal/aidl/BufferTypes.cpp
+++ b/media/codec2/hal/aidl/BufferTypes.cpp
@@ -15,10 +15,15 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-types"
+#define LOG_TAG "Codec2-AIDL-BufferTypes"
#include <android-base/logging.h>
-#include <codec2/hidl/1.0/types.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/common/BufferTypes.h>
+#include <cutils/native_handle.h>
#include <media/stagefright/foundation/AUtils.h>
#include <C2AllocatorIon.h>
@@ -28,1431 +33,42 @@
#include <C2Component.h>
#include <C2FenceFactory.h>
#include <C2Param.h>
-#include <C2ParamInternal.h>
#include <C2PlatformSupport.h>
#include <C2Work.h>
-#include <util/C2ParamUtils.h>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <unordered_map>
+#include "ParamTypes-specialization.h"
+
namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-using ::android::hardware::Return;
-using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
-using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
- ClientManager;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
- TransactionId;
+using ::aidl::android::hardware::media::bufferpool2::BufferPoolData;
+using ::aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
+using ::aidl::android::hardware::media::bufferpool2::ResultStatus;
+using ::aidl::android::hardware::media::bufferpool2::implementation::BufferPoolStatus;
+using ::aidl::android::hardware::media::bufferpool2::implementation::ClientManager;
+using ::aidl::android::hardware::media::c2::BaseBlock;
+using ::aidl::android::hardware::media::c2::utils::BufferPoolTypes;
-const char* asString(Status status, const char* def) {
- return asString(static_cast<c2_status_t>(status), def);
-}
+using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
-namespace /* unnamed */ {
-
-template <typename EnumClass>
-typename std::underlying_type<EnumClass>::type underlying_value(
- EnumClass x) {
- return static_cast<typename std::underlying_type<EnumClass>::type>(x);
-}
-
-template <typename Common, typename DstVector, typename SrcVector>
-void copyVector(DstVector* d, const SrcVector& s) {
- static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
- "DstVector's component size does not match Common");
- static_assert(sizeof(Common) == sizeof(decltype(s[0])),
- "SrcVector's component size does not match Common");
- d->resize(s.size());
- std::copy(
- reinterpret_cast<const Common*>(&s[0]),
- reinterpret_cast<const Common*>(&s[0] + s.size()),
- reinterpret_cast<Common*>(&(*d)[0]));
-}
-
-// C2ParamField -> ParamField
-bool objcpy(ParamField *d, const C2ParamField &s) {
- d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
- d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
- d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
- return true;
-}
-
-struct C2ParamFieldBuilder : public C2ParamField {
- C2ParamFieldBuilder() : C2ParamField(
- static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
- }
- // ParamField -> C2ParamField
- C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
- static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
- static_cast<uint32_t>(s.fieldId.offset),
- static_cast<uint32_t>(s.fieldId.size)) {
- }
-};
-
-// C2WorkOrdinalStruct -> WorkOrdinal
-bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
- d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
- d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
- d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
- return true;
-}
-
-// WorkOrdinal -> C2WorkOrdinalStruct
-bool objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
- d->frameIndex = c2_cntr64_t(s.frameIndex);
- d->timestamp = c2_cntr64_t(s.timestampUs);
- d->customOrdinal = c2_cntr64_t(s.customOrdinal);
- return true;
-}
-
-// C2FieldSupportedValues::range's type -> ValueRange
-bool objcpy(
- ValueRange* d,
- const decltype(C2FieldSupportedValues::range)& s) {
- d->min = static_cast<PrimitiveValue>(s.min.u64);
- d->max = static_cast<PrimitiveValue>(s.max.u64);
- d->step = static_cast<PrimitiveValue>(s.step.u64);
- d->num = static_cast<PrimitiveValue>(s.num.u64);
- d->denom = static_cast<PrimitiveValue>(s.denom.u64);
- return true;
-}
-
-// C2FieldSupportedValues -> FieldSupportedValues
-bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
- switch (s.type) {
- case C2FieldSupportedValues::EMPTY: {
- d->empty(::android::hidl::safe_union::V1_0::Monostate{});
- break;
- }
- case C2FieldSupportedValues::RANGE: {
- ValueRange range{};
- if (!objcpy(&range, s.range)) {
- LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
- d->range(range);
- return false;
- }
- d->range(range);
- break;
- }
- case C2FieldSupportedValues::VALUES: {
- hidl_vec<PrimitiveValue> values;
- copyVector<uint64_t>(&values, s.values);
- d->values(values);
- break;
- }
- case C2FieldSupportedValues::FLAGS: {
- hidl_vec<PrimitiveValue> flags;
- copyVector<uint64_t>(&flags, s.values);
- d->flags(flags);
- break;
- }
- default:
- LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- return false;
- }
- return true;
-}
-
-// ValueRange -> C2FieldSupportedValues::range's type
-bool objcpy(
- decltype(C2FieldSupportedValues::range)* d,
- const ValueRange& s) {
- d->min.u64 = static_cast<uint64_t>(s.min);
- d->max.u64 = static_cast<uint64_t>(s.max);
- d->step.u64 = static_cast<uint64_t>(s.step);
- d->num.u64 = static_cast<uint64_t>(s.num);
- d->denom.u64 = static_cast<uint64_t>(s.denom);
- return true;
-}
-
-// FieldSupportedValues -> C2FieldSupportedValues
-bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
- switch (s.getDiscriminator()) {
- case FieldSupportedValues::hidl_discriminator::empty: {
- d->type = C2FieldSupportedValues::EMPTY;
- break;
- }
- case FieldSupportedValues::hidl_discriminator::range: {
- d->type = C2FieldSupportedValues::RANGE;
- if (!objcpy(&d->range, s.range())) {
- LOG(ERROR) << "Invalid FieldSupportedValues::range.";
- return false;
- }
- d->values.resize(0);
- break;
- }
- case FieldSupportedValues::hidl_discriminator::values: {
- d->type = C2FieldSupportedValues::VALUES;
- copyVector<uint64_t>(&d->values, s.values());
- break;
- }
- case FieldSupportedValues::hidl_discriminator::flags: {
- d->type = C2FieldSupportedValues::FLAGS;
- copyVector<uint64_t>(&d->values, s.flags());
- break;
- }
- default:
- LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
- return false;
- }
- return true;
-}
-
-} // unnamed namespace
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-bool objcpy(
- FieldSupportedValuesQuery* d,
- const C2FieldSupportedValuesQuery& s) {
- if (!objcpy(&d->field, s.field())) {
- LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
- return false;
- }
- switch (s.type()) {
- case C2FieldSupportedValuesQuery::POSSIBLE:
- d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
- break;
- case C2FieldSupportedValuesQuery::CURRENT:
- d->type = FieldSupportedValuesQuery::Type::CURRENT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
- << "with underlying value " << underlying_value(s.type())
- << ".";
- d->type = static_cast<FieldSupportedValuesQuery::Type>(s.type());
- }
- return true;
-}
-
-// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& s) {
- C2FieldSupportedValuesQuery::type_t dType;
- switch (s.type) {
- case FieldSupportedValuesQuery::Type::POSSIBLE:
- dType = C2FieldSupportedValuesQuery::POSSIBLE;
- break;
- case FieldSupportedValuesQuery::Type::CURRENT:
- dType = C2FieldSupportedValuesQuery::CURRENT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
- }
- *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
- return true;
-}
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-bool objcpy(
- FieldSupportedValuesQueryResult* d,
- const C2FieldSupportedValuesQuery& s) {
- d->status = static_cast<Status>(s.status);
- return objcpy(&d->values, s.values);
-}
-
-// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
-// C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& sq,
- const FieldSupportedValuesQueryResult& sr) {
- if (!objcpy(d, sq)) {
- LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
- return false;
- }
- d->status = static_cast<c2_status_t>(sr.status);
- if (!objcpy(&d->values, sr.values)) {
- LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
- return false;
- }
- return true;
-}
-
-// C2Component::Traits -> IComponentStore::ComponentTraits
-bool objcpy(
- IComponentStore::ComponentTraits *d,
- const C2Component::Traits &s) {
- d->name = s.name;
-
- switch (s.domain) {
- case C2Component::DOMAIN_VIDEO:
- d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
- break;
- case C2Component::DOMAIN_AUDIO:
- d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
- break;
- case C2Component::DOMAIN_IMAGE:
- d->domain = IComponentStore::ComponentTraits::Domain::IMAGE;
- break;
- case C2Component::DOMAIN_OTHER:
- d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2Component::domain_t "
- << "with underlying value " << underlying_value(s.domain)
- << ".";
- d->domain = static_cast<IComponentStore::ComponentTraits::Domain>(
- s.domain);
- }
-
- switch (s.kind) {
- case C2Component::KIND_DECODER:
- d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
- break;
- case C2Component::KIND_ENCODER:
- d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
- break;
- case C2Component::KIND_OTHER:
- d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2Component::kind_t "
- << "with underlying value " << underlying_value(s.kind)
- << ".";
- d->kind = static_cast<IComponentStore::ComponentTraits::Kind>(
- s.kind);
- }
-
- d->rank = static_cast<uint32_t>(s.rank);
-
- d->mediaType = s.mediaType;
-
- d->aliases.resize(s.aliases.size());
- for (size_t ix = s.aliases.size(); ix > 0; ) {
- --ix;
- d->aliases[ix] = s.aliases[ix];
- }
- return true;
-}
-
-// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
-bool objcpy(
- C2Component::Traits* d,
- const IComponentStore::ComponentTraits& s) {
- d->name = s.name.c_str();
-
- switch (s.domain) {
- case IComponentStore::ComponentTraits::Domain::VIDEO:
- d->domain = C2Component::DOMAIN_VIDEO;
- break;
- case IComponentStore::ComponentTraits::Domain::AUDIO:
- d->domain = C2Component::DOMAIN_AUDIO;
- break;
- case IComponentStore::ComponentTraits::Domain::IMAGE:
- d->domain = C2Component::DOMAIN_IMAGE;
- break;
- case IComponentStore::ComponentTraits::Domain::OTHER:
- d->domain = C2Component::DOMAIN_OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
- << "with underlying value " << underlying_value(s.domain)
- << ".";
- d->domain = static_cast<C2Component::domain_t>(s.domain);
- }
-
- switch (s.kind) {
- case IComponentStore::ComponentTraits::Kind::DECODER:
- d->kind = C2Component::KIND_DECODER;
- break;
- case IComponentStore::ComponentTraits::Kind::ENCODER:
- d->kind = C2Component::KIND_ENCODER;
- break;
- case IComponentStore::ComponentTraits::Kind::OTHER:
- d->kind = C2Component::KIND_OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
- << "with underlying value " << underlying_value(s.kind)
- << ".";
- d->kind = static_cast<C2Component::kind_t>(s.kind);
- }
-
- d->rank = static_cast<C2Component::rank_t>(s.rank);
- d->mediaType = s.mediaType.c_str();
- d->aliases.resize(s.aliases.size());
- for (size_t i = 0; i < s.aliases.size(); ++i) {
- d->aliases[i] = s.aliases[i];
- }
- return true;
-}
-
-namespace /* unnamed */ {
-
-// C2ParamFieldValues -> ParamFieldValues
-bool objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
- if (!objcpy(&d->paramOrField, s.paramOrField)) {
- LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
- return false;
- }
- if (s.values) {
- d->values.resize(1);
- if (!objcpy(&d->values[0], *s.values)) {
- LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
- return false;
- }
- return true;
- }
- d->values.resize(0);
- return true;
-}
-
-// ParamFieldValues -> C2ParamFieldValues
-bool objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
- d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
- if (s.values.size() == 1) {
- d->values = std::make_unique<C2FieldSupportedValues>();
- if (!objcpy(d->values.get(), s.values[0])) {
- LOG(ERROR) << "Invalid ParamFieldValues::values.";
- return false;
- }
- return true;
- } else if (s.values.size() == 0) {
- d->values.reset();
- return true;
- }
- LOG(ERROR) << "Invalid ParamFieldValues: "
- "Two or more FieldSupportedValues objects exist in "
- "ParamFieldValues. "
- "Only zero or one is allowed.";
- return false;
-}
-
-} // unnamed namespace
-
-// C2SettingResult -> SettingResult
-bool objcpy(SettingResult *d, const C2SettingResult &s) {
- switch (s.failure) {
- case C2SettingResult::BAD_TYPE:
- d->failure = SettingResult::Failure::BAD_TYPE;
- break;
- case C2SettingResult::BAD_PORT:
- d->failure = SettingResult::Failure::BAD_PORT;
- break;
- case C2SettingResult::BAD_INDEX:
- d->failure = SettingResult::Failure::BAD_INDEX;
- break;
- case C2SettingResult::READ_ONLY:
- d->failure = SettingResult::Failure::READ_ONLY;
- break;
- case C2SettingResult::MISMATCH:
- d->failure = SettingResult::Failure::MISMATCH;
- break;
- case C2SettingResult::BAD_VALUE:
- d->failure = SettingResult::Failure::BAD_VALUE;
- break;
- case C2SettingResult::CONFLICT:
- d->failure = SettingResult::Failure::CONFLICT;
- break;
- case C2SettingResult::UNSUPPORTED:
- d->failure = SettingResult::Failure::UNSUPPORTED;
- break;
- case C2SettingResult::INFO_BAD_VALUE:
- d->failure = SettingResult::Failure::INFO_BAD_VALUE;
- break;
- case C2SettingResult::INFO_CONFLICT:
- d->failure = SettingResult::Failure::INFO_CONFLICT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
- << "with underlying value " << underlying_value(s.failure)
- << ".";
- d->failure = static_cast<SettingResult::Failure>(s.failure);
- }
- if (!objcpy(&d->field, s.field)) {
- LOG(ERROR) << "Invalid C2SettingResult::field.";
- return false;
- }
- d->conflicts.resize(s.conflicts.size());
- size_t i = 0;
- for (const C2ParamFieldValues& sConflict : s.conflicts) {
- ParamFieldValues &dConflict = d->conflicts[i++];
- if (!objcpy(&dConflict, sConflict)) {
- LOG(ERROR) << "Invalid C2SettingResult::conflicts["
- << i - 1 << "].";
- return false;
- }
- }
- return true;
-}
-
-// SettingResult -> std::unique_ptr<C2SettingResult>
-bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
- *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
- .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
- if (!*d) {
- LOG(ERROR) << "No memory for C2SettingResult.";
- return false;
- }
-
- // failure
- switch (s.failure) {
- case SettingResult::Failure::BAD_TYPE:
- (*d)->failure = C2SettingResult::BAD_TYPE;
- break;
- case SettingResult::Failure::BAD_PORT:
- (*d)->failure = C2SettingResult::BAD_PORT;
- break;
- case SettingResult::Failure::BAD_INDEX:
- (*d)->failure = C2SettingResult::BAD_INDEX;
- break;
- case SettingResult::Failure::READ_ONLY:
- (*d)->failure = C2SettingResult::READ_ONLY;
- break;
- case SettingResult::Failure::MISMATCH:
- (*d)->failure = C2SettingResult::MISMATCH;
- break;
- case SettingResult::Failure::BAD_VALUE:
- (*d)->failure = C2SettingResult::BAD_VALUE;
- break;
- case SettingResult::Failure::CONFLICT:
- (*d)->failure = C2SettingResult::CONFLICT;
- break;
- case SettingResult::Failure::UNSUPPORTED:
- (*d)->failure = C2SettingResult::UNSUPPORTED;
- break;
- case SettingResult::Failure::INFO_BAD_VALUE:
- (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
- break;
- case SettingResult::Failure::INFO_CONFLICT:
- (*d)->failure = C2SettingResult::INFO_CONFLICT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized SettingResult::Failure "
- << "with underlying value " << underlying_value(s.failure)
- << ".";
- (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
- }
-
- // field
- if (!objcpy(&(*d)->field, s.field)) {
- LOG(ERROR) << "Invalid SettingResult::field.";
- return false;
- }
-
- // conflicts
- (*d)->conflicts.clear();
- (*d)->conflicts.reserve(s.conflicts.size());
- for (const ParamFieldValues& sConflict : s.conflicts) {
- (*d)->conflicts.emplace_back(
- C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
- if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
- LOG(ERROR) << "Invalid SettingResult::conflicts.";
- return false;
- }
- }
- return true;
-}
-
-// C2ParamDescriptor -> ParamDescriptor
-bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
- d->index = static_cast<ParamIndex>(s.index());
- d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
- _C2ParamInspector::GetAttrib(s));
- d->name = s.name();
- copyVector<uint32_t>(&d->dependencies, s.dependencies());
- return true;
-}
-
-// ParamDescriptor -> C2ParamDescriptor
-bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
- std::vector<C2Param::Index> dDependencies;
- dDependencies.reserve(s.dependencies.size());
- for (const ParamIndex& sDependency : s.dependencies) {
- dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
- }
- *d = std::make_shared<C2ParamDescriptor>(
- C2Param::Index(static_cast<uint32_t>(s.index)),
- static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
- C2String(s.name.c_str()),
- std::move(dDependencies));
- return true;
-}
-
-// C2StructDescriptor -> StructDescriptor
-bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
- d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
- d->fields.resize(s.numFields());
- size_t i = 0;
- for (const auto& sField : s) {
- FieldDescriptor& dField = d->fields[i++];
- dField.fieldId.offset = static_cast<uint32_t>(
- _C2ParamInspector::GetOffset(sField));
- dField.fieldId.size = static_cast<uint32_t>(
- _C2ParamInspector::GetSize(sField));
- dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
- sField.type());
- dField.extent = static_cast<uint32_t>(sField.extent());
- dField.name = static_cast<hidl_string>(sField.name());
- const auto& sNamedValues = sField.namedValues();
- dField.namedValues.resize(sNamedValues.size());
- size_t j = 0;
- for (const auto& sNamedValue : sNamedValues) {
- FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
- dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
- dNamedValue.value = static_cast<PrimitiveValue>(
- sNamedValue.second.u64);
- }
- }
- return true;
-}
-
-// StructDescriptor -> C2StructDescriptor
-bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
- C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
- std::vector<C2FieldDescriptor> dFields;
- dFields.reserve(s.fields.size());
- for (const auto &sField : s.fields) {
- C2FieldDescriptor dField = {
- static_cast<uint32_t>(sField.type),
- sField.extent,
- sField.name,
- sField.fieldId.offset,
- sField.fieldId.size };
- C2FieldDescriptor::NamedValuesType namedValues;
- namedValues.reserve(sField.namedValues.size());
- for (const auto& sNamedValue : sField.namedValues) {
- namedValues.emplace_back(
- sNamedValue.name,
- C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
- }
- _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
- dFields.emplace_back(dField);
- }
- *d = std::make_unique<C2StructDescriptor>(
- _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
- return true;
-}
-
-namespace /* unnamed */ {
-
-// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
-// associated map.
-// Note: The handle is not cloned.
-bool _addBaseBlock(
- uint32_t* index,
- const C2Handle* handle,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!handle) {
- LOG(ERROR) << "addBaseBlock called on a null C2Handle.";
- return false;
- }
- auto it = baseBlockIndices->find(handle);
- if (it != baseBlockIndices->end()) {
- *index = it->second;
- } else {
- *index = baseBlocks->size();
- baseBlockIndices->emplace(handle, *index);
- baseBlocks->emplace_back();
-
- BaseBlock &dBaseBlock = baseBlocks->back();
- // This does not clone the handle.
- dBaseBlock.nativeBlock(
- reinterpret_cast<const native_handle_t*>(handle));
-
- }
- return true;
-}
-
-// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
-// an associated map.
-bool _addBaseBlock(
- uint32_t* index,
- const std::shared_ptr<BufferPoolData> bpData,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!bpData) {
- LOG(ERROR) << "addBaseBlock called on a null BufferPoolData.";
- return false;
- }
- auto it = baseBlockIndices->find(bpData.get());
- if (it != baseBlockIndices->end()) {
- *index = it->second;
- } else {
- *index = baseBlocks->size();
- baseBlockIndices->emplace(bpData.get(), *index);
- baseBlocks->emplace_back();
-
- BaseBlock &dBaseBlock = baseBlocks->back();
-
- if (bufferPoolSender) {
- BufferStatusMessage pooledBlock;
- ResultStatus bpStatus = bufferPoolSender->send(
- bpData,
- &pooledBlock);
-
- if (bpStatus != ResultStatus::OK) {
- LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
- << static_cast<int32_t>(bpStatus)
- << ".";
- return false;
- }
- dBaseBlock.pooledBlock(pooledBlock);
- }
- }
- return true;
-}
-
-bool addBaseBlock(
- uint32_t* index,
- const C2Handle* handle,
- const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!blockPoolData) {
- // No BufferPoolData ==> NATIVE block.
- return _addBaseBlock(
- index, handle,
- baseBlocks, baseBlockIndices);
- }
- switch (blockPoolData->getType()) {
- case _C2BlockPoolData::TYPE_BUFFERPOOL: {
- // BufferPoolData
- std::shared_ptr<BufferPoolData> bpData;
- if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
- || !bpData) {
- LOG(ERROR) << "BufferPoolData unavailable in a block.";
- return false;
- }
- return _addBaseBlock(
- index, bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- }
- case _C2BlockPoolData::TYPE_BUFFERQUEUE:
- uint32_t gen;
- uint64_t bqId;
- int32_t bqSlot;
- // Update handle if migration happened.
- if (_C2BlockFactory::GetBufferQueueData(
- blockPoolData, &gen, &bqId, &bqSlot)) {
- android::MigrateNativeCodec2GrallocHandle(
- const_cast<native_handle_t*>(handle), gen, bqId, bqSlot);
- }
- return _addBaseBlock(
- index, handle,
- baseBlocks, baseBlockIndices);
- default:
- LOG(ERROR) << "Unknown C2BlockPoolData type.";
- return false;
- }
-}
-
-// C2Fence -> hidl_handle
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(hidl_handle* d, const C2Fence& s) {
- d->setTo(nullptr);
- native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
- if (handle) {
- d->setTo(handle, true /* owns */);
-// } else if (!s.ready()) {
-// // TODO: we should wait for unmarshallable fences but this may not be
-// // the best place for it. We can safely ignore here as at this time
-// // all fences used here are marshallable.
- }
- return true;
-}
-
-// C2ConstLinearBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstLinearBlock& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- std::shared_ptr<const _C2BlockPoolData> bpData =
- _C2BlockFactory::GetLinearBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
- return false;
- }
-
- // Create the metadata.
- C2Hidl_RangeInfo dRangeInfo;
- dRangeInfo.offset = static_cast<uint32_t>(s.offset());
- dRangeInfo.length = static_cast<uint32_t>(s.size());
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
- LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
- return false;
- }
-
- // Copy the fence
- if (!objcpy(&d->fence, s.fence())) {
- LOG(ERROR) << "Invalid C2ConstLinearBlock::fence.";
- return false;
- }
- return true;
-}
-
-// C2ConstGraphicBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstGraphicBlock& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- std::shared_ptr<const _C2BlockPoolData> bpData =
- _C2BlockFactory::GetGraphicBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
- return false;
- }
-
- // Create the metadata.
- C2Hidl_RectInfo dRectInfo;
- C2Rect sRect = s.crop();
- dRectInfo.left = static_cast<uint32_t>(sRect.left);
- dRectInfo.top = static_cast<uint32_t>(sRect.top);
- dRectInfo.width = static_cast<uint32_t>(sRect.width);
- dRectInfo.height = static_cast<uint32_t>(sRect.height);
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
- LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
- return false;
- }
-
- // Copy the fence
- if (!objcpy(&d->fence, s.fence())) {
- LOG(ERROR) << "Invalid C2ConstGraphicBlock::fence.";
- return false;
- }
- return true;
-}
-
-// C2BufferData -> Buffer
-// This function only fills in d->blocks.
-bool objcpy(Buffer* d, const C2BufferData& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->blocks.resize(
- s.linearBlocks().size() +
- s.graphicBlocks().size());
- size_t i = 0;
- for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
- Block& dBlock = d->blocks[i++];
- if (!objcpy(
- &dBlock, linearBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2BufferData::linearBlocks. "
- << "(Destination index = " << i - 1 << ".)";
- return false;
- }
- }
- for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
- Block& dBlock = d->blocks[i++];
- if (!objcpy(
- &dBlock, graphicBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2BufferData::graphicBlocks. "
- << "(Destination index = " << i - 1 << ".)";
- return false;
- }
- }
- return true;
-}
-
-// C2Buffer -> Buffer
-bool objcpy(Buffer* d, const C2Buffer& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!createParamsBlob(&d->info, s.info())) {
- LOG(ERROR) << "Invalid C2Buffer::info.";
- return false;
- }
- if (!objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Buffer::data.";
- return false;
- }
- return true;
-}
-
-// C2InfoBuffer -> InfoBuffer
-bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->index = static_cast<ParamIndex>(s.index());
- Buffer& dBuffer = d->buffer;
- if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2InfoBuffer::data";
- return false;
- }
- return true;
-}
-
-// C2FrameData -> FrameData
-bool objcpy(FrameData* d, const C2FrameData& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
- if (!objcpy(&d->ordinal, s.ordinal)) {
- LOG(ERROR) << "Invalid C2FrameData::ordinal.";
- return false;
- }
-
- d->buffers.resize(s.buffers.size());
- size_t i = 0;
- for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
- Buffer& dBuffer = d->buffers[i++];
- if (!sBuffer) {
- // A null (pointer to) C2Buffer corresponds to a Buffer with empty
- // info and blocks.
- dBuffer.info.resize(0);
- dBuffer.blocks.resize(0);
- continue;
- }
- if (!objcpy(
- &dBuffer, *sBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2FrameData::buffers["
- << i - 1 << "].";
- return false;
- }
- }
-
- if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
- LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
- return false;
- }
-
- d->infoBuffers.resize(s.infoBuffers.size());
- i = 0;
- for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
- InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
- if (!objcpy(&dInfoBuffer, sInfoBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
- << i - 1 << "].";
- return false;
- }
- }
-
- return true;
-}
-
-} // unnamed namespace
-
-// DefaultBufferPoolSender's implementation
-
-DefaultBufferPoolSender::DefaultBufferPoolSender(
- const sp<IClientManager>& receiverManager,
- std::chrono::steady_clock::duration refreshInterval)
- : mReceiverManager(receiverManager),
- mRefreshInterval(refreshInterval) {
-}
-
-void DefaultBufferPoolSender::setReceiver(
- const sp<IClientManager>& receiverManager,
- std::chrono::steady_clock::duration refreshInterval) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mReceiverManager != receiverManager) {
- mReceiverManager = receiverManager;
- mConnections.clear();
- }
- mRefreshInterval = refreshInterval;
-}
-
-ResultStatus DefaultBufferPoolSender::send(
- const std::shared_ptr<BufferPoolData>& bpData,
- BufferStatusMessage* bpMessage) {
- int64_t connectionId = bpData->mConnectionId;
- if (connectionId == 0) {
- LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
- return ResultStatus::CRITICAL_ERROR;
- }
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mReceiverManager) {
- LOG(ERROR) << "No access to receiver's BufferPool.";
- return ResultStatus::NOT_FOUND;
- }
- if (!mSenderManager) {
- mSenderManager = ClientManager::getInstance();
- if (!mSenderManager) {
- LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
- return ResultStatus::CRITICAL_ERROR;
- }
- }
-
- int64_t receiverConnectionId{0};
- auto foundConnection = mConnections.find(connectionId);
- bool isNewConnection = foundConnection == mConnections.end();
- std::chrono::steady_clock::time_point now =
- std::chrono::steady_clock::now();
- if (isNewConnection ||
- (now - foundConnection->second.lastSent > mRefreshInterval)) {
- // Initialize the bufferpool connection.
- ResultStatus rs =
- mSenderManager->registerSender(mReceiverManager,
- connectionId,
- &receiverConnectionId);
- if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
- LOG(WARNING) << "registerSender -- returned error: "
- << static_cast<int32_t>(rs)
- << ".";
- return rs;
- } else if (receiverConnectionId == 0) {
- LOG(WARNING) << "registerSender -- "
- "invalid receiver connection id (0).";
- return ResultStatus::CRITICAL_ERROR;
- } else {
- if (isNewConnection) {
- foundConnection = mConnections.try_emplace(
- connectionId, receiverConnectionId, now).first;
- } else {
- foundConnection->second.receiverConnectionId = receiverConnectionId;
- }
- }
- } else {
- receiverConnectionId = foundConnection->second.receiverConnectionId;
- }
-
- uint64_t transactionId;
- int64_t timestampUs;
- ResultStatus rs = mSenderManager->postSend(
- receiverConnectionId, bpData, &transactionId, ×tampUs);
- if (rs != ResultStatus::OK) {
- LOG(ERROR) << "ClientManager::postSend -- returned error: "
- << static_cast<int32_t>(rs)
- << ".";
- mConnections.erase(foundConnection);
- return rs;
- }
- if (!bpMessage) {
- LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
- mConnections.erase(foundConnection);
- return ResultStatus::CRITICAL_ERROR;
- }
- bpMessage->connectionId = receiverConnectionId;
- bpMessage->bufferId = bpData->mId;
- bpMessage->transactionId = transactionId;
- bpMessage->timestampUs = timestampUs;
- foundConnection->second.lastSent = now;
- return rs;
-}
-
-// std::list<std::unique_ptr<C2Work>> -> WorkBundle
-bool objcpy(
- WorkBundle* d,
- const std::list<std::unique_ptr<C2Work>>& s,
- BufferPoolSender* bufferPoolSender) {
- // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
- std::list<BaseBlock> baseBlocks;
-
- // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
- // inside baseBlocks to the corresponding index into baseBlocks. The keys
- // (pointers) are used to identify blocks that have the same "base block" in
- // s, a list of C2Work objects. Because baseBlocks will be copied into a
- // hidl_vec eventually, the values of baseBlockIndices are zero-based
- // integer indices instead of list iterators.
- //
- // Note that the pointers can be raw because baseBlockIndices has a shorter
- // lifespan than all of base blocks.
- std::map<const void*, uint32_t> baseBlockIndices;
-
- d->works.resize(s.size());
- size_t i = 0;
- for (const std::unique_ptr<C2Work>& sWork : s) {
- Work &dWork = d->works[i++];
- if (!sWork) {
- LOG(WARNING) << "Null C2Work encountered.";
- continue;
- }
-
- // chain info is not in use currently.
-
- // input
- if (!objcpy(&dWork.input, sWork->input,
- bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Work::input.";
- return false;
- }
-
- // worklets
- if (sWork->worklets.size() == 0) {
- LOG(DEBUG) << "Work with no worklets.";
- } else {
- // Parcel the worklets.
- hidl_vec<Worklet> &dWorklets = dWork.worklets;
- dWorklets.resize(sWork->worklets.size());
- size_t j = 0;
- for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
- {
- if (!sWorklet) {
- LOG(WARNING) << "Null C2Work::worklets["
- << j << "].";
- continue;
- }
- Worklet &dWorklet = dWorklets[j++];
-
- // component id
- dWorklet.componentId = static_cast<uint32_t>(
- sWorklet->component);
-
- // tunings
- if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->tunings.";
- return false;
- }
-
- // failures
- dWorklet.failures.resize(sWorklet->failures.size());
- size_t k = 0;
- for (const std::unique_ptr<C2SettingResult>& sFailure :
- sWorklet->failures) {
- if (!sFailure) {
- LOG(WARNING) << "Null C2Work::worklets["
- << j - 1 << "]->failures["
- << k << "].";
- continue;
- }
- if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->failures["
- << k - 1 << "].";
- return false;
- }
- }
-
- // output
- if (!objcpy(&dWorklet.output, sWorklet->output,
- bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->output.";
- return false;
- }
- }
- }
-
- // worklets processed
- dWork.workletsProcessed = sWork->workletsProcessed;
-
- // result
- dWork.result = static_cast<Status>(sWork->result);
- }
-
- // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
- {
- d->baseBlocks.resize(baseBlocks.size());
- size_t i = 0;
- for (const BaseBlock& baseBlock : baseBlocks) {
- d->baseBlocks[i++] = baseBlock;
- }
- }
-
- return true;
-}
-
-namespace /* unnamed */ {
-
-struct C2BaseBlock {
- enum type_t {
- LINEAR,
- GRAPHIC,
- };
- type_t type;
- std::shared_ptr<C2LinearBlock> linear;
- std::shared_ptr<C2GraphicBlock> graphic;
-};
-
-// hidl_handle -> C2Fence
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(C2Fence* d, const hidl_handle& s) {
- const native_handle_t* handle = s.getNativeHandle();
- *d = _C2FenceFactory::CreateFromNativeHandle(handle);
- return true;
-}
-
-// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createLinearBuffer(
- std::shared_ptr<C2Buffer>* buffer,
- const std::shared_ptr<C2LinearBlock>& block,
- const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RangeInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2LinearBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
- LOG(ERROR) << "Invalid range info in C2LinearBlock.";
- return false;
- }
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
-
- // Create C2Buffer from C2LinearBlock.
- *buffer = C2Buffer::CreateLinearBuffer(block->share(
- rangeInfo->offset, rangeInfo->length,
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateLinearBuffer failed.";
- return false;
- }
- return true;
-}
-
-// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createGraphicBuffer(
- std::shared_ptr<C2Buffer>* buffer,
- const std::shared_ptr<C2GraphicBlock>& block,
- const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RectInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
- LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
- return false;
- }
- C2Hidl_RectInfo *rectInfo =
- reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
-
- // Create C2Buffer from C2GraphicBlock.
- *buffer = C2Buffer::CreateGraphicBuffer(block->share(
- C2Rect(rectInfo->width, rectInfo->height).
- at(rectInfo->left, rectInfo->top),
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateGraphicBuffer failed.";
- return false;
- }
- return true;
-}
-
-// Buffer -> C2Buffer
-// Note: The native handles will be cloned.
-bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
- *d = nullptr;
-
- // Currently, a non-null C2Buffer must contain exactly 1 block.
- if (s.blocks.size() == 0) {
- return true;
- } else if (s.blocks.size() != 1) {
- LOG(ERROR) << "Invalid Buffer: "
- "Currently, a C2Buffer must contain exactly 1 block.";
- return false;
- }
-
- const Block &sBlock = s.blocks[0];
- if (sBlock.index >= baseBlocks.size()) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
- "Array index out of range.";
- return false;
- }
- const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
- // Parse meta.
- std::vector<C2Param*> sBlockMeta;
- if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
- return false;
- }
-
- // Copy fence.
- C2Fence dFence;
- if (!objcpy(&dFence, sBlock.fence)) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
- return false;
- }
-
- // Construct a block.
- switch (baseBlock.type) {
- case C2BaseBlock::LINEAR:
- if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
- LOG(ERROR) << "Invalid C2BaseBlock::linear.";
- return false;
- }
- break;
- case C2BaseBlock::GRAPHIC:
- if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
- LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
- return false;
- }
- break;
- default:
- LOG(ERROR) << "Invalid C2BaseBlock::type.";
- return false;
- }
-
- // Parse info
- std::vector<C2Param*> params;
- if (!parseParamsBlob(¶ms, s.info)) {
- LOG(ERROR) << "Invalid Buffer::info.";
- return false;
- }
- for (C2Param* param : params) {
- if (param == nullptr) {
- LOG(ERROR) << "Null param in Buffer::info.";
- return false;
- }
- std::shared_ptr<C2Param> c2param{
- C2Param::Copy(*param).release()};
- if (!c2param) {
- LOG(ERROR) << "Invalid param in Buffer::info.";
- return false;
- }
- c2_status_t status =
- (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
- if (status != C2_OK) {
- LOG(ERROR) << "C2Buffer::setInfo failed.";
- return false;
- }
- }
-
- return true;
-}
-
-// InfoBuffer -> C2InfoBuffer
-bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
-
- // Currently, a non-null C2InfoBufer must contain exactly 1 block.
- if (s.buffer.blocks.size() == 0) {
- return true;
- } else if (s.buffer.blocks.size() != 1) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer "
- "Currently, a C2InfoBuffer must contain exactly 1 block.";
- return false;
- }
-
- const Block &sBlock = s.buffer.blocks[0];
- if (sBlock.index >= baseBlocks.size()) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
- "Array index out of range.";
- return false;
- }
- const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
- // Parse meta.
- std::vector<C2Param*> sBlockMeta;
- if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
- return false;
- }
-
- // Copy fence.
- C2Fence dFence;
- if (!objcpy(&dFence, sBlock.fence)) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
- return false;
- }
-
- // Construct a block.
- switch (baseBlock.type) {
- case C2BaseBlock::LINEAR:
- if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
- sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
- d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
- s.index,
- baseBlock.linear->share(
- rangeInfo->offset, rangeInfo->length, dFence)));
- return true;
- }
- LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
- break;
- case C2BaseBlock::GRAPHIC:
- // It's not used now
- LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
- break;
- default:
- LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
- break;
- }
-
- return false;
-}
-
-// FrameData -> C2FrameData
-bool objcpy(C2FrameData* d, const FrameData& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
- d->flags = static_cast<C2FrameData::flags_t>(s.flags);
- if (!objcpy(&d->ordinal, s.ordinal)) {
- LOG(ERROR) << "Invalid FrameData::ordinal.";
- return false;
- }
- d->buffers.clear();
- d->buffers.reserve(s.buffers.size());
- for (const Buffer& sBuffer : s.buffers) {
- std::shared_ptr<C2Buffer> dBuffer;
- if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
- LOG(ERROR) << "Invalid FrameData::buffers.";
- return false;
- }
- d->buffers.emplace_back(dBuffer);
- }
-
- std::vector<C2Param*> params;
- if (!parseParamsBlob(¶ms, s.configUpdate)) {
- LOG(ERROR) << "Invalid FrameData::configUpdate.";
- return false;
- }
- d->configUpdate.clear();
- for (C2Param* param : params) {
- d->configUpdate.emplace_back(C2Param::Copy(*param));
- if (!d->configUpdate.back()) {
- LOG(ERROR) << "Unexpected error while parsing "
- "FrameData::configUpdate.";
- return false;
- }
- }
-
- d->infoBuffers.clear();
- if (s.infoBuffers.size() == 0) {
- // InfoBuffer is optional
- return true;
- }
- d->infoBuffers.reserve(s.infoBuffers.size());
- for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
- if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
- LOG(ERROR) << "Invalid Framedata::infoBuffers.";
- return false;
- }
- }
- return true;
-}
+constexpr BaseBlock::Tag NATIVE_BLOCK = BaseBlock::nativeBlock;
+constexpr BaseBlock::Tag POOLED_BLOCK = BaseBlock::pooledBlock;
// BaseBlock -> C2BaseBlock
+template<>
bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
- switch (s.getDiscriminator()) {
- case BaseBlock::hidl_discriminator::nativeBlock: {
- if (s.nativeBlock() == nullptr) {
+ switch (s.getTag()) {
+ case NATIVE_BLOCK: {
+ if (isAidlNativeHandleEmpty(s.get<NATIVE_BLOCK>())) {
LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
return false;
}
native_handle_t* sHandle =
- native_handle_clone(s.nativeBlock());
+ ::android::dupFromAidl(s.get<NATIVE_BLOCK>());
if (sHandle == nullptr) {
LOG(ERROR) << "Null BaseBlock::nativeBlock.";
return false;
@@ -1460,15 +76,17 @@
const C2Handle *sC2Handle =
reinterpret_cast<const C2Handle*>(sHandle);
+ // If successful, the handle is deleted(!) and fds are owned by the block.
d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
+ d->type = ::android::C2BaseBlock::LINEAR;
return true;
}
+ // If successful, the handle is deleted(!) and fds are owned by the block.
d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
+ d->type = ::android::C2BaseBlock::GRAPHIC;
return true;
}
@@ -1479,13 +97,12 @@
}
return false;
}
- case BaseBlock::hidl_discriminator::pooledBlock: {
- const BufferStatusMessage &bpMessage =
- s.pooledBlock();
- sp<ClientManager> bp = ClientManager::getInstance();
+ case POOLED_BLOCK: {
+ const BufferStatusMessage &bpMessage = s.get<POOLED_BLOCK>();
+ std::shared_ptr<ClientManager> bp = ClientManager::getInstance();
std::shared_ptr<BufferPoolData> bpData;
native_handle_t *cHandle;
- ResultStatus bpStatus = bp->receive(
+ BufferPoolStatus bpStatus = bp->receive(
bpMessage.connectionId,
bpMessage.transactionId,
bpMessage.bufferId,
@@ -1494,23 +111,24 @@
&bpData);
if (bpStatus != ResultStatus::OK) {
LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
- << "resultStatus = " << underlying_value(bpStatus)
- << ".";
+ << "resultStatus = " << bpStatus << ".";
return false;
} else if (!bpData) {
LOG(ERROR) << "No data in bufferpool transaction.";
return false;
}
+ // If successful, the handle is deleted(!) and fds are owned by the block.
d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
+ d->type = ::android::C2BaseBlock::LINEAR;
return true;
}
+ // If successful, the handle is deleted(!) and fds are owned by the block.
d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
+ d->type = ::android::C2BaseBlock::GRAPHIC;
return true;
}
if (cHandle) {
@@ -1525,404 +143,193 @@
default:
LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
<< "underlying value "
- << underlying_value(s.getDiscriminator()) << ".";
+ << ::android::underlying_value(s.getTag()) << ".";
return false;
}
}
-} // unnamed namespace
+// C2Fence -> AidlNativeHandle
+template<>
+bool objcpy(AidlNativeHandle* d, const C2Fence& s) {
+ // fds are not duplicated here
+ native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
+ if (handle) {
+ // |d| copies the fds without duplicating
+ *d = makeToAidl(handle);
+ // no fds are duplicated, just delete the handle
+ // Note: C2Fence still owns the fds and should not be cleared
+ // before the transaction is complete.
+ native_handle_delete(handle);
+// } else if (!s.ready()) {
+// // TODO: we should wait for unmarshallable fences but this may not be
+// // the best place for it. We can safely ignore here as at this time
+// // all fences used here are marshallable.
+ }
+ return true;
+}
+
+// AidlNativeHandle -> C2Fence
+template<>
+bool objcpy(C2Fence* d, const AidlNativeHandle& s) {
+ // makeFromAidl does not duplicate the fds.
+ native_handle_t* handle = makeFromAidl(s);
+ // C2Fence duplicates and owns the fds
+ *d = _C2FenceFactory::CreateFromNativeHandle(handle);
+ if (handle) {
+ // |handle| should not be closed here, as the fds are owned by |s|
+ native_handle_delete(handle);
+ }
+ return true;
+}
+
+template<>
+void SetHandle(BaseBlock *block, const C2Handle *handle) {
+ block->set<BaseBlock::nativeBlock>(makeToAidl(handle));
+}
+
+template<>
+void SetPooledBlock<BufferPoolTypes>(
+ BaseBlock *baseBlock,
+ const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
+ baseBlock->set<POOLED_BLOCK>(pooledBlock);
+}
+
+template<>
+bool GetBufferPoolData<BufferPoolTypes>(
+ const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
+ std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData) {
+ return _C2BlockFactory::GetBufferPoolData(blockPoolData, bpData);
+}
+
+} // namespace android
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace utils {
+
+namespace bufferpool2 = ::aidl::android::hardware::media::bufferpool2;
+namespace bufferpool2_impl = ::aidl::android::hardware::media::bufferpool2::implementation;
+
+// DefaultBufferPoolSender's implementation
+
+DefaultBufferPoolSender::DefaultBufferPoolSender(
+ const std::shared_ptr<IClientManager>& receiverManager,
+ std::chrono::steady_clock::duration refreshInterval)
+ : mReceiverManager(receiverManager),
+ mRefreshInterval(refreshInterval) {
+}
+
+void DefaultBufferPoolSender::setReceiver(
+ const std::shared_ptr<IClientManager>& receiverManager,
+ std::chrono::steady_clock::duration refreshInterval) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mReceiverManager != receiverManager) {
+ mReceiverManager = receiverManager;
+ mConnections.clear();
+ }
+ mRefreshInterval = refreshInterval;
+}
+
+BufferPoolTypes::BufferPoolStatus DefaultBufferPoolSender::send(
+ const std::shared_ptr<bufferpool2::BufferPoolData>& bpData,
+ bufferpool2::BufferStatusMessage* bpMessage) {
+ int64_t connectionId = bpData->mConnectionId;
+ if (connectionId == 0) {
+ LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
+ return bufferpool2::ResultStatus::CRITICAL_ERROR;
+ }
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (!mReceiverManager) {
+ LOG(ERROR) << "No access to receiver's BufferPool.";
+ return bufferpool2::ResultStatus::NOT_FOUND;
+ }
+ if (!mSenderManager) {
+ mSenderManager = ClientManager::getInstance();
+ if (!mSenderManager) {
+ LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
+ return bufferpool2::ResultStatus::CRITICAL_ERROR;
+ }
+ }
+
+ int64_t receiverConnectionId{0};
+ auto foundConnection = mConnections.find(connectionId);
+ bool isNewConnection = foundConnection == mConnections.end();
+ std::chrono::steady_clock::time_point now =
+ std::chrono::steady_clock::now();
+ if (isNewConnection ||
+ (now - foundConnection->second.lastSent > mRefreshInterval)) {
+ // Initialize the bufferpool connection.
+ bufferpool2_impl::BufferPoolStatus rs =
+ mSenderManager->registerSender(mReceiverManager,
+ connectionId,
+ &receiverConnectionId,
+ &isNewConnection);
+ if ((rs != bufferpool2::ResultStatus::OK)
+ && (rs != bufferpool2::ResultStatus::ALREADY_EXISTS)) {
+ LOG(WARNING) << "registerSender -- returned error: "
+ << static_cast<int32_t>(rs)
+ << ".";
+ return rs;
+ } else if (receiverConnectionId == 0) {
+ LOG(WARNING) << "registerSender -- "
+ "invalid receiver connection id (0).";
+ return bufferpool2::ResultStatus::CRITICAL_ERROR;
+ } else {
+ if (isNewConnection) {
+ foundConnection = mConnections.try_emplace(
+ connectionId, receiverConnectionId, now).first;
+ } else {
+ foundConnection->second.receiverConnectionId = receiverConnectionId;
+ }
+ }
+ } else {
+ receiverConnectionId = foundConnection->second.receiverConnectionId;
+ }
+
+ uint64_t transactionId;
+ int64_t timestampUs;
+ bufferpool2_impl::BufferPoolStatus rs = mSenderManager->postSend(
+ receiverConnectionId, bpData, &transactionId, ×tampUs);
+ if (rs != bufferpool2::ResultStatus::OK) {
+ LOG(ERROR) << "ClientManager::postSend -- returned error: "
+ << static_cast<int32_t>(rs)
+ << ".";
+ mConnections.erase(foundConnection);
+ return rs;
+ }
+ if (!bpMessage) {
+ LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
+ mConnections.erase(foundConnection);
+ return bufferpool2::ResultStatus::CRITICAL_ERROR;
+ }
+ bpMessage->connectionId = receiverConnectionId;
+ bpMessage->bufferId = bpData->mId;
+ bpMessage->transactionId = transactionId;
+ bpMessage->timestampUs = timestampUs;
+ foundConnection->second.lastSent = now;
+ return rs;
+}
+
+// std::list<std::unique_ptr<C2Work>> -> WorkBundle
+bool ToAidl(
+ WorkBundle* d,
+ const std::list<std::unique_ptr<C2Work>>& s,
+ ::android::BufferPoolSender<BufferPoolTypes>* bufferPoolSender) {
+ return ::android::objcpy(d, s, bufferPoolSender);
+}
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
-bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
- // Convert BaseBlocks to C2BaseBlocks.
- std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
- for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
- if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
- LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
- << i << "].";
- return false;
- }
- }
-
- d->clear();
- for (const Work& sWork : s.works) {
- d->emplace_back(std::make_unique<C2Work>());
- C2Work& dWork = *d->back();
-
- // chain info is not in use currently.
-
- // input
- if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
- LOG(ERROR) << "Invalid Work::input.";
- return false;
- }
-
- // worklet(s)
- dWork.worklets.clear();
- for (const Worklet& sWorklet : sWork.worklets) {
- std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
-
- // component id
- dWorklet->component = static_cast<c2_node_id_t>(
- sWorklet.componentId);
-
- // tunings
- if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
- LOG(ERROR) << "Invalid Worklet::tunings";
- return false;
- }
-
- // failures
- dWorklet->failures.clear();
- dWorklet->failures.reserve(sWorklet.failures.size());
- for (const SettingResult& sFailure : sWorklet.failures) {
- std::unique_ptr<C2SettingResult> dFailure;
- if (!objcpy(&dFailure, sFailure)) {
- LOG(ERROR) << "Invalid Worklet::failures.";
- return false;
- }
- dWorklet->failures.emplace_back(std::move(dFailure));
- }
-
- // output
- if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
- LOG(ERROR) << "Invalid Worklet::output.";
- return false;
- }
-
- dWork.worklets.emplace_back(std::move(dWorklet));
- }
-
- // workletsProcessed
- dWork.workletsProcessed = sWork.workletsProcessed;
-
- // result
- dWork.result = static_cast<c2_status_t>(sWork.result);
- }
-
- return true;
-}
-
-constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment
-static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
-
-// Params -> std::vector<C2Param*>
-bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
- // assuming blob is const here
- size_t size = blob.size();
- size_t ix = 0;
- size_t old_ix = 0;
- const uint8_t *data = blob.data();
- C2Param *p = nullptr;
-
- do {
- p = C2ParamUtils::ParseFirst(data + ix, size - ix);
- if (p) {
- params->emplace_back(p);
- old_ix = ix;
- ix += p->size();
- ix = align(ix, PARAMS_ALIGNMENT);
- if (ix <= old_ix || ix > size) {
- android_errorWriteLog(0x534e4554, "238083570");
- break;
- }
- }
- } while (p);
-
- if (ix != size) {
- LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
- return false;
- }
- return true;
-}
-
-namespace /* unnamed */ {
-
-/**
- * Concatenates a list of C2Params into a params blob. T is a container type
- * whose member type is compatible with C2Param*.
- *
- * \param[out] blob target blob
- * \param[in] params parameters to concatenate
- * \retval C2_OK if the blob was successfully created
- * \retval C2_BAD_VALUE if the blob was not successful created (this only
- * happens if the parameters were not const)
- */
-template <typename T>
-bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) {
- // assuming the parameter values are const
- size_t size = 0;
- for (const auto &p : params) {
- if (!p) {
- continue;
- }
- size += p->size();
- size = align(size, PARAMS_ALIGNMENT);
- }
- blob->resize(size);
- size_t ix = 0;
- for (const auto &p : params) {
- if (!p) {
- continue;
- }
- // NEVER overwrite even if param values (e.g. size) changed
- size_t paramSize = std::min(p->size(), size - ix);
- std::copy(
- reinterpret_cast<const uint8_t*>(&*p),
- reinterpret_cast<const uint8_t*>(&*p) + paramSize,
- &(*blob)[ix]);
- ix += paramSize;
- ix = align(ix, PARAMS_ALIGNMENT);
- }
- blob->resize(ix);
- if (ix != size) {
- LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
- return false;
- }
- return true;
-}
-
-/**
- * Parses a params blob and create a vector of new T objects that contain copies
- * of the params in the blob. T is C2Param or its compatible derived class.
- *
- * \param[out] params the resulting vector
- * \param[in] blob parameter blob to parse
- * \retval C2_OK if the full blob was parsed and params was constructed
- * \retval C2_BAD_VALUE otherwise
- */
-template <typename T>
-bool _copyParamsFromBlob(
- std::vector<std::unique_ptr<T>>* params,
- Params blob) {
-
- std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, blob)) {
- LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
- return false;
- }
-
- params->resize(paramPointers.size());
- size_t i = 0;
- for (C2Param* const& paramPointer : paramPointers) {
- if (!paramPointer) {
- LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
- return false;
- }
- (*params)[i++].reset(reinterpret_cast<T*>(
- C2Param::Copy(*paramPointer).release()));
- }
- return true;
-}
-
-} // unnamed namespace
-
-// std::vector<const C2Param*> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<const C2Param*> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<C2Param*> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<C2Param*> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Param>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Param>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Tuning>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Tuning>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::shared_ptr<const C2Info>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::shared_ptr<const C2Info>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Param>>
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Param>>* params,
- Params blob) {
- return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Tuning>>
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Tuning>>* params,
- Params blob) {
- return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> update std::vector<std::unique_ptr<C2Param>>
-bool updateParamsFromBlob(
- const std::vector<C2Param*>& params,
- const Params& blob) {
- std::unordered_map<uint32_t, C2Param*> index2param;
- for (C2Param* const& param : params) {
- if (!param) {
- LOG(ERROR) << "updateParamsFromBlob -- null output param.";
- return false;
- }
- if (index2param.find(param->index()) == index2param.end()) {
- index2param.emplace(param->index(), param);
- }
- }
-
- std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, blob)) {
- LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
- return false;
- }
-
- for (C2Param* const& paramPointer : paramPointers) {
- if (!paramPointer) {
- LOG(ERROR) << "updateParamsFromBlob -- null input param.";
- return false;
- }
- decltype(index2param)::iterator i = index2param.find(
- paramPointer->index());
- if (i == index2param.end()) {
- LOG(DEBUG) << "updateParamsFromBlob -- index "
- << paramPointer->index() << " not found. Skipping...";
- continue;
- }
- if (!i->second->updateFrom(*paramPointer)) {
- LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
- << params.size() << " vs " << paramPointer->size()
- << " (index = " << i->first << ").";
- return false;
- }
- }
- return true;
-}
-
-// Convert BufferPool ResultStatus to c2_status_t.
-c2_status_t toC2Status(ResultStatus rs) {
- switch (rs) {
- case ResultStatus::OK:
- return C2_OK;
- case ResultStatus::NO_MEMORY:
- return C2_NO_MEMORY;
- case ResultStatus::ALREADY_EXISTS:
- return C2_DUPLICATE;
- case ResultStatus::NOT_FOUND:
- return C2_NOT_FOUND;
- case ResultStatus::CRITICAL_ERROR:
- return C2_CORRUPTED;
- default:
- LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
- << static_cast<int32_t>(rs) << ".";
- return C2_CORRUPTED;
- }
-}
-
-namespace /* unnamed */ {
-
-template <typename BlockProcessor>
-void forEachBlock(C2FrameData& frameData,
- BlockProcessor process) {
- for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
- if (buffer) {
- for (const C2ConstGraphicBlock& block :
- buffer->data().graphicBlocks()) {
- process(block);
- }
- }
- }
-}
-
-template <typename BlockProcessor>
-void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
- BlockProcessor process,
- bool processInput, bool processOutput) {
- for (const std::unique_ptr<C2Work>& work : workList) {
- if (!work) {
- continue;
- }
- if (processInput) {
- forEachBlock(work->input, process);
- }
- if (processOutput) {
- for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
- if (worklet) {
- forEachBlock(worklet->output,
- process);
- }
- }
- }
- }
-}
-
-} // unnamed namespace
-
-bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::BeginTransferBlockToClient(data);
- return true;
- }
- return false;
-}
-
-void beginTransferBufferQueueBlocks(
- const std::list<std::unique_ptr<C2Work>>& workList,
- bool processInput, bool processOutput) {
- forEachBlock(workList, beginTransferBufferQueueBlock,
- processInput, processOutput);
-}
-
-bool endTransferBufferQueueBlock(
- const C2ConstGraphicBlock& block,
- bool transfer) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::EndTransferBlockToClient(data, transfer);
- return true;
- }
- return false;
-}
-
-void endTransferBufferQueueBlocks(
- const std::list<std::unique_ptr<C2Work>>& workList,
- bool transfer,
- bool processInput, bool processOutput) {
- forEachBlock(workList,
- std::bind(endTransferBufferQueueBlock,
- std::placeholders::_1, transfer),
- processInput, processOutput);
-}
-
-bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::DisplayBlockToBufferQueue(data);
- return true;
- }
- return false;
+bool FromAidl(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
+ return ::android::objcpy(d, s);
}
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
new file mode 100644
index 0000000..7994d32
--- /dev/null
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Component@1.2"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.2/Component.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <codec2/hidl/1.2/InputBufferManager.h>
+
+#ifndef __ANDROID_APEX__
+#include <FilterWrapper.h>
+#endif
+
+#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_2 {
+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;
+#ifdef __ANDROID_APEX__
+ c2_status_t status = CreateCodec2BlockPool(
+ static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+ mComponent,
+ &blockPool);
+#else
+ c2_status_t status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ static_cast<C2PlatformAllocatorStore::id_t>(allocatorId),
+ mComponent,
+ &blockPool);
+#endif
+ 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();
+}
+
+Return<Status> Component::setOutputSurfaceWithSyncObj(
+ uint64_t blockPoolId, const sp<HGraphicBufferProducer2>& surface,
+ const SurfaceSyncObj& syncObject) {
+ 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) {
+ const native_handle_t *h = syncObject.syncMemory;
+ native_handle_t *syncMemory = h ? native_handle_clone(h) : nullptr;
+ uint64_t bqId = syncObject.bqId;
+ uint32_t generationId = syncObject.generationId;
+ uint64_t consumerUsage = syncObject.consumerUsage;
+
+ bqPool->setRenderCallback(cb);
+ bqPool->configureProducer(surface, syncMemory, bqId,
+ generationId, consumerUsage);
+ }
+ }
+ return Status::OK;
+}
+
+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;
+ }
+
+ struct ListenerDeathRecipient : public HwDeathRecipient {
+ ListenerDeathRecipient(const wp<Component>& comp)
+ : component{comp} {
+ }
+
+ virtual void serviceDied(
+ uint64_t /* cookie */,
+ const wp<::android::hidl::base::V1_0::IBase>& /* who */
+ ) override {
+ auto strongComponent = component.promote();
+ if (strongComponent) {
+ LOG(INFO) << "Client died ! release the component !!";
+ strongComponent->release();
+ } else {
+ LOG(ERROR) << "Client died ! no component to release !!";
+ }
+ }
+
+ wp<Component> component;
+ };
+
+ mDeathRecipient = new ListenerDeathRecipient(self);
+ Return<bool> transStatus = mListener->linkToDeath(
+ mDeathRecipient, 0);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Listener linkToDeath() transaction failed.";
+ }
+ if (!static_cast<bool>(transStatus)) {
+ LOG(DEBUG) << "Listener linkToDeath() call failed.";
+ }
+}
+
+Component::~Component() {
+ InputBufferManager::unregisterFrameData(mListener);
+ mStore->reportComponentDeath(this);
+}
+
+} // namespace utils
+} // namespace V1_2
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hal/aidl/ComponentInterface.cpp b/media/codec2/hal/aidl/ComponentInterface.cpp
new file mode 100644
index 0000000..12078e0
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentInterface.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentInterface"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/ComponentStore.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_0 {
+namespace utils {
+
+using namespace ::android;
+
+namespace /* unnamed */ {
+
+// Implementation of ConfigurableC2Intf based on C2ComponentInterface
+struct CompIntf : public ConfigurableC2Intf {
+ CompIntf(const std::shared_ptr<C2ComponentInterface>& intf) :
+ ConfigurableC2Intf{intf->getName(), intf->getId()},
+ mIntf{intf} {
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*>& params,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ return mIntf->config_vb(params, mayBlock, 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 {
+ return mIntf->query_vb({}, indices, mayBlock, params);
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ return mIntf->querySupportedParams_nb(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ return mIntf->querySupportedValues_vb(fields, mayBlock);
+ }
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mIntf;
+};
+
+} // unnamed namespace
+
+// ComponentInterface
+ComponentInterface::ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& intf,
+ const std::shared_ptr<ParameterCache>& cache)
+ : mInterface{intf},
+ mConfigurable{new CachedConfigurable(std::make_unique<CompIntf>(intf))} {
+ mInit = mConfigurable->init(cache);
+}
+
+c2_status_t ComponentInterface::status() const {
+ return mInit;
+}
+
+Return<sp<IConfigurable>> ComponentInterface::getConfigurable() {
+ return mConfigurable;
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
new file mode 100644
index 0000000..9fac5d5
--- /dev/null
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-ComponentStore@1.2"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.2/ComponentStore.h>
+#include <codec2/hidl/1.2/InputSurface.h>
+#include <codec2/hidl/1.2/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>
+
+#ifndef __ANDROID_APEX__
+#include <codec2/hidl/plugin/FilterPlugin.h>
+#include <dlfcn.h>
+#include <C2Config.h>
+#include <DefaultFilterPlugin.h>
+#include <FilterWrapper.h>
+#endif
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_2 {
+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;
+}
+
+#ifndef __ANDROID_APEX__
+// static
+std::shared_ptr<FilterWrapper> ComponentStore::GetFilterWrapper() {
+ constexpr const char kPluginPath[] = "libc2filterplugin.so";
+ static std::shared_ptr<FilterWrapper> wrapper = FilterWrapper::Create(
+ std::make_unique<DefaultFilterPlugin>(kPluginPath));
+ return wrapper;
+}
+#endif
+
+// 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) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+ 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) {
+#ifndef __ANDROID_APEX__
+ c2interface = GetFilterWrapper()->maybeWrapInterface(c2interface);
+#endif
+ 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) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+ 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();
+}
+
+// Methods from ::android::hardware::media::c2::V1_2::IComponentStore
+Return<void> ComponentStore::createComponent_1_2(
+ const hidl_string& name,
+ const sp<IComponentListener>& listener,
+ const sp<IClientManager>& pool,
+ createComponent_1_2_cb _hidl_cb) {
+
+ sp<Component> component;
+ std::shared_ptr<C2Component> c2component;
+ Status status = static_cast<Status>(
+ mStore->createComponent(name, &c2component));
+
+ if (status == Status::OK) {
+#ifndef __ANDROID_APEX__
+ c2component = GetFilterWrapper()->maybeWrapComponent(c2component);
+#endif
+ 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_2
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/codec2/hal/aidl/Configurable.cpp b/media/codec2/hal/aidl/Configurable.cpp
new file mode 100644
index 0000000..530576d
--- /dev/null
+++ b/media/codec2/hal/aidl/Configurable.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-Configurable"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/ComponentStore.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <C2ParamInternal.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+CachedConfigurable::CachedConfigurable(
+ std::unique_ptr<ConfigurableC2Intf>&& intf)
+ : mIntf{std::move(intf)} {
+}
+
+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 = cache->validate(mSupportedParams);
+ return init == C2_OK ? C2_OK : validate;
+}
+
+// Methods from ::android::hardware::media::c2::V1_0::IConfigurable follow.
+Return<uint32_t> CachedConfigurable::getId() {
+ return mIntf->getId();
+}
+
+Return<void> CachedConfigurable::getName(getName_cb _hidl_cb) {
+ _hidl_cb(mIntf->getName());
+ return Void();
+}
+
+Return<void> CachedConfigurable::query(
+ const hidl_vec<uint32_t>& indices,
+ bool mayBlock,
+ query_cb _hidl_cb) {
+ typedef C2Param::Index Index;
+ std::vector<Index> c2heapParamIndices(
+ (Index*)indices.data(),
+ (Index*)indices.data() + indices.size());
+ std::vector<std::unique_ptr<C2Param>> c2heapParams;
+ c2_status_t c2res = mIntf->query(
+ c2heapParamIndices,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+ &c2heapParams);
+
+ hidl_vec<uint8_t> params;
+ if (!createParamsBlob(¶ms, c2heapParams)) {
+ LOG(WARNING) << "query -- invalid output params.";
+ }
+ _hidl_cb(static_cast<Status>(c2res), params);
+ return Void();
+}
+
+Return<void> CachedConfigurable::config(
+ const hidl_vec<uint8_t>& inParams,
+ bool mayBlock,
+ config_cb _hidl_cb) {
+ // inParams is not writable, so create a copy as config modifies the parameters
+ hidl_vec<uint8_t> inParamsCopy = inParams;
+ std::vector<C2Param*> c2params;
+ if (!parseParamsBlob(&c2params, inParamsCopy)) {
+ LOG(WARNING) << "config -- invalid input params.";
+ _hidl_cb(Status::CORRUPTED,
+ hidl_vec<SettingResult>(),
+ hidl_vec<uint8_t>());
+ return Void();
+ }
+ // TODO: check if blob was invalid
+ std::vector<std::unique_ptr<C2SettingResult>> c2failures;
+ c2_status_t c2res = mIntf->config(
+ c2params,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK,
+ &c2failures);
+ hidl_vec<SettingResult> failures(c2failures.size());
+ {
+ size_t ix = 0;
+ for (const std::unique_ptr<C2SettingResult>& c2result : c2failures) {
+ if (c2result) {
+ if (objcpy(&failures[ix], *c2result)) {
+ ++ix;
+ } else {
+ LOG(DEBUG) << "config -- invalid setting results.";
+ break;
+ }
+ }
+ }
+ failures.resize(ix);
+ }
+ hidl_vec<uint8_t> outParams;
+ if (!createParamsBlob(&outParams, c2params)) {
+ LOG(DEBUG) << "config -- invalid output params.";
+ }
+ _hidl_cb((Status)c2res, failures, outParams);
+ return Void();
+}
+
+Return<void> CachedConfigurable::querySupportedParams(
+ uint32_t start,
+ uint32_t count,
+ querySupportedParams_cb _hidl_cb) {
+ C2LinearRange request = C2LinearCapacity(mSupportedParams.size()).range(
+ start, count);
+ hidl_vec<ParamDescriptor> params(request.size());
+ Status res = Status::OK;
+ size_t dstIx = 0;
+ for (size_t srcIx = request.offset(); srcIx < request.endOffset(); ++srcIx) {
+ if (mSupportedParams[srcIx]) {
+ if (objcpy(¶ms[dstIx], *mSupportedParams[srcIx])) {
+ ++dstIx;
+ } else {
+ res = Status::CORRUPTED;
+ LOG(WARNING) << "querySupportedParams -- invalid output params.";
+ break;
+ }
+ } else {
+ res = Status::BAD_INDEX;
+ }
+ }
+ params.resize(dstIx);
+ _hidl_cb(res, params);
+ return Void();
+}
+
+Return<void> CachedConfigurable::querySupportedValues(
+ const hidl_vec<FieldSupportedValuesQuery>& inFields,
+ bool mayBlock,
+ querySupportedValues_cb _hidl_cb) {
+ std::vector<C2FieldSupportedValuesQuery> c2fields;
+ {
+ // C2FieldSupportedValuesQuery objects are restricted in that some
+ // members are const.
+ // C2ParamField - required for its constructor - has no constructors
+ // from fields. Use C2ParamInspector.
+ for (const FieldSupportedValuesQuery &query : inFields) {
+ c2fields.emplace_back(_C2ParamInspector::CreateParamField(
+ query.field.index,
+ query.field.fieldId.offset,
+ query.field.fieldId.size),
+ query.type == FieldSupportedValuesQuery::Type::POSSIBLE ?
+ C2FieldSupportedValuesQuery::POSSIBLE :
+ C2FieldSupportedValuesQuery::CURRENT);
+ }
+ }
+ c2_status_t c2res = mIntf->querySupportedValues(
+ c2fields,
+ mayBlock ? C2_MAY_BLOCK : C2_DONT_BLOCK);
+ hidl_vec<FieldSupportedValuesQueryResult> outFields(inFields.size());
+ size_t dstIx = 0;
+ for (const C2FieldSupportedValuesQuery &result : c2fields) {
+ if (objcpy(&outFields[dstIx], result)) {
+ ++dstIx;
+ } else {
+ outFields.resize(dstIx);
+ c2res = C2_CORRUPTED;
+ LOG(WARNING) << "querySupportedValues -- invalid output params.";
+ break;
+ }
+ }
+ _hidl_cb((Status)c2res, outFields);
+ return Void();
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
diff --git a/media/codec2/hal/aidl/InputBufferManager.cpp b/media/codec2/hal/aidl/InputBufferManager.cpp
new file mode 100644
index 0000000..8c0d0a4
--- /dev/null
+++ b/media/codec2/hal/aidl/InputBufferManager.cpp
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputBufferManager"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputBufferManager.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <android-base/logging.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+void InputBufferManager::registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._registerFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ getInstance()._unregisterFrameData(listener, input);
+}
+
+void InputBufferManager::unregisterFrameData(
+ const wp<IComponentListener>& listener) {
+ getInstance()._unregisterFrameData(listener);
+}
+
+void InputBufferManager::setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ getInstance()._setNotificationInterval(notificationIntervalNs);
+}
+
+void InputBufferManager::_registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ std::set<TrackedBuffer*> &bufferIds =
+ mTrackedBuffersMap[listener][frameIndex];
+
+ for (size_t i = 0; i < input.buffers.size(); ++i) {
+ if (!input.buffers[i]) {
+ LOG(VERBOSE) << "InputBufferManager::_registerFrameData -- "
+ << "Input buffer at index " << i << " is null.";
+ continue;
+ }
+ TrackedBuffer *bufferId =
+ new TrackedBuffer(listener, frameIndex, i, input.buffers[i]);
+ mTrackedBufferCache.emplace(bufferId);
+ bufferIds.emplace(bufferId);
+
+ c2_status_t status = input.buffers[i]->registerOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_registerFrameData -- "
+ << "registerOnDestroyNotify() failed "
+ << "(listener @ 0x" << std::hex << listener.get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ", bufferIndex = " << i
+ << ") => status = " << status
+ << ".";
+ }
+ }
+
+ mDeathNotifications.emplace(
+ listener,
+ DeathNotifications(
+ mNotificationIntervalNs.load(std::memory_order_relaxed)));
+}
+
+// Remove a pair (listener, frameIndex) from mTrackedBuffersMap and
+// mDeathNotifications. This implies all bufferIndices are removed.
+//
+// This is called from onWorkDone() and flush().
+void InputBufferManager::_unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input) {
+ uint64_t frameIndex = input.ordinal.frameIndex.peeku();
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.unsafe_get()
+ << ", frameIndex = " << std::dec << frameIndex
+ << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(frameIndex);
+ if (findFrameIndex != frameIndex2BufferIds.end()) {
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ for (TrackedBuffer* bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(listener @ 0x"
+ << std::hex
+ << bufferId->listener.unsafe_get()
+ << ", frameIndex = "
+ << std::dec << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ }
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+ }
+
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+ }
+
+ auto findListenerD = mDeathNotifications.find(listener);
+ if (findListenerD != mDeathNotifications.end()) {
+ DeathNotifications &deathNotifications = findListenerD->second;
+ auto findFrameIndex = deathNotifications.indices.find(frameIndex);
+ if (findFrameIndex != deathNotifications.indices.end()) {
+ std::vector<size_t> &bufferIndices = findFrameIndex->second;
+ deathNotifications.count -= bufferIndices.size();
+ deathNotifications.indices.erase(findFrameIndex);
+ }
+ }
+}
+
+// Remove listener from mTrackedBuffersMap and mDeathNotifications. This implies
+// all frameIndices and bufferIndices are removed.
+//
+// This is called when the component cleans up all input buffers, i.e., when
+// reset(), release(), stop() or ~Component() is called.
+void InputBufferManager::_unregisterFrameData(
+ const wp<IComponentListener>& listener) {
+ LOG(VERBOSE) << "InputBufferManager::_unregisterFrameData -- called with "
+ << "listener @ 0x" << std::hex << listener.unsafe_get()
+ << std::dec << ".";
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ auto findListener = mTrackedBuffersMap.find(listener);
+ if (findListener != mTrackedBuffersMap.end()) {
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds =
+ findListener->second;
+ for (auto findFrameIndex = frameIndex2BufferIds.begin();
+ findFrameIndex != frameIndex2BufferIds.end();
+ ++findFrameIndex) {
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ for (TrackedBuffer* bufferId : bufferIds) {
+ std::shared_ptr<C2Buffer> buffer = bufferId->buffer.lock();
+ if (buffer) {
+ c2_status_t status = buffer->unregisterOnDestroyNotify(
+ onBufferDestroyed,
+ reinterpret_cast<void*>(bufferId));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "InputBufferManager::_unregisterFrameData "
+ << "-- unregisterOnDestroyNotify() failed "
+ << "(listener @ 0x"
+ << std::hex
+ << bufferId->listener.unsafe_get()
+ << ", frameIndex = "
+ << std::dec << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ") => status = " << status
+ << ".";
+ }
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+ }
+ }
+ }
+ mTrackedBuffersMap.erase(findListener);
+ }
+
+ mDeathNotifications.erase(listener);
+}
+
+// Set mNotificationIntervalNs.
+void InputBufferManager::_setNotificationInterval(
+ nsecs_t notificationIntervalNs) {
+ mNotificationIntervalNs.store(
+ notificationIntervalNs,
+ std::memory_order_relaxed);
+}
+
+// Move a buffer from mTrackedBuffersMap to mDeathNotifications.
+// This is called when a registered C2Buffer object is destroyed.
+void InputBufferManager::onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ getInstance()._onBufferDestroyed(buf, arg);
+}
+
+void InputBufferManager::_onBufferDestroyed(const C2Buffer* buf, void* arg) {
+ if (!buf || !arg) {
+ LOG(WARNING) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "null argument (s): "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << ".";
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ TrackedBuffer *bufferId = reinterpret_cast<TrackedBuffer*>(arg);
+
+ if (mTrackedBufferCache.find(bufferId) == mTrackedBufferCache.end()) {
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "unregistered buffer: "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << ".";
+ return;
+ }
+
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- called with "
+ << "buf @ 0x" << std::hex << buf
+ << ", arg @ 0x" << std::hex << arg
+ << std::dec << " -- "
+ << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+ << ", frameIndex = " << std::dec << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ".";
+ auto findListener = mTrackedBuffersMap.find(bufferId->listener);
+ if (findListener == mTrackedBuffersMap.end()) {
+ LOG(VERBOSE) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid listener: "
+ << "listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+ << " (frameIndex = " << std::dec << bufferId->frameIndex
+ << ", bufferIndex = " << bufferId->bufferIndex
+ << ").";
+ return;
+ }
+
+ std::map<uint64_t, std::set<TrackedBuffer*>> &frameIndex2BufferIds
+ = findListener->second;
+ auto findFrameIndex = frameIndex2BufferIds.find(bufferId->frameIndex);
+ if (findFrameIndex == frameIndex2BufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid frame index: "
+ << "frameIndex = " << bufferId->frameIndex
+ << " (listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+ << ", bufferIndex = " << std::dec << bufferId->bufferIndex
+ << ").";
+ return;
+ }
+
+ std::set<TrackedBuffer*> &bufferIds = findFrameIndex->second;
+ auto findBufferId = bufferIds.find(bufferId);
+ if (findBufferId == bufferIds.end()) {
+ LOG(DEBUG) << "InputBufferManager::_onBufferDestroyed -- "
+ << "received invalid buffer index: "
+ << "bufferIndex = " << bufferId->bufferIndex
+ << " (frameIndex = " << bufferId->frameIndex
+ << ", listener @ 0x" << std::hex << bufferId->listener.unsafe_get()
+ << std::dec << ").";
+ return;
+ }
+
+ bufferIds.erase(findBufferId);
+ if (bufferIds.empty()) {
+ frameIndex2BufferIds.erase(findFrameIndex);
+ if (frameIndex2BufferIds.empty()) {
+ mTrackedBuffersMap.erase(findListener);
+ }
+ }
+
+ DeathNotifications &deathNotifications = mDeathNotifications[bufferId->listener];
+ deathNotifications.indices[bufferId->frameIndex].emplace_back(bufferId->bufferIndex);
+ ++deathNotifications.count;
+ mOnBufferDestroyed.notify_one();
+
+ mTrackedBufferCache.erase(bufferId);
+ delete bufferId;
+}
+
+// Notify the clients about buffer destructions.
+// Return false if all destructions have been notified.
+// Return true and set timeToRetry to the time point to wait for before
+// retrying if some destructions have not been notified.
+bool InputBufferManager::processNotifications(nsecs_t* timeToRetryNs) {
+
+ struct Notification {
+ sp<IComponentListener> listener;
+ hidl_vec<IComponentListener::InputBuffer> inputBuffers;
+ Notification(const sp<IComponentListener>& l, size_t s)
+ : listener(l), inputBuffers(s) {}
+ };
+ std::list<Notification> notifications;
+ nsecs_t notificationIntervalNs =
+ mNotificationIntervalNs.load(std::memory_order_relaxed);
+
+ bool retry = false;
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ *timeToRetryNs = notificationIntervalNs;
+ nsecs_t timeNowNs = systemTime();
+ for (auto it = mDeathNotifications.begin();
+ it != mDeathNotifications.end(); ) {
+ sp<IComponentListener> listener = it->first.promote();
+ if (!listener) {
+ ++it;
+ continue;
+ }
+ DeathNotifications &deathNotifications = it->second;
+
+ nsecs_t timeSinceLastNotifiedNs =
+ timeNowNs - deathNotifications.lastSentNs;
+ // If not enough time has passed since the last callback, leave the
+ // notifications for this listener untouched for now and retry
+ // later.
+ if (timeSinceLastNotifiedNs < notificationIntervalNs) {
+ retry = true;
+ *timeToRetryNs = std::min(*timeToRetryNs,
+ notificationIntervalNs - timeSinceLastNotifiedNs);
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "Notifications for listener @ "
+ << std::hex << listener.get()
+ << " will be postponed.";
+ ++it;
+ continue;
+ }
+
+ // If enough time has passed since the last notification to this
+ // listener but there are currently no pending notifications, the
+ // listener can be removed from mDeathNotifications---there is no
+ // need to keep track of the last notification time anymore.
+ if (deathNotifications.count == 0) {
+ it = mDeathNotifications.erase(it);
+ continue;
+ }
+
+ // Create the argument for the callback.
+ notifications.emplace_back(listener, deathNotifications.count);
+ hidl_vec<IComponentListener::InputBuffer> &inputBuffers =
+ notifications.back().inputBuffers;
+ size_t i = 0;
+ for (std::pair<const uint64_t, std::vector<size_t>>& p :
+ deathNotifications.indices) {
+ uint64_t frameIndex = p.first;
+ const std::vector<size_t> &bufferIndices = p.second;
+ for (const size_t& bufferIndex : bufferIndices) {
+ IComponentListener::InputBuffer &inputBuffer
+ = inputBuffers[i++];
+ inputBuffer.arrayIndex = bufferIndex;
+ inputBuffer.frameIndex = frameIndex;
+ }
+ }
+
+ // Clear deathNotifications for this listener and set retry to true
+ // so processNotifications will be called again. This will
+ // guarantee that a listener with no pending notifications will
+ // eventually be removed from mDeathNotifications after
+ // mNotificationIntervalNs nanoseconds has passed.
+ retry = true;
+ deathNotifications.indices.clear();
+ deathNotifications.count = 0;
+ deathNotifications.lastSentNs = timeNowNs;
+ ++it;
+ }
+ }
+
+ // Call onInputBuffersReleased() outside the lock to avoid deadlock.
+ for (const Notification& notification : notifications) {
+ if (!notification.listener->onInputBuffersReleased(
+ notification.inputBuffers).isOk()) {
+ // This may trigger if the client has died.
+ LOG(DEBUG) << "InputBufferManager::processNotifications -- "
+ << "failed to send death notifications to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec << ".";
+ } else {
+#if LOG_NDEBUG == 0
+ std::stringstream inputBufferLog;
+ for (const IComponentListener::InputBuffer& inputBuffer :
+ notification.inputBuffers) {
+ inputBufferLog << " (" << inputBuffer.frameIndex
+ << ", " << inputBuffer.arrayIndex
+ << ")";
+ }
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "death notifications sent to "
+ << "listener @ 0x" << std::hex
+ << notification.listener.get()
+ << std::dec
+ << " with these (frameIndex, bufferIndex) pairs:"
+ << inputBufferLog.str();
+#endif
+ }
+ }
+#if LOG_NDEBUG == 0
+ if (retry) {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "will retry again in " << *timeToRetryNs << "ns.";
+ } else {
+ LOG(VERBOSE) << "InputBufferManager::processNotifications -- "
+ << "no pending death notifications.";
+ }
+#endif
+ return retry;
+}
+
+void InputBufferManager::main() {
+ LOG(VERBOSE) << "InputBufferManager main -- started.";
+ nsecs_t timeToRetryNs;
+ while (true) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ while (mDeathNotifications.empty()) {
+ mOnBufferDestroyed.wait(lock);
+ }
+ lock.unlock();
+ while (processNotifications(&timeToRetryNs)) {
+ std::this_thread::sleep_for(
+ std::chrono::nanoseconds(timeToRetryNs));
+ }
+ }
+}
+
+InputBufferManager::InputBufferManager()
+ : mMainThread{&InputBufferManager::main, this} {
+}
+
+InputBufferManager& InputBufferManager::getInstance() {
+ static InputBufferManager instance{};
+ return instance;
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+
+
diff --git a/media/codec2/hal/aidl/InputSurface.cpp b/media/codec2/hal/aidl/InputSurface.cpp
new file mode 100644
index 0000000..c3c32e9
--- /dev/null
+++ b/media/codec2/hal/aidl/InputSurface.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputSurface"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputSurface.h>
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+
+#include <C2Component.h>
+#include <C2Config.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+// Derived class of C2InterfaceHelper
+class InputSurface::Interface : public C2InterfaceHelper {
+public:
+ explicit Interface(
+ const std::shared_ptr<C2ReflectorHelper> &helper)
+ : C2InterfaceHelper(helper) {
+
+ setDerivedInstance(this);
+
+ addParameter(
+ DefineParam(mEos, C2_PARAMKEY_INPUT_SURFACE_EOS)
+ .withDefault(new C2InputSurfaceEosTuning(false))
+ .withFields({C2F(mEos, value).oneOf({true, false})})
+ .withSetter(EosSetter)
+ .build());
+ }
+
+ static C2R EosSetter(bool mayBlock, C2P<C2InputSurfaceEosTuning> &me) {
+ (void)mayBlock;
+ return me.F(me.v.value).validatePossible(me.v.value);
+ }
+
+ bool eos() const { return mEos->value; }
+
+private:
+ std::shared_ptr<C2InputSurfaceEosTuning> mEos;
+};
+
+// Derived class of ConfigurableC2Intf
+class InputSurface::ConfigurableIntf : public ConfigurableC2Intf {
+public:
+ ConfigurableIntf(
+ const std::shared_ptr<InputSurface::Interface> &intf,
+ const sp<GraphicBufferSource> &source)
+ : ConfigurableC2Intf("input-surface", 0),
+ mIntf(intf),
+ mSource(source) {
+ }
+
+ virtual ~ConfigurableIntf() override = default;
+
+ 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 {
+ return mIntf->query({}, indices, mayBlock, params);
+ }
+
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures
+ ) override {
+ c2_status_t err = mIntf->config(params, mayBlock, failures);
+ if (mIntf->eos()) {
+ sp<GraphicBufferSource> source = mSource.promote();
+ if (source == nullptr || source->signalEndOfInputStream() != OK) {
+ // TODO: put something in |failures|
+ err = C2_BAD_VALUE;
+ }
+ // TODO: reset eos?
+ }
+ return err;
+ }
+
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
+ ) const override {
+ return mIntf->querySupportedParams(params);
+ }
+
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields,
+ c2_blocking_t mayBlock) const override {
+ return mIntf->querySupportedValues(fields, mayBlock);
+ }
+
+private:
+ const std::shared_ptr<InputSurface::Interface> mIntf;
+ wp<GraphicBufferSource> mSource;
+};
+
+Return<sp<InputSurface::HGraphicBufferProducer>> InputSurface::getGraphicBufferProducer() {
+ return mProducer;
+}
+
+Return<sp<IConfigurable>> InputSurface::getConfigurable() {
+ return mConfigurable;
+}
+
+Return<void> InputSurface::connect(
+ const sp<IInputSink>& sink,
+ connect_cb _hidl_cb) {
+ Status status;
+ sp<InputSurfaceConnection> connection;
+ if (!sink) {
+ _hidl_cb(Status::BAD_VALUE, nullptr);
+ return Void();
+ }
+ std::shared_ptr<C2Component> comp = Component::findLocalComponent(sink);
+ if (comp) {
+ connection = new InputSurfaceConnection(mSource, comp, mParameterCache);
+ } else {
+ connection = new InputSurfaceConnection(mSource, sink, mParameterCache);
+ }
+ if (!connection->init()) {
+ connection = nullptr;
+ status = Status::BAD_VALUE;
+ } else {
+ status = Status::OK;
+ }
+ _hidl_cb(status, connection);
+ return Void();
+}
+
+// Constructor is exclusive to ComponentStore.
+InputSurface::InputSurface(
+ const std::shared_ptr<ParameterCache>& cache,
+ const std::shared_ptr<C2ReflectorHelper>& reflector,
+ const sp<HGraphicBufferProducer>& producer,
+ const sp<GraphicBufferSource>& source)
+ : mParameterCache{cache},
+ mProducer{producer},
+ mSource{source},
+ mIntf{std::make_shared<Interface>(reflector)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<ConfigurableIntf>(
+ mIntf, source))} {
+
+ mConfigurable->init(mParameterCache);
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
diff --git a/media/codec2/hal/aidl/InputSurfaceConnection.cpp b/media/codec2/hal/aidl/InputSurfaceConnection.cpp
new file mode 100644
index 0000000..7c2e014
--- /dev/null
+++ b/media/codec2/hal/aidl/InputSurfaceConnection.cpp
@@ -0,0 +1,531 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-InputSurfaceConnection"
+#include <android-base/logging.h>
+
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+#include <codec2/hidl/1.0/InputSurfaceConnection.h>
+
+#include <memory>
+#include <list>
+#include <mutex>
+#include <atomic>
+
+#include <hidl/HidlSupport.h>
+#include <media/stagefright/bqhelper/ComponentWrapper.h>
+#include <system/graphics.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Errors.h>
+
+#include <C2.h>
+#include <C2AllocatorGralloc.h>
+#include <C2BlockInternal.h>
+#include <C2Buffer.h>
+#include <C2Component.h>
+#include <C2Config.h>
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <C2Work.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+constexpr int32_t kBufferCount = 16;
+
+using namespace ::android;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+namespace /* unnamed */ {
+
+class Buffer2D : public C2Buffer {
+public:
+ explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {
+ }
+};
+
+} // unnamed namespace
+
+// Derived class of ComponentWrapper for use with
+// GraphicBufferSource::configure().
+//
+struct InputSurfaceConnection::Impl : public ComponentWrapper {
+
+ Impl(const sp<GraphicBufferSource>& source,
+ const std::shared_ptr<C2Component>& localComp)
+ : mSource{source}, mLocalComp{localComp}, mSink{}, mFrameIndex{0} {
+ std::shared_ptr<C2ComponentInterface> intf = localComp->intf();
+ mSinkName = intf ? intf->getName() : "";
+ }
+
+ Impl(const sp<GraphicBufferSource>& source,
+ const sp<IInputSink>& sink)
+ : mSource{source}, mLocalComp{}, mSink{sink}, mFrameIndex{0} {
+ Return<sp<IConfigurable>> transResult = sink->getConfigurable();
+ if (!transResult.isOk()) {
+ LOG(ERROR) << "Remote sink is dead.";
+ return;
+ }
+ mSinkConfigurable =
+ static_cast<sp<IConfigurable>>(transResult);
+ if (!mSinkConfigurable) {
+ LOG(ERROR) << "Remote sink is not configurable.";
+ mSinkName = "";
+ return;
+ }
+
+ hidl_string name;
+ Return<void> transStatus = mSinkConfigurable->getName(
+ [&name](const hidl_string& n) {
+ name = n;
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "Remote sink's configurable is dead.";
+ mSinkName = "";
+ return;
+ }
+ mSinkName = name.c_str();
+ }
+
+ virtual ~Impl() {
+ mSource->stop();
+ mSource->release();
+ }
+
+ bool init() {
+ if (mSource == nullptr) {
+ return false;
+ }
+ status_t err = mSource->initCheck();
+ if (err != OK) {
+ LOG(WARNING) << "Impl::init -- GraphicBufferSource init failed: "
+ << "status = " << err << ".";
+ return false;
+ }
+
+ // TODO: read settings properly from the interface
+ C2StreamPictureSizeInfo::input inputSize;
+ C2StreamUsageTuning::input usage;
+ c2_status_t c2Status = queryFromSink({ &inputSize, &usage },
+ {},
+ C2_MAY_BLOCK,
+ nullptr);
+ if (c2Status != C2_OK) {
+ LOG(WARNING) << "Impl::init -- cannot query information from "
+ "the component interface: "
+ << "status = " << asString(c2Status) << ".";
+ return false;
+ }
+
+ // TODO: proper color aspect & dataspace
+ android_dataspace dataSpace = HAL_DATASPACE_BT709;
+
+ // TODO: use the usage read from intf
+ // uint32_t grallocUsage =
+ // C2AndroidMemoryUsage(C2MemoryUsage(usage.value)).
+ // asGrallocUsage();
+
+ uint32_t grallocUsage =
+ mSinkName.compare(0, 11, "c2.android.") == 0 ?
+ GRALLOC_USAGE_SW_READ_OFTEN :
+ GRALLOC_USAGE_HW_VIDEO_ENCODER;
+
+ err = mSource->configure(
+ this, dataSpace, kBufferCount,
+ inputSize.width, inputSize.height,
+ grallocUsage);
+ if (err != OK) {
+ LOG(WARNING) << "Impl::init -- GBS configure failed: "
+ << "status = " << err << ".";
+ return false;
+ }
+ for (int32_t i = 0; i < kBufferCount; ++i) {
+ if (mSource->onInputBufferAdded(i) != OK) {
+ LOG(WARNING) << "Impl::init: failed to populate GBS slots.";
+ return false;
+ }
+ }
+ if (mSource->start() != OK) {
+ LOG(WARNING) << "Impl::init -- GBS failed to start.";
+ return false;
+ }
+ mAllocatorMutex.lock();
+ c2_status_t c2err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
+ C2AllocatorStore::PLATFORM_START + 1, // GRALLOC
+ &mAllocator);
+ mAllocatorMutex.unlock();
+ if (c2err != OK) {
+ LOG(WARNING) << "Impl::init -- failed to fetch gralloc allocator: "
+ << "status = " << asString(c2err) << ".";
+ return false;
+ }
+ return true;
+ }
+
+ // From ComponentWrapper
+ virtual status_t submitBuffer(
+ int32_t bufferId,
+ const sp<GraphicBuffer>& buffer,
+ int64_t timestamp,
+ int fenceFd) override {
+ LOG(VERBOSE) << "Impl::submitBuffer -- bufferId = " << bufferId << ".";
+ // TODO: Use fd to construct fence
+ (void)fenceFd;
+
+ std::shared_ptr<C2GraphicAllocation> alloc;
+ C2Handle* handle = WrapNativeCodec2GrallocHandle(
+ buffer->handle,
+ buffer->width, buffer->height,
+ buffer->format, buffer->usage, buffer->stride);
+ mAllocatorMutex.lock();
+ c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
+ mAllocatorMutex.unlock();
+ if (err != OK) {
+ native_handle_close(handle);
+ native_handle_delete(handle);
+ return UNKNOWN_ERROR;
+ }
+ std::shared_ptr<C2GraphicBlock> block =
+ _C2BlockFactory::CreateGraphicBlock(alloc);
+
+ std::unique_ptr<C2Work> work(new C2Work);
+ work->input.flags = (C2FrameData::flags_t)0;
+ work->input.ordinal.timestamp = timestamp;
+ work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
+ 1, std::memory_order_relaxed);
+ work->input.buffers.clear();
+ std::shared_ptr<C2Buffer> c2Buffer(
+ // TODO: fence
+ new Buffer2D(block->share(
+ C2Rect(block->width(), block->height()), ::C2Fence())),
+ [bufferId, source = mSource](C2Buffer* ptr) {
+ delete ptr;
+ if (source != nullptr) {
+ // TODO: fence
+ (void)source->onInputBufferEmptied(bufferId, -1);
+ }
+ });
+ work->input.buffers.push_back(c2Buffer);
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+
+ err = queueToSink(&items);
+ return (err == C2_OK) ? OK : UNKNOWN_ERROR;
+ }
+
+ virtual status_t submitEos(int32_t bufferId) override {
+ LOG(VERBOSE) << "Impl::submitEos -- bufferId = " << bufferId << ".";
+ (void)bufferId;
+
+ std::unique_ptr<C2Work> work(new C2Work);
+ work->input.flags = (C2FrameData::flags_t)0;
+ work->input.ordinal.frameIndex = mFrameIndex.fetch_add(
+ 1, std::memory_order_relaxed);
+ work->input.buffers.clear();
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+
+ c2_status_t err = queueToSink(&items);
+ return (err == C2_OK) ? OK : UNKNOWN_ERROR;
+ }
+
+ virtual void dispatchDataSpaceChanged(
+ int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override {
+ // TODO
+ (void)dataSpace;
+ (void)aspects;
+ (void)pixelFormat;
+ }
+
+ // Configurable interface for InputSurfaceConnection::Impl.
+ //
+ // This class is declared as an inner class so that it will have access to
+ // all Impl's members.
+ struct ConfigurableIntf : public ConfigurableC2Intf {
+ sp<Impl> mConnection;
+ ConfigurableIntf(const sp<Impl>& connection)
+ : ConfigurableC2Intf{"input-surface-connection", 0},
+ mConnection{connection} {}
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures
+ ) override;
+ 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;
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params
+ ) const override;
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const override;
+ };
+
+private:
+ c2_status_t queryFromSink(
+ const std::vector<C2Param*> &stackParams,
+ const std::vector<C2Param::Index> &heapParamIndices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const heapParams) {
+ if (mLocalComp) {
+ std::shared_ptr<C2ComponentInterface> intf = mLocalComp->intf();
+ if (intf) {
+ return intf->query_vb(stackParams,
+ heapParamIndices,
+ mayBlock,
+ heapParams);
+ } else {
+ LOG(ERROR) << "queryFromSink -- "
+ << "component does not have an interface.";
+ return C2_BAD_STATE;
+ }
+ }
+
+ CHECK(mSink) << "-- queryFromSink "
+ << "-- connection has no sink.";
+ CHECK(mSinkConfigurable) << "-- queryFromSink "
+ << "-- sink has no configurable.";
+
+ hidl_vec<ParamIndex> indices(
+ stackParams.size() + heapParamIndices.size());
+ size_t numIndices = 0;
+ for (C2Param* const& stackParam : stackParams) {
+ if (!stackParam) {
+ LOG(DEBUG) << "queryFromSink -- null stack param encountered.";
+ continue;
+ }
+ indices[numIndices++] = static_cast<ParamIndex>(stackParam->index());
+ }
+ size_t numStackIndices = numIndices;
+ for (const C2Param::Index& index : heapParamIndices) {
+ indices[numIndices++] =
+ static_cast<ParamIndex>(static_cast<uint32_t>(index));
+ }
+ indices.resize(numIndices);
+ if (heapParams) {
+ heapParams->reserve(heapParams->size() + numIndices);
+ }
+ c2_status_t status;
+ Return<void> transStatus = mSinkConfigurable->query(
+ indices,
+ mayBlock == C2_MAY_BLOCK,
+ [&status, &numStackIndices, &stackParams, heapParams](
+ Status s, const Params& p) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK && status != C2_BAD_INDEX) {
+ LOG(DEBUG) << "queryFromSink -- call failed: "
+ << "status = " << asString(status) << ".";
+ return;
+ }
+ std::vector<C2Param*> paramPointers;
+ if (!parseParamsBlob(¶mPointers, p)) {
+ LOG(DEBUG) << "queryFromSink -- error while "
+ << "parsing params.";
+ status = C2_CORRUPTED;
+ return;
+ }
+ size_t i = 0;
+ for (auto it = paramPointers.begin();
+ it != paramPointers.end(); ) {
+ C2Param* paramPointer = *it;
+ if (numStackIndices > 0) {
+ --numStackIndices;
+ if (!paramPointer) {
+ LOG(DEBUG) << "queryFromSink -- "
+ "null stack param.";
+ ++it;
+ continue;
+ }
+ for (; i < stackParams.size() &&
+ !stackParams[i]; ) {
+ ++i;
+ }
+ CHECK(i < stackParams.size());
+ if (stackParams[i]->index() !=
+ paramPointer->index()) {
+ LOG(DEBUG) << "queryFromSink -- "
+ "param skipped (index = "
+ << stackParams[i]->index() << ").";
+ stackParams[i++]->invalidate();
+ continue;
+ }
+ if (!stackParams[i++]->updateFrom(*paramPointer)) {
+ LOG(DEBUG) << "queryFromSink -- "
+ "param update failed (index = "
+ << paramPointer->index() << ").";
+ }
+ } else {
+ if (!paramPointer) {
+ LOG(DEBUG) << "queryFromSink -- "
+ "null heap param.";
+ ++it;
+ continue;
+ }
+ if (!heapParams) {
+ LOG(WARNING) << "queryFromSink -- "
+ "too many stack params.";
+ break;
+ }
+ heapParams->emplace_back(C2Param::Copy(*paramPointer));
+ }
+ ++it;
+ }
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "queryFromSink -- transaction failed.";
+ return C2_CORRUPTED;
+ }
+ return status;
+ }
+
+ c2_status_t queueToSink(std::list<std::unique_ptr<C2Work>>* const items) {
+ if (mLocalComp) {
+ return mLocalComp->queue_nb(items);
+ }
+
+ CHECK(mSink) << "-- queueToSink "
+ << "-- connection has no sink.";
+
+ WorkBundle workBundle;
+ if (!objcpy(&workBundle, *items, nullptr)) {
+ LOG(ERROR) << "queueToSink -- bad input.";
+ return C2_CORRUPTED;
+ }
+ Return<Status> transStatus = mSink->queue(workBundle);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "queueToSink -- transaction failed.";
+ return C2_CORRUPTED;
+ }
+ c2_status_t status =
+ static_cast<c2_status_t>(static_cast<Status>(transStatus));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "queueToSink -- call failed: "
+ << asString(status);
+ }
+ return status;
+ }
+
+ sp<GraphicBufferSource> mSource;
+ std::shared_ptr<C2Component> mLocalComp;
+ sp<IInputSink> mSink;
+ sp<IConfigurable> mSinkConfigurable;
+ std::string mSinkName;
+
+ // Needed for ComponentWrapper implementation
+ std::mutex mAllocatorMutex;
+ std::shared_ptr<C2Allocator> mAllocator;
+ std::atomic_uint64_t mFrameIndex;
+
+};
+
+InputSurfaceConnection::InputSurfaceConnection(
+ const sp<GraphicBufferSource>& source,
+ const std::shared_ptr<C2Component>& comp,
+ const std::shared_ptr<ParameterCache>& cache)
+ : mImpl{new Impl(source, comp)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+ mConfigurable->init(cache);
+}
+
+InputSurfaceConnection::InputSurfaceConnection(
+ const sp<GraphicBufferSource>& source,
+ const sp<IInputSink>& sink,
+ const std::shared_ptr<ParameterCache>& cache)
+ : mImpl{new Impl(source, sink)},
+ mConfigurable{new CachedConfigurable(
+ std::make_unique<Impl::ConfigurableIntf>(mImpl))} {
+ mConfigurable->init(cache);
+}
+
+Return<Status> InputSurfaceConnection::disconnect() {
+ std::lock_guard<std::mutex> lock(mImplMutex);
+ mImpl = nullptr;
+ return Status::OK;
+}
+
+InputSurfaceConnection::~InputSurfaceConnection() {
+ mImpl = nullptr;
+}
+
+bool InputSurfaceConnection::init() {
+ std::lock_guard<std::mutex> lock(mImplMutex);
+ return mImpl->init();
+}
+
+Return<sp<IConfigurable>> InputSurfaceConnection::getConfigurable() {
+ return mConfigurable;
+}
+
+// Configurable interface for InputSurfaceConnection::Impl
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>> *const failures) {
+ // TODO: implement
+ (void)params;
+ (void)mayBlock;
+ (void)failures;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>> *const params) const {
+ // TODO: implement
+ (void)indices;
+ (void)mayBlock;
+ (void)params;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>> *const params) const {
+ // TODO: implement
+ (void)params;
+ return C2_OK;
+}
+
+c2_status_t InputSurfaceConnection::Impl::ConfigurableIntf::querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery> &fields,
+ c2_blocking_t mayBlock) const {
+ // TODO: implement
+ (void)fields;
+ (void)mayBlock;
+ return C2_OK;
+}
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
diff --git a/media/codec2/hal/aidl/ParamTypes.cpp b/media/codec2/hal/aidl/ParamTypes.cpp
index 0a430f9..7026f4c 100644
--- a/media/codec2/hal/aidl/ParamTypes.cpp
+++ b/media/codec2/hal/aidl/ParamTypes.cpp
@@ -157,14 +157,13 @@
namespace c2 {
namespace utils {
+// TODO: read it from aconfig flags
+bool IsEnabled() { return false; }
+
const char* asString(Status status, const char* def) {
return asString(static_cast<c2_status_t>(status.status), def);
}
-namespace /* unnamed */ {
-
-} // unnamed namespace
-
// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
bool ToAidl(
FieldSupportedValuesQuery* d,
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
index f111f81..470863c 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/BufferTypes.h
@@ -14,156 +14,36 @@
* limitations under the License.
*/
-#ifndef CODEC2_HIDL_V1_0_UTILS_TYPES_H
-#define CODEC2_HIDL_V1_0_UTILS_TYPES_H
+#ifndef CODEC2_AIDL_BUFFER_TYPES_H
+#define CODEC2_AIDL_BUFFER_TYPES_H
-#include <bufferpool/ClientManager.h>
-#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
-#include <android/hardware/media/bufferpool/2.0/types.h>
-#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/c2/1.0/types.h>
-#include <android/hidl/safe_union/1.0/types.h>
+#include <codec2/common/BufferTypes.h>
-#include <C2Component.h>
-#include <C2Param.h>
-#include <C2ParamDef.h>
-#include <C2Work.h>
-#include <util/C2Debug-base.h>
+#include <aidl/android/hardware/media/bufferpool2/BufferStatusMessage.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/bufferpool2/ResultStatus.h>
+#include <aidl/android/hardware/media/c2/WorkBundle.h>
-#include <chrono>
+#include <bufferpool2/BufferPoolTypes.h>
+#include <bufferpool2/ClientManager.h>
-using namespace std::chrono_literals;
+namespace aidl {
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
namespace utils {
-using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::status_t;
-using ::android::sp;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
- ConnectionId;
+namespace bufferpool2 = ::aidl::android::hardware::media::bufferpool2;
-// Types of metadata for Blocks.
-struct C2Hidl_Range {
- uint32_t offset;
- uint32_t length; // Do not use "size" because the name collides with C2Info::size().
-};
-typedef C2GlobalParam<C2Info, C2Hidl_Range, 0> C2Hidl_RangeInfo;
+using namespace std::chrono_literals;
-struct C2Hidl_Rect {
- uint32_t left;
- uint32_t top;
- uint32_t width;
- uint32_t height;
-};
-typedef C2GlobalParam<C2Info, C2Hidl_Rect, 1> C2Hidl_RectInfo;
-
-// Make asString() and operator<< work with Status as well as c2_status_t.
-C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
-
-/**
- * All objcpy() functions will return a boolean value indicating whether the
- * conversion succeeds or not.
- */
-
-// C2SettingResult -> SettingResult
-bool objcpy(
- SettingResult* d,
- const C2SettingResult& s);
-
-// SettingResult -> std::unique_ptr<C2SettingResult>
-bool objcpy(
- std::unique_ptr<C2SettingResult>* d,
- const SettingResult& s);
-
-// C2ParamDescriptor -> ParamDescriptor
-bool objcpy(
- ParamDescriptor* d,
- const C2ParamDescriptor& s);
-
-// ParamDescriptor -> std::shared_ptr<C2ParamDescriptor>
-bool objcpy(
- std::shared_ptr<C2ParamDescriptor>* d,
- const ParamDescriptor& s);
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-bool objcpy(
- FieldSupportedValuesQuery* d,
- const C2FieldSupportedValuesQuery& s);
-
-// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& s);
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-bool objcpy(
- FieldSupportedValuesQueryResult* d,
- const C2FieldSupportedValuesQuery& s);
-
-// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult -> C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& sq,
- const FieldSupportedValuesQueryResult& sr);
-
-// C2Component::Traits -> ComponentTraits
-bool objcpy(
- IComponentStore::ComponentTraits* d,
- const C2Component::Traits& s);
-
-// ComponentTraits -> C2Component::Traits
-bool objcpy(
- C2Component::Traits* d,
- const IComponentStore::ComponentTraits& s);
-
-// C2StructDescriptor -> StructDescriptor
-bool objcpy(
- StructDescriptor* d,
- const C2StructDescriptor& s);
-
-// StructDescriptor -> C2StructDescriptor
-bool objcpy(
- std::unique_ptr<C2StructDescriptor>* d,
- const StructDescriptor& s);
-
-// Abstract class to be used in
-// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
-struct BufferPoolSender {
- typedef ::android::hardware::media::bufferpool::V2_0::
- ResultStatus ResultStatus;
- typedef ::android::hardware::media::bufferpool::V2_0::
- BufferStatusMessage BufferStatusMessage;
- typedef ::android::hardware::media::bufferpool::
- BufferPoolData BufferPoolData;
-
- /**
- * Send bpData and return BufferStatusMessage that can be supplied to
- * IClientManager::receive() in the receiving process.
- *
- * This function will be called from within the function
- * objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
- *
- * \param[in] bpData BufferPoolData identifying the buffer to send.
- * \param[out] bpMessage BufferStatusMessage of the transaction. Information
- * inside \p bpMessage should be passed to the receiving process by some
- * other means so it can call receive() properly.
- * \return ResultStatus value that determines the success of the operation.
- * (See the possible values of ResultStatus in
- * hardware/interfaces/media/bufferpool/2.0/types.hal.)
- */
- virtual ResultStatus send(
- const std::shared_ptr<BufferPoolData>& bpData,
- BufferStatusMessage* bpMessage) = 0;
-
- virtual ~BufferPoolSender() = default;
+struct BufferPoolTypes {
+ typedef bufferpool2::BufferPoolData BufferPoolData;
+ typedef bufferpool2::ResultStatus ResultStatus;
+ typedef bufferpool2::implementation::BufferPoolStatus BufferPoolStatus;
+ typedef bufferpool2::BufferStatusMessage BufferStatusMessage;
};
// Default implementation of BufferPoolSender.
@@ -173,18 +53,16 @@
// hold a strong reference to the IClientManager instance and use it to call
// IClientManager::registerSender() to establish the bufferpool connection when
// send() is called.
-struct DefaultBufferPoolSender : BufferPoolSender {
- typedef ::android::hardware::media::bufferpool::V2_0::implementation::
- ClientManager ClientManager;
- typedef ::android::hardware::media::bufferpool::V2_0::
- IClientManager IClientManager;
+struct DefaultBufferPoolSender : ::android::BufferPoolSender<BufferPoolTypes> {
+ typedef bufferpool2::implementation::ClientManager ClientManager;
+ typedef bufferpool2::IClientManager IClientManager;
// Set the IClientManager instance of the receiving process and the refresh
// interval for the connection. The default interval is 4.5 seconds, which
// is slightly shorter than the amount of time the bufferpool will keep an
// inactive connection for.
DefaultBufferPoolSender(
- const sp<IClientManager>& receiverManager = nullptr,
+ const std::shared_ptr<IClientManager>& receiverManager = nullptr,
std::chrono::steady_clock::duration refreshInterval = 4500ms);
// Set the IClientManager instance of the receiving process and the refresh
@@ -192,20 +70,20 @@
// is slightly shorter than the amount of time the bufferpool will keep an
// inactive connection for.
void setReceiver(
- const sp<IClientManager>& receiverManager,
+ const std::shared_ptr<IClientManager>& receiverManager,
std::chrono::steady_clock::duration refreshInterval = 4500ms);
// Implementation of BufferPoolSender::send(). send() will establish a
// bufferpool connection if needed, then send the bufferpool data over to
// the receiving process.
- virtual ResultStatus send(
+ BufferPoolStatus send(
const std::shared_ptr<BufferPoolData>& bpData,
BufferStatusMessage* bpMessage) override;
private:
std::mutex mMutex;
- sp<ClientManager> mSenderManager;
- sp<IClientManager> mReceiverManager;
+ std::shared_ptr<ClientManager> mSenderManager;
+ std::shared_ptr<IClientManager> mReceiverManager;
std::chrono::steady_clock::duration mRefreshInterval;
struct Connection {
@@ -227,137 +105,28 @@
// std::list<std::unique_ptr<C2Work>> -> WorkBundle
// Note: If bufferpool will be used, bpSender must not be null.
-bool objcpy(
+bool ToAidl(
WorkBundle* d,
const std::list<std::unique_ptr<C2Work>>& s,
- BufferPoolSender* bpSender = nullptr);
+ ::android::BufferPoolSender<BufferPoolTypes>* bpSender = nullptr);
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
-bool objcpy(
+bool FromAidl(
std::list<std::unique_ptr<C2Work>>* d,
const WorkBundle& s);
/**
- * Parses a params blob and returns C2Param pointers to its params. The pointers
- * point to locations inside the underlying buffer of \p blob. If \p blob is
- * destroyed, the pointers become invalid.
- *
- * \param[out] params target vector of C2Param pointers
- * \param[in] blob parameter blob to parse
- * \retval true if the full blob was parsed
- * \retval false otherwise
- */
-bool parseParamsBlob(
- std::vector<C2Param*> *params,
- const hidl_vec<uint8_t> &blob);
-
-/**
- * Concatenates a list of C2Params into a params blob.
- *
- * \param[out] blob target blob
- * \param[in] params parameters to concatenate
- * \retval true if the blob was successfully created
- * \retval false if the blob was not successful (this only happens if the
- * parameters were not const)
- */
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<C2Param*> ¶ms);
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Param>> ¶ms);
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::shared_ptr<const C2Info>> ¶ms);
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Tuning>> ¶ms);
-
-/**
- * Parses a params blob and create a vector of C2Params whose members are copies
- * of the params in the blob.
- *
- * \param[out] params the resulting vector
- * \param[in] blob parameter blob to parse
- * \retval true if the full blob was parsed and params was constructed
- * \retval false otherwise
- */
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Param>>* params,
- Params blob);
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Tuning>>* params,
- Params blob);
-
-/**
- * Parses a params blob and applies updates to params.
- *
- * \param[in,out] params params to be updated
- * \param[in] blob parameter blob containing updates
- * \retval true if the full blob was parsed and params was updated
- * \retval false otherwise
- */
-bool updateParamsFromBlob(
- const std::vector<C2Param*>& params,
- const Params& blob);
-
-/**
* Converts a BufferPool status value to c2_status_t.
* \param BufferPool status
* \return Corresponding c2_status_t
*/
-c2_status_t toC2Status(::android::hardware::media::bufferpool::V2_0::
- ResultStatus rs);
-
-// BufferQueue-Based Block Operations
-// ==================================
-
-// Call before transferring block to other processes.
-//
-// The given block is ready to transfer to other processes. This will guarantee
-// the given block data is not mutated by bufferqueue migration.
-bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block);
-
-// Call beginTransferBufferQueueBlock() on blocks in the given workList.
-// processInput determines whether input blocks are yielded. processOutput
-// works similarly on output blocks. (The default value of processInput is
-// false while the default value of processOutput is true. This implies that in
-// most cases, only output buffers contain bufferqueue-based blocks.)
-void beginTransferBufferQueueBlocks(
- const std::list<std::unique_ptr<C2Work>>& workList,
- bool processInput = false,
- bool processOutput = true);
-
-// Call after transferring block is finished and make sure that
-// beginTransferBufferQueueBlock() is called before.
-//
-// The transfer of given block is finished. If transfer is successful the given
-// block is not owned by process anymore. Since transfer is finished the given
-// block data is OK to mutate by bufferqueue migration after this call.
-bool endTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
- bool transfer);
-
-// Call endTransferBufferQueueBlock() on blocks in the given workList.
-// processInput determines whether input blocks are yielded. processOutput
-// works similarly on output blocks. (The default value of processInput is
-// false while the default value of processOutput is true. This implies that in
-// most cases, only output buffers contain bufferqueue-based blocks.)
-void endTransferBufferQueueBlocks(
- const std::list<std::unique_ptr<C2Work>>& workList,
- bool transfer,
- bool processInput = false,
- bool processOutput = true);
-
-// The given block is ready to be rendered. the given block is not owned by
-// process anymore. If migration is in progress, this returns false in order
-// not to render.
-bool displayBufferQueueBlock(const C2ConstGraphicBlock& block);
+c2_status_t toC2Status(BufferPoolTypes::BufferPoolStatus rs);
} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
} // namespace android
+} // namespace aidl
-#endif // CODEC2_HIDL_V1_0_UTILS_TYPES_H
+#endif // CODEC2_AIDL_BUFFER_TYPES_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Component.h b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
new file mode 100644
index 0000000..e343655
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Component.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
+
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.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/IInputSink.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_0 {
+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;
+
+ // 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_0::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;
+
+ using HwDeathRecipient = ::android::hardware::hidl_death_recipient;
+ sp<HwDeathRecipient> mDeathRecipient;
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENT_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
new file mode 100644
index 0000000..9102f92
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentInterface.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
+
+#include <codec2/hidl/1.0/Configurable.h>
+#include <codec2/hidl/1.0/types.h>
+
+#include <android/hardware/media/c2/1.0/IComponentInterface.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Buffer.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore;
+
+struct ComponentInterface : public IComponentInterface {
+ ComponentInterface(
+ const std::shared_ptr<C2ComponentInterface>& interface,
+ const std::shared_ptr<ParameterCache>& cache);
+ c2_status_t status() const;
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+protected:
+ std::shared_ptr<C2ComponentInterface> mInterface;
+ sp<CachedConfigurable> mConfigurable;
+ c2_status_t mInit;
+};
+
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENT_INTERFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
new file mode 100644
index 0000000..27e2a05
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+#define CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/ComponentInterface.h>
+#include <codec2/hidl/1.0/Configurable.h>
+
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/c2/1.0/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 {
+class FilterWrapper;
+
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+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;
+
+ static std::shared_ptr<FilterWrapper> GetFilterWrapper();
+
+ // 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;
+
+ /**
+ * 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_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_COMPONENTSTORE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
new file mode 100644
index 0000000..8f49a97
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/Configurable.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+#define CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+#include <C2Param.h>
+#include <C2.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct ComponentStore;
+
+/**
+ * Codec2 objects of different types may have different querying and configuring
+ * functions, but across the Treble boundary, they share the same HIDL
+ * interface, IConfigurable.
+ *
+ * ConfigurableC2Intf is an abstract class that a Codec2 object can implement to
+ * easily expose an IConfigurable instance. See CachedConfigurable below.
+ */
+struct ConfigurableC2Intf {
+ C2String getName() const { return mName; }
+ uint32_t getId() const { return mId; }
+ /** C2ComponentInterface::query_vb sans stack params */
+ virtual c2_status_t query(
+ const std::vector<C2Param::Index> &indices,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2Param>>* const params) const = 0;
+ /** C2ComponentInterface::config_vb */
+ virtual c2_status_t config(
+ const std::vector<C2Param*> ¶ms,
+ c2_blocking_t mayBlock,
+ std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedParams(
+ std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const = 0;
+ /** C2ComponentInterface::querySupportedParams_nb */
+ virtual c2_status_t querySupportedValues(
+ std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0;
+
+ virtual ~ConfigurableC2Intf() = default;
+
+ ConfigurableC2Intf(const C2String& name, uint32_t id)
+ : mName{name}, mId{id} {}
+
+protected:
+ C2String mName; /* cached component name */
+ uint32_t mId;
+};
+
+/**
+ * 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.
+ *
+ * CachedConfigurable essentially converts a ConfigurableC2Intf into HIDL's
+ * IConfigurable. A Codec2 object generally implements ConfigurableC2Intf and
+ * passes the implementation to the constructor of CachedConfigurable.
+ *
+ * Note that caching happens
+ */
+struct CachedConfigurable : public IConfigurable {
+ CachedConfigurable(std::unique_ptr<ConfigurableC2Intf>&& intf);
+
+ // Populates mSupportedParams.
+ c2_status_t init(const std::shared_ptr<ParameterCache> &cache);
+
+ // Methods from ::android::hardware::media::c2::V1_0::IConfigurable
+
+ virtual Return<uint32_t> getId() override;
+
+ virtual Return<void> getName(getName_cb _hidl_cb) override;
+
+ virtual Return<void> query(
+ const hidl_vec<uint32_t>& indices,
+ bool mayBlock,
+ query_cb _hidl_cb) override;
+
+ virtual Return<void> config(
+ const hidl_vec<uint8_t>& inParams,
+ bool mayBlock,
+ config_cb _hidl_cb) override;
+
+ virtual Return<void> querySupportedParams(
+ uint32_t start,
+ uint32_t count,
+ querySupportedParams_cb _hidl_cb) override;
+
+ virtual Return<void> querySupportedValues(
+ const hidl_vec<FieldSupportedValuesQuery>& inFields,
+ bool mayBlock,
+ querySupportedValues_cb _hidl_cb) override;
+
+protected:
+ // Common Codec2.0 interface wrapper
+ std::unique_ptr<ConfigurableC2Intf> mIntf;
+
+ // Cached supported params
+ std::vector<std::shared_ptr<C2ParamDescriptor>> mSupportedParams;
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_CONFIGURABLE_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
new file mode 100644
index 0000000..42fa557
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputBufferManager.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
+#include <android/hardware/media/c2/1.0/IComponentListener.h>
+#include <utils/Timers.h>
+
+#include <C2Buffer.h>
+#include <C2Work.h>
+
+#include <set>
+#include <map>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using namespace ::android;
+
+/**
+ * InputBufferManager
+ * ==================
+ *
+ * InputBufferManager presents a way to track and untrack input buffers in this
+ * (codec) process and send a notification to a listener, possibly in a
+ * different process, when a tracked buffer no longer has any references in this
+ * process.
+ *
+ * InputBufferManager holds a collection of records representing tracked buffers
+ * and their callback listeners. Conceptually, one record is a triple (listener,
+ * frameIndex, bufferIndex) where
+ *
+ * - (frameIndex, bufferIndex) is a pair of indices used to identify the buffer.
+ * - listener is of type IComponentListener. Its onInputBuffersReleased()
+ * function will be called after the associated buffer dies. The argument of
+ * onInputBuffersReleased() is a list of InputBuffer objects, each of which
+ * has the following members:
+ *
+ * uint64_t frameIndex
+ * uint32_t arrayIndex
+ *
+ * When a tracked buffer associated to the triple (listener, frameIndex,
+ * bufferIndex) goes out of scope, listener->onInputBuffersReleased() will be
+ * called with an InputBuffer object whose members are set as follows:
+ *
+ * inputBuffer.frameIndex = frameIndex
+ * inputBuffer.arrayIndex = bufferIndex
+ *
+ * IPC Optimization
+ * ----------------
+ *
+ * Since onInputBuffersReleased() is an IPC call, InputBufferManager tries not
+ * to call it too often. Any two calls to the same listener are at least
+ * mNotificationIntervalNs nanoseconds apart, where mNotificationIntervalNs is
+ * configurable via calling setNotificationInterval(). The default value of
+ * mNotificationIntervalNs is kDefaultNotificationInternalNs.
+ *
+ * Public Member Functions
+ * -----------------------
+ *
+ * InputBufferManager is a singleton class. Its only instance is accessible via
+ * the following public functions:
+ *
+ * - registerFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener,
+ * const C2FrameData& input)
+ *
+ * - unregisterFrameData(const sp<IComponentListener>& listener)
+ *
+ * - setNotificationInterval(nsecs_t notificationIntervalNs)
+ *
+ */
+
+struct InputBufferManager {
+
+ /**
+ * The default value for the time interval between 2 subsequent IPCs.
+ */
+ static constexpr nsecs_t kDefaultNotificationIntervalNs = 1000000; /* 1ms */
+
+ /**
+ * Track all buffers in a C2FrameData object.
+ *
+ * input (C2FrameData) has the following two members that are of interest:
+ *
+ * C2WorkOrdinal ordinal
+ * vector<shared_ptr<C2Buffer>> buffers
+ *
+ * Calling registerFrameData(listener, input) will register multiple
+ * triples (listener, frameIndex, bufferIndex) where frameIndex is equal to
+ * input.ordinal.frameIndex and bufferIndex runs through the indices of
+ * input.buffers such that input.buffers[bufferIndex] is not null.
+ *
+ * This should be called from queue().
+ *
+ * \param listener Listener of death notifications.
+ * \param input Input frame data whose input buffers are to be tracked.
+ */
+ static void registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers in a C2FrameData object.
+ *
+ * Calling unregisterFrameData(listener, input) will unregister and remove
+ * pending notifications for all triples (l, fi, bufferIndex) such that
+ * l = listener and fi = input.ordinal.frameIndex.
+ *
+ * This should be called from onWorkDone() and flush().
+ *
+ * \param listener Previously registered listener.
+ * \param input Previously registered frame data.
+ */
+ static void unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input);
+
+ /**
+ * Untrack all buffers associated to a given listener.
+ *
+ * Calling unregisterFrameData(listener) will unregister and remove
+ * pending notifications for all triples (l, frameIndex, bufferIndex) such
+ * that l = listener.
+ *
+ * This should be called when the component cleans up all input buffers,
+ * i.e., when reset(), release(), stop() or ~Component() is called.
+ *
+ * \param listener Previously registered listener.
+ */
+ static void unregisterFrameData(
+ const wp<IComponentListener>& listener);
+
+ /**
+ * Set the notification interval.
+ *
+ * \param notificationIntervalNs New notification interval, in nanoseconds.
+ */
+ static void setNotificationInterval(nsecs_t notificationIntervalNs);
+
+private:
+ void _registerFrameData(
+ const sp<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const wp<IComponentListener>& listener,
+ const C2FrameData& input);
+ void _unregisterFrameData(
+ const wp<IComponentListener>& listener);
+ void _setNotificationInterval(nsecs_t notificationIntervalNs);
+
+ // The callback function tied to C2Buffer objects.
+ //
+ // Note: This function assumes that sInstance is the only instance of this
+ // class.
+ static void onBufferDestroyed(const C2Buffer* buf, void* arg);
+ void _onBufferDestroyed(const C2Buffer* buf, void* arg);
+
+ // Persistent data to be passed as "arg" in onBufferDestroyed().
+ // This is essentially the triple (listener, frameIndex, bufferIndex) plus a
+ // weak pointer to the C2Buffer object.
+ //
+ // Note that the "key" is bufferIndex according to operator<(). This is
+ // designed to work with TrackedBuffersMap defined below.
+ struct TrackedBuffer {
+ wp<IComponentListener> listener;
+ uint64_t frameIndex;
+ size_t bufferIndex;
+ std::weak_ptr<C2Buffer> buffer;
+ TrackedBuffer(const wp<IComponentListener>& listener,
+ uint64_t frameIndex,
+ size_t bufferIndex,
+ const std::shared_ptr<C2Buffer>& buffer)
+ : listener(listener),
+ frameIndex(frameIndex),
+ bufferIndex(bufferIndex),
+ buffer(buffer) {}
+ };
+
+ // Map: listener -> frameIndex -> set<TrackedBuffer*>.
+ // Essentially, this is used to store triples (listener, frameIndex,
+ // bufferIndex) that's searchable by listener and (listener, frameIndex).
+ // However, the value of the innermost map is TrackedBuffer, which also
+ // contains an extra copy of listener and frameIndex. This is needed
+ // because onBufferDestroyed() needs to know listener and frameIndex too.
+ typedef std::map<wp<IComponentListener>,
+ std::map<uint64_t,
+ std::set<TrackedBuffer*>>> TrackedBuffersMap;
+
+ // Storage for pending (unsent) death notifications for one listener.
+ // Each pair in member named "indices" are (frameIndex, bufferIndex) from
+ // the (listener, frameIndex, bufferIndex) triple.
+ struct DeathNotifications {
+
+ // The number of pending notifications for this listener.
+ // count may be 0, in which case the DeathNotifications object will
+ // remain valid for only a small period (specified
+ // nanoseconds).
+ size_t count;
+
+ // The timestamp of the most recent callback on this listener. This is
+ // used to guarantee that callbacks do not occur too frequently, and
+ // also to trigger expiration of a DeathNotifications object that has
+ // count = 0.
+ nsecs_t lastSentNs;
+
+ // Map: frameIndex -> vector of bufferIndices
+ // This is essentially a collection of (framdeIndex, bufferIndex).
+ std::map<uint64_t, std::vector<size_t>> indices;
+
+ DeathNotifications(
+ nsecs_t notificationIntervalNs = kDefaultNotificationIntervalNs)
+ : count(0),
+ lastSentNs(systemTime() - notificationIntervalNs),
+ indices() {}
+ };
+
+ // The minimum time period between IPC calls to notify the client about the
+ // destruction of input buffers.
+ std::atomic<nsecs_t> mNotificationIntervalNs{kDefaultNotificationIntervalNs};
+
+ // Mutex for the management of all input buffers.
+ std::mutex mMutex;
+
+ // Cache for all TrackedBuffers.
+ //
+ // Whenever registerOnDestroyNotify() is called, an argument of type
+ // TrackedBuffer is created and stored into this cache.
+ // Whenever unregisterOnDestroyNotify() or onBufferDestroyed() is called,
+ // the TrackedBuffer is removed from this cache.
+ //
+ // mTrackedBuffersMap stores references to TrackedBuffers inside this cache.
+ std::set<TrackedBuffer*> mTrackedBufferCache;
+
+ // Tracked input buffers.
+ TrackedBuffersMap mTrackedBuffersMap;
+
+ // Death notifications to be sent.
+ //
+ // A DeathNotifications object is associated to each listener. An entry in
+ // this map will be removed if its associated DeathNotifications has count =
+ // 0 and lastSentNs < systemTime() - mNotificationIntervalNs.
+ std::map<wp<IComponentListener>, DeathNotifications> mDeathNotifications;
+
+ // Condition variable signaled when an entry is added to mDeathNotifications.
+ std::condition_variable mOnBufferDestroyed;
+
+ // Notify the clients about buffer destructions.
+ // Return false if all destructions have been notified.
+ // Return true and set timeToRetry to the duration to wait for before
+ // retrying if some destructions have not been notified.
+ bool processNotifications(nsecs_t* timeToRetryNs);
+
+ // Main function for the input buffer manager thread.
+ void main();
+
+ // The thread that manages notifications.
+ //
+ // Note: This variable is declared last so its initialization will happen
+ // after all other member variables have been initialized.
+ std::thread mMainThread;
+
+ // Private constructor.
+ InputBufferManager();
+
+ // The only instance of this class.
+ static InputBufferManager& getInstance();
+
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_INPUT_BUFFER_MANAGER_H
+
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
new file mode 100644
index 0000000..062dcd9
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputSurface.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
+
+#include <codec2/hidl/1.0/ComponentStore.h>
+
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
+#include <android/hardware/media/c2/1.0/IInputSink.h>
+#include <android/hardware/media/c2/1.0/IInputSurface.h>
+#include <hidl/Status.h>
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+
+#include <util/C2InterfaceHelper.h>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+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 InputSurface : public IInputSurface {
+
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer;
+
+ typedef ::android::
+ GraphicBufferSource GraphicBufferSource;
+
+ virtual Return<sp<HGraphicBufferProducer>> getGraphicBufferProducer() override;
+
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+ virtual Return<void> connect(
+ 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;
+
+ std::shared_ptr<ParameterCache> mParameterCache;
+ sp<HGraphicBufferProducer> mProducer;
+ sp<GraphicBufferSource> mSource;
+ std::shared_ptr<Interface> mIntf;
+ sp<CachedConfigurable> mConfigurable;
+
+ virtual ~InputSurface() override = default;
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACE_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h b/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
new file mode 100644
index 0000000..475ce8b
--- /dev/null
+++ b/media/codec2/hal/aidl/include/codec2/aidl/InputSurfaceConnection.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
+#define CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
+
+#include <codec2/hidl/1.0/Component.h>
+#include <codec2/hidl/1.0/Configurable.h>
+
+#include <android/hardware/media/c2/1.0/IComponent.h>
+#include <android/hardware/media/c2/1.0/IConfigurable.h>
+#include <android/hardware/media/c2/1.0/IInputSurfaceConnection.h>
+
+#include <media/stagefright/bqhelper/GraphicBufferSource.h>
+
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.h>
+
+#include <C2Component.h>
+
+#include <memory>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace c2 {
+namespace V1_0 {
+namespace utils {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::GraphicBufferSource;
+
+// An InputSurfaceConnection connects an InputSurface to a sink, which may be an
+// IInputSink or a local C2Component. This can be specified by choosing the
+// corresponding constructor. The reason for distinguishing these two cases is
+// that when an InputSurfaceConnection lives in the same process as the
+// component that processes the buffers, data parceling is not needed.
+struct InputSurfaceConnection : public IInputSurfaceConnection {
+
+ virtual Return<Status> disconnect() override;
+
+ virtual Return<sp<IConfigurable>> getConfigurable() override;
+
+protected:
+
+ InputSurfaceConnection(
+ const sp<GraphicBufferSource>& source,
+ const std::shared_ptr<C2Component>& comp,
+ const std::shared_ptr<ParameterCache>& cache);
+
+ InputSurfaceConnection(
+ const sp<GraphicBufferSource>& source,
+ const sp<IInputSink>& sink,
+ const std::shared_ptr<ParameterCache>& cache);
+
+ bool init();
+
+ friend struct InputSurface;
+
+ InputSurfaceConnection() = delete;
+ InputSurfaceConnection(const InputSurfaceConnection&) = delete;
+ void operator=(const InputSurfaceConnection&) = delete;
+
+ struct Impl;
+
+ std::mutex mImplMutex;
+ sp<Impl> mImpl;
+ sp<CachedConfigurable> mConfigurable;
+
+ virtual ~InputSurfaceConnection() override;
+};
+
+} // namespace utils
+} // namespace V1_0
+} // namespace c2
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // CODEC2_HIDL_V1_0_UTILS_INPUTSURFACECONNECTION_H
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
index ff69039..3f82ee3 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ParamTypes.h
@@ -37,11 +37,14 @@
namespace c2 {
namespace utils {
+// Returns true iff AIDL c2 HAL is enabled
+bool IsEnabled();
+
// Make asString() and operator<< work with Status as well as c2_status_t.
C2_DECLARE_AS_STRING_AND_DEFINE_STREAM_OUT(Status);
/**
- * All objcpy() functions will return a boolean value indicating whether the
+ * All To/FromAidl() functions will return a boolean value indicating whether the
* conversion succeeds or not.
*/
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 7a0525b..22aa35e 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -28,6 +28,10 @@
"output.cpp",
],
+ defaults: [
+ "libcodec2-aidl-client-defaults",
+ ],
+
header_libs: [
"libcodec2_internal", // private
],
@@ -38,6 +42,7 @@
"android.hardware.media.c2@1.0",
"android.hardware.media.c2@1.1",
"android.hardware.media.c2@1.2",
+ "android.hardware.media.bufferpool2-V1-ndk",
"android.hardware.media.c2-V1-ndk",
"libbase",
"libbinder",
@@ -52,11 +57,16 @@
"libhidlbase",
"liblog",
"libnativewindow",
+ "libstagefright_aidl_bufferpool2",
"libstagefright_bufferpool@2.0.1",
"libui",
"libutils",
],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+
export_include_dirs: [
"include",
],
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index 9a4b385..b680931 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -25,7 +25,6 @@
#include <C2Config.h> // for C2StreamUsageTuning
#include <C2PlatformSupport.h>
-#include <android/binder_auto_utils.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>
@@ -34,6 +33,8 @@
#include <android/hardware/media/c2/1.0/IConfigurable.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <aidl/android/hardware/media/bufferpool2/IClientManager.h>
+#include <aidl/android/hardware/media/c2/BnComponentListener.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValues.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValuesQuery.h>
#include <aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.h>
@@ -42,9 +43,18 @@
#include <aidl/android/hardware/media/c2/IComponentStore.h>
#include <aidl/android/hardware/media/c2/IConfigurable.h>
#include <aidl/android/hardware/media/c2/ParamDescriptor.h>
+#include <aidl/android/hardware/media/c2/StructDescriptor.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <bufferpool/ClientManager.h>
+#include <bufferpool2/ClientManager.h>
+#include <codec2/aidl/BufferTypes.h>
+#include <codec2/aidl/ParamTypes.h>
#include <codec2/hidl/1.0/types.h>
#include <codec2/hidl/1.1/types.h>
#include <codec2/hidl/1.2/types.h>
@@ -85,6 +95,7 @@
V2_0::utils::H2BGraphicBufferProducer;
using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
+namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
namespace c2_aidl = ::aidl::android::hardware::media::c2;
namespace c2_hidl_base = ::android::hardware::media::c2;
@@ -178,6 +189,20 @@
}
};
+c2_status_t GetC2Status(const ::ndk::ScopedAStatus &transStatus, const char *method) {
+ if (!transStatus.isOk()) {
+ if (transStatus.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ c2_status_t status = static_cast<c2_status_t>(transStatus.getServiceSpecificError());
+ LOG(DEBUG) << method << " -- call failed: " << status << ".";
+ return status;
+ } else {
+ LOG(ERROR) << method << " -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+ return C2_OK;
+}
+
} // unnamed namespace
// This class caches a Codec2Client object and its component traits. The client
@@ -585,33 +610,174 @@
const std::vector<C2Param::Index> &heapParamIndices,
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
- (void)stackParams, (void)heapParamIndices, (void)mayBlock, (void)heapParams;
- // TODO: implementation
- return C2_OMITTED;
+ std::vector<int> indices(
+ stackParams.size() + heapParamIndices.size());
+ size_t numIndices = 0;
+ for (C2Param* const& stackParam : stackParams) {
+ if (!stackParam) {
+ LOG(WARNING) << "query -- null stack param encountered.";
+ continue;
+ }
+ indices[numIndices++] = int(stackParam->index());
+ }
+ size_t numStackIndices = numIndices;
+ for (const C2Param::Index& index : heapParamIndices) {
+ indices[numIndices++] = int(static_cast<uint32_t>(index));
+ }
+ indices.resize(numIndices);
+ if (heapParams) {
+ heapParams->reserve(heapParams->size() + numIndices);
+ }
+ c2_aidl::Params result;
+ ndk::ScopedAStatus transStatus = mBase->query(indices, (mayBlock == C2_MAY_BLOCK), &result);
+ c2_status_t status = GetC2Status(transStatus, "query");
+ if (status != C2_OK) {
+ return status;
+ }
+
+ std::vector<C2Param*> paramPointers;
+ if (!c2_aidl::utils::ParseParamsBlob(¶mPointers, result)) {
+ LOG(ERROR) << "query -- error while parsing params.";
+ return C2_CORRUPTED;
+ }
+ size_t i = 0;
+ for (auto it = paramPointers.begin();
+ it != paramPointers.end(); ) {
+ C2Param* paramPointer = *it;
+ if (numStackIndices > 0) {
+ --numStackIndices;
+ if (!paramPointer) {
+ LOG(DEBUG) << "query -- null stack param.";
+ ++it;
+ continue;
+ }
+ for (; i < stackParams.size() && !stackParams[i]; ) {
+ ++i;
+ }
+ if (i >= stackParams.size()) {
+ LOG(ERROR) << "query -- unexpected error.";
+ status = C2_CORRUPTED;
+ break;
+ }
+ if (stackParams[i]->index() != paramPointer->index()) {
+ LOG(DEBUG) << "query -- param skipped: "
+ "index = "
+ << stackParams[i]->index() << ".";
+ stackParams[i++]->invalidate();
+ // this means that the param could not be queried.
+ // signalling C2_BAD_INDEX to the client.
+ status = C2_BAD_INDEX;
+ continue;
+ }
+ if (!stackParams[i++]->updateFrom(*paramPointer)) {
+ LOG(WARNING) << "query -- param update failed: "
+ "index = "
+ << paramPointer->index() << ".";
+ }
+ } else {
+ if (!paramPointer) {
+ LOG(DEBUG) << "query -- null heap param.";
+ ++it;
+ continue;
+ }
+ if (!heapParams) {
+ LOG(WARNING) << "query -- "
+ "unexpected extra stack param.";
+ } else {
+ heapParams->emplace_back(C2Param::Copy(*paramPointer));
+ }
+ }
+ ++it;
+ }
+ return status;
}
c2_status_t Codec2ConfigurableClient::AidlImpl::config(
const std::vector<C2Param*> ¶ms,
c2_blocking_t mayBlock,
std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
- (void)params, (void)mayBlock, (void)failures;
- // TODO: implementation
- return C2_OMITTED;
+ c2_aidl::Params aidlParams;
+ if (!c2_aidl::utils::CreateParamsBlob(&aidlParams, params)) {
+ LOG(ERROR) << "config -- bad input.";
+ return C2_TRANSACTION_FAILED;
+ }
+ c2_aidl::IConfigurable::ConfigResult result;
+ ndk::ScopedAStatus transStatus = mBase->config(aidlParams, (mayBlock == C2_MAY_BLOCK), &result);
+ c2_status_t status = GetC2Status(transStatus, "config");
+ if (status != C2_OK) {
+ return status;
+ }
+ size_t i = failures->size();
+ failures->resize(i + result.failures.size());
+ for (const c2_aidl::SettingResult& sf : result.failures) {
+ if (!c2_aidl::utils::FromAidl(&(*failures)[i++], sf)) {
+ LOG(ERROR) << "config -- invalid SettingResult returned.";
+ return C2_CORRUPTED;
+ }
+ }
+ if (!c2_aidl::utils::UpdateParamsFromBlob(params, result.params)) {
+ LOG(ERROR) << "config -- "
+ << "failed to parse returned params.";
+ status = C2_CORRUPTED;
+ }
+ return status;
}
c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedParams(
std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
- (void)params;
- // TODO: implementation
- return C2_OMITTED;
+ // TODO: Cache and query properly!
+ std::vector<c2_aidl::ParamDescriptor> result;
+ ndk::ScopedAStatus transStatus = mBase->querySupportedParams(
+ std::numeric_limits<uint32_t>::min(),
+ std::numeric_limits<uint32_t>::max(),
+ &result);
+ c2_status_t status = GetC2Status(transStatus, "querySupportedParams");
+ if (status != C2_OK) {
+ return status;
+ }
+ size_t i = params->size();
+ params->resize(i + result.size());
+ for (const c2_aidl::ParamDescriptor& sp : result) {
+ if (!c2_aidl::utils::FromAidl(&(*params)[i++], sp)) {
+ LOG(ERROR) << "querySupportedParams -- invalid returned ParamDescriptor.";
+ return C2_CORRUPTED;
+ }
+ }
+ return status;
}
c2_status_t Codec2ConfigurableClient::AidlImpl::querySupportedValues(
std::vector<C2FieldSupportedValuesQuery>& fields,
c2_blocking_t mayBlock) const {
- (void)fields, (void)mayBlock;
- // TODO: implementation
- return C2_OMITTED;
+ std::vector<c2_aidl::FieldSupportedValuesQuery> inFields(fields.size());
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!c2_aidl::utils::ToAidl(&inFields[i], fields[i])) {
+ LOG(ERROR) << "querySupportedValues -- bad input";
+ return C2_TRANSACTION_FAILED;
+ }
+ }
+
+ std::vector<c2_aidl::FieldSupportedValuesQueryResult> result;
+ ndk::ScopedAStatus transStatus = mBase->querySupportedValues(
+ inFields, (mayBlock == C2_MAY_BLOCK), &result);
+ c2_status_t status = GetC2Status(transStatus, "querySupportedValues");
+ if (status != C2_OK) {
+ return status;
+ }
+ if (result.size() != fields.size()) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "input and output lists "
+ "have different sizes.";
+ return C2_CORRUPTED;
+ }
+ for (size_t i = 0; i < fields.size(); ++i) {
+ if (!c2_aidl::utils::FromAidl(&fields[i], inFields[i], result[i])) {
+ LOG(ERROR) << "querySupportedValues -- "
+ "invalid returned value.";
+ return C2_CORRUPTED;
+ }
+ }
+ return status;
}
// Codec2ConfigurableClient
@@ -753,14 +919,119 @@
};
-// Codec2Client::Component::BufferPoolSender
-struct Codec2Client::Component::BufferPoolSender :
+// Codec2Client::Component::AidlListener
+struct Codec2Client::Component::AidlListener : public c2_aidl::BnComponentListener {
+ std::weak_ptr<Component> component;
+ std::weak_ptr<Listener> base;
+
+ virtual ::ndk::ScopedAStatus onWorkDone(const c2_aidl::WorkBundle& workBundle) override {
+ std::list<std::unique_ptr<C2Work>> workItems;
+ if (!c2_aidl::utils::FromAidl(&workItems, workBundle)) {
+ LOG(DEBUG) << "onWorkDone -- received corrupted WorkBundle.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ // release input buffers potentially held by the component from queue
+ std::shared_ptr<Codec2Client::Component> strongComponent =
+ component.lock();
+ if (strongComponent) {
+ strongComponent->handleOnWorkDone(workItems);
+ }
+ if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+ listener->onWorkDone(component, workItems);
+ } else {
+ LOG(DEBUG) << "onWorkDone -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onTripped(
+ const std::vector<c2_aidl::SettingResult>& settingResults) override {
+ std::vector<std::shared_ptr<C2SettingResult>> c2SettingResults(
+ settingResults.size());
+ for (size_t i = 0; i < settingResults.size(); ++i) {
+ std::unique_ptr<C2SettingResult> c2SettingResult;
+ if (!c2_aidl::utils::FromAidl(&c2SettingResult, settingResults[i])) {
+ LOG(DEBUG) << "onTripped -- received corrupted SettingResult.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ c2SettingResults[i] = std::move(c2SettingResult);
+ }
+ if (std::shared_ptr<Codec2Client::Listener> listener = base.lock()) {
+ listener->onTripped(component, c2SettingResults);
+ } else {
+ LOG(DEBUG) << "onTripped -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onError(const c2_aidl::Status &s, int32_t errorCode) override {
+ LOG(DEBUG) << "onError --"
+ << " status = " << s.status
+ << ", errorCode = " << errorCode
+ << ".";
+ if (std::shared_ptr<Listener> listener = base.lock()) {
+ listener->onError(component, s.status == c2_aidl::Status::OK ?
+ errorCode : static_cast<c2_status_t>(s.status));
+ } else {
+ LOG(DEBUG) << "onError -- listener died.";
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onFramesRendered(
+ const std::vector<RenderedFrame>& renderedFrames) override {
+ std::shared_ptr<Listener> listener = base.lock();
+ if (!listener) {
+ LOG(DEBUG) << "onFramesRendered -- listener died.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ for (const RenderedFrame& renderedFrame : renderedFrames) {
+ listener->onFrameRendered(
+ renderedFrame.bufferQueueId,
+ renderedFrame.slotId,
+ renderedFrame.timestampNs);
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ virtual ::ndk::ScopedAStatus onInputBuffersReleased(
+ const std::vector<InputBuffer>& inputBuffers) override {
+ std::shared_ptr<Listener> listener = base.lock();
+ if (!listener) {
+ LOG(DEBUG) << "onInputBuffersReleased -- listener died.";
+ return ::ndk::ScopedAStatus::ok();
+ }
+ for (const InputBuffer& inputBuffer : inputBuffers) {
+ LOG(VERBOSE) << "onInputBuffersReleased --"
+ " received death notification of"
+ " input buffer:"
+ " frameIndex = " << inputBuffer.frameIndex
+ << ", bufferIndex = " << inputBuffer.arrayIndex
+ << ".";
+ listener->onInputBufferDone(
+ inputBuffer.frameIndex, inputBuffer.arrayIndex);
+ }
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+};
+
+// Codec2Client::Component::HidlBufferPoolSender
+struct Codec2Client::Component::HidlBufferPoolSender :
hardware::media::c2::V1_1::utils::DefaultBufferPoolSender {
- BufferPoolSender()
+ HidlBufferPoolSender()
: hardware::media::c2::V1_1::utils::DefaultBufferPoolSender() {
}
};
+// Codec2Client::Component::AidlBufferPoolSender
+struct Codec2Client::Component::AidlBufferPoolSender :
+ c2_aidl::utils::DefaultBufferPoolSender {
+ AidlBufferPoolSender()
+ : c2_aidl::utils::DefaultBufferPoolSender() {
+ }
+};
+
// Codec2Client::Component::OutputBufferQueue
struct Codec2Client::Component::OutputBufferQueue :
hardware::media::c2::OutputBufferQueue {
@@ -770,36 +1041,53 @@
};
// Codec2Client
-Codec2Client::Codec2Client(sp<Base> const& base,
+Codec2Client::Codec2Client(sp<HidlBase> const& base,
sp<c2_hidl::IConfigurable> const& configurable,
size_t serviceIndex)
: Configurable{configurable},
- mBase1_0{base},
- mBase1_1{Base1_1::castFrom(base)},
- mBase1_2{Base1_2::castFrom(base)},
+ mHidlBase1_0{base},
+ mHidlBase1_1{HidlBase1_1::castFrom(base)},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
mServiceIndex{serviceIndex} {
Return<sp<bufferpool_hidl::IClientManager>> transResult = base->getPoolClientManager();
if (!transResult.isOk()) {
LOG(ERROR) << "getPoolClientManager -- transaction failed.";
} else {
- mHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
+ mHidlHostPoolManager = static_cast<sp<bufferpool_hidl::IClientManager>>(transResult);
}
}
-sp<Codec2Client::Base> const& Codec2Client::getBase() const {
- return mBase1_0;
+Codec2Client::Codec2Client(std::shared_ptr<AidlBase> const& base,
+ std::shared_ptr<c2_aidl::IConfigurable> const& configurable,
+ size_t serviceIndex)
+ : Configurable{configurable},
+ mAidlBase{base},
+ mServiceIndex{serviceIndex} {
+ ::ndk::ScopedAStatus transStatus = base->getPoolClientManager(&mAidlHostPoolManager);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "getPoolClientManager -- transaction failed.";
+ mAidlHostPoolManager.reset();
+ }
}
-sp<Codec2Client::Base1_0> const& Codec2Client::getBase1_0() const {
- return mBase1_0;
+sp<Codec2Client::HidlBase> const& Codec2Client::getHidlBase() const {
+ return mHidlBase1_0;
}
-sp<Codec2Client::Base1_1> const& Codec2Client::getBase1_1() const {
- return mBase1_1;
+sp<Codec2Client::HidlBase1_0> const& Codec2Client::getHidlBase1_0() const {
+ return mHidlBase1_0;
}
-sp<Codec2Client::Base1_2> const& Codec2Client::getBase1_2() const {
- return mBase1_2;
+sp<Codec2Client::HidlBase1_1> const& Codec2Client::getHidlBase1_1() const {
+ return mHidlBase1_1;
+}
+
+sp<Codec2Client::HidlBase1_2> const& Codec2Client::getHidlBase1_2() const {
+ return mHidlBase1_2;
+}
+
+::ndk::SpAIBinder Codec2Client::getAidlBase() const {
+ return mAidlBase ? mAidlBase->asBinder() : nullptr;
}
std::string const& Codec2Client::getServiceName() const {
@@ -810,13 +1098,41 @@
const C2String& name,
const std::shared_ptr<Codec2Client::Listener>& listener,
std::shared_ptr<Codec2Client::Component>* const component) {
+ if (mAidlBase) {
+ std::shared_ptr<Component::AidlListener> aidlListener =
+ Component::AidlListener::make<Component::AidlListener>();
+ aidlListener->base = listener;
+ std::shared_ptr<c2_aidl::IComponent> aidlComponent;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createComponent(
+ name,
+ aidlListener,
+ bufferpool2_aidl::implementation::ClientManager::getInstance(),
+ &aidlComponent);
+ c2_status_t status = GetC2Status(transStatus, "createComponent");
+ if (status != C2_OK) {
+ return status;
+ } else if (!aidlComponent) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- null component.";
+ return C2_CORRUPTED;
+ }
+ *component = std::make_shared<Codec2Client::Component>(aidlComponent);
+ status = (*component)->setDeathListener((*component), listener);
+ if (status != C2_OK) {
+ LOG(ERROR) << "createComponent(" << name.c_str()
+ << ") -- failed to set up death listener: "
+ << status << ".";
+ }
+ (*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
+ return status;
+ }
c2_status_t status;
sp<Component::HidlListener> hidlListener = new Component::HidlListener{};
hidlListener->base = listener;
Return<void> transStatus;
- if (mBase1_2) {
- transStatus = mBase1_2->createComponent_1_2(
+ if (mHidlBase1_2) {
+ transStatus = mHidlBase1_2->createComponent_1_2(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -831,8 +1147,8 @@
hidlListener->component = *component;
});
}
- else if (mBase1_1) {
- transStatus = mBase1_1->createComponent_1_1(
+ else if (mHidlBase1_1) {
+ transStatus = mHidlBase1_1->createComponent_1_1(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -846,8 +1162,8 @@
*component = std::make_shared<Codec2Client::Component>(c);
hidlListener->component = *component;
});
- } else if (mBase1_0) { // ver1_0
- transStatus = mBase1_0->createComponent(
+ } else if (mHidlBase1_0) { // ver1_0
+ transStatus = mHidlBase1_0->createComponent(
name,
hidlListener,
bufferpool_hidl::implementation::ClientManager::getInstance(),
@@ -890,15 +1206,32 @@
<< status << ".";
}
- (*component)->mBufferPoolSender->setReceiver(mHostPoolManager);
+ (*component)->mHidlBufferPoolSender->setReceiver(mHidlHostPoolManager);
return status;
}
c2_status_t Codec2Client::createInterface(
const C2String& name,
std::shared_ptr<Codec2Client::Interface>* const interface) {
+ if (mAidlBase) {
+ std::shared_ptr<c2_aidl::IComponentInterface> aidlInterface;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createInterface(
+ name,
+ &aidlInterface);
+ c2_status_t status = GetC2Status(transStatus, "createInterface");
+ if (status != C2_OK) {
+ return status;
+ } else if (!aidlInterface) {
+ LOG(ERROR) << "createInterface(" << name.c_str()
+ << ") -- null interface.";
+ return C2_CORRUPTED;
+ }
+ interface->reset(new Codec2Client::Interface(aidlInterface));
+ return C2_OK;
+ }
+
c2_status_t status;
- Return<void> transStatus = mBase1_0->createInterface(
+ Return<void> transStatus = mHidlBase1_0->createInterface(
name,
[&status, interface](
c2_hidl::Status s,
@@ -929,8 +1262,13 @@
c2_status_t Codec2Client::createInputSurface(
std::shared_ptr<InputSurface>* const inputSurface) {
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
+
c2_status_t status;
- Return<void> transStatus = mBase1_0->createInputSurface(
+ Return<void> transStatus = mHidlBase1_0->createInputSurface(
[&status, inputSurface](
c2_hidl::Status s,
const sp<c2_hidl::IInputSurface>& i) {
@@ -958,7 +1296,29 @@
bool* success) const {
std::vector<C2Component::Traits> traits;
std::string const& serviceName = getServiceName();
- Return<void> transStatus = mBase1_0->listComponents(
+
+ if (mAidlBase) {
+ std::vector<c2_aidl::IComponentStore::ComponentTraits> aidlTraits;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->listComponents(&aidlTraits);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "_listComponents -- transaction failed.";
+ *success = false;
+ } else {
+ traits.resize(aidlTraits.size());
+ *success = true;
+ for (size_t i = 0; i < aidlTraits.size(); ++i) {
+ if (!c2_aidl::utils::FromAidl(&traits[i], aidlTraits[i])) {
+ LOG(ERROR) << "_listComponents -- corrupted output.";
+ *success = false;
+ traits.clear();
+ break;
+ }
+ traits[i].owner = serviceName;
+ }
+ }
+ return traits;
+ }
+ Return<void> transStatus = mHidlBase1_0->listComponents(
[&traits, &serviceName](c2_hidl::Status s,
const hidl_vec<c2_hidl::IComponentStore::ComponentTraits>& t) {
if (s != c2_hidl::Status::OK) {
@@ -994,12 +1354,12 @@
return C2_OMITTED;
}
-std::shared_ptr<C2ParamReflector>
- Codec2Client::getParamReflector() {
+std::shared_ptr<C2ParamReflector> Codec2Client::getParamReflector() {
// TODO: this is not meant to be exposed as C2ParamReflector on the client side; instead, it
// should reflect the HAL API.
- struct SimpleParamReflector : public C2ParamReflector {
- virtual std::unique_ptr<C2StructDescriptor> describe(C2Param::CoreIndex coreIndex) const {
+ struct HidlSimpleParamReflector : public C2ParamReflector {
+ std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const override {
hidl_vec<c2_hidl::ParamIndex> indices(1);
indices[0] = static_cast<c2_hidl::ParamIndex>(coreIndex.coreIndex());
std::unique_ptr<C2StructDescriptor> descriptor;
@@ -1041,80 +1401,112 @@
return descriptor;
}
- SimpleParamReflector(sp<Base> base)
+ HidlSimpleParamReflector(sp<HidlBase> base)
: mBase(base) { }
- sp<Base> mBase;
+ sp<HidlBase> mBase;
+ };
+ struct AidlSimpleParamReflector : public C2ParamReflector {
+ std::unique_ptr<C2StructDescriptor> describe(
+ C2Param::CoreIndex coreIndex) const override {
+ std::vector<c2_aidl::StructDescriptor> aidlDesc;
+ std::unique_ptr<C2StructDescriptor> descriptor;
+ ::ndk::ScopedAStatus transStatus = mBase->getStructDescriptors(
+ {int32_t(coreIndex.coreIndex())},
+ &aidlDesc);
+ c2_status_t status = GetC2Status(transStatus, "describe");
+ if (status != C2_OK) {
+ descriptor.reset();
+ } else if (!c2_aidl::utils::FromAidl(&descriptor, aidlDesc[0])) {
+ LOG(ERROR) << "describe -- conversion failed.";
+ descriptor.reset();
+ }
+ return descriptor;
+ }
+
+ AidlSimpleParamReflector(const std::shared_ptr<AidlBase> &base)
+ : mBase(base) { }
+
+ std::shared_ptr<AidlBase> mBase;
};
- return std::make_shared<SimpleParamReflector>(mBase1_0);
+ if (mAidlBase) {
+ return std::make_shared<AidlSimpleParamReflector>(mAidlBase);
+ }
+ return std::make_shared<HidlSimpleParamReflector>(mHidlBase1_0);
};
-std::vector<std::string> const& Codec2Client::GetServiceNames() {
- static std::vector<std::string> sServiceNames{[]() {
- using ::android::hardware::media::c2::V1_0::IComponentStore;
- using ::android::hidl::manager::V1_2::IServiceManager;
+std::vector<std::string> Codec2Client::CacheServiceNames() {
+ std::vector<std::string> names;
- while (true) {
- sp<IServiceManager> serviceManager = IServiceManager::getService();
- CHECK(serviceManager) << "Hardware service manager is not running.";
+ if (c2_aidl::utils::IsEnabled()) {
+ // Get AIDL service names
+ AServiceManager_forEachDeclaredInstance(
+ AidlBase::descriptor, &names, [](const char *name, void *context) {
+ std::vector<std::string> *names = (std::vector<std::string> *)context;
+ names->emplace_back(name);
+ });
+ }
- // There are three categories of services based on names.
- std::vector<std::string> defaultNames; // Prefixed with "default"
- std::vector<std::string> vendorNames; // Prefixed with "vendor"
- std::vector<std::string> otherNames; // Others
- Return<void> transResult;
- transResult = serviceManager->listManifestByInterface(
- IComponentStore::descriptor,
- [&defaultNames, &vendorNames, &otherNames](
- hidl_vec<hidl_string> const& instanceNames) {
- for (hidl_string const& instanceName : instanceNames) {
- char const* name = instanceName.c_str();
- if (strncmp(name, "default", 7) == 0) {
- defaultNames.emplace_back(name);
- } else if (strncmp(name, "vendor", 6) == 0) {
- vendorNames.emplace_back(name);
- } else {
- otherNames.emplace_back(name);
- }
- }
- });
- if (transResult.isOk()) {
- // Sort service names in each category.
- std::sort(defaultNames.begin(), defaultNames.end());
- std::sort(vendorNames.begin(), vendorNames.end());
- std::sort(otherNames.begin(), otherNames.end());
+ // Get HIDL service names
+ using ::android::hardware::media::c2::V1_0::IComponentStore;
+ using ::android::hidl::manager::V1_2::IServiceManager;
+ while (true) {
+ sp<IServiceManager> serviceManager = IServiceManager::getService();
+ CHECK(serviceManager) << "Hardware service manager is not running.";
- // Concatenate the three lists in this order: default, vendor,
- // other.
- std::vector<std::string>& names = defaultNames;
- names.reserve(names.size() + vendorNames.size() + otherNames.size());
- names.insert(names.end(),
- std::make_move_iterator(vendorNames.begin()),
- std::make_move_iterator(vendorNames.end()));
- names.insert(names.end(),
- std::make_move_iterator(otherNames.begin()),
- std::make_move_iterator(otherNames.end()));
-
- // Summarize to logcat.
- if (names.empty()) {
- LOG(INFO) << "No Codec2 services declared in the manifest.";
- } else {
- std::stringstream stringOutput;
- stringOutput << "Available Codec2 services:";
- for (std::string const& name : names) {
- stringOutput << " \"" << name << "\"";
- }
- LOG(INFO) << stringOutput.str();
- }
-
- return names;
- }
- LOG(ERROR) << "Could not retrieve the list of service instances of "
- << IComponentStore::descriptor
- << ". Retrying...";
+ Return<void> transResult;
+ transResult = serviceManager->listManifestByInterface(
+ IComponentStore::descriptor,
+ [&names](
+ hidl_vec<hidl_string> const& instanceNames) {
+ names.insert(names.end(), instanceNames.begin(), instanceNames.end());
+ });
+ if (transResult.isOk()) {
+ break;
}
- }()};
+ LOG(ERROR) << "Could not retrieve the list of service instances of "
+ << IComponentStore::descriptor
+ << ". Retrying...";
+ }
+ // Sort service names in each category.
+ std::stable_sort(
+ names.begin(), names.end(),
+ [](const std::string &a, const std::string &b) {
+ // First compare by prefix: default -> vendor -> {everything else}
+ constexpr int DEFAULT = 1;
+ constexpr int VENDOR = 2;
+ constexpr int OTHER = 3;
+ int aPrefix = ((a.compare(0, 7, "default") == 0) ? DEFAULT :
+ (a.compare(0, 6, "vendor") == 0) ? VENDOR :
+ OTHER);
+ int bPrefix = ((b.compare(0, 7, "default") == 0) ? DEFAULT :
+ (b.compare(0, 6, "vendor") == 0) ? VENDOR :
+ OTHER);
+ if (aPrefix != bPrefix) {
+ return aPrefix < bPrefix;
+ }
+ // If the prefix is the same, compare alphabetically
+ return a < b;
+ });
+
+ // Summarize to logcat.
+ if (names.empty()) {
+ LOG(INFO) << "No Codec2 services declared in the manifest.";
+ } else {
+ std::stringstream stringOutput;
+ stringOutput << "Available Codec2 services:";
+ for (std::string const& name : names) {
+ stringOutput << " \"" << name << "\"";
+ }
+ LOG(INFO) << stringOutput.str();
+ }
+
+ return names;
+}
+
+std::vector<std::string> const& Codec2Client::GetServiceNames() {
+ static std::vector<std::string> sServiceNames = CacheServiceNames();
return sServiceNames;
}
@@ -1153,14 +1545,34 @@
std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
std::string const& name = GetServiceNames()[index];
LOG(VERBOSE) << "Creating a Codec2 client to service \"" << name << "\"";
- sp<Base> baseStore = Base::getService(name);
+
+ if (c2_aidl::utils::IsEnabled()) {
+ std::string instanceName =
+ ::android::base::StringPrintf("%s/%s", AidlBase::descriptor, name.c_str());
+ if (AServiceManager_isDeclared(instanceName.c_str())) {
+ std::shared_ptr<AidlBase> baseStore = AidlBase::fromBinder(
+ ::ndk::SpAIBinder(AServiceManager_waitForService(instanceName.c_str())));
+ CHECK(baseStore) << "Codec2 AIDL service \"" << name << "\""
+ " inaccessible for unknown reasons.";
+ LOG(VERBOSE) << "Client to Codec2 AIDL service \"" << name << "\" created";
+ std::shared_ptr<c2_aidl::IConfigurable> configurable;
+ ::ndk::ScopedAStatus transStatus = baseStore->getConfigurable(&configurable);
+ CHECK(transStatus.isOk()) << "Codec2 AIDL service \"" << name << "\""
+ "does not have IConfigurable.";
+ return std::make_shared<Codec2Client>(baseStore, configurable, index);
+ }
+ }
+
+ std::string instanceName = "android.hardware.media.c2/" + name;
+ sp<HidlBase> baseStore = HidlBase::getService(name);
CHECK(baseStore) << "Codec2 service \"" << name << "\""
" inaccessible for unknown reasons.";
LOG(VERBOSE) << "Client to Codec2 service \"" << name << "\" created";
- Return<sp<IConfigurable>> transResult = baseStore->getConfigurable();
+ Return<sp<c2_hidl::IConfigurable>> transResult = baseStore->getConfigurable();
CHECK(transResult.isOk()) << "Codec2 service \"" << name << "\""
"does not have IConfigurable.";
- sp<IConfigurable> configurable = static_cast<sp<IConfigurable>>(transResult);
+ sp<c2_hidl::IConfigurable> configurable =
+ static_cast<sp<c2_hidl::IConfigurable>>(transResult);
return std::make_shared<Codec2Client>(baseStore, configurable, index);
}
@@ -1262,8 +1674,7 @@
return status;
}
-std::shared_ptr<Codec2Client::Interface>
- Codec2Client::CreateInterfaceByName(
+std::shared_ptr<Codec2Client::Interface> Codec2Client::CreateInterfaceByName(
const char* interfaceName,
std::shared_ptr<Codec2Client>* owner,
size_t numberOfAttempts) {
@@ -1349,13 +1760,8 @@
return nullptr;
}
-// Codec2Client::Listener
-
-Codec2Client::Listener::~Listener() {
-}
-
// Codec2Client::Interface
-Codec2Client::Interface::Interface(const sp<Base>& base)
+Codec2Client::Interface::Interface(const sp<HidlBase>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IConfigurable>> transResult =
@@ -1365,11 +1771,91 @@
nullptr;
}()
},
- mBase{base} {
+ mHidlBase{base} {
+}
+
+Codec2Client::Interface::Interface(const std::shared_ptr<AidlBase>& base)
+ : Configurable{
+ [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+ std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+ ::ndk::ScopedAStatus transStatus =
+ base->getConfigurable(&aidlConfigurable);
+ return transStatus.isOk() ? aidlConfigurable : nullptr;
+ }()
+ },
+ mAidlBase{base} {
}
// Codec2Client::Component
-Codec2Client::Component::Component(const sp<Base>& base)
+
+class Codec2Client::Component::AidlDeathManager {
+public:
+ AidlDeathManager()
+ : mSeq(0),
+ mDeathRecipient(AIBinder_DeathRecipient_new(OnBinderDied)) {
+ }
+
+ ~AidlDeathManager() = default;
+
+ bool linkToDeath(
+ const std::shared_ptr<Component> &comp,
+ const std::shared_ptr<Listener> &listener,
+ size_t *seqPtr) {
+ std::unique_lock lock(mMutex);
+ size_t seq = mSeq++;
+ if (!mMap.try_emplace(seq, comp, listener).second) {
+ return false;
+ }
+ if (STATUS_OK != AIBinder_linkToDeath(
+ comp->mAidlBase->asBinder().get(), mDeathRecipient.get(), (void *)seq)) {
+ mMap.erase(seq);
+ return false;
+ }
+ *seqPtr = seq;
+ return true;
+ }
+
+ void unlinkToDeath(size_t seq, const std::shared_ptr<AidlBase> &base) {
+ std::unique_lock lock(mMutex);
+ AIBinder_unlinkToDeath(base->asBinder().get(), mDeathRecipient.get(), (void *)seq);
+ mMap.erase(seq);
+ }
+
+private:
+ std::mutex mMutex;
+ size_t mSeq;
+ typedef std::tuple<std::weak_ptr<Component>, std::weak_ptr<Listener>> Context;
+ std::map<size_t, Context> mMap;
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+ bool extractContext(size_t seq, Context *context) {
+ std::unique_lock lock(mMutex);
+ auto node = mMap.extract(seq);
+ if (!node) {
+ return false;
+ }
+ *context = node.mapped();
+ return true;
+ }
+
+ static void OnBinderDied(void *cookie) {
+ size_t seq = size_t(cookie);
+ Context context;
+ if (!Component::GetAidlDeathManager()->extractContext(seq, &context)) {
+ return;
+ }
+ std::weak_ptr<Component> weakComponent;
+ std::weak_ptr<Listener> weakListener;
+ std::tie(weakComponent, weakListener) = context;
+ if (std::shared_ptr<Listener> listener = weakListener.lock()) {
+ listener->onDeath(weakComponent);
+ } else {
+ LOG(DEBUG) << "onDeath -- listener died.";
+ }
+ }
+};
+
+Codec2Client::Component::Component(const sp<HidlBase>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1385,14 +1871,14 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{Base1_1::castFrom(base)},
- mBase1_2{Base1_2::castFrom(base)},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{HidlBase1_1::castFrom(base)},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
-Codec2Client::Component::Component(const sp<Base1_1>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_1>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1408,14 +1894,14 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{base},
- mBase1_2{Base1_2::castFrom(base)},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{base},
+ mHidlBase1_2{HidlBase1_2::castFrom(base)},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
-Codec2Client::Component::Component(const sp<Base1_2>& base)
+Codec2Client::Component::Component(const sp<HidlBase1_2>& base)
: Configurable{
[base]() -> sp<c2_hidl::IConfigurable> {
Return<sp<c2_hidl::IComponentInterface>> transResult1 =
@@ -1431,22 +1917,54 @@
nullptr;
}()
},
- mBase1_0{base},
- mBase1_1{base},
- mBase1_2{base},
- mBufferPoolSender{std::make_unique<BufferPoolSender>()},
+ mHidlBase1_0{base},
+ mHidlBase1_1{base},
+ mHidlBase1_2{base},
+ mHidlBufferPoolSender{std::make_unique<HidlBufferPoolSender>()},
+ mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+}
+
+Codec2Client::Component::Component(const std::shared_ptr<AidlBase> &base)
+ : Configurable{
+ [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
+ std::shared_ptr<c2_aidl::IComponentInterface> aidlIntf;
+ ::ndk::ScopedAStatus transStatus = base->getInterface(&aidlIntf);
+ if (!transStatus.isOk()) {
+ return nullptr;
+ }
+ std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
+ transStatus = aidlIntf->getConfigurable(&aidlConfigurable);
+ return transStatus.isOk() ? aidlConfigurable : nullptr;
+ }()
+ },
+ mAidlBase{base},
+ mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
}
Codec2Client::Component::~Component() {
+ if (mAidlDeathSeq) {
+ GetAidlDeathManager()->unlinkToDeath(*mAidlDeathSeq, mAidlBase);
+ }
}
c2_status_t Codec2Client::Component::createBlockPool(
C2Allocator::id_t id,
C2BlockPool::local_id_t* blockPoolId,
std::shared_ptr<Codec2Client::Configurable>* configurable) {
+ if (mAidlBase) {
+ c2_aidl::IComponent::BlockPool aidlBlockPool;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(id, &aidlBlockPool);
+ c2_status_t status = GetC2Status(transStatus, "createBlockPool");
+ if (status != C2_OK) {
+ return status;
+ }
+ *blockPoolId = aidlBlockPool.blockPoolId;
+ *configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
+ return C2_OK;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->createBlockPool(
+ Return<void> transStatus = mHidlBase1_0->createBlockPool(
static_cast<uint32_t>(id),
[&status, blockPoolId, configurable](
c2_hidl::Status s,
@@ -1471,7 +1989,11 @@
c2_status_t Codec2Client::Component::destroyBlockPool(
C2BlockPool::local_id_t localId) {
- Return<c2_hidl::Status> transResult = mBase1_0->destroyBlockPool(
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
+ return GetC2Status(transStatus, "destroyBlockPool");
+ }
+ Return<c2_hidl::Status> transResult = mHidlBase1_0->destroyBlockPool(
static_cast<uint64_t>(localId));
if (!transResult.isOk()) {
LOG(ERROR) << "destroyBlockPool -- transaction failed.";
@@ -1488,12 +2010,21 @@
c2_status_t Codec2Client::Component::queue(
std::list<std::unique_ptr<C2Work>>* const items) {
+ if (mAidlBase) {
+ c2_aidl::WorkBundle workBundle;
+ if (!c2_aidl::utils::ToAidl(&workBundle, *items, mAidlBufferPoolSender.get())) {
+ LOG(ERROR) << "queue -- bad input.";
+ return C2_TRANSACTION_FAILED;
+ }
+ ::ndk::ScopedAStatus transStatus = mAidlBase->queue(workBundle);
+ return GetC2Status(transStatus, "queue");
+ }
c2_hidl::WorkBundle workBundle;
- if (!objcpy(&workBundle, *items, mBufferPoolSender.get())) {
+ if (!c2_hidl::utils::objcpy(&workBundle, *items, mHidlBufferPoolSender.get())) {
LOG(ERROR) << "queue -- bad input.";
return C2_TRANSACTION_FAILED;
}
- Return<c2_hidl::Status> transStatus = mBase1_0->queue(workBundle);
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->queue(workBundle);
if (!transStatus.isOk()) {
LOG(ERROR) << "queue -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1509,25 +2040,38 @@
c2_status_t Codec2Client::Component::flush(
C2Component::flush_mode_t mode,
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 = mBase1_0->flush(
- [&status, flushedWork](
- c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
- status = static_cast<c2_status_t>(s);
- if (status != C2_OK) {
- LOG(DEBUG) << "flush -- call failed: " << status << ".";
- return;
- }
- if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
- status = C2_CORRUPTED;
- } else {
- status = C2_OK;
- }
- });
- if (!transStatus.isOk()) {
- LOG(ERROR) << "flush -- transaction failed.";
- return C2_TRANSACTION_FAILED;
+ (void)mode; // Flush mode isn't supported in HIDL/AIDL yet.
+ c2_status_t status = C2_OK;
+ if (mAidlBase) {
+ c2_aidl::WorkBundle workBundle;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->flush(&workBundle);
+ c2_status_t status = GetC2Status(transStatus, "flush");
+ if (status != C2_OK) {
+ return status;
+ }
+ if (!c2_aidl::utils::FromAidl(flushedWork, workBundle)) {
+ LOG(DEBUG) << "flush -- flushedWork corrupted.";
+ return C2_CORRUPTED;
+ }
+ } else {
+ Return<void> transStatus = mHidlBase1_0->flush(
+ [&status, flushedWork](
+ c2_hidl::Status s, const c2_hidl::WorkBundle& wb) {
+ status = static_cast<c2_status_t>(s);
+ if (status != C2_OK) {
+ LOG(DEBUG) << "flush -- call failed: " << status << ".";
+ return;
+ }
+ if (!c2_hidl::utils::objcpy(flushedWork, wb)) {
+ status = C2_CORRUPTED;
+ } else {
+ status = C2_OK;
+ }
+ });
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "flush -- transaction failed.";
+ return C2_TRANSACTION_FAILED;
+ }
}
// Indices of flushed work items.
@@ -1552,7 +2096,12 @@
}
c2_status_t Codec2Client::Component::drain(C2Component::drain_mode_t mode) {
- Return<c2_hidl::Status> transStatus = mBase1_0->drain(
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->drain(
+ mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
+ return GetC2Status(transStatus, "drain");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->drain(
mode == C2Component::DRAIN_COMPONENT_WITH_EOS);
if (!transStatus.isOk()) {
LOG(ERROR) << "drain -- transaction failed.";
@@ -1567,7 +2116,11 @@
}
c2_status_t Codec2Client::Component::start() {
- Return<c2_hidl::Status> transStatus = mBase1_0->start();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->start();
+ return GetC2Status(transStatus, "start");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->start();
if (!transStatus.isOk()) {
LOG(ERROR) << "start -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1581,7 +2134,11 @@
}
c2_status_t Codec2Client::Component::stop() {
- Return<c2_hidl::Status> transStatus = mBase1_0->stop();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->stop();
+ return GetC2Status(transStatus, "stop");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->stop();
if (!transStatus.isOk()) {
LOG(ERROR) << "stop -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1595,7 +2152,11 @@
}
c2_status_t Codec2Client::Component::reset() {
- Return<c2_hidl::Status> transStatus = mBase1_0->reset();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->reset();
+ return GetC2Status(transStatus, "reset");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->reset();
if (!transStatus.isOk()) {
LOG(ERROR) << "reset -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1609,7 +2170,11 @@
}
c2_status_t Codec2Client::Component::release() {
- Return<c2_hidl::Status> transStatus = mBase1_0->release();
+ if (mAidlBase) {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->release();
+ return GetC2Status(transStatus, "release");
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->release();
if (!transStatus.isOk()) {
LOG(ERROR) << "release -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1626,11 +2191,25 @@
uint32_t avSyncHwId,
native_handle_t** sidebandHandle) {
*sidebandHandle = nullptr;
- if (!mBase1_1) {
+ if (mAidlBase) {
+ ::aidl::android::hardware::common::NativeHandle handle;
+ ::ndk::ScopedAStatus transStatus = mAidlBase->configureVideoTunnel(avSyncHwId, &handle);
+ c2_status_t status = GetC2Status(transStatus, "configureVideoTunnel");
+ if (status != C2_OK) {
+ return status;
+ }
+ if (isAidlNativeHandleEmpty(handle)) {
+ LOG(DEBUG) << "configureVideoTunnel -- empty handle returned";
+ } else {
+ *sidebandHandle = dupFromAidl(handle);
+ }
+ return C2_OK;
+ }
+ if (!mHidlBase1_1) {
return C2_OMITTED;
}
c2_status_t status{};
- Return<void> transStatus = mBase1_1->configureVideoTunnel(avSyncHwId,
+ Return<void> transStatus = mHidlBase1_1->configureVideoTunnel(avSyncHwId,
[&status, sidebandHandle](
c2_hidl::Status s, hardware::hidl_handle const& h) {
status = static_cast<c2_status_t>(s);
@@ -1671,8 +2250,8 @@
bqId = 0;
mOutputBufferQueue->configure(nullIgbp, generation, 0, maxDequeueCount, nullptr);
} else {
- mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount, mBase1_2 ?
- &syncObj : nullptr);
+ mOutputBufferQueue->configure(surface, generation, bqId, maxDequeueCount,
+ mHidlBase1_2 ? &syncObj : nullptr);
}
// set consumer bits
@@ -1711,11 +2290,15 @@
ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
generation, (long long)consumerUsage, syncObj ? " sync" : "");
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
Return<c2_hidl::Status> transStatus = syncObj ?
- mBase1_2->setOutputSurfaceWithSyncObj(
+ mHidlBase1_2->setOutputSurfaceWithSyncObj(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp, *syncObj) :
- mBase1_0->setOutputSurface(
+ mHidlBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId),
bqId == 0 ? nullHgbp : igbp);
@@ -1755,7 +2338,11 @@
C2BlockPool::local_id_t blockPoolId) {
std::scoped_lock lock(mOutputMutex);
mOutputBufferQueue->stop();
- Return<c2_hidl::Status> transStatus = mBase1_0->setOutputSurface(
+ if (mAidlBase) {
+ // FIXME
+ return;
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId), nullptr);
if (!transStatus.isOk()) {
LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
@@ -1773,8 +2360,12 @@
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->connectToInputSurface(
+ Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
inputSurface->mBase,
[&status, connection](
c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1797,8 +2388,12 @@
const sp<HGraphicBufferProducer1>& producer,
const sp<HGraphicBufferSource>& source,
std::shared_ptr<InputSurfaceConnection>* connection) {
+ if (mAidlBase) {
+ LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
+ return C2_OMITTED;
+ }
c2_status_t status;
- Return<void> transStatus = mBase1_0->connectToOmxInputSurface(
+ Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
producer, source,
[&status, connection](
c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
@@ -1818,7 +2413,11 @@
}
c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
- Return<c2_hidl::Status> transStatus = mBase1_0->disconnectFromInputSurface();
+ if (mAidlBase) {
+ // FIXME
+ return C2_OMITTED;
+ }
+ Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
if (!transStatus.isOk()) {
LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1832,6 +2431,12 @@
return status;
}
+Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
+ // This object never gets destructed
+ static AidlDeathManager *sManager = new AidlDeathManager();
+ return sManager;
+}
+
c2_status_t Codec2Client::Component::setDeathListener(
const std::shared_ptr<Component>& component,
const std::shared_ptr<Listener>& listener) {
@@ -1852,12 +2457,20 @@
}
};
+ if (component->mAidlBase) {
+ size_t seq;
+ if (GetAidlDeathManager()->linkToDeath(component, listener, &seq)) {
+ component->mAidlDeathSeq = seq;
+ }
+ return C2_OK;
+ }
+
sp<HidlDeathRecipient> deathRecipient = new HidlDeathRecipient();
deathRecipient->base = listener;
deathRecipient->component = component;
component->mDeathRecipient = deathRecipient;
- Return<bool> transResult = component->mBase1_0->linkToDeath(
+ Return<bool> transResult = component->mHidlBase1_0->linkToDeath(
component->mDeathRecipient, 0);
if (!transResult.isOk()) {
LOG(ERROR) << "setDeathListener -- linkToDeath() transaction failed.";
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index 6fa19b0..0c7dd77 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -95,6 +95,11 @@
struct IClientManager;
} // namespace android::hardware::media::bufferpool::V2_0
+namespace aidl::android::hardware::media::bufferpool2 {
+class IClientManager;
+} // namespace aidl::android::hardware::media::c2
+
+
namespace android::hardware::graphics::bufferqueue::V1_0 {
struct IGraphicBufferProducer;
} // android::hardware::graphics::bufferqueue::V1_0
@@ -173,12 +178,12 @@
struct Codec2Client : public Codec2ConfigurableClient {
- typedef ::android::hardware::media::c2::V1_0::IComponentStore Base1_0;
- typedef ::android::hardware::media::c2::V1_1::IComponentStore Base1_1;
- typedef ::android::hardware::media::c2::V1_2::IComponentStore Base1_2;
- typedef Base1_0 Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponentStore HidlBase1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponentStore HidlBase1_1;
+ typedef ::android::hardware::media::c2::V1_2::IComponentStore HidlBase1_2;
+ typedef HidlBase1_0 HidlBase;
- typedef ::android::hardware::media::c2::V1_0::IConfigurable IConfigurable;
+ typedef ::aidl::android::hardware::media::c2::IComponentStore AidlBase;
struct Listener;
@@ -194,10 +199,11 @@
typedef Codec2Client Store;
- sp<Base> const& getBase() const;
- sp<Base1_0> const& getBase1_0() const;
- sp<Base1_1> const& getBase1_1() const;
- sp<Base1_2> const& getBase1_2() const;
+ sp<HidlBase> const& getHidlBase() const;
+ sp<HidlBase1_0> const& getHidlBase1_0() const;
+ sp<HidlBase1_1> const& getHidlBase1_1() const;
+ sp<HidlBase1_2> const& getHidlBase1_2() const;
+ ::ndk::SpAIBinder getAidlBase() const;
std::string const& getServiceName() const;
@@ -266,14 +272,19 @@
// base and/or configurable cannot be null.
Codec2Client(
- sp<Base> const& base,
- sp<IConfigurable> const& configurable,
+ sp<HidlBase> const& base,
+ sp<Codec2ConfigurableClient::HidlBase> const& configurable,
+ size_t serviceIndex);
+ Codec2Client(
+ std::shared_ptr<AidlBase> const& base,
+ std::shared_ptr<Codec2ConfigurableClient::AidlBase> const& configurable,
size_t serviceIndex);
protected:
- sp<Base1_0> mBase1_0;
- sp<Base1_1> mBase1_1;
- sp<Base1_2> mBase1_2;
+ sp<HidlBase1_0> mHidlBase1_0;
+ sp<HidlBase1_1> mHidlBase1_1;
+ sp<HidlBase1_2> mHidlBase1_2;
+ std::shared_ptr<AidlBase> mAidlBase;
// 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
@@ -301,8 +312,11 @@
mutable std::vector<C2Component::Traits> mTraitsList;
sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
- mHostPoolManager;
+ mHidlHostPoolManager;
+ std::shared_ptr<::aidl::android::hardware::media::bufferpool2::IClientManager>
+ mAidlHostPoolManager;
+ static std::vector<std::string> CacheServiceNames();
static std::shared_ptr<Codec2Client> _CreateFromIndex(size_t index);
std::vector<C2Component::Traits> _listComponents(bool* success) const;
@@ -312,12 +326,15 @@
struct Codec2Client::Interface : public Codec2Client::Configurable {
- typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponentInterface HidlBase;
+ typedef ::aidl::android::hardware::media::c2::IComponentInterface AidlBase;
- Interface(const sp<Base>& base);
+ Interface(const sp<HidlBase>& base);
+ Interface(const std::shared_ptr<AidlBase>& base);
protected:
- sp<Base> mBase;
+ sp<HidlBase> mHidlBase;
+ std::shared_ptr<AidlBase> mAidlBase;
};
struct Codec2Client::Listener {
@@ -356,16 +373,17 @@
int32_t slotId,
int64_t timestampNs) = 0;
- virtual ~Listener();
-
+ virtual ~Listener() = default;
};
struct Codec2Client::Component : public Codec2Client::Configurable {
- typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
- typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
- typedef ::android::hardware::media::c2::V1_2::IComponent Base1_2;
- typedef Base1_0 Base;
+ typedef ::android::hardware::media::c2::V1_0::IComponent HidlBase1_0;
+ typedef ::android::hardware::media::c2::V1_1::IComponent HidlBase1_1;
+ typedef ::android::hardware::media::c2::V1_2::IComponent HidlBase1_2;
+ typedef HidlBase1_0 HidlBase;
+
+ typedef ::aidl::android::hardware::media::c2::IComponent AidlBase;
c2_status_t createBlockPool(
C2Allocator::id_t id,
@@ -469,19 +487,23 @@
c2_status_t disconnectFromInputSurface();
// base cannot be null.
- Component(const sp<Base>& base);
- Component(const sp<Base1_1>& base);
- Component(const sp<Base1_2>& base);
+ Component(const sp<HidlBase>& base);
+ Component(const sp<HidlBase1_1>& base);
+ Component(const sp<HidlBase1_2>& base);
+ Component(const std::shared_ptr<AidlBase>& base);
~Component();
protected:
- sp<Base1_0> mBase1_0;
- sp<Base1_1> mBase1_1;
- sp<Base1_2> mBase1_2;
+ sp<HidlBase1_0> mHidlBase1_0;
+ sp<HidlBase1_1> mHidlBase1_1;
+ sp<HidlBase1_2> mHidlBase1_2;
+ std::shared_ptr<AidlBase> mAidlBase;
- struct BufferPoolSender;
- std::unique_ptr<BufferPoolSender> mBufferPoolSender;
+ struct HidlBufferPoolSender;
+ struct AidlBufferPoolSender;
+ std::unique_ptr<HidlBufferPoolSender> mHidlBufferPoolSender;
+ std::unique_ptr<AidlBufferPoolSender> mAidlBufferPoolSender;
struct OutputBufferQueue;
std::unique_ptr<OutputBufferQueue> mOutputBufferQueue;
@@ -491,6 +513,10 @@
// In order to prevent the race condition mutex is added.
std::mutex mOutputMutex;
+ class AidlDeathManager;
+ static AidlDeathManager *GetAidlDeathManager();
+ std::optional<size_t> mAidlDeathSeq;
+
static c2_status_t setDeathListener(
const std::shared_ptr<Component>& component,
const std::shared_ptr<Listener>& listener);
@@ -499,16 +525,15 @@
friend struct Codec2Client;
struct HidlListener;
+ struct AidlListener;
void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
-
};
struct Codec2Client::InputSurface : public Codec2Client::Configurable {
public:
typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
- typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection
- ConnectionBase;
+ typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection ConnectionBase;
typedef Codec2Client::InputSurfaceConnection Connection;
diff --git a/media/codec2/hal/common/Android.bp b/media/codec2/hal/common/Android.bp
index e158cd2..f0193d7 100644
--- a/media/codec2/hal/common/Android.bp
+++ b/media/codec2/hal/common/Android.bp
@@ -1,6 +1,6 @@
-cc_library_headers {
+cc_library {
name: "libcodec2_hal_common",
- export_include_dirs: ["include/"],
+ double_loadable: true,
vendor_available: true,
apex_available: [
"//apex_available:platform",
@@ -8,4 +8,23 @@
"com.android.media.swcodec",
],
min_sdk_version: "29",
+
+ srcs: [
+ "BufferTypes.cpp",
+ ],
+
+ export_include_dirs: ["include/"],
+
+ header_libs: [
+ "libcodec2_internal", // private
+ "libgui_headers",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcodec2",
+ "libcodec2_vndk",
+ "liblog",
+ "libstagefright_foundation",
+ ],
}
diff --git a/media/codec2/hal/common/BufferTypes.cpp b/media/codec2/hal/common/BufferTypes.cpp
new file mode 100644
index 0000000..f10a195
--- /dev/null
+++ b/media/codec2/hal/common/BufferTypes.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2-BufferTypes"
+#include <android-base/logging.h>
+
+#include <codec2/common/BufferTypes.h>
+
+#include <C2AllocatorIon.h>
+#include <C2AllocatorGralloc.h>
+#include <C2BlockInternal.h>
+#include <C2Buffer.h>
+#include <C2Component.h>
+#include <C2FenceFactory.h>
+#include <C2PlatformSupport.h>
+#include <C2Work.h>
+
+namespace android {
+
+// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
+bool CreateLinearBuffer(
+ std::shared_ptr<C2Buffer>* buffer,
+ const std::shared_ptr<C2LinearBlock>& block,
+ const std::vector<C2Param*>& meta,
+ const C2Fence& fence) {
+ // Check the block meta. It should have exactly 1 C2Info:
+ // C2Hal_RangeInfo.
+ if ((meta.size() != 1) || !meta[0]) {
+ LOG(ERROR) << "Invalid C2LinearBlock::meta.";
+ return false;
+ }
+ if (meta[0]->size() != sizeof(C2Hal_RangeInfo)) {
+ LOG(ERROR) << "Invalid range info in C2LinearBlock.";
+ return false;
+ }
+ C2Hal_RangeInfo *rangeInfo =
+ reinterpret_cast<C2Hal_RangeInfo*>(meta[0]);
+
+ // Create C2Buffer from C2LinearBlock.
+ *buffer = C2Buffer::CreateLinearBuffer(block->share(
+ rangeInfo->offset, rangeInfo->length,
+ fence));
+ if (!(*buffer)) {
+ LOG(ERROR) << "CreateLinearBuffer failed.";
+ return false;
+ }
+ return true;
+}
+
+// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
+bool CreateGraphicBuffer(
+ std::shared_ptr<C2Buffer>* buffer,
+ const std::shared_ptr<C2GraphicBlock>& block,
+ const std::vector<C2Param*>& meta,
+ const C2Fence& fence) {
+ // Check the block meta. It should have exactly 1 C2Info:
+ // C2Hal_RectInfo.
+ if ((meta.size() != 1) || !meta[0]) {
+ LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
+ return false;
+ }
+ if (meta[0]->size() != sizeof(C2Hal_RectInfo)) {
+ LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
+ return false;
+ }
+ C2Hal_RectInfo *rectInfo =
+ reinterpret_cast<C2Hal_RectInfo*>(meta[0]);
+
+ // Create C2Buffer from C2GraphicBlock.
+ *buffer = C2Buffer::CreateGraphicBuffer(block->share(
+ C2Rect(rectInfo->width, rectInfo->height).
+ at(rectInfo->left, rectInfo->top),
+ fence));
+ if (!(*buffer)) {
+ LOG(ERROR) << "CreateGraphicBuffer failed.";
+ return false;
+ }
+ return true;
+}
+
+namespace /* unnamed */ {
+
+template <typename BlockProcessor>
+void forEachBlock(C2FrameData& frameData,
+ BlockProcessor process) {
+ for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
+ if (buffer) {
+ for (const C2ConstGraphicBlock& block :
+ buffer->data().graphicBlocks()) {
+ process(block);
+ }
+ }
+ }
+}
+
+template <typename BlockProcessor>
+void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
+ BlockProcessor process,
+ bool processInput, bool processOutput) {
+ for (const std::unique_ptr<C2Work>& work : workList) {
+ if (!work) {
+ continue;
+ }
+ if (processInput) {
+ forEachBlock(work->input, process);
+ }
+ if (processOutput) {
+ for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
+ if (worklet) {
+ forEachBlock(worklet->output,
+ process);
+ }
+ }
+ }
+ }
+}
+
+} // unnamed namespace
+
+bool BeginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
+ std::shared_ptr<_C2BlockPoolData> data =
+ _C2BlockFactory::GetGraphicBlockPoolData(block);
+ if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+ _C2BlockFactory::BeginTransferBlockToClient(data);
+ return true;
+ }
+ return false;
+}
+
+void BeginTransferBufferQueueBlocks(
+ const std::list<std::unique_ptr<C2Work>>& workList,
+ bool processInput, bool processOutput) {
+ forEachBlock(workList, BeginTransferBufferQueueBlock,
+ processInput, processOutput);
+}
+
+bool EndTransferBufferQueueBlock(
+ const C2ConstGraphicBlock& block,
+ bool transfer) {
+ std::shared_ptr<_C2BlockPoolData> data =
+ _C2BlockFactory::GetGraphicBlockPoolData(block);
+ if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+ _C2BlockFactory::EndTransferBlockToClient(data, transfer);
+ return true;
+ }
+ return false;
+}
+
+void EndTransferBufferQueueBlocks(
+ const std::list<std::unique_ptr<C2Work>>& workList,
+ bool transfer,
+ bool processInput, bool processOutput) {
+ forEachBlock(workList,
+ std::bind(EndTransferBufferQueueBlock,
+ std::placeholders::_1, transfer),
+ processInput, processOutput);
+}
+
+bool DisplayBufferQueueBlock(const C2ConstGraphicBlock& block) {
+ std::shared_ptr<_C2BlockPoolData> data =
+ _C2BlockFactory::GetGraphicBlockPoolData(block);
+ if (data && _C2BlockFactory::GetBufferQueueData(data)) {
+ _C2BlockFactory::DisplayBlockToBufferQueue(data);
+ return true;
+ }
+ return false;
+}
+
+} // namespace android
+
diff --git a/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h b/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h
new file mode 100644
index 0000000..a9e5942
--- /dev/null
+++ b/media/codec2/hal/common/include/codec2/common/BufferPoolSender.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC2_COMMON_BUFFER_POOL_SENDER_H
+#define CODEC2_COMMON_BUFFER_POOL_SENDER_H
+
+#include <memory>
+
+namespace android {
+
+// Template class to be used in
+// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
+template <typename BufferPoolTypes>
+struct BufferPoolSender {
+ // BufferPoolTypes should define the following types:
+ typedef typename BufferPoolTypes::BufferPoolData BufferPoolData;
+ typedef typename BufferPoolTypes::ResultStatus ResultStatus;
+ typedef typename BufferPoolTypes::BufferPoolStatus BufferPoolStatus;
+ typedef typename BufferPoolTypes::BufferStatusMessage BufferStatusMessage;
+
+ /**
+ * Send bpData and return BufferStatusMessage that can be supplied to
+ * IClientManager::receive() in the receiving process.
+ *
+ * This function will be called from within the function
+ * objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
+ *
+ * \param[in] bpData BufferPoolData identifying the buffer to send.
+ * \param[out] bpMessage BufferStatusMessage of the transaction. Information
+ * inside \p bpMessage should be passed to the receiving process by some
+ * other means so it can call receive() properly.
+ * \return ResultStatus value that determines the success of the operation.
+ * (See the possible values of ResultStatus in
+ * hardware/interfaces/media/bufferpool/2.0/types.hal.)
+ */
+ virtual BufferPoolStatus send(
+ const std::shared_ptr<BufferPoolData>& bpData,
+ BufferStatusMessage* bpMessage) = 0;
+
+ virtual ~BufferPoolSender() = default;
+};
+
+} // namespace android
+
+#endif // CODEC2_COMMON_BUFFER_POOL_SENDER_H
diff --git a/media/codec2/hal/common/include/codec2/common/BufferTypes.h b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
index 319ba62..8998a6d 100644
--- a/media/codec2/hal/common/include/codec2/common/BufferTypes.h
+++ b/media/codec2/hal/common/include/codec2/common/BufferTypes.h
@@ -14,11 +14,16 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
-#define LOG_TAG "Codec2-types"
+#ifndef CODEC2_COMMON_BUFFER_TYPES_H
+#define CODEC2_COMMON_BUFFER_TYPES_H
+
+#ifndef LOG_TAG
+#define LOG_TAG "Codec2-BufferTypes"
+#endif
#include <android-base/logging.h>
-#include <codec2/hidl/1.0/types.h>
+#include <codec2/common/BufferPoolSender.h>
+#include <codec2/common/ParamTypes.h>
#include <media/stagefright/foundation/AUtils.h>
#include <C2AllocatorIon.h>
@@ -28,623 +33,50 @@
#include <C2Component.h>
#include <C2FenceFactory.h>
#include <C2Param.h>
-#include <C2ParamInternal.h>
+#include <C2ParamDef.h>
#include <C2PlatformSupport.h>
#include <C2Work.h>
-#include <util/C2ParamUtils.h>
#include <algorithm>
#include <functional>
#include <iomanip>
-#include <unordered_map>
+#include <map>
namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_0 {
-namespace utils {
-using ::android::hardware::Return;
-using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
-using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
- ClientManager;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
- TransactionId;
-
-const char* asString(Status status, const char* def) {
- return asString(static_cast<c2_status_t>(status), def);
-}
-
-namespace /* unnamed */ {
-
-template <typename EnumClass>
-typename std::underlying_type<EnumClass>::type underlying_value(
- EnumClass x) {
- return static_cast<typename std::underlying_type<EnumClass>::type>(x);
-}
-
-template <typename Common, typename DstVector, typename SrcVector>
-void copyVector(DstVector* d, const SrcVector& s) {
- static_assert(sizeof(Common) == sizeof(decltype((*d)[0])),
- "DstVector's component size does not match Common");
- static_assert(sizeof(Common) == sizeof(decltype(s[0])),
- "SrcVector's component size does not match Common");
- d->resize(s.size());
- std::copy(
- reinterpret_cast<const Common*>(&s[0]),
- reinterpret_cast<const Common*>(&s[0] + s.size()),
- reinterpret_cast<Common*>(&(*d)[0]));
-}
-
-// C2ParamField -> ParamField
-bool objcpy(ParamField *d, const C2ParamField &s) {
- d->index = static_cast<ParamIndex>(_C2ParamInspector::GetIndex(s));
- d->fieldId.offset = static_cast<uint32_t>(_C2ParamInspector::GetOffset(s));
- d->fieldId.size = static_cast<uint32_t>(_C2ParamInspector::GetSize(s));
- return true;
-}
-
-struct C2ParamFieldBuilder : public C2ParamField {
- C2ParamFieldBuilder() : C2ParamField(
- static_cast<C2Param::Index>(static_cast<uint32_t>(0)), 0, 0) {
- }
- // ParamField -> C2ParamField
- C2ParamFieldBuilder(const ParamField& s) : C2ParamField(
- static_cast<C2Param::Index>(static_cast<uint32_t>(s.index)),
- static_cast<uint32_t>(s.fieldId.offset),
- static_cast<uint32_t>(s.fieldId.size)) {
- }
+// Types of metadata for Blocks.
+struct C2Hal_Range {
+ uint32_t offset;
+ uint32_t length; // Do not use "size" because the name collides with C2Info::size().
};
+typedef C2GlobalParam<C2Info, C2Hal_Range, 0> C2Hal_RangeInfo;
-// C2WorkOrdinalStruct -> WorkOrdinal
-bool objcpy(WorkOrdinal *d, const C2WorkOrdinalStruct &s) {
- d->frameIndex = static_cast<uint64_t>(s.frameIndex.peeku());
- d->timestampUs = static_cast<uint64_t>(s.timestamp.peeku());
- d->customOrdinal = static_cast<uint64_t>(s.customOrdinal.peeku());
- return true;
-}
+struct C2Hal_Rect {
+ uint32_t left;
+ uint32_t top;
+ uint32_t width;
+ uint32_t height;
+};
+typedef C2GlobalParam<C2Info, C2Hal_Rect, 1> C2Hal_RectInfo;
-// WorkOrdinal -> C2WorkOrdinalStruct
-bool objcpy(C2WorkOrdinalStruct *d, const WorkOrdinal &s) {
- d->frameIndex = c2_cntr64_t(s.frameIndex);
- d->timestamp = c2_cntr64_t(s.timestampUs);
- d->customOrdinal = c2_cntr64_t(s.customOrdinal);
- return true;
-}
+// Note: The handle is not cloned.
+template <typename BaseBlock>
+void SetHandle(BaseBlock *baseBlock, const C2Handle *handle);
-// C2FieldSupportedValues::range's type -> ValueRange
-bool objcpy(
- ValueRange* d,
- const decltype(C2FieldSupportedValues::range)& s) {
- d->min = static_cast<PrimitiveValue>(s.min.u64);
- d->max = static_cast<PrimitiveValue>(s.max.u64);
- d->step = static_cast<PrimitiveValue>(s.step.u64);
- d->num = static_cast<PrimitiveValue>(s.num.u64);
- d->denom = static_cast<PrimitiveValue>(s.denom.u64);
- return true;
-}
+template <typename BufferPoolTypes, typename BaseBlock>
+void SetPooledBlock(
+ BaseBlock *baseBlock,
+ const typename BufferPoolTypes::BufferStatusMessage &pooledBlock);
-// C2FieldSupportedValues -> FieldSupportedValues
-bool objcpy(FieldSupportedValues *d, const C2FieldSupportedValues &s) {
- switch (s.type) {
- case C2FieldSupportedValues::EMPTY: {
- d->empty(::android::hidl::safe_union::V1_0::Monostate{});
- break;
- }
- case C2FieldSupportedValues::RANGE: {
- ValueRange range{};
- if (!objcpy(&range, s.range)) {
- LOG(ERROR) << "Invalid C2FieldSupportedValues::range.";
- d->range(range);
- return false;
- }
- d->range(range);
- break;
- }
- case C2FieldSupportedValues::VALUES: {
- hidl_vec<PrimitiveValue> values;
- copyVector<uint64_t>(&values, s.values);
- d->values(values);
- break;
- }
- case C2FieldSupportedValues::FLAGS: {
- hidl_vec<PrimitiveValue> flags;
- copyVector<uint64_t>(&flags, s.values);
- d->flags(flags);
- break;
- }
- default:
- LOG(DEBUG) << "Unrecognized C2FieldSupportedValues::type_t "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- return false;
- }
- return true;
-}
+template <typename BufferPoolTypes>
+bool GetBufferPoolData(
+ const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
+ std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData);
-// ValueRange -> C2FieldSupportedValues::range's type
-bool objcpy(
- decltype(C2FieldSupportedValues::range)* d,
- const ValueRange& s) {
- d->min.u64 = static_cast<uint64_t>(s.min);
- d->max.u64 = static_cast<uint64_t>(s.max);
- d->step.u64 = static_cast<uint64_t>(s.step);
- d->num.u64 = static_cast<uint64_t>(s.num);
- d->denom.u64 = static_cast<uint64_t>(s.denom);
- return true;
-}
-
-// FieldSupportedValues -> C2FieldSupportedValues
-bool objcpy(C2FieldSupportedValues *d, const FieldSupportedValues &s) {
- switch (s.getDiscriminator()) {
- case FieldSupportedValues::hidl_discriminator::empty: {
- d->type = C2FieldSupportedValues::EMPTY;
- break;
- }
- case FieldSupportedValues::hidl_discriminator::range: {
- d->type = C2FieldSupportedValues::RANGE;
- if (!objcpy(&d->range, s.range())) {
- LOG(ERROR) << "Invalid FieldSupportedValues::range.";
- return false;
- }
- d->values.resize(0);
- break;
- }
- case FieldSupportedValues::hidl_discriminator::values: {
- d->type = C2FieldSupportedValues::VALUES;
- copyVector<uint64_t>(&d->values, s.values());
- break;
- }
- case FieldSupportedValues::hidl_discriminator::flags: {
- d->type = C2FieldSupportedValues::FLAGS;
- copyVector<uint64_t>(&d->values, s.flags());
- break;
- }
- default:
- LOG(WARNING) << "Unrecognized FieldSupportedValues::getDiscriminator()";
- return false;
- }
- return true;
-}
-
-} // unnamed namespace
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQuery
-bool objcpy(
- FieldSupportedValuesQuery* d,
- const C2FieldSupportedValuesQuery& s) {
- if (!objcpy(&d->field, s.field())) {
- LOG(ERROR) << "Invalid C2FieldSupportedValuesQuery::field.";
- return false;
- }
- switch (s.type()) {
- case C2FieldSupportedValuesQuery::POSSIBLE:
- d->type = FieldSupportedValuesQuery::Type::POSSIBLE;
- break;
- case C2FieldSupportedValuesQuery::CURRENT:
- d->type = FieldSupportedValuesQuery::Type::CURRENT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2FieldSupportedValuesQuery::type_t "
- << "with underlying value " << underlying_value(s.type())
- << ".";
- d->type = static_cast<FieldSupportedValuesQuery::Type>(s.type());
- }
- return true;
-}
-
-// FieldSupportedValuesQuery -> C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& s) {
- C2FieldSupportedValuesQuery::type_t dType;
- switch (s.type) {
- case FieldSupportedValuesQuery::Type::POSSIBLE:
- dType = C2FieldSupportedValuesQuery::POSSIBLE;
- break;
- case FieldSupportedValuesQuery::Type::CURRENT:
- dType = C2FieldSupportedValuesQuery::CURRENT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized FieldSupportedValuesQuery::Type "
- << "with underlying value " << underlying_value(s.type)
- << ".";
- dType = static_cast<C2FieldSupportedValuesQuery::type_t>(s.type);
- }
- *d = C2FieldSupportedValuesQuery(C2ParamFieldBuilder(s.field), dType);
- return true;
-}
-
-// C2FieldSupportedValuesQuery -> FieldSupportedValuesQueryResult
-bool objcpy(
- FieldSupportedValuesQueryResult* d,
- const C2FieldSupportedValuesQuery& s) {
- d->status = static_cast<Status>(s.status);
- return objcpy(&d->values, s.values);
-}
-
-// FieldSupportedValuesQuery, FieldSupportedValuesQueryResult ->
-// C2FieldSupportedValuesQuery
-bool objcpy(
- C2FieldSupportedValuesQuery* d,
- const FieldSupportedValuesQuery& sq,
- const FieldSupportedValuesQueryResult& sr) {
- if (!objcpy(d, sq)) {
- LOG(ERROR) << "Invalid FieldSupportedValuesQuery.";
- return false;
- }
- d->status = static_cast<c2_status_t>(sr.status);
- if (!objcpy(&d->values, sr.values)) {
- LOG(ERROR) << "Invalid FieldSupportedValuesQueryResult::values.";
- return false;
- }
- return true;
-}
-
-// C2Component::Traits -> IComponentStore::ComponentTraits
-bool objcpy(
- IComponentStore::ComponentTraits *d,
- const C2Component::Traits &s) {
- d->name = s.name;
-
- switch (s.domain) {
- case C2Component::DOMAIN_VIDEO:
- d->domain = IComponentStore::ComponentTraits::Domain::VIDEO;
- break;
- case C2Component::DOMAIN_AUDIO:
- d->domain = IComponentStore::ComponentTraits::Domain::AUDIO;
- break;
- case C2Component::DOMAIN_IMAGE:
- d->domain = IComponentStore::ComponentTraits::Domain::IMAGE;
- break;
- case C2Component::DOMAIN_OTHER:
- d->domain = IComponentStore::ComponentTraits::Domain::OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2Component::domain_t "
- << "with underlying value " << underlying_value(s.domain)
- << ".";
- d->domain = static_cast<IComponentStore::ComponentTraits::Domain>(
- s.domain);
- }
-
- switch (s.kind) {
- case C2Component::KIND_DECODER:
- d->kind = IComponentStore::ComponentTraits::Kind::DECODER;
- break;
- case C2Component::KIND_ENCODER:
- d->kind = IComponentStore::ComponentTraits::Kind::ENCODER;
- break;
- case C2Component::KIND_OTHER:
- d->kind = IComponentStore::ComponentTraits::Kind::OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2Component::kind_t "
- << "with underlying value " << underlying_value(s.kind)
- << ".";
- d->kind = static_cast<IComponentStore::ComponentTraits::Kind>(
- s.kind);
- }
-
- d->rank = static_cast<uint32_t>(s.rank);
-
- d->mediaType = s.mediaType;
-
- d->aliases.resize(s.aliases.size());
- for (size_t ix = s.aliases.size(); ix > 0; ) {
- --ix;
- d->aliases[ix] = s.aliases[ix];
- }
- return true;
-}
-
-// ComponentTraits -> C2Component::Traits, std::unique_ptr<std::vector<std::string>>
-bool objcpy(
- C2Component::Traits* d,
- const IComponentStore::ComponentTraits& s) {
- d->name = s.name.c_str();
-
- switch (s.domain) {
- case IComponentStore::ComponentTraits::Domain::VIDEO:
- d->domain = C2Component::DOMAIN_VIDEO;
- break;
- case IComponentStore::ComponentTraits::Domain::AUDIO:
- d->domain = C2Component::DOMAIN_AUDIO;
- break;
- case IComponentStore::ComponentTraits::Domain::IMAGE:
- d->domain = C2Component::DOMAIN_IMAGE;
- break;
- case IComponentStore::ComponentTraits::Domain::OTHER:
- d->domain = C2Component::DOMAIN_OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized ComponentTraits::Domain "
- << "with underlying value " << underlying_value(s.domain)
- << ".";
- d->domain = static_cast<C2Component::domain_t>(s.domain);
- }
-
- switch (s.kind) {
- case IComponentStore::ComponentTraits::Kind::DECODER:
- d->kind = C2Component::KIND_DECODER;
- break;
- case IComponentStore::ComponentTraits::Kind::ENCODER:
- d->kind = C2Component::KIND_ENCODER;
- break;
- case IComponentStore::ComponentTraits::Kind::OTHER:
- d->kind = C2Component::KIND_OTHER;
- break;
- default:
- LOG(DEBUG) << "Unrecognized ComponentTraits::Kind "
- << "with underlying value " << underlying_value(s.kind)
- << ".";
- d->kind = static_cast<C2Component::kind_t>(s.kind);
- }
-
- d->rank = static_cast<C2Component::rank_t>(s.rank);
- d->mediaType = s.mediaType.c_str();
- d->aliases.resize(s.aliases.size());
- for (size_t i = 0; i < s.aliases.size(); ++i) {
- d->aliases[i] = s.aliases[i];
- }
- return true;
-}
-
-namespace /* unnamed */ {
-
-// C2ParamFieldValues -> ParamFieldValues
-bool objcpy(ParamFieldValues *d, const C2ParamFieldValues &s) {
- if (!objcpy(&d->paramOrField, s.paramOrField)) {
- LOG(ERROR) << "Invalid C2ParamFieldValues::paramOrField.";
- return false;
- }
- if (s.values) {
- d->values.resize(1);
- if (!objcpy(&d->values[0], *s.values)) {
- LOG(ERROR) << "Invalid C2ParamFieldValues::values.";
- return false;
- }
- return true;
- }
- d->values.resize(0);
- return true;
-}
-
-// ParamFieldValues -> C2ParamFieldValues
-bool objcpy(C2ParamFieldValues *d, const ParamFieldValues &s) {
- d->paramOrField = C2ParamFieldBuilder(s.paramOrField);
- if (s.values.size() == 1) {
- d->values = std::make_unique<C2FieldSupportedValues>();
- if (!objcpy(d->values.get(), s.values[0])) {
- LOG(ERROR) << "Invalid ParamFieldValues::values.";
- return false;
- }
- return true;
- } else if (s.values.size() == 0) {
- d->values.reset();
- return true;
- }
- LOG(ERROR) << "Invalid ParamFieldValues: "
- "Two or more FieldSupportedValues objects exist in "
- "ParamFieldValues. "
- "Only zero or one is allowed.";
- return false;
-}
-
-} // unnamed namespace
-
-// C2SettingResult -> SettingResult
-bool objcpy(SettingResult *d, const C2SettingResult &s) {
- switch (s.failure) {
- case C2SettingResult::BAD_TYPE:
- d->failure = SettingResult::Failure::BAD_TYPE;
- break;
- case C2SettingResult::BAD_PORT:
- d->failure = SettingResult::Failure::BAD_PORT;
- break;
- case C2SettingResult::BAD_INDEX:
- d->failure = SettingResult::Failure::BAD_INDEX;
- break;
- case C2SettingResult::READ_ONLY:
- d->failure = SettingResult::Failure::READ_ONLY;
- break;
- case C2SettingResult::MISMATCH:
- d->failure = SettingResult::Failure::MISMATCH;
- break;
- case C2SettingResult::BAD_VALUE:
- d->failure = SettingResult::Failure::BAD_VALUE;
- break;
- case C2SettingResult::CONFLICT:
- d->failure = SettingResult::Failure::CONFLICT;
- break;
- case C2SettingResult::UNSUPPORTED:
- d->failure = SettingResult::Failure::UNSUPPORTED;
- break;
- case C2SettingResult::INFO_BAD_VALUE:
- d->failure = SettingResult::Failure::INFO_BAD_VALUE;
- break;
- case C2SettingResult::INFO_CONFLICT:
- d->failure = SettingResult::Failure::INFO_CONFLICT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized C2SettingResult::Failure "
- << "with underlying value " << underlying_value(s.failure)
- << ".";
- d->failure = static_cast<SettingResult::Failure>(s.failure);
- }
- if (!objcpy(&d->field, s.field)) {
- LOG(ERROR) << "Invalid C2SettingResult::field.";
- return false;
- }
- d->conflicts.resize(s.conflicts.size());
- size_t i = 0;
- for (const C2ParamFieldValues& sConflict : s.conflicts) {
- ParamFieldValues &dConflict = d->conflicts[i++];
- if (!objcpy(&dConflict, sConflict)) {
- LOG(ERROR) << "Invalid C2SettingResult::conflicts["
- << i - 1 << "].";
- return false;
- }
- }
- return true;
-}
-
-// SettingResult -> std::unique_ptr<C2SettingResult>
-bool objcpy(std::unique_ptr<C2SettingResult> *d, const SettingResult &s) {
- *d = std::unique_ptr<C2SettingResult>(new C2SettingResult {
- .field = C2ParamFieldValues(C2ParamFieldBuilder()) });
- if (!*d) {
- LOG(ERROR) << "No memory for C2SettingResult.";
- return false;
- }
-
- // failure
- switch (s.failure) {
- case SettingResult::Failure::BAD_TYPE:
- (*d)->failure = C2SettingResult::BAD_TYPE;
- break;
- case SettingResult::Failure::BAD_PORT:
- (*d)->failure = C2SettingResult::BAD_PORT;
- break;
- case SettingResult::Failure::BAD_INDEX:
- (*d)->failure = C2SettingResult::BAD_INDEX;
- break;
- case SettingResult::Failure::READ_ONLY:
- (*d)->failure = C2SettingResult::READ_ONLY;
- break;
- case SettingResult::Failure::MISMATCH:
- (*d)->failure = C2SettingResult::MISMATCH;
- break;
- case SettingResult::Failure::BAD_VALUE:
- (*d)->failure = C2SettingResult::BAD_VALUE;
- break;
- case SettingResult::Failure::CONFLICT:
- (*d)->failure = C2SettingResult::CONFLICT;
- break;
- case SettingResult::Failure::UNSUPPORTED:
- (*d)->failure = C2SettingResult::UNSUPPORTED;
- break;
- case SettingResult::Failure::INFO_BAD_VALUE:
- (*d)->failure = C2SettingResult::INFO_BAD_VALUE;
- break;
- case SettingResult::Failure::INFO_CONFLICT:
- (*d)->failure = C2SettingResult::INFO_CONFLICT;
- break;
- default:
- LOG(DEBUG) << "Unrecognized SettingResult::Failure "
- << "with underlying value " << underlying_value(s.failure)
- << ".";
- (*d)->failure = static_cast<C2SettingResult::Failure>(s.failure);
- }
-
- // field
- if (!objcpy(&(*d)->field, s.field)) {
- LOG(ERROR) << "Invalid SettingResult::field.";
- return false;
- }
-
- // conflicts
- (*d)->conflicts.clear();
- (*d)->conflicts.reserve(s.conflicts.size());
- for (const ParamFieldValues& sConflict : s.conflicts) {
- (*d)->conflicts.emplace_back(
- C2ParamFieldValues{ C2ParamFieldBuilder(), nullptr });
- if (!objcpy(&(*d)->conflicts.back(), sConflict)) {
- LOG(ERROR) << "Invalid SettingResult::conflicts.";
- return false;
- }
- }
- return true;
-}
-
-// C2ParamDescriptor -> ParamDescriptor
-bool objcpy(ParamDescriptor *d, const C2ParamDescriptor &s) {
- d->index = static_cast<ParamIndex>(s.index());
- d->attrib = static_cast<hidl_bitfield<ParamDescriptor::Attrib>>(
- _C2ParamInspector::GetAttrib(s));
- d->name = s.name();
- copyVector<uint32_t>(&d->dependencies, s.dependencies());
- return true;
-}
-
-// ParamDescriptor -> C2ParamDescriptor
-bool objcpy(std::shared_ptr<C2ParamDescriptor> *d, const ParamDescriptor &s) {
- std::vector<C2Param::Index> dDependencies;
- dDependencies.reserve(s.dependencies.size());
- for (const ParamIndex& sDependency : s.dependencies) {
- dDependencies.emplace_back(static_cast<uint32_t>(sDependency));
- }
- *d = std::make_shared<C2ParamDescriptor>(
- C2Param::Index(static_cast<uint32_t>(s.index)),
- static_cast<C2ParamDescriptor::attrib_t>(s.attrib),
- C2String(s.name.c_str()),
- std::move(dDependencies));
- return true;
-}
-
-// C2StructDescriptor -> StructDescriptor
-bool objcpy(StructDescriptor *d, const C2StructDescriptor &s) {
- d->type = static_cast<ParamIndex>(s.coreIndex().coreIndex());
- d->fields.resize(s.numFields());
- size_t i = 0;
- for (const auto& sField : s) {
- FieldDescriptor& dField = d->fields[i++];
- dField.fieldId.offset = static_cast<uint32_t>(
- _C2ParamInspector::GetOffset(sField));
- dField.fieldId.size = static_cast<uint32_t>(
- _C2ParamInspector::GetSize(sField));
- dField.type = static_cast<hidl_bitfield<FieldDescriptor::Type>>(
- sField.type());
- dField.extent = static_cast<uint32_t>(sField.extent());
- dField.name = static_cast<hidl_string>(sField.name());
- const auto& sNamedValues = sField.namedValues();
- dField.namedValues.resize(sNamedValues.size());
- size_t j = 0;
- for (const auto& sNamedValue : sNamedValues) {
- FieldDescriptor::NamedValue& dNamedValue = dField.namedValues[j++];
- dNamedValue.name = static_cast<hidl_string>(sNamedValue.first);
- dNamedValue.value = static_cast<PrimitiveValue>(
- sNamedValue.second.u64);
- }
- }
- return true;
-}
-
-// StructDescriptor -> C2StructDescriptor
-bool objcpy(std::unique_ptr<C2StructDescriptor> *d, const StructDescriptor &s) {
- C2Param::CoreIndex dIndex = C2Param::CoreIndex(static_cast<uint32_t>(s.type));
- std::vector<C2FieldDescriptor> dFields;
- dFields.reserve(s.fields.size());
- for (const auto &sField : s.fields) {
- C2FieldDescriptor dField = {
- static_cast<uint32_t>(sField.type),
- sField.extent,
- sField.name,
- sField.fieldId.offset,
- sField.fieldId.size };
- C2FieldDescriptor::NamedValuesType namedValues;
- namedValues.reserve(sField.namedValues.size());
- for (const auto& sNamedValue : sField.namedValues) {
- namedValues.emplace_back(
- sNamedValue.name,
- C2Value::Primitive(static_cast<uint64_t>(sNamedValue.value)));
- }
- _C2ParamInspector::AddNamedValues(dField, std::move(namedValues));
- dFields.emplace_back(dField);
- }
- *d = std::make_unique<C2StructDescriptor>(
- _C2ParamInspector::CreateStructDescriptor(dIndex, std::move(dFields)));
- return true;
-}
-
-namespace /* unnamed */ {
-
-// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
+// Find or add a HAL BaseBlock object from a given C2Handle* to a list and an
// associated map.
// Note: The handle is not cloned.
+template <typename BaseBlock>
bool _addBaseBlock(
uint32_t* index,
const C2Handle* handle,
@@ -663,20 +95,18 @@
baseBlocks->emplace_back();
BaseBlock &dBaseBlock = baseBlocks->back();
- // This does not clone the handle.
- dBaseBlock.nativeBlock(
- reinterpret_cast<const native_handle_t*>(handle));
-
+ SetHandle(&dBaseBlock, handle);
}
return true;
}
// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
// an associated map.
+template <typename BufferPoolTypes, typename BaseBlock>
bool _addBaseBlock(
uint32_t* index,
- const std::shared_ptr<BufferPoolData> bpData,
- BufferPoolSender* bufferPoolSender,
+ const std::shared_ptr<typename BufferPoolTypes::BufferPoolData> &bpData,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
if (!bpData) {
@@ -694,28 +124,28 @@
BaseBlock &dBaseBlock = baseBlocks->back();
if (bufferPoolSender) {
- BufferStatusMessage pooledBlock;
- ResultStatus bpStatus = bufferPoolSender->send(
- bpData,
- &pooledBlock);
+ typename BufferPoolTypes::BufferStatusMessage pooledBlock;
+ typename BufferPoolTypes::BufferPoolStatus bpStatus =
+ bufferPoolSender->send(bpData, &pooledBlock);
- if (bpStatus != ResultStatus::OK) {
+ if (bpStatus != BufferPoolTypes::ResultStatus::OK) {
LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
<< static_cast<int32_t>(bpStatus)
<< ".";
return false;
}
- dBaseBlock.pooledBlock(pooledBlock);
+ SetPooledBlock<BufferPoolTypes>(&dBaseBlock, pooledBlock);
}
}
return true;
}
+template <typename BufferPoolTypes, typename BaseBlock>
bool addBaseBlock(
uint32_t* index,
const C2Handle* handle,
const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
if (!blockPoolData) {
@@ -727,9 +157,8 @@
switch (blockPoolData->getType()) {
case _C2BlockPoolData::TYPE_BUFFERPOOL: {
// BufferPoolData
- std::shared_ptr<BufferPoolData> bpData;
- if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
- || !bpData) {
+ std::shared_ptr<typename BufferPoolTypes::BufferPoolData> bpData;
+ if (!GetBufferPoolData<BufferPoolTypes>(blockPoolData, &bpData) || !bpData) {
LOG(ERROR) << "BufferPoolData unavailable in a block.";
return false;
}
@@ -756,10 +185,11 @@
}
}
-// C2Fence -> hidl_handle
+// C2Fence -> Handle
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
-bool objcpy(hidl_handle* d, const C2Fence& s) {
+template <typename Handle>
+bool objcpy(Handle* d, const C2Fence& s) {
d->setTo(nullptr);
native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
if (handle) {
@@ -775,23 +205,24 @@
// C2ConstLinearBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
+template <typename Block, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(Block* d, const C2ConstLinearBlock& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
std::shared_ptr<const _C2BlockPoolData> bpData =
_C2BlockFactory::GetLinearBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
+ if (!addBaseBlock((uint32_t *)&d->index, s.handle(), bpData,
bufferPoolSender, baseBlocks, baseBlockIndices)) {
LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
return false;
}
// Create the metadata.
- C2Hidl_RangeInfo dRangeInfo;
+ C2Hal_RangeInfo dRangeInfo;
dRangeInfo.offset = static_cast<uint32_t>(s.offset());
dRangeInfo.length = static_cast<uint32_t>(s.size());
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
+ if (!_createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
return false;
}
@@ -807,26 +238,27 @@
// C2ConstGraphicBlock -> Block
// Note: Native handles are not duplicated. The original handles must not be
// closed before the transaction is complete.
+template <typename Block, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(Block* d, const C2ConstGraphicBlock& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
std::shared_ptr<const _C2BlockPoolData> bpData =
_C2BlockFactory::GetGraphicBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
+ if (!addBaseBlock((uint32_t *)&d->index, s.handle(), bpData,
bufferPoolSender, baseBlocks, baseBlockIndices)) {
LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
return false;
}
// Create the metadata.
- C2Hidl_RectInfo dRectInfo;
+ C2Hal_RectInfo dRectInfo;
C2Rect sRect = s.crop();
dRectInfo.left = static_cast<uint32_t>(sRect.left);
dRectInfo.top = static_cast<uint32_t>(sRect.top);
dRectInfo.width = static_cast<uint32_t>(sRect.width);
dRectInfo.height = static_cast<uint32_t>(sRect.height);
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
+ if (!_createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
return false;
}
@@ -841,8 +273,9 @@
// C2BufferData -> Buffer
// This function only fills in d->blocks.
+template <typename Buffer, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(Buffer* d, const C2BufferData& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
d->blocks.resize(
@@ -850,7 +283,7 @@
s.graphicBlocks().size());
size_t i = 0;
for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
- Block& dBlock = d->blocks[i++];
+ auto& dBlock = d->blocks[i++];
if (!objcpy(
&dBlock, linearBlock,
bufferPoolSender, baseBlocks, baseBlockIndices)) {
@@ -860,7 +293,7 @@
}
}
for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
- Block& dBlock = d->blocks[i++];
+ auto& dBlock = d->blocks[i++];
if (!objcpy(
&dBlock, graphicBlock,
bufferPoolSender, baseBlocks, baseBlockIndices)) {
@@ -873,11 +306,12 @@
}
// C2Buffer -> Buffer
+template <typename Buffer, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(Buffer* d, const C2Buffer& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!createParamsBlob(&d->info, s.info())) {
+ if (!_createParamsBlob(&d->info, s.info())) {
LOG(ERROR) << "Invalid C2Buffer::info.";
return false;
}
@@ -889,12 +323,13 @@
}
// C2InfoBuffer -> InfoBuffer
+template <typename InfoBuffer, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- d->index = static_cast<ParamIndex>(s.index());
- Buffer& dBuffer = d->buffer;
+ d->index = static_cast<decltype(d->index)>(s.index());
+ auto& dBuffer = d->buffer;
if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
LOG(ERROR) << "Invalid C2InfoBuffer::data";
return false;
@@ -903,11 +338,12 @@
}
// C2FrameData -> FrameData
+template <typename FrameData, typename BufferPoolTypes, typename BaseBlock>
bool objcpy(FrameData* d, const C2FrameData& s,
- BufferPoolSender* bufferPoolSender,
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender,
std::list<BaseBlock>* baseBlocks,
std::map<const void*, uint32_t>* baseBlockIndices) {
- d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
+ d->flags = static_cast<decltype(d->flags)>(s.flags);
if (!objcpy(&d->ordinal, s.ordinal)) {
LOG(ERROR) << "Invalid C2FrameData::ordinal.";
return false;
@@ -916,11 +352,12 @@
d->buffers.resize(s.buffers.size());
size_t i = 0;
for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
- Buffer& dBuffer = d->buffers[i++];
+ auto& dBuffer = d->buffers[i++];
if (!sBuffer) {
// A null (pointer to) C2Buffer corresponds to a Buffer with empty
// info and blocks.
- dBuffer.info.resize(0);
+ auto *dInfo = GetBlob(&dBuffer.info);
+ dInfo->resize(0);
dBuffer.blocks.resize(0);
continue;
}
@@ -933,7 +370,7 @@
}
}
- if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
+ if (!_createParamsBlob(&d->configUpdate, s.configUpdate)) {
LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
return false;
}
@@ -941,7 +378,7 @@
d->infoBuffers.resize(s.infoBuffers.size());
i = 0;
for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
- InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
+ auto& dInfoBuffer = d->infoBuffers[i++];
if (!objcpy(&dInfoBuffer, sInfoBuffer,
bufferPoolSender, baseBlocks, baseBlockIndices)) {
LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
@@ -953,113 +390,14 @@
return true;
}
-} // unnamed namespace
-
-// DefaultBufferPoolSender's implementation
-
-DefaultBufferPoolSender::DefaultBufferPoolSender(
- const sp<IClientManager>& receiverManager,
- std::chrono::steady_clock::duration refreshInterval)
- : mReceiverManager(receiverManager),
- mRefreshInterval(refreshInterval) {
-}
-
-void DefaultBufferPoolSender::setReceiver(
- const sp<IClientManager>& receiverManager,
- std::chrono::steady_clock::duration refreshInterval) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mReceiverManager != receiverManager) {
- mReceiverManager = receiverManager;
- mConnections.clear();
- }
- mRefreshInterval = refreshInterval;
-}
-
-ResultStatus DefaultBufferPoolSender::send(
- const std::shared_ptr<BufferPoolData>& bpData,
- BufferStatusMessage* bpMessage) {
- int64_t connectionId = bpData->mConnectionId;
- if (connectionId == 0) {
- LOG(WARNING) << "registerSender -- invalid sender connection id (0).";
- return ResultStatus::CRITICAL_ERROR;
- }
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mReceiverManager) {
- LOG(ERROR) << "No access to receiver's BufferPool.";
- return ResultStatus::NOT_FOUND;
- }
- if (!mSenderManager) {
- mSenderManager = ClientManager::getInstance();
- if (!mSenderManager) {
- LOG(ERROR) << "Failed to retrieve local BufferPool ClientManager.";
- return ResultStatus::CRITICAL_ERROR;
- }
- }
-
- int64_t receiverConnectionId{0};
- auto foundConnection = mConnections.find(connectionId);
- bool isNewConnection = foundConnection == mConnections.end();
- std::chrono::steady_clock::time_point now =
- std::chrono::steady_clock::now();
- if (isNewConnection ||
- (now - foundConnection->second.lastSent > mRefreshInterval)) {
- // Initialize the bufferpool connection.
- ResultStatus rs =
- mSenderManager->registerSender(mReceiverManager,
- connectionId,
- &receiverConnectionId);
- if ((rs != ResultStatus::OK) && (rs != ResultStatus::ALREADY_EXISTS)) {
- LOG(WARNING) << "registerSender -- returned error: "
- << static_cast<int32_t>(rs)
- << ".";
- return rs;
- } else if (receiverConnectionId == 0) {
- LOG(WARNING) << "registerSender -- "
- "invalid receiver connection id (0).";
- return ResultStatus::CRITICAL_ERROR;
- } else {
- if (isNewConnection) {
- foundConnection = mConnections.try_emplace(
- connectionId, receiverConnectionId, now).first;
- } else {
- foundConnection->second.receiverConnectionId = receiverConnectionId;
- }
- }
- } else {
- receiverConnectionId = foundConnection->second.receiverConnectionId;
- }
-
- uint64_t transactionId;
- int64_t timestampUs;
- ResultStatus rs = mSenderManager->postSend(
- receiverConnectionId, bpData, &transactionId, ×tampUs);
- if (rs != ResultStatus::OK) {
- LOG(ERROR) << "ClientManager::postSend -- returned error: "
- << static_cast<int32_t>(rs)
- << ".";
- mConnections.erase(foundConnection);
- return rs;
- }
- if (!bpMessage) {
- LOG(ERROR) << "Null output parameter for BufferStatusMessage.";
- mConnections.erase(foundConnection);
- return ResultStatus::CRITICAL_ERROR;
- }
- bpMessage->connectionId = receiverConnectionId;
- bpMessage->bufferId = bpData->mId;
- bpMessage->transactionId = transactionId;
- bpMessage->timestampUs = timestampUs;
- foundConnection->second.lastSent = now;
- return rs;
-}
-
// std::list<std::unique_ptr<C2Work>> -> WorkBundle
+template <typename WorkBundle, typename BufferPoolTypes>
bool objcpy(
WorkBundle* d,
const std::list<std::unique_ptr<C2Work>>& s,
- BufferPoolSender* bufferPoolSender) {
+ BufferPoolSender<BufferPoolTypes>* bufferPoolSender) {
// baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
- std::list<BaseBlock> baseBlocks;
+ std::list<typename decltype(d->baseBlocks)::value_type> baseBlocks;
// baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
// inside baseBlocks to the corresponding index into baseBlocks. The keys
@@ -1075,7 +413,7 @@
d->works.resize(s.size());
size_t i = 0;
for (const std::unique_ptr<C2Work>& sWork : s) {
- Work &dWork = d->works[i++];
+ auto &dWork = d->works[i++];
if (!sWork) {
LOG(WARNING) << "Null C2Work encountered.";
continue;
@@ -1095,7 +433,7 @@
LOG(DEBUG) << "Work with no worklets.";
} else {
// Parcel the worklets.
- hidl_vec<Worklet> &dWorklets = dWork.worklets;
+ auto &dWorklets = dWork.worklets;
dWorklets.resize(sWork->worklets.size());
size_t j = 0;
for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
@@ -1105,14 +443,14 @@
<< j << "].";
continue;
}
- Worklet &dWorklet = dWorklets[j++];
+ auto &dWorklet = dWorklets[j++];
// component id
dWorklet.componentId = static_cast<uint32_t>(
sWorklet->component);
// tunings
- if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
+ if (!_createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
LOG(ERROR) << "Invalid C2Work::worklets["
<< j - 1 << "]->tunings.";
return false;
@@ -1151,23 +489,21 @@
dWork.workletsProcessed = sWork->workletsProcessed;
// result
- dWork.result = static_cast<Status>(sWork->result);
+ SetStatus(&dWork.result, sWork->result);
}
- // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
+ // Move std::list<BaseBlock> to vector<BaseBlock>.
{
d->baseBlocks.resize(baseBlocks.size());
size_t i = 0;
- for (const BaseBlock& baseBlock : baseBlocks) {
- d->baseBlocks[i++] = baseBlock;
+ for (auto&& baseBlock : baseBlocks) {
+ d->baseBlocks[i++] = std::move(baseBlock);
}
}
return true;
}
-namespace /* unnamed */ {
-
struct C2BaseBlock {
enum type_t {
LINEAR,
@@ -1178,78 +514,33 @@
std::shared_ptr<C2GraphicBlock> graphic;
};
-// hidl_handle -> C2Fence
+// Handle -> C2Fence
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
-bool objcpy(C2Fence* d, const hidl_handle& s) {
+template <typename Handle>
+bool objcpy(C2Fence* d, const Handle& s) {
const native_handle_t* handle = s.getNativeHandle();
*d = _C2FenceFactory::CreateFromNativeHandle(handle);
return true;
}
// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createLinearBuffer(
+bool CreateLinearBuffer(
std::shared_ptr<C2Buffer>* buffer,
const std::shared_ptr<C2LinearBlock>& block,
const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RangeInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2LinearBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
- LOG(ERROR) << "Invalid range info in C2LinearBlock.";
- return false;
- }
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
-
- // Create C2Buffer from C2LinearBlock.
- *buffer = C2Buffer::CreateLinearBuffer(block->share(
- rangeInfo->offset, rangeInfo->length,
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateLinearBuffer failed.";
- return false;
- }
- return true;
-}
+ const C2Fence& fence);
// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createGraphicBuffer(
+bool CreateGraphicBuffer(
std::shared_ptr<C2Buffer>* buffer,
const std::shared_ptr<C2GraphicBlock>& block,
const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RectInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
- LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
- return false;
- }
- C2Hidl_RectInfo *rectInfo =
- reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
-
- // Create C2Buffer from C2GraphicBlock.
- *buffer = C2Buffer::CreateGraphicBuffer(block->share(
- C2Rect(rectInfo->width, rectInfo->height).
- at(rectInfo->left, rectInfo->top),
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateGraphicBuffer failed.";
- return false;
- }
- return true;
-}
+ const C2Fence& fence);
// Buffer -> C2Buffer
// Note: The native handles will be cloned.
+template <typename Buffer>
bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
const std::vector<C2BaseBlock>& baseBlocks) {
*d = nullptr;
@@ -1263,7 +554,7 @@
return false;
}
- const Block &sBlock = s.blocks[0];
+ const auto &sBlock = s.blocks[0];
if (sBlock.index >= baseBlocks.size()) {
LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
"Array index out of range.";
@@ -1288,13 +579,13 @@
// Construct a block.
switch (baseBlock.type) {
case C2BaseBlock::LINEAR:
- if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
+ if (!CreateLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
LOG(ERROR) << "Invalid C2BaseBlock::linear.";
return false;
}
break;
case C2BaseBlock::GRAPHIC:
- if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
+ if (!CreateGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
return false;
}
@@ -1333,7 +624,10 @@
}
// InfoBuffer -> C2InfoBuffer
-bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
+template <typename InfoBuffer>
+bool objcpy(
+ std::vector<C2InfoBuffer> *d,
+ const InfoBuffer& s,
const std::vector<C2BaseBlock>& baseBlocks) {
// Currently, a non-null C2InfoBufer must contain exactly 1 block.
@@ -1345,7 +639,7 @@
return false;
}
- const Block &sBlock = s.buffer.blocks[0];
+ const auto &sBlock = s.buffer.blocks[0];
if (sBlock.index >= baseBlocks.size()) {
LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
"Array index out of range.";
@@ -1371,11 +665,11 @@
switch (baseBlock.type) {
case C2BaseBlock::LINEAR:
if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
- sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
+ sBlockMeta[0]->size() == sizeof(C2Hal_RangeInfo)) {
+ C2Hal_RangeInfo *rangeInfo =
+ reinterpret_cast<C2Hal_RangeInfo*>(sBlockMeta[0]);
d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
- s.index,
+ uint32_t(s.index),
baseBlock.linear->share(
rangeInfo->offset, rangeInfo->length, dFence)));
return true;
@@ -1395,6 +689,7 @@
}
// FrameData -> C2FrameData
+template <typename FrameData>
bool objcpy(C2FrameData* d, const FrameData& s,
const std::vector<C2BaseBlock>& baseBlocks) {
d->flags = static_cast<C2FrameData::flags_t>(s.flags);
@@ -1404,7 +699,7 @@
}
d->buffers.clear();
d->buffers.reserve(s.buffers.size());
- for (const Buffer& sBuffer : s.buffers) {
+ for (const auto& sBuffer : s.buffers) {
std::shared_ptr<C2Buffer> dBuffer;
if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
LOG(ERROR) << "Invalid FrameData::buffers.";
@@ -1434,7 +729,7 @@
return true;
}
d->infoBuffers.reserve(s.infoBuffers.size());
- for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
+ for (const auto &sInfoBuffer: s.infoBuffers) {
if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
LOG(ERROR) << "Invalid Framedata::infoBuffers.";
return false;
@@ -1444,95 +739,11 @@
}
// BaseBlock -> C2BaseBlock
-bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
- switch (s.getDiscriminator()) {
- case BaseBlock::hidl_discriminator::nativeBlock: {
- if (s.nativeBlock() == nullptr) {
- LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
- return false;
- }
- native_handle_t* sHandle =
- native_handle_clone(s.nativeBlock());
- if (sHandle == nullptr) {
- LOG(ERROR) << "Null BaseBlock::nativeBlock.";
- return false;
- }
- const C2Handle *sC2Handle =
- reinterpret_cast<const C2Handle*>(sHandle);
-
- d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
- if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
- return true;
- }
-
- d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
- if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
- return true;
- }
-
- LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
- if (sHandle) {
- native_handle_close(sHandle);
- native_handle_delete(sHandle);
- }
- return false;
- }
- case BaseBlock::hidl_discriminator::pooledBlock: {
- const BufferStatusMessage &bpMessage =
- s.pooledBlock();
- sp<ClientManager> bp = ClientManager::getInstance();
- std::shared_ptr<BufferPoolData> bpData;
- native_handle_t *cHandle;
- ResultStatus bpStatus = bp->receive(
- bpMessage.connectionId,
- bpMessage.transactionId,
- bpMessage.bufferId,
- bpMessage.timestampUs,
- &cHandle,
- &bpData);
- if (bpStatus != ResultStatus::OK) {
- LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
- << "resultStatus = " << underlying_value(bpStatus)
- << ".";
- return false;
- } else if (!bpData) {
- LOG(ERROR) << "No data in bufferpool transaction.";
- return false;
- }
-
- d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
- if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
- return true;
- }
-
- d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
- if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
- return true;
- }
- if (cHandle) {
- // Though we got cloned handle, creating block failed.
- native_handle_close(cHandle);
- native_handle_delete(cHandle);
- }
-
- LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
- return false;
- }
- default:
- LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
- << "underlying value "
- << underlying_value(s.getDiscriminator()) << ".";
- return false;
- }
-}
-
-} // unnamed namespace
+template <typename BaseBlock>
+bool objcpy(C2BaseBlock* d, const BaseBlock& s);
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
+template <typename WorkBundle>
bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
// Convert BaseBlocks to C2BaseBlocks.
std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
@@ -1545,7 +756,7 @@
}
d->clear();
- for (const Work& sWork : s.works) {
+ for (const auto& sWork : s.works) {
d->emplace_back(std::make_unique<C2Work>());
C2Work& dWork = *d->back();
@@ -1559,7 +770,7 @@
// worklet(s)
dWork.worklets.clear();
- for (const Worklet& sWorklet : sWork.worklets) {
+ for (const auto& sWorklet : sWork.worklets) {
std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
// component id
@@ -1567,7 +778,7 @@
sWorklet.componentId);
// tunings
- if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
+ if (!_copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
LOG(ERROR) << "Invalid Worklet::tunings";
return false;
}
@@ -1575,7 +786,7 @@
// failures
dWorklet->failures.clear();
dWorklet->failures.reserve(sWorklet.failures.size());
- for (const SettingResult& sFailure : sWorklet.failures) {
+ for (const auto& sFailure : sWorklet.failures) {
std::unique_ptr<C2SettingResult> dFailure;
if (!objcpy(&dFailure, sFailure)) {
LOG(ERROR) << "Invalid Worklet::failures.";
@@ -1597,332 +808,56 @@
dWork.workletsProcessed = sWork.workletsProcessed;
// result
- dWork.result = static_cast<c2_status_t>(sWork.result);
+ dWork.result = GetStatus(sWork.result);
}
return true;
}
-constexpr size_t PARAMS_ALIGNMENT = 8; // 64-bit alignment
-static_assert(PARAMS_ALIGNMENT % alignof(C2Param) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Info) == 0, "C2Param alignment mismatch");
-static_assert(PARAMS_ALIGNMENT % alignof(C2Tuning) == 0, "C2Param alignment mismatch");
+// BufferQueue-Based Block Operations
+// ==================================
-// Params -> std::vector<C2Param*>
-bool parseParamsBlob(std::vector<C2Param*> *params, const hidl_vec<uint8_t> &blob) {
- // assuming blob is const here
- size_t size = blob.size();
- size_t ix = 0;
- size_t old_ix = 0;
- const uint8_t *data = blob.data();
- C2Param *p = nullptr;
+// Call before transferring block to other processes.
+//
+// The given block is ready to transfer to other processes. This will guarantee
+// the given block data is not mutated by bufferqueue migration.
+bool BeginTransferBufferQueueBlock(const C2ConstGraphicBlock& block);
- do {
- p = C2ParamUtils::ParseFirst(data + ix, size - ix);
- if (p) {
- params->emplace_back(p);
- old_ix = ix;
- ix += p->size();
- ix = align(ix, PARAMS_ALIGNMENT);
- if (ix <= old_ix || ix > size) {
- android_errorWriteLog(0x534e4554, "238083570");
- break;
- }
- }
- } while (p);
-
- if (ix != size) {
- LOG(ERROR) << "parseParamsBlob -- inconsistent sizes.";
- return false;
- }
- return true;
-}
-
-namespace /* unnamed */ {
-
-/**
- * Concatenates a list of C2Params into a params blob. T is a container type
- * whose member type is compatible with C2Param*.
- *
- * \param[out] blob target blob
- * \param[in] params parameters to concatenate
- * \retval C2_OK if the blob was successfully created
- * \retval C2_BAD_VALUE if the blob was not successful created (this only
- * happens if the parameters were not const)
- */
-template <typename T>
-bool _createParamsBlob(hidl_vec<uint8_t> *blob, const T ¶ms) {
- // assuming the parameter values are const
- size_t size = 0;
- for (const auto &p : params) {
- if (!p) {
- continue;
- }
- size += p->size();
- size = align(size, PARAMS_ALIGNMENT);
- }
- blob->resize(size);
- size_t ix = 0;
- for (const auto &p : params) {
- if (!p) {
- continue;
- }
- // NEVER overwrite even if param values (e.g. size) changed
- size_t paramSize = std::min(p->size(), size - ix);
- std::copy(
- reinterpret_cast<const uint8_t*>(&*p),
- reinterpret_cast<const uint8_t*>(&*p) + paramSize,
- &(*blob)[ix]);
- ix += paramSize;
- ix = align(ix, PARAMS_ALIGNMENT);
- }
- blob->resize(ix);
- if (ix != size) {
- LOG(ERROR) << "createParamsBlob -- inconsistent sizes.";
- return false;
- }
- return true;
-}
-
-/**
- * Parses a params blob and create a vector of new T objects that contain copies
- * of the params in the blob. T is C2Param or its compatible derived class.
- *
- * \param[out] params the resulting vector
- * \param[in] blob parameter blob to parse
- * \retval C2_OK if the full blob was parsed and params was constructed
- * \retval C2_BAD_VALUE otherwise
- */
-template <typename T>
-bool _copyParamsFromBlob(
- std::vector<std::unique_ptr<T>>* params,
- Params blob) {
-
- std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, blob)) {
- LOG(ERROR) << "copyParamsFromBlob -- failed to parse.";
- return false;
- }
-
- params->resize(paramPointers.size());
- size_t i = 0;
- for (C2Param* const& paramPointer : paramPointers) {
- if (!paramPointer) {
- LOG(ERROR) << "copyParamsFromBlob -- null paramPointer.";
- return false;
- }
- (*params)[i++].reset(reinterpret_cast<T*>(
- C2Param::Copy(*paramPointer).release()));
- }
- return true;
-}
-
-} // unnamed namespace
-
-// std::vector<const C2Param*> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<const C2Param*> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<C2Param*> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<C2Param*> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Param>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Param>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::unique_ptr<C2Tuning>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::unique_ptr<C2Tuning>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// std::vector<std::shared_ptr<const C2Info>> -> Params
-bool createParamsBlob(
- hidl_vec<uint8_t> *blob,
- const std::vector<std::shared_ptr<const C2Info>> ¶ms) {
- return _createParamsBlob(blob, params);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Param>>
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Param>>* params,
- Params blob) {
- return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> std::vector<std::unique_ptr<C2Tuning>>
-bool copyParamsFromBlob(
- std::vector<std::unique_ptr<C2Tuning>>* params,
- Params blob) {
- return _copyParamsFromBlob(params, blob);
-}
-
-// Params -> update std::vector<std::unique_ptr<C2Param>>
-bool updateParamsFromBlob(
- const std::vector<C2Param*>& params,
- const Params& blob) {
- std::unordered_map<uint32_t, C2Param*> index2param;
- for (C2Param* const& param : params) {
- if (!param) {
- LOG(ERROR) << "updateParamsFromBlob -- null output param.";
- return false;
- }
- if (index2param.find(param->index()) == index2param.end()) {
- index2param.emplace(param->index(), param);
- }
- }
-
- std::vector<C2Param*> paramPointers;
- if (!parseParamsBlob(¶mPointers, blob)) {
- LOG(ERROR) << "updateParamsFromBlob -- failed to parse.";
- return false;
- }
-
- for (C2Param* const& paramPointer : paramPointers) {
- if (!paramPointer) {
- LOG(ERROR) << "updateParamsFromBlob -- null input param.";
- return false;
- }
- decltype(index2param)::iterator i = index2param.find(
- paramPointer->index());
- if (i == index2param.end()) {
- LOG(DEBUG) << "updateParamsFromBlob -- index "
- << paramPointer->index() << " not found. Skipping...";
- continue;
- }
- if (!i->second->updateFrom(*paramPointer)) {
- LOG(ERROR) << "updateParamsFromBlob -- size mismatch: "
- << params.size() << " vs " << paramPointer->size()
- << " (index = " << i->first << ").";
- return false;
- }
- }
- return true;
-}
-
-// Convert BufferPool ResultStatus to c2_status_t.
-c2_status_t toC2Status(ResultStatus rs) {
- switch (rs) {
- case ResultStatus::OK:
- return C2_OK;
- case ResultStatus::NO_MEMORY:
- return C2_NO_MEMORY;
- case ResultStatus::ALREADY_EXISTS:
- return C2_DUPLICATE;
- case ResultStatus::NOT_FOUND:
- return C2_NOT_FOUND;
- case ResultStatus::CRITICAL_ERROR:
- return C2_CORRUPTED;
- default:
- LOG(WARNING) << "Unrecognized BufferPool ResultStatus: "
- << static_cast<int32_t>(rs) << ".";
- return C2_CORRUPTED;
- }
-}
-
-namespace /* unnamed */ {
-
-template <typename BlockProcessor>
-void forEachBlock(C2FrameData& frameData,
- BlockProcessor process) {
- for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
- if (buffer) {
- for (const C2ConstGraphicBlock& block :
- buffer->data().graphicBlocks()) {
- process(block);
- }
- }
- }
-}
-
-template <typename BlockProcessor>
-void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
- BlockProcessor process,
- bool processInput, bool processOutput) {
- for (const std::unique_ptr<C2Work>& work : workList) {
- if (!work) {
- continue;
- }
- if (processInput) {
- forEachBlock(work->input, process);
- }
- if (processOutput) {
- for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
- if (worklet) {
- forEachBlock(worklet->output,
- process);
- }
- }
- }
- }
-}
-
-} // unnamed namespace
-
-bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::BeginTransferBlockToClient(data);
- return true;
- }
- return false;
-}
-
-void beginTransferBufferQueueBlocks(
+// Call beginTransferBufferQueueBlock() on blocks in the given workList.
+// processInput determines whether input blocks are yielded. processOutput
+// works similarly on output blocks. (The default value of processInput is
+// false while the default value of processOutput is true. This implies that in
+// most cases, only output buffers contain bufferqueue-based blocks.)
+void BeginTransferBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList,
- bool processInput, bool processOutput) {
- forEachBlock(workList, beginTransferBufferQueueBlock,
- processInput, processOutput);
-}
+ bool processInput = false,
+ bool processOutput = true);
-bool endTransferBufferQueueBlock(
- const C2ConstGraphicBlock& block,
- bool transfer) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::EndTransferBlockToClient(data, transfer);
- return true;
- }
- return false;
-}
+// Call after transferring block is finished and make sure that
+// beginTransferBufferQueueBlock() is called before.
+//
+// The transfer of given block is finished. If transfer is successful the given
+// block is not owned by process anymore. Since transfer is finished the given
+// block data is OK to mutate by bufferqueue migration after this call.
+bool EndTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
+ bool transfer);
-void endTransferBufferQueueBlocks(
+// Call endTransferBufferQueueBlock() on blocks in the given workList.
+// processInput determines whether input blocks are yielded. processOutput
+// works similarly on output blocks. (The default value of processInput is
+// false while the default value of processOutput is true. This implies that in
+// most cases, only output buffers contain bufferqueue-based blocks.)
+void EndTransferBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList,
bool transfer,
- bool processInput, bool processOutput) {
- forEachBlock(workList,
- std::bind(endTransferBufferQueueBlock,
- std::placeholders::_1, transfer),
- processInput, processOutput);
-}
+ bool processInput = false,
+ bool processOutput = true);
-bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::DisplayBlockToBufferQueue(data);
- return true;
- }
- return false;
-}
+// The given block is ready to be rendered. the given block is not owned by
+// process anymore. If migration is in progress, this returns false in order
+// not to render.
+bool DisplayBufferQueueBlock(const C2ConstGraphicBlock& block);
-} // namespace utils
-} // namespace V1_0
-} // namespace c2
-} // namespace media
-} // namespace hardware
} // namespace android
+#endif // CODEC2_COMMON_BUFFER_TYPES_H
diff --git a/media/codec2/hal/hidl/1.0/utils/Android.bp b/media/codec2/hal/hidl/1.0/utils/Android.bp
index 2933940..2f2ecd1 100644
--- a/media/codec2/hal/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hal/hidl/1.0/utils/Android.bp
@@ -19,7 +19,6 @@
],
header_libs: [
- "libcodec2_hal_common",
"libcodec2_internal", // private
],
@@ -28,6 +27,7 @@
"android.hardware.media.c2@1.0",
"libbase",
"libcodec2",
+ "libcodec2_hal_common",
"libcodec2_vndk",
"libcutils",
"libgui",
@@ -45,6 +45,7 @@
export_shared_lib_headers: [
"android.hardware.media.c2@1.0",
"libcodec2",
+ "libcodec2_hal_common",
"libgui",
"libstagefright_bufferpool@2.0.1",
"libui",
@@ -78,7 +79,6 @@
header_libs: [
"libbinder_headers",
- "libcodec2_hal_common",
"libcodec2_internal", // private
"libsystem_headers",
],
@@ -93,8 +93,9 @@
"android.hardware.media.omx@1.0",
"libbase",
"libcodec2",
- "libcodec2_vndk",
+ "libcodec2_hal_common",
"libcodec2_hidl_plugin_stub",
+ "libcodec2_vndk",
"libcutils",
"libhidlbase",
"liblog",
@@ -130,6 +131,7 @@
export_shared_lib_headers: [
"android.hardware.media.c2@1.0",
"libcodec2",
+ "libcodec2_hal_common",
"libcodec2_vndk",
"libhidlbase",
"libstagefright_bufferpool@2.0.1",
diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index f111f81..20e3fb5 100644
--- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -23,6 +23,7 @@
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <android/hardware/media/c2/1.0/types.h>
#include <android/hidl/safe_union/1.0/types.h>
+#include <codec2/common/BufferPoolSender.h>
#include <C2Component.h>
#include <C2Param.h>
@@ -42,8 +43,6 @@
namespace utils {
using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::status_t;
using ::android::sp;
@@ -134,38 +133,15 @@
std::unique_ptr<C2StructDescriptor>* d,
const StructDescriptor& s);
-// Abstract class to be used in
-// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
-struct BufferPoolSender {
- typedef ::android::hardware::media::bufferpool::V2_0::
- ResultStatus ResultStatus;
- typedef ::android::hardware::media::bufferpool::V2_0::
- BufferStatusMessage BufferStatusMessage;
- typedef ::android::hardware::media::bufferpool::
- BufferPoolData BufferPoolData;
-
- /**
- * Send bpData and return BufferStatusMessage that can be supplied to
- * IClientManager::receive() in the receiving process.
- *
- * This function will be called from within the function
- * objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
- *
- * \param[in] bpData BufferPoolData identifying the buffer to send.
- * \param[out] bpMessage BufferStatusMessage of the transaction. Information
- * inside \p bpMessage should be passed to the receiving process by some
- * other means so it can call receive() properly.
- * \return ResultStatus value that determines the success of the operation.
- * (See the possible values of ResultStatus in
- * hardware/interfaces/media/bufferpool/2.0/types.hal.)
- */
- virtual ResultStatus send(
- const std::shared_ptr<BufferPoolData>& bpData,
- BufferStatusMessage* bpMessage) = 0;
-
- virtual ~BufferPoolSender() = default;
+struct BufferPoolTypes {
+ typedef bufferpool::BufferPoolData BufferPoolData;
+ typedef bufferpool::V2_0::ResultStatus BufferPoolStatus;
+ typedef bufferpool::V2_0::ResultStatus ResultStatus;
+ typedef bufferpool::V2_0::BufferStatusMessage BufferStatusMessage;
};
+typedef ::android::BufferPoolSender<BufferPoolTypes> BufferPoolSender;
+
// Default implementation of BufferPoolSender.
//
// To use DefaultBufferPoolSender, the IClientManager instance of the receiving
@@ -198,7 +174,7 @@
// Implementation of BufferPoolSender::send(). send() will establish a
// bufferpool connection if needed, then send the bufferpool data over to
// the receiving process.
- virtual ResultStatus send(
+ ResultStatus send(
const std::shared_ptr<BufferPoolData>& bpData,
BufferStatusMessage* bpMessage) override;
diff --git a/media/codec2/hal/hidl/1.0/utils/types.cpp b/media/codec2/hal/hidl/1.0/utils/types.cpp
index e17aad4..abe5494 100644
--- a/media/codec2/hal/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/types.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "Codec2-types"
#include <android-base/logging.h>
+#include <bufferpool/ClientManager.h>
+#include <codec2/common/BufferTypes.h>
#include <codec2/common/ParamTypes.h>
#include <codec2/hidl/1.0/types.h>
@@ -32,9 +34,12 @@
namespace android {
+using hardware::media::bufferpool::V2_0::implementation::ClientManager;
+using hardware::media::c2::V1_0::BaseBlock;
using hardware::media::c2::V1_0::FieldSupportedValues;
using hardware::media::c2::V1_0::PrimitiveValue;
using hardware::media::c2::V1_0::ValueRange;
+using hardware::media::c2::V1_0::utils::BufferPoolTypes;
using hardware::hidl_vec;
// C2FieldSupportedValues -> FieldSupportedValues
@@ -112,6 +117,112 @@
return true;
}
+template<>
+bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
+ switch (s.getDiscriminator()) {
+ case BaseBlock::hidl_discriminator::nativeBlock: {
+ if (s.nativeBlock() == nullptr) {
+ LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
+ return false;
+ }
+ native_handle_t* sHandle =
+ native_handle_clone(s.nativeBlock());
+ if (sHandle == nullptr) {
+ LOG(ERROR) << "Null BaseBlock::nativeBlock.";
+ return false;
+ }
+ const C2Handle *sC2Handle =
+ reinterpret_cast<const C2Handle*>(sHandle);
+
+ d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
+ if (d->linear) {
+ d->type = C2BaseBlock::LINEAR;
+ return true;
+ }
+
+ d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
+ if (d->graphic) {
+ d->type = C2BaseBlock::GRAPHIC;
+ return true;
+ }
+
+ LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
+ if (sHandle) {
+ native_handle_close(sHandle);
+ native_handle_delete(sHandle);
+ }
+ return false;
+ }
+ case BaseBlock::hidl_discriminator::pooledBlock: {
+ const BufferPoolTypes::BufferStatusMessage &bpMessage =
+ s.pooledBlock();
+ sp<ClientManager> bp = ClientManager::getInstance();
+ std::shared_ptr<BufferPoolTypes::BufferPoolData> bpData;
+ native_handle_t *cHandle;
+ BufferPoolTypes::BufferPoolStatus bpStatus = bp->receive(
+ bpMessage.connectionId,
+ bpMessage.transactionId,
+ bpMessage.bufferId,
+ bpMessage.timestampUs,
+ &cHandle,
+ &bpData);
+ if (bpStatus != BufferPoolTypes::ResultStatus::OK) {
+ LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
+ << "resultStatus = " << underlying_value(bpStatus)
+ << ".";
+ return false;
+ } else if (!bpData) {
+ LOG(ERROR) << "No data in bufferpool transaction.";
+ return false;
+ }
+
+ d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
+ if (d->linear) {
+ d->type = C2BaseBlock::LINEAR;
+ return true;
+ }
+
+ d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
+ if (d->graphic) {
+ d->type = C2BaseBlock::GRAPHIC;
+ return true;
+ }
+ if (cHandle) {
+ // Though we got cloned handle, creating block failed.
+ native_handle_close(cHandle);
+ native_handle_delete(cHandle);
+ }
+
+ LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
+ return false;
+ }
+ default:
+ LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
+ << "underlying value "
+ << underlying_value(s.getDiscriminator()) << ".";
+ return false;
+ }
+}
+
+template<>
+void SetHandle(BaseBlock *block, const C2Handle *handle) {
+ block->nativeBlock(reinterpret_cast<const native_handle_t*>(handle));
+}
+
+template<>
+void SetPooledBlock<BufferPoolTypes>(
+ BaseBlock *baseBlock,
+ const typename BufferPoolTypes::BufferStatusMessage &pooledBlock) {
+ baseBlock->pooledBlock(pooledBlock);
+}
+
+template<>
+bool GetBufferPoolData<BufferPoolTypes>(
+ const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
+ std::shared_ptr<typename BufferPoolTypes::BufferPoolData> *bpData) {
+ return _C2BlockFactory::GetBufferPoolData(blockPoolData, bpData);
+}
+
namespace hardware {
namespace media {
namespace c2 {
@@ -119,11 +230,8 @@
namespace utils {
using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
using ::android::hardware::media::bufferpool::V2_0::implementation::
- ClientManager;
-using ::android::hardware::media::bufferpool::V2_0::implementation::
TransactionId;
const char* asString(Status status, const char* def) {
@@ -204,320 +312,6 @@
return ::android::objcpy(d, s);
}
-namespace /* unnamed */ {
-
-// Find or add a hidl BaseBlock object from a given C2Handle* to a list and an
-// associated map.
-// Note: The handle is not cloned.
-bool _addBaseBlock(
- uint32_t* index,
- const C2Handle* handle,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!handle) {
- LOG(ERROR) << "addBaseBlock called on a null C2Handle.";
- return false;
- }
- auto it = baseBlockIndices->find(handle);
- if (it != baseBlockIndices->end()) {
- *index = it->second;
- } else {
- *index = baseBlocks->size();
- baseBlockIndices->emplace(handle, *index);
- baseBlocks->emplace_back();
-
- BaseBlock &dBaseBlock = baseBlocks->back();
- // This does not clone the handle.
- dBaseBlock.nativeBlock(
- reinterpret_cast<const native_handle_t*>(handle));
- }
- return true;
-}
-
-// Find or add a hidl BaseBlock object from a given BufferPoolData to a list and
-// an associated map.
-bool _addBaseBlock(
- uint32_t* index,
- const std::shared_ptr<BufferPoolData> bpData,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!bpData) {
- LOG(ERROR) << "addBaseBlock called on a null BufferPoolData.";
- return false;
- }
- auto it = baseBlockIndices->find(bpData.get());
- if (it != baseBlockIndices->end()) {
- *index = it->second;
- } else {
- *index = baseBlocks->size();
- baseBlockIndices->emplace(bpData.get(), *index);
- baseBlocks->emplace_back();
-
- BaseBlock &dBaseBlock = baseBlocks->back();
-
- if (bufferPoolSender) {
- BufferStatusMessage pooledBlock;
- ResultStatus bpStatus = bufferPoolSender->send(
- bpData,
- &pooledBlock);
-
- if (bpStatus != ResultStatus::OK) {
- LOG(ERROR) << "Failed to send buffer with BufferPool. Error: "
- << static_cast<int32_t>(bpStatus)
- << ".";
- return false;
- }
- dBaseBlock.pooledBlock(pooledBlock);
- }
- }
- return true;
-}
-
-bool addBaseBlock(
- uint32_t* index,
- const C2Handle* handle,
- const std::shared_ptr<const _C2BlockPoolData>& blockPoolData,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!blockPoolData) {
- // No BufferPoolData ==> NATIVE block.
- return _addBaseBlock(
- index, handle,
- baseBlocks, baseBlockIndices);
- }
- switch (blockPoolData->getType()) {
- case _C2BlockPoolData::TYPE_BUFFERPOOL: {
- // BufferPoolData
- std::shared_ptr<BufferPoolData> bpData;
- if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData)
- || !bpData) {
- LOG(ERROR) << "BufferPoolData unavailable in a block.";
- return false;
- }
- return _addBaseBlock(
- index, bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices);
- }
- case _C2BlockPoolData::TYPE_BUFFERQUEUE:
- uint32_t gen;
- uint64_t bqId;
- int32_t bqSlot;
- // Update handle if migration happened.
- if (_C2BlockFactory::GetBufferQueueData(
- blockPoolData, &gen, &bqId, &bqSlot)) {
- android::MigrateNativeCodec2GrallocHandle(
- const_cast<native_handle_t*>(handle), gen, bqId, bqSlot);
- }
- return _addBaseBlock(
- index, handle,
- baseBlocks, baseBlockIndices);
- default:
- LOG(ERROR) << "Unknown C2BlockPoolData type.";
- return false;
- }
-}
-
-// C2Fence -> hidl_handle
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(hidl_handle* d, const C2Fence& s) {
- d->setTo(nullptr);
- native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
- if (handle) {
- d->setTo(handle, true /* owns */);
-// } else if (!s.ready()) {
-// // TODO: we should wait for unmarshallable fences but this may not be
-// // the best place for it. We can safely ignore here as at this time
-// // all fences used here are marshallable.
- }
- return true;
-}
-
-// C2ConstLinearBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstLinearBlock& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- std::shared_ptr<const _C2BlockPoolData> bpData =
- _C2BlockFactory::GetLinearBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid block data in C2ConstLinearBlock.";
- return false;
- }
-
- // Create the metadata.
- C2Hidl_RangeInfo dRangeInfo;
- dRangeInfo.offset = static_cast<uint32_t>(s.offset());
- dRangeInfo.length = static_cast<uint32_t>(s.size());
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRangeInfo })) {
- LOG(ERROR) << "Invalid range info in C2ConstLinearBlock.";
- return false;
- }
-
- // Copy the fence
- if (!objcpy(&d->fence, s.fence())) {
- LOG(ERROR) << "Invalid C2ConstLinearBlock::fence.";
- return false;
- }
- return true;
-}
-
-// C2ConstGraphicBlock -> Block
-// Note: Native handles are not duplicated. The original handles must not be
-// closed before the transaction is complete.
-bool objcpy(Block* d, const C2ConstGraphicBlock& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- std::shared_ptr<const _C2BlockPoolData> bpData =
- _C2BlockFactory::GetGraphicBlockPoolData(s);
- if (!addBaseBlock(&d->index, s.handle(), bpData,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid block data in C2ConstGraphicBlock.";
- return false;
- }
-
- // Create the metadata.
- C2Hidl_RectInfo dRectInfo;
- C2Rect sRect = s.crop();
- dRectInfo.left = static_cast<uint32_t>(sRect.left);
- dRectInfo.top = static_cast<uint32_t>(sRect.top);
- dRectInfo.width = static_cast<uint32_t>(sRect.width);
- dRectInfo.height = static_cast<uint32_t>(sRect.height);
- if (!createParamsBlob(&d->meta, std::vector<C2Param*>{ &dRectInfo })) {
- LOG(ERROR) << "Invalid rect info in C2ConstGraphicBlock.";
- return false;
- }
-
- // Copy the fence
- if (!objcpy(&d->fence, s.fence())) {
- LOG(ERROR) << "Invalid C2ConstGraphicBlock::fence.";
- return false;
- }
- return true;
-}
-
-// C2BufferData -> Buffer
-// This function only fills in d->blocks.
-bool objcpy(Buffer* d, const C2BufferData& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->blocks.resize(
- s.linearBlocks().size() +
- s.graphicBlocks().size());
- size_t i = 0;
- for (const C2ConstLinearBlock& linearBlock : s.linearBlocks()) {
- Block& dBlock = d->blocks[i++];
- if (!objcpy(
- &dBlock, linearBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2BufferData::linearBlocks. "
- << "(Destination index = " << i - 1 << ".)";
- return false;
- }
- }
- for (const C2ConstGraphicBlock& graphicBlock : s.graphicBlocks()) {
- Block& dBlock = d->blocks[i++];
- if (!objcpy(
- &dBlock, graphicBlock,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2BufferData::graphicBlocks. "
- << "(Destination index = " << i - 1 << ".)";
- return false;
- }
- }
- return true;
-}
-
-// C2Buffer -> Buffer
-bool objcpy(Buffer* d, const C2Buffer& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- if (!createParamsBlob(&d->info, s.info())) {
- LOG(ERROR) << "Invalid C2Buffer::info.";
- return false;
- }
- if (!objcpy(d, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Buffer::data.";
- return false;
- }
- return true;
-}
-
-// C2InfoBuffer -> InfoBuffer
-bool objcpy(InfoBuffer* d, const C2InfoBuffer& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->index = static_cast<ParamIndex>(s.index());
- Buffer& dBuffer = d->buffer;
- if (!objcpy(&dBuffer, s.data(), bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2InfoBuffer::data";
- return false;
- }
- return true;
-}
-
-// C2FrameData -> FrameData
-bool objcpy(FrameData* d, const C2FrameData& s,
- BufferPoolSender* bufferPoolSender,
- std::list<BaseBlock>* baseBlocks,
- std::map<const void*, uint32_t>* baseBlockIndices) {
- d->flags = static_cast<hidl_bitfield<FrameData::Flags>>(s.flags);
- if (!::android::objcpy(&d->ordinal, s.ordinal)) {
- LOG(ERROR) << "Invalid C2FrameData::ordinal.";
- return false;
- }
-
- d->buffers.resize(s.buffers.size());
- size_t i = 0;
- for (const std::shared_ptr<C2Buffer>& sBuffer : s.buffers) {
- Buffer& dBuffer = d->buffers[i++];
- if (!sBuffer) {
- // A null (pointer to) C2Buffer corresponds to a Buffer with empty
- // info and blocks.
- dBuffer.info.resize(0);
- dBuffer.blocks.resize(0);
- continue;
- }
- if (!objcpy(
- &dBuffer, *sBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2FrameData::buffers["
- << i - 1 << "].";
- return false;
- }
- }
-
- if (!createParamsBlob(&d->configUpdate, s.configUpdate)) {
- LOG(ERROR) << "Invalid C2FrameData::configUpdate.";
- return false;
- }
-
- d->infoBuffers.resize(s.infoBuffers.size());
- i = 0;
- for (const C2InfoBuffer& sInfoBuffer : s.infoBuffers) {
- InfoBuffer& dInfoBuffer = d->infoBuffers[i++];
- if (!objcpy(&dInfoBuffer, sInfoBuffer,
- bufferPoolSender, baseBlocks, baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2FrameData::infoBuffers["
- << i - 1 << "].";
- return false;
- }
- }
-
- return true;
-}
-
-} // unnamed namespace
-
// DefaultBufferPoolSender's implementation
DefaultBufferPoolSender::DefaultBufferPoolSender(
@@ -621,549 +415,12 @@
WorkBundle* d,
const std::list<std::unique_ptr<C2Work>>& s,
BufferPoolSender* bufferPoolSender) {
- // baseBlocks holds a list of BaseBlock objects that Blocks can refer to.
- std::list<BaseBlock> baseBlocks;
-
- // baseBlockIndices maps a raw pointer to native_handle_t or BufferPoolData
- // inside baseBlocks to the corresponding index into baseBlocks. The keys
- // (pointers) are used to identify blocks that have the same "base block" in
- // s, a list of C2Work objects. Because baseBlocks will be copied into a
- // hidl_vec eventually, the values of baseBlockIndices are zero-based
- // integer indices instead of list iterators.
- //
- // Note that the pointers can be raw because baseBlockIndices has a shorter
- // lifespan than all of base blocks.
- std::map<const void*, uint32_t> baseBlockIndices;
-
- d->works.resize(s.size());
- size_t i = 0;
- for (const std::unique_ptr<C2Work>& sWork : s) {
- Work &dWork = d->works[i++];
- if (!sWork) {
- LOG(WARNING) << "Null C2Work encountered.";
- continue;
- }
-
- // chain info is not in use currently.
-
- // input
- if (!objcpy(&dWork.input, sWork->input,
- bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Work::input.";
- return false;
- }
-
- // worklets
- if (sWork->worklets.size() == 0) {
- LOG(DEBUG) << "Work with no worklets.";
- } else {
- // Parcel the worklets.
- hidl_vec<Worklet> &dWorklets = dWork.worklets;
- dWorklets.resize(sWork->worklets.size());
- size_t j = 0;
- for (const std::unique_ptr<C2Worklet>& sWorklet : sWork->worklets)
- {
- if (!sWorklet) {
- LOG(WARNING) << "Null C2Work::worklets["
- << j << "].";
- continue;
- }
- Worklet &dWorklet = dWorklets[j++];
-
- // component id
- dWorklet.componentId = static_cast<uint32_t>(
- sWorklet->component);
-
- // tunings
- if (!createParamsBlob(&dWorklet.tunings, sWorklet->tunings)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->tunings.";
- return false;
- }
-
- // failures
- dWorklet.failures.resize(sWorklet->failures.size());
- size_t k = 0;
- for (const std::unique_ptr<C2SettingResult>& sFailure :
- sWorklet->failures) {
- if (!sFailure) {
- LOG(WARNING) << "Null C2Work::worklets["
- << j - 1 << "]->failures["
- << k << "].";
- continue;
- }
- if (!objcpy(&dWorklet.failures[k++], *sFailure)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->failures["
- << k - 1 << "].";
- return false;
- }
- }
-
- // output
- if (!objcpy(&dWorklet.output, sWorklet->output,
- bufferPoolSender, &baseBlocks, &baseBlockIndices)) {
- LOG(ERROR) << "Invalid C2Work::worklets["
- << j - 1 << "]->output.";
- return false;
- }
- }
- }
-
- // worklets processed
- dWork.workletsProcessed = sWork->workletsProcessed;
-
- // result
- dWork.result = static_cast<Status>(sWork->result);
- }
-
- // Copy std::list<BaseBlock> to hidl_vec<BaseBlock>.
- {
- d->baseBlocks.resize(baseBlocks.size());
- size_t i = 0;
- for (const BaseBlock& baseBlock : baseBlocks) {
- d->baseBlocks[i++] = baseBlock;
- }
- }
-
- return true;
+ return ::android::objcpy(d, s, bufferPoolSender);
}
-namespace /* unnamed */ {
-
-struct C2BaseBlock {
- enum type_t {
- LINEAR,
- GRAPHIC,
- };
- type_t type;
- std::shared_ptr<C2LinearBlock> linear;
- std::shared_ptr<C2GraphicBlock> graphic;
-};
-
-// hidl_handle -> C2Fence
-// Note: File descriptors are not duplicated. The original file descriptor must
-// not be closed before the transaction is complete.
-bool objcpy(C2Fence* d, const hidl_handle& s) {
- const native_handle_t* handle = s.getNativeHandle();
- *d = _C2FenceFactory::CreateFromNativeHandle(handle);
- return true;
-}
-
-// C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createLinearBuffer(
- std::shared_ptr<C2Buffer>* buffer,
- const std::shared_ptr<C2LinearBlock>& block,
- const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RangeInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2LinearBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RangeInfo)) {
- LOG(ERROR) << "Invalid range info in C2LinearBlock.";
- return false;
- }
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(meta[0]);
-
- // Create C2Buffer from C2LinearBlock.
- *buffer = C2Buffer::CreateLinearBuffer(block->share(
- rangeInfo->offset, rangeInfo->length,
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateLinearBuffer failed.";
- return false;
- }
- return true;
-}
-
-// C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
-bool createGraphicBuffer(
- std::shared_ptr<C2Buffer>* buffer,
- const std::shared_ptr<C2GraphicBlock>& block,
- const std::vector<C2Param*>& meta,
- const C2Fence& fence) {
- // Check the block meta. It should have exactly 1 C2Info:
- // C2Hidl_RectInfo.
- if ((meta.size() != 1) || !meta[0]) {
- LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
- return false;
- }
- if (meta[0]->size() != sizeof(C2Hidl_RectInfo)) {
- LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
- return false;
- }
- C2Hidl_RectInfo *rectInfo =
- reinterpret_cast<C2Hidl_RectInfo*>(meta[0]);
-
- // Create C2Buffer from C2GraphicBlock.
- *buffer = C2Buffer::CreateGraphicBuffer(block->share(
- C2Rect(rectInfo->width, rectInfo->height).
- at(rectInfo->left, rectInfo->top),
- fence));
- if (!(*buffer)) {
- LOG(ERROR) << "CreateGraphicBuffer failed.";
- return false;
- }
- return true;
-}
-
-// Buffer -> C2Buffer
-// Note: The native handles will be cloned.
-bool objcpy(std::shared_ptr<C2Buffer>* d, const Buffer& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
- *d = nullptr;
-
- // Currently, a non-null C2Buffer must contain exactly 1 block.
- if (s.blocks.size() == 0) {
- return true;
- } else if (s.blocks.size() != 1) {
- LOG(ERROR) << "Invalid Buffer: "
- "Currently, a C2Buffer must contain exactly 1 block.";
- return false;
- }
-
- const Block &sBlock = s.blocks[0];
- if (sBlock.index >= baseBlocks.size()) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].index: "
- "Array index out of range.";
- return false;
- }
- const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
- // Parse meta.
- std::vector<C2Param*> sBlockMeta;
- if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].meta.";
- return false;
- }
-
- // Copy fence.
- C2Fence dFence;
- if (!objcpy(&dFence, sBlock.fence)) {
- LOG(ERROR) << "Invalid Buffer::blocks[0].fence.";
- return false;
- }
-
- // Construct a block.
- switch (baseBlock.type) {
- case C2BaseBlock::LINEAR:
- if (!createLinearBuffer(d, baseBlock.linear, sBlockMeta, dFence)) {
- LOG(ERROR) << "Invalid C2BaseBlock::linear.";
- return false;
- }
- break;
- case C2BaseBlock::GRAPHIC:
- if (!createGraphicBuffer(d, baseBlock.graphic, sBlockMeta, dFence)) {
- LOG(ERROR) << "Invalid C2BaseBlock::graphic.";
- return false;
- }
- break;
- default:
- LOG(ERROR) << "Invalid C2BaseBlock::type.";
- return false;
- }
-
- // Parse info
- std::vector<C2Param*> params;
- if (!parseParamsBlob(¶ms, s.info)) {
- LOG(ERROR) << "Invalid Buffer::info.";
- return false;
- }
- for (C2Param* param : params) {
- if (param == nullptr) {
- LOG(ERROR) << "Null param in Buffer::info.";
- return false;
- }
- std::shared_ptr<C2Param> c2param{
- C2Param::Copy(*param).release()};
- if (!c2param) {
- LOG(ERROR) << "Invalid param in Buffer::info.";
- return false;
- }
- c2_status_t status =
- (*d)->setInfo(std::static_pointer_cast<C2Info>(c2param));
- if (status != C2_OK) {
- LOG(ERROR) << "C2Buffer::setInfo failed.";
- return false;
- }
- }
-
- return true;
-}
-
-// InfoBuffer -> C2InfoBuffer
-bool objcpy(std::vector<C2InfoBuffer> *d, const InfoBuffer& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
-
- // Currently, a non-null C2InfoBufer must contain exactly 1 block.
- if (s.buffer.blocks.size() == 0) {
- return true;
- } else if (s.buffer.blocks.size() != 1) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer "
- "Currently, a C2InfoBuffer must contain exactly 1 block.";
- return false;
- }
-
- const Block &sBlock = s.buffer.blocks[0];
- if (sBlock.index >= baseBlocks.size()) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].index: "
- "Array index out of range.";
- return false;
- }
- const C2BaseBlock &baseBlock = baseBlocks[sBlock.index];
-
- // Parse meta.
- std::vector<C2Param*> sBlockMeta;
- if (!parseParamsBlob(&sBlockMeta, sBlock.meta)) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].meta.";
- return false;
- }
-
- // Copy fence.
- C2Fence dFence;
- if (!objcpy(&dFence, sBlock.fence)) {
- LOG(ERROR) << "Invalid InfoBuffer::Buffer::blocks[0].fence.";
- return false;
- }
-
- // Construct a block.
- switch (baseBlock.type) {
- case C2BaseBlock::LINEAR:
- if (sBlockMeta.size() == 1 && sBlockMeta[0] != nullptr &&
- sBlockMeta[0]->size() == sizeof(C2Hidl_RangeInfo)) {
- C2Hidl_RangeInfo *rangeInfo =
- reinterpret_cast<C2Hidl_RangeInfo*>(sBlockMeta[0]);
- d->emplace_back(C2InfoBuffer::CreateLinearBuffer(
- s.index,
- baseBlock.linear->share(
- rangeInfo->offset, rangeInfo->length, dFence)));
- return true;
- }
- LOG(ERROR) << "Invalid Meta for C2BaseBlock::Linear InfoBuffer.";
- break;
- case C2BaseBlock::GRAPHIC:
- // It's not used now
- LOG(ERROR) << "Non-Used C2BaseBlock::type for InfoBuffer.";
- break;
- default:
- LOG(ERROR) << "Invalid C2BaseBlock::type for InfoBuffer.";
- break;
- }
-
- return false;
-}
-
-// FrameData -> C2FrameData
-bool objcpy(C2FrameData* d, const FrameData& s,
- const std::vector<C2BaseBlock>& baseBlocks) {
- d->flags = static_cast<C2FrameData::flags_t>(s.flags);
- if (!::android::objcpy(&d->ordinal, s.ordinal)) {
- LOG(ERROR) << "Invalid FrameData::ordinal.";
- return false;
- }
- d->buffers.clear();
- d->buffers.reserve(s.buffers.size());
- for (const Buffer& sBuffer : s.buffers) {
- std::shared_ptr<C2Buffer> dBuffer;
- if (!objcpy(&dBuffer, sBuffer, baseBlocks)) {
- LOG(ERROR) << "Invalid FrameData::buffers.";
- return false;
- }
- d->buffers.emplace_back(dBuffer);
- }
-
- std::vector<C2Param*> params;
- if (!parseParamsBlob(¶ms, s.configUpdate)) {
- LOG(ERROR) << "Invalid FrameData::configUpdate.";
- return false;
- }
- d->configUpdate.clear();
- for (C2Param* param : params) {
- d->configUpdate.emplace_back(C2Param::Copy(*param));
- if (!d->configUpdate.back()) {
- LOG(ERROR) << "Unexpected error while parsing "
- "FrameData::configUpdate.";
- return false;
- }
- }
-
- d->infoBuffers.clear();
- if (s.infoBuffers.size() == 0) {
- // InfoBuffer is optional
- return true;
- }
- d->infoBuffers.reserve(s.infoBuffers.size());
- for (const InfoBuffer &sInfoBuffer: s.infoBuffers) {
- if (!objcpy(&(d->infoBuffers), sInfoBuffer, baseBlocks)) {
- LOG(ERROR) << "Invalid Framedata::infoBuffers.";
- return false;
- }
- }
- return true;
-}
-
-// BaseBlock -> C2BaseBlock
-bool objcpy(C2BaseBlock* d, const BaseBlock& s) {
- switch (s.getDiscriminator()) {
- case BaseBlock::hidl_discriminator::nativeBlock: {
- if (s.nativeBlock() == nullptr) {
- LOG(ERROR) << "Null BaseBlock::nativeBlock handle";
- return false;
- }
- native_handle_t* sHandle =
- native_handle_clone(s.nativeBlock());
- if (sHandle == nullptr) {
- LOG(ERROR) << "Null BaseBlock::nativeBlock.";
- return false;
- }
- const C2Handle *sC2Handle =
- reinterpret_cast<const C2Handle*>(sHandle);
-
- d->linear = _C2BlockFactory::CreateLinearBlock(sC2Handle);
- if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
- return true;
- }
-
- d->graphic = _C2BlockFactory::CreateGraphicBlock(sC2Handle);
- if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
- return true;
- }
-
- LOG(ERROR) << "Unknown handle type in BaseBlock::nativeBlock.";
- if (sHandle) {
- native_handle_close(sHandle);
- native_handle_delete(sHandle);
- }
- return false;
- }
- case BaseBlock::hidl_discriminator::pooledBlock: {
- const BufferStatusMessage &bpMessage =
- s.pooledBlock();
- sp<ClientManager> bp = ClientManager::getInstance();
- std::shared_ptr<BufferPoolData> bpData;
- native_handle_t *cHandle;
- ResultStatus bpStatus = bp->receive(
- bpMessage.connectionId,
- bpMessage.transactionId,
- bpMessage.bufferId,
- bpMessage.timestampUs,
- &cHandle,
- &bpData);
- if (bpStatus != ResultStatus::OK) {
- LOG(ERROR) << "Failed to receive buffer from bufferpool -- "
- << "resultStatus = " << underlying_value(bpStatus)
- << ".";
- return false;
- } else if (!bpData) {
- LOG(ERROR) << "No data in bufferpool transaction.";
- return false;
- }
-
- d->linear = _C2BlockFactory::CreateLinearBlock(cHandle, bpData);
- if (d->linear) {
- d->type = C2BaseBlock::LINEAR;
- return true;
- }
-
- d->graphic = _C2BlockFactory::CreateGraphicBlock(cHandle, bpData);
- if (d->graphic) {
- d->type = C2BaseBlock::GRAPHIC;
- return true;
- }
- if (cHandle) {
- // Though we got cloned handle, creating block failed.
- native_handle_close(cHandle);
- native_handle_delete(cHandle);
- }
-
- LOG(ERROR) << "Unknown handle type in BaseBlock::pooledBlock.";
- return false;
- }
- default:
- LOG(ERROR) << "Unrecognized BaseBlock's discriminator with "
- << "underlying value "
- << underlying_value(s.getDiscriminator()) << ".";
- return false;
- }
-}
-
-} // unnamed namespace
-
// WorkBundle -> std::list<std::unique_ptr<C2Work>>
bool objcpy(std::list<std::unique_ptr<C2Work>>* d, const WorkBundle& s) {
- // Convert BaseBlocks to C2BaseBlocks.
- std::vector<C2BaseBlock> dBaseBlocks(s.baseBlocks.size());
- for (size_t i = 0; i < s.baseBlocks.size(); ++i) {
- if (!objcpy(&dBaseBlocks[i], s.baseBlocks[i])) {
- LOG(ERROR) << "Invalid WorkBundle::baseBlocks["
- << i << "].";
- return false;
- }
- }
-
- d->clear();
- for (const Work& sWork : s.works) {
- d->emplace_back(std::make_unique<C2Work>());
- C2Work& dWork = *d->back();
-
- // chain info is not in use currently.
-
- // input
- if (!objcpy(&dWork.input, sWork.input, dBaseBlocks)) {
- LOG(ERROR) << "Invalid Work::input.";
- return false;
- }
-
- // worklet(s)
- dWork.worklets.clear();
- for (const Worklet& sWorklet : sWork.worklets) {
- std::unique_ptr<C2Worklet> dWorklet = std::make_unique<C2Worklet>();
-
- // component id
- dWorklet->component = static_cast<c2_node_id_t>(
- sWorklet.componentId);
-
- // tunings
- if (!copyParamsFromBlob(&dWorklet->tunings, sWorklet.tunings)) {
- LOG(ERROR) << "Invalid Worklet::tunings";
- return false;
- }
-
- // failures
- dWorklet->failures.clear();
- dWorklet->failures.reserve(sWorklet.failures.size());
- for (const SettingResult& sFailure : sWorklet.failures) {
- std::unique_ptr<C2SettingResult> dFailure;
- if (!objcpy(&dFailure, sFailure)) {
- LOG(ERROR) << "Invalid Worklet::failures.";
- return false;
- }
- dWorklet->failures.emplace_back(std::move(dFailure));
- }
-
- // output
- if (!objcpy(&dWorklet->output, sWorklet.output, dBaseBlocks)) {
- LOG(ERROR) << "Invalid Worklet::output.";
- return false;
- }
-
- dWork.worklets.emplace_back(std::move(dWorklet));
- }
-
- // workletsProcessed
- dWork.workletsProcessed = sWork.workletsProcessed;
-
- // result
- dWork.result = static_cast<c2_status_t>(sWork.result);
- }
-
- return true;
+ return ::android::objcpy(d, s);
}
// Params -> std::vector<C2Param*>
@@ -1247,92 +504,35 @@
}
}
-namespace /* unnamed */ {
-
-template <typename BlockProcessor>
-void forEachBlock(C2FrameData& frameData,
- BlockProcessor process) {
- for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
- if (buffer) {
- for (const C2ConstGraphicBlock& block :
- buffer->data().graphicBlocks()) {
- process(block);
- }
- }
- }
-}
-
-template <typename BlockProcessor>
-void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
- BlockProcessor process,
- bool processInput, bool processOutput) {
- for (const std::unique_ptr<C2Work>& work : workList) {
- if (!work) {
- continue;
- }
- if (processInput) {
- forEachBlock(work->input, process);
- }
- if (processOutput) {
- for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
- if (worklet) {
- forEachBlock(worklet->output,
- process);
- }
- }
- }
- }
-}
-
-} // unnamed namespace
-
+// BufferQueue-Based Block Operations
bool beginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::BeginTransferBlockToClient(data);
- return true;
- }
- return false;
+ return ::android::BeginTransferBufferQueueBlock(block);
}
void beginTransferBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList,
- bool processInput, bool processOutput) {
- forEachBlock(workList, beginTransferBufferQueueBlock,
- processInput, processOutput);
+ bool processInput,
+ bool processOutput) {
+ return ::android::BeginTransferBufferQueueBlocks(
+ workList, processInput, processOutput);
}
-bool endTransferBufferQueueBlock(
- const C2ConstGraphicBlock& block,
- bool transfer) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::EndTransferBlockToClient(data, transfer);
- return true;
- }
- return false;
+bool endTransferBufferQueueBlock(const C2ConstGraphicBlock& block,
+ bool transfer) {
+ return ::android::EndTransferBufferQueueBlock(block, transfer);
}
void endTransferBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList,
bool transfer,
- bool processInput, bool processOutput) {
- forEachBlock(workList,
- std::bind(endTransferBufferQueueBlock,
- std::placeholders::_1, transfer),
- processInput, processOutput);
+ bool processInput,
+ bool processOutput) {
+ return ::android::EndTransferBufferQueueBlocks(
+ workList, transfer, processInput, processOutput);
}
bool displayBufferQueueBlock(const C2ConstGraphicBlock& block) {
- std::shared_ptr<_C2BlockPoolData> data =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (data && _C2BlockFactory::GetBufferQueueData(data)) {
- _C2BlockFactory::DisplayBlockToBufferQueue(data);
- return true;
- }
- return false;
+ return ::android::DisplayBufferQueueBlock(block);
}
} // namespace utils
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index e4daf5c..d867eb1 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -52,7 +52,6 @@
"android.hardware.drm@1.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
- "android.hardware.graphics.mapper@4.0",
"libbase",
"libbinder",
"libcodec2",
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index f60b6fa..2bdb7bc 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -62,8 +62,8 @@
void setCrypto(const sp<ICrypto> &crypto) override;
void setDescrambler(const sp<IDescrambler> &descrambler) override;
- virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual status_t queueSecureInputBuffer(
+ status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ status_t queueSecureInputBuffer(
const sp<MediaCodecBuffer> &buffer,
bool secure,
const uint8_t *key,
@@ -73,10 +73,10 @@
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
AString *errorDetailMsg) override;
- virtual status_t attachBuffer(
+ status_t attachBuffer(
const std::shared_ptr<C2Buffer> &c2Buffer,
const sp<MediaCodecBuffer> &buffer) override;
- virtual status_t attachEncryptedBuffer(
+ status_t attachEncryptedBuffer(
const sp<hardware::HidlMemory> &memory,
bool secure,
const uint8_t *key,
@@ -88,12 +88,12 @@
size_t numSubSamples,
const sp<MediaCodecBuffer> &buffer,
AString* errorDetailMsg) override;
- virtual status_t renderOutputBuffer(
+ status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
- virtual void pollForRenderedBuffers() override;
- virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
- virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+ void pollForRenderedBuffers() override;
+ status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+ void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
// Methods below are interface for CCodec to use.
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 228ad7e..3bb6593 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -26,9 +26,6 @@
#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
#include <android/hardware/drm/1.0/types.h>
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
-#include <gralloctypes/Gralloc4.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/CodecBase.h>
@@ -38,6 +35,7 @@
#include <media/stagefright/foundation/AUtils.h>
#include <mediadrm/ICrypto.h>
#include <nativebase/nativebase.h>
+#include <ui/GraphicBufferMapper.h>
#include <ui/Fence.h>
#include <C2AllocatorGralloc.h>
@@ -1039,34 +1037,15 @@
}
using ::aidl::android::hardware::graphics::common::Cta861_3;
-using ::aidl::android::hardware::graphics::common::Dataspace;
using ::aidl::android::hardware::graphics::common::Smpte2086;
-using ::android::gralloc4::MetadataType_Cta861_3;
-using ::android::gralloc4::MetadataType_Dataspace;
-using ::android::gralloc4::MetadataType_Smpte2086;
-using ::android::gralloc4::MetadataType_Smpte2094_40;
-
-using ::android::hardware::Return;
-using ::android::hardware::hidl_vec;
-
-using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
-using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
-
namespace {
-sp<IMapper4> GetMapper4() {
- static ::android::base::NoDestructor<sp<IMapper4>> sMapper(IMapper4::getService());
- return *sMapper;
-}
-
-class Gralloc4Buffer {
+class GrallocBuffer {
public:
- Gralloc4Buffer(const C2Handle *const handle) : mBuffer(nullptr) {
- sp<IMapper4> mapper = GetMapper4();
- if (!mapper) {
- return;
- }
+ GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+
// Unwrap raw buffer handle from the C2Handle
native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
if (!nh) {
@@ -1074,13 +1053,14 @@
}
// Import the raw handle so IMapper can use the buffer. The imported
// handle must be freed when the client is done with the buffer.
- mapper->importBuffer(
- hardware::hidl_handle(nh),
- [&](const Error4 &error, void *buffer) {
- if (error == Error4::NONE) {
- mBuffer = buffer;
- }
- });
+ status_t status = mapper.importBufferNoValidate(
+ nh,
+ &mBuffer);
+
+ if (status != OK) {
+ ALOGE("Failed to import buffer. Status: %d.", status);
+ return;
+ }
// TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
// does not clone the fds. Thus we need to delete the handle
@@ -1088,19 +1068,19 @@
native_handle_delete(nh);
}
- ~Gralloc4Buffer() {
- sp<IMapper4> mapper = GetMapper4();
- if (mapper && mBuffer) {
+ ~GrallocBuffer() {
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ if (mBuffer) {
// Free the imported buffer handle. This does not release the
// underlying buffer itself.
- mapper->freeBuffer(mBuffer);
+ mapper.freeBuffer(mBuffer);
}
}
- void *get() const { return mBuffer; }
+ buffer_handle_t get() const { return mBuffer; }
operator bool() const { return (mBuffer != nullptr); }
private:
- void *mBuffer;
+ buffer_handle_t mBuffer;
};
} // namspace
@@ -1110,69 +1090,48 @@
std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
c2_status_t err = C2_OK;
- sp<IMapper4> mapper = GetMapper4();
- Gralloc4Buffer buffer(handle);
- if (!mapper || !buffer) {
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ GrallocBuffer buffer(handle);
+ if (!buffer) {
// Gralloc4 not supported; nothing to do
return err;
}
- Error4 mapperErr = Error4::NONE;
if (staticInfo) {
- ALOGV("Grabbing static HDR info from gralloc4 metadata");
+ ALOGV("Grabbing static HDR info from gralloc metadata");
staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
(*staticInfo)->maxCll = 0;
(*staticInfo)->maxFall = 0;
- IMapper4::get_cb cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
- mapperErr = err;
- if (err != Error4::NONE) {
- return;
- }
- std::optional<Smpte2086> smpte2086;
- gralloc4::decodeSmpte2086(vec, &smpte2086);
+ std::optional<Smpte2086> smpte2086;
+ status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
+ if (status != OK) {
+ err = C2_CORRUPTED;
+ } else {
if (smpte2086) {
- (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
- (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
- (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
- (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
- (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
- (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
- (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
- (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
+ (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
+ (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
+ (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
+ (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
+ (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
+ (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
+ (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
+ (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
- (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
- (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
- } else {
- mapperErr = Error4::BAD_VALUE;
+ (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
+ (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
}
- };
- Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2086, cb);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (mapperErr != Error4::NONE) {
- err = C2_CORRUPTED;
}
- cb = [&mapperErr, staticInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
- mapperErr = err;
- if (err != Error4::NONE) {
- return;
- }
- std::optional<Cta861_3> cta861_3;
- gralloc4::decodeCta861_3(vec, &cta861_3);
- if (cta861_3) {
- (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
- (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
- } else {
- mapperErr = Error4::BAD_VALUE;
- }
- };
- ret = mapper->get(buffer.get(), MetadataType_Cta861_3, cb);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (mapperErr != Error4::NONE) {
+ std::optional<Cta861_3> cta861_3;
+ status = mapper.getCta861_3(buffer.get(), &cta861_3);
+ if (status != OK) {
err = C2_CORRUPTED;
+ } else {
+ if (cta861_3) {
+ (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
+ (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
+ }
}
}
@@ -1181,23 +1140,19 @@
}
if (dynamicInfo) {
- ALOGV("Grabbing dynamic HDR info from gralloc4 metadata");
+ ALOGV("Grabbing dynamic HDR info from gralloc metadata");
dynamicInfo->reset();
- IMapper4::get_cb cb = [&mapperErr, dynamicInfo](Error4 err, const hidl_vec<uint8_t> &vec) {
- mapperErr = err;
- if (err != Error4::NONE) {
- return;
- }
- if (!dynamicInfo) {
- return;
- }
- *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
- vec.size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
- memcpy((*dynamicInfo)->m.data, vec.data(), vec.size());
- };
- Return<void> ret = mapper->get(buffer.get(), MetadataType_Smpte2094_40, cb);
- if (!ret.isOk() || mapperErr != Error4::NONE) {
+ std::optional<std::vector<uint8_t>> vec;
+ status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
+ if (status != OK) {
dynamicInfo->reset();
+ err = C2_CORRUPTED;
+ } else {
+ if (vec) {
+ *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
+ vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
+ memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
+ }
}
}
@@ -1210,25 +1165,18 @@
const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
const C2Handle *const handle) {
c2_status_t err = C2_OK;
- sp<IMapper4> mapper = GetMapper4();
- Gralloc4Buffer buffer(handle);
- if (!mapper || !buffer) {
+ GraphicBufferMapper& mapper = GraphicBufferMapper::get();
+ GrallocBuffer buffer(handle);
+ if (!buffer) {
// Gralloc4 not supported; nothing to do
return err;
}
- {
- hidl_vec<uint8_t> metadata;
- if (gralloc4::encodeDataspace(static_cast<Dataspace>(dataSpace), &metadata) == OK) {
- Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Dataspace, metadata);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (ret != Error4::NONE) {
- err = C2_CORRUPTED;
- }
- }
+ status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
+ if (status != OK) {
+ err = C2_CORRUPTED;
}
if (staticInfo && *staticInfo) {
- ALOGV("Setting static HDR info as gralloc4 metadata");
+ ALOGV("Setting static HDR info as gralloc metadata");
std::optional<Smpte2086> smpte2086 = Smpte2086{
{staticInfo->mastering.red.x, staticInfo->mastering.red.y},
{staticInfo->mastering.green.x, staticInfo->mastering.green.y},
@@ -1237,7 +1185,6 @@
staticInfo->mastering.maxLuminance,
staticInfo->mastering.minLuminance,
};
- hidl_vec<uint8_t> vec;
if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
&& 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
&& 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
@@ -1246,12 +1193,9 @@
&& 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
&& 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
&& 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
- && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance
- && gralloc4::encodeSmpte2086(smpte2086, &vec) == OK) {
- Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Smpte2086, vec);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (ret != Error4::NONE) {
+ && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
+ status = mapper.setSmpte2086(buffer.get(), smpte2086);
+ if (status != OK) {
err = C2_CORRUPTED;
}
}
@@ -1259,41 +1203,23 @@
staticInfo->maxCll,
staticInfo->maxFall,
};
- if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel
- && gralloc4::encodeCta861_3(cta861_3, &vec) == OK) {
- Return<Error4> ret = mapper->set(buffer.get(), MetadataType_Cta861_3, vec);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (ret != Error4::NONE) {
+ if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
+ status = mapper.setCta861_3(buffer.get(), cta861_3);
+ if (status != OK) {
err = C2_CORRUPTED;
}
}
}
if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
- ALOGV("Setting dynamic HDR info as gralloc4 metadata");
- std::optional<IMapper4::MetadataType> metadataType;
- switch (dynamicInfo->m.type_) {
- case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_10:
- // TODO
- break;
- case C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40:
- metadataType = MetadataType_Smpte2094_40;
- break;
- }
+ ALOGV("Setting dynamic HDR info as gralloc metadata");
+ if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
+ std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
+ smpte2094_40->resize(dynamicInfo->flexCount());
+ memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
- if (metadataType) {
- std::vector<uint8_t> smpte2094_40;
- smpte2094_40.resize(dynamicInfo->flexCount());
- memcpy(smpte2094_40.data(), dynamicInfo->m.data, dynamicInfo->flexCount());
-
- hidl_vec<uint8_t> vec;
- if (gralloc4::encodeSmpte2094_40({ smpte2094_40 }, &vec) == OK) {
- Return<Error4> ret = mapper->set(buffer.get(), *metadataType, vec);
- if (!ret.isOk()) {
- err = C2_REFUSED;
- } else if (ret != Error4::NONE) {
- err = C2_CORRUPTED;
- }
+ status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
+ if (status != OK) {
+ err = C2_CORRUPTED;
}
} else {
err = C2_BAD_VALUE;
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index ba25226..a59bd47 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -173,6 +173,7 @@
"libbase", // for C2_LOG
"liblog", // for ALOG
"libcodec2",
+ "libcodec2_hal_common",
"libcodec2_vndk",
"libutils",
],
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 1eefd87..81cdb43 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -17,10 +17,14 @@
#ifndef ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
#define ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-
#include <C2Buffer.h>
+#include <utils/RefBase.h>
+
+namespace android::hardware::graphics::bufferqueue::V2_0 {
+struct IGraphicBufferProducer;
+}
+
// Note: HIDL-BufferPool and AIDL-BufferPool are not compatible
namespace android::hardware::media::bufferpool {
diff --git a/media/img_utils/src/FileInput.cpp b/media/img_utils/src/FileInput.cpp
index 4c85a51..1eb614b 100644
--- a/media/img_utils/src/FileInput.cpp
+++ b/media/img_utils/src/FileInput.cpp
@@ -33,12 +33,12 @@
status_t FileInput::open() {
if (mOpen) {
- ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.string());
+ ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.c_str());
return OK;
}
mFp = ::fopen(mPath, "rb");
if (!mFp) {
- ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.string());
+ ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.c_str());
return BAD_VALUE;
}
mOpen = true;
@@ -47,14 +47,14 @@
ssize_t FileInput::read(uint8_t* buf, size_t offset, size_t count) {
if (!mOpen) {
- ALOGE("%s: Could not read file %s, file not open.", __FUNCTION__, mPath.string());
+ ALOGE("%s: Could not read file %s, file not open.", __FUNCTION__, mPath.c_str());
return BAD_VALUE;
}
size_t bytesRead = ::fread(buf + offset, sizeof(uint8_t), count, mFp);
int error = ::ferror(mFp);
if (error != 0) {
- ALOGE("%s: Error %d occurred while reading file %s.", __FUNCTION__, error, mPath.string());
+ ALOGE("%s: Error %d occurred while reading file %s.", __FUNCTION__, error, mPath.c_str());
return BAD_VALUE;
}
@@ -68,13 +68,13 @@
status_t FileInput::close() {
if(!mOpen) {
- ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.string());
+ ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.c_str());
return OK;
}
status_t ret = OK;
if(::fclose(mFp) != 0) {
- ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.string());
+ ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.c_str());
ret = BAD_VALUE;
}
mOpen = false;
diff --git a/media/img_utils/src/FileOutput.cpp b/media/img_utils/src/FileOutput.cpp
index 0346762..5e37324 100644
--- a/media/img_utils/src/FileOutput.cpp
+++ b/media/img_utils/src/FileOutput.cpp
@@ -25,19 +25,19 @@
FileOutput::~FileOutput() {
if (mOpen) {
- ALOGW("%s: Destructor called with %s still open.", __FUNCTION__, mPath.string());
+ ALOGW("%s: Destructor called with %s still open.", __FUNCTION__, mPath.c_str());
close();
}
}
status_t FileOutput::open() {
if (mOpen) {
- ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.string());
+ ALOGW("%s: Open called when file %s already open.", __FUNCTION__, mPath.c_str());
return OK;
}
mFp = ::fopen(mPath, "wb");
if (!mFp) {
- ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.string());
+ ALOGE("%s: Could not open file %s", __FUNCTION__, mPath.c_str());
return BAD_VALUE;
}
mOpen = true;
@@ -46,7 +46,7 @@
status_t FileOutput::write(const uint8_t* buf, size_t offset, size_t count) {
if (!mOpen) {
- ALOGE("%s: Could not write file %s, file not open.", __FUNCTION__, mPath.string());
+ ALOGE("%s: Could not write file %s, file not open.", __FUNCTION__, mPath.c_str());
return BAD_VALUE;
}
@@ -54,7 +54,7 @@
int error = ::ferror(mFp);
if (error != 0) {
- ALOGE("%s: Error %d occurred while writing file %s.", __FUNCTION__, error, mPath.string());
+ ALOGE("%s: Error %d occurred while writing file %s.", __FUNCTION__, error, mPath.c_str());
return BAD_VALUE;
}
return OK;
@@ -62,13 +62,13 @@
status_t FileOutput::close() {
if(!mOpen) {
- ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.string());
+ ALOGW("%s: Close called when file %s already close.", __FUNCTION__, mPath.c_str());
return OK;
}
status_t ret = OK;
if(::fclose(mFp) != 0) {
- ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.string());
+ ALOGE("%s: Failed to close file %s.", __FUNCTION__, mPath.c_str());
ret = BAD_VALUE;
}
mOpen = false;
diff --git a/media/img_utils/src/TiffIfd.cpp b/media/img_utils/src/TiffIfd.cpp
index 3fb00cc..b272814 100644
--- a/media/img_utils/src/TiffIfd.cpp
+++ b/media/img_utils/src/TiffIfd.cpp
@@ -377,7 +377,7 @@
size_t s = mEntries.size();
ALOGI("[ifd: %x, num_entries: %zu, entries:\n", getId(), s);
for(size_t i = 0; i < s; ++i) {
- ALOGI("\t%s", mEntries[i]->toString().string());
+ ALOGI("\t%s", mEntries[i]->toString().c_str());
}
ALOGI(", next_ifd: %x]", ((mNextIfd != NULL) ? mNextIfd->getId() : 0));
}
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 74f7e6b..c3b32e6 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -539,6 +539,22 @@
* Available since API level 29.
*/
AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE = 10,
+
+ /**
+ * Use this preset for an echo canceller to capture the reference signal.
+ * Reserved for system components.
+ * Requires CAPTURE_AUDIO_OUTPUT permission
+ * Available since API level 35.
+ */
+ AAUDIO_INPUT_PRESET_SYSTEM_ECHO_REFERENCE = 1997,
+
+ /**
+ * Use this preset for preemptible, low-priority software hotword detection.
+ * Reserved for system components.
+ * Requires CAPTURE_AUDIO_HOTWORD permission.
+ * Available since API level 35.
+ */
+ AAUDIO_INPUT_PRESET_SYSTEM_HOTWORD = 1999,
};
typedef int32_t aaudio_input_preset_t;
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index f305e46..1db62f3 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -184,6 +184,8 @@
case AAUDIO_INPUT_PRESET_VOICE_RECOGNITION:
case AAUDIO_INPUT_PRESET_UNPROCESSED:
case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
+ case AAUDIO_INPUT_PRESET_SYSTEM_ECHO_REFERENCE:
+ case AAUDIO_INPUT_PRESET_SYSTEM_HOTWORD:
break; // valid
default:
ALOGD("input preset not valid = %d", mInputPreset);
@@ -317,4 +319,4 @@
ALOGD("mHardwareSamplesPerFrame = %6d", mHardwareSamplesPerFrame);
ALOGD("mHardwareSampleRate = %6d", mHardwareSampleRate);
ALOGD("mHardwareAudioFormat = %6d", (int)mHardwareAudioFormat);
-}
\ No newline at end of file
+}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 01e3d53..d35708c 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -336,6 +336,7 @@
srcs: [
"aidl/android/media/AudioAttributesEx.aidl",
"aidl/android/media/AudioMix.aidl",
+ "aidl/android/media/AudioMixUpdate.aidl",
"aidl/android/media/AudioMixerAttributesInternal.aidl",
"aidl/android/media/AudioMixerBehavior.aidl",
"aidl/android/media/AudioMixCallbackFlag.aidl",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f07ea1d..073a030 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -760,7 +760,7 @@
mInput, mLatency, mSelectedDeviceId, mRoutedDeviceId);
result.appendFormat(" mic direction(%d) mic field dimension(%f)",
mSelectedMicDirection, mSelectedMicFieldDimension);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 763de70..5bfdd5f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include <android/media/IAudioPolicyService.h>
+#include <android/media/AudioMixUpdate.h>
#include <android/media/BnCaptureStateListener.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
@@ -87,7 +88,7 @@
void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
ALOGE("setAudioFlingerBinder: received a binder of type %s",
- String8(audioFlinger->getInterfaceDescriptor()).string());
+ String8(audioFlinger->getInterfaceDescriptor()).c_str());
return;
}
Mutex::Autolock _l(gLock);
@@ -1842,6 +1843,27 @@
return statusTFromBinderStatus(aps->registerPolicyMixes(mixesAidl, registration));
}
+status_t AudioSystem::updatePolicyMixes(
+ const std::vector<std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>&
+ mixesWithUpdates) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ std::vector<media::AudioMixUpdate> updatesAidl;
+ updatesAidl.reserve(mixesWithUpdates.size());
+
+ for (const auto& update : mixesWithUpdates) {
+ media::AudioMixUpdate updateAidl;
+ updateAidl.audioMix = VALUE_OR_RETURN_STATUS(legacy2aidl_AudioMix(update.first));
+ RETURN_STATUS_IF_ERROR(convertRange(update.second.begin(), update.second.end(),
+ std::back_inserter(updateAidl.newCriteria),
+ legacy2aidl_AudioMixMatchCriterion));
+ updatesAidl.emplace_back(updateAidl);
+ }
+
+ return statusTFromBinderStatus(aps->updatePolicyMixes(updatesAidl));
+}
+
status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 4269aa2..8b8f7cd 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -3036,7 +3036,7 @@
param.addInt(String8(AudioParameter::keyPresentationId), presentationId);
param.addInt(String8(AudioParameter::keyProgramId), programId);
ALOGV("%s(%d): PresentationId/ProgramId[%s]",
- __func__, mPortId, param.toString().string());
+ __func__, mPortId, param.toString().c_str());
status_t status;
mAudioTrack->setParameters(param.toString().c_str(), &status);
@@ -3479,7 +3479,7 @@
if (output != AUDIO_IO_HANDLE_NONE) {
return AudioSystem::getParameters(output, keys);
} else {
- return String8::empty();
+ return String8();
}
}
@@ -3525,7 +3525,7 @@
mLatency, mSelectedDeviceId, mRoutedDeviceId);
result.appendFormat(" output(%d) AF latency (%u) AF frame count(%zu) AF SampleRate(%u)\n",
mOutput, mAfLatency, mAfFrameCount, mAfSampleRate);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
return NO_ERROR;
}
diff --git a/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl b/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl
new file mode 100644
index 0000000..d481b1c
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioMixUpdate.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioMix;
+import android.media.AudioMixMatchCriterion;
+
+
+/**
+ * {@hide}
+ */
+parcelable AudioMixUpdate {
+ // Audio mix to update.
+ AudioMix audioMix;
+ // Updated audio mixing rule.
+ AudioMixMatchCriterion[] newCriteria;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 3e9b27f..52c8da0 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -20,6 +20,7 @@
import android.media.AudioDirectMode;
import android.media.AudioMix;
+import android.media.AudioMixUpdate;
import android.media.AudioMixerAttributesInternal;
import android.media.AudioOffloadMode;
import android.media.AudioPatchFw;
@@ -262,6 +263,8 @@
void registerPolicyMixes(in AudioMix[] mixes, boolean registration);
+ void updatePolicyMixes(in AudioMixUpdate[] updates);
+
void setUidDeviceAffinities(int /* uid_t */ uid, in AudioDevice[] devices);
void removeUidDeviceAffinities(int /* uid_t */ uid);
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 0215f3c..a1f7941 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -462,6 +462,10 @@
static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);
+ static status_t updatePolicyMixes(
+ const std::vector<
+ std::pair<AudioMix, std::vector<AudioMixMatchCriterion>>>& mixesWithUpdates);
+
static status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices);
static status_t removeUidDeviceAffinities(uid_t uid);
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 976a532..9a46b20 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -143,7 +143,8 @@
}
AudioDeviceDescription make_ADD_RSubmixIn() {
- return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX);
+ return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX,
+ AudioDeviceDescription::CONNECTION_VIRTUAL());
}
AudioDeviceDescription make_ADD_DefaultOut() {
diff --git a/media/libaudioclient/tests/audiotrack_tests.cpp b/media/libaudioclient/tests/audiotrack_tests.cpp
index 8daba0a..2b68225 100644
--- a/media/libaudioclient/tests/audiotrack_tests.cpp
+++ b/media/libaudioclient/tests/audiotrack_tests.cpp
@@ -144,7 +144,7 @@
EXPECT_EQ(cb->mDeviceId, ap->getAudioTrackHandle()->getRoutedDeviceId());
String8 keys;
keys = ap->getAudioTrackHandle()->getParameters(keys);
- if (!keys.isEmpty()) {
+ if (!keys.empty()) {
std::cerr << "track parameters :: " << keys << std::endl;
}
EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
index 7197bf2..46abfda 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -69,7 +69,7 @@
// Re-parse the vendor-provided string to ensure that it is correct.
AudioParameter reparse(String8(vendorParameters.c_str()));
if (reparse.size() != 0) {
- if (!values->empty()) {
+ if (values->length() > 0) {
values->append(";");
}
values->append(reparse.toString().c_str());
diff --git a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
index 2ac8a42..b801187 100644
--- a/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
+++ b/media/libaudiohal/impl/CoreConversionHelperHidl.cpp
@@ -69,7 +69,7 @@
keepValueParam.add(key, value);
key = keepValueParam.toString();
}
- (*hidlKeys)[i] = key.string();
+ (*hidlKeys)[i] = key.c_str();
}
return OK;
}
@@ -84,8 +84,8 @@
String8 key, value;
status_t status = params.getAt(i, key, value);
if (status != OK) return status;
- (*hidlParams)[i].key = key.string();
- (*hidlParams)[i].value = value.string();
+ (*hidlParams)[i].key = key.c_str();
+ (*hidlParams)[i].value = value.c_str();
}
return OK;
}
@@ -97,7 +97,7 @@
for (size_t i = 0; i < parameters.size(); ++i) {
params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
}
- values->setTo(params.toString());
+ *values = params.toString();
}
CoreConversionHelperHidl::CoreConversionHelperHidl(std::string_view className)
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 9cf0cb8..4e34fca 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -25,6 +25,7 @@
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionEffect.h>
+#include <media/AudioContainers.h>
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Log.h>
@@ -61,6 +62,7 @@
{EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
{EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
{EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+ {EFFECT_CMD_SET_AUDIO_MODE, &EffectConversionHelperAidl::handleSetAudioMode},
{EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
{EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
{EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
@@ -279,6 +281,10 @@
pReplyData);
return BAD_VALUE;
}
+ if (!getDescriptor().common.flags.audioSourceIndication) {
+ ALOGW("%s parameter no audioSourceIndication, skipping", __func__);
+ return OK;
+ }
audio_source_t source = *(audio_source_t*)pCmdData;
AudioSource aidlSource =
@@ -295,6 +301,10 @@
pReplyData);
return BAD_VALUE;
}
+ if (!getDescriptor().common.flags.audioModeIndication) {
+ ALOGW("%s parameter no audioModeIndication, skipping", __func__);
+ return OK;
+ }
audio_mode_t mode = *(audio_mode_t *)pCmdData;
AudioMode aidlMode =
VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
@@ -310,9 +320,26 @@
pReplyData);
return BAD_VALUE;
}
- // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
- // const auto& legacyDevice = *(uint32_t*)(pCmdData);
+ if (!getDescriptor().common.flags.deviceIndication) {
+ ALOGW("%s parameter no deviceIndication, skipping", __func__);
+ return OK;
+ }
+ // convert from bitmask of audio_devices_t to std::vector<AudioDeviceDescription>
+ auto legacyDevices = *(uint32_t*)(pCmdData);
+ // extract the input bit and remove it from bitmasks
+ const auto inputBit = legacyDevices & AUDIO_DEVICE_BIT_IN;
+ legacyDevices &= ~AUDIO_DEVICE_BIT_IN;
std::vector<AudioDeviceDescription> aidlDevices;
+ while (legacyDevices) {
+ // get audio_devices_t represented by the last true bit and convert to AIDL
+ const auto lowestBitDevice = legacyDevices & -legacyDevices;
+ AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ static_cast<audio_devices_t>(lowestBitDevice | inputBit)));
+ aidlDevices.emplace_back(deviceDesc);
+ legacyDevices -= lowestBitDevice;
+ }
+
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
return *static_cast<int32_t*>(pReplyData) = OK;
@@ -435,5 +462,19 @@
(mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
}
+Descriptor EffectConversionHelperAidl::getDescriptor() const {
+ if (!mIsProxyEffect) {
+ return mDesc;
+ }
+
+ Descriptor desc;
+ if (const auto status = mEffect->getDescriptor(&desc); !status.isOk()) {
+ ALOGE("%s failed to get proxy descriptor (%d:%s), using default", __func__,
+ status.getStatus(), status.getMessage());
+ return mDesc;
+ }
+ return desc;
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 7c8f11b..85e877e 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -43,6 +43,8 @@
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
bool isBypassing() const;
+ ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
+
protected:
const int32_t mSessionId;
const int32_t mIoId;
@@ -134,7 +136,6 @@
virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
return BAD_VALUE;
}
-
};
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index b8e62ae..642d352 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -69,7 +69,6 @@
mEffect(effect),
mSessionId(sessionId),
mIoId(ioId),
- mDesc(desc),
mIsProxyEffect(isProxyEffect) {
createAidlConversion(effect, sessionId, ioId, desc);
}
@@ -169,7 +168,8 @@
State state = State::INIT;
if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
state != State::PROCESSING) {
- ALOGI("%s skipping %s process because it's %s", __func__, mDesc.common.name.c_str(),
+ ALOGI("%s skipping %s process because it's %s", __func__,
+ mConversion->getDescriptor().common.name.c_str(),
mConversion->isBypassing()
? "bypassing"
: aidl::android::hardware::audio::effect::toString(state).c_str());
@@ -225,8 +225,8 @@
return INVALID_OPERATION;
}
- ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
- floatsToRead);
+ ALOGD("%s %s consumed %zu produced %zu", __func__,
+ mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead);
return OK;
}
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 1b7a3d6..bbcb7e2 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -72,7 +72,6 @@
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
const int32_t mSessionId;
const int32_t mIoId;
- const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
const bool mIsProxyEffect;
std::unique_ptr<EffectConversionHelperAidl> mConversion;
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 8b629ed..7b5e195 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -169,12 +169,6 @@
common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
}
- // initial flag values before we know which sub-effect to active (with setOffloadParam)
- // same as HIDL EffectProxy flags
- common.flags.type = Flags::Type::INSERT;
- common.flags.insert = Flags::Insert::LAST;
- common.flags.volume = Flags::Volume::NONE;
-
// set indication if any sub-effect indication was set
common.flags.offloadIndication |= desc.common.flags.offloadIndication;
common.flags.deviceIndication |= desc.common.flags.deviceIndication;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 80e19a0..f9aea37 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -267,7 +267,11 @@
if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
return status;
}
- *latency = std::max<int32_t>(0, reply.latencyMs);
+
+ *latency = std::clamp(std::max<int32_t>(0, reply.latencyMs), 1, 3000);
+ ALOGW_IF(reply.latencyMs != static_cast<int32_t>(*latency),
+ "Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
+ *latency);
return OK;
}
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index ea20794..adff110 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -452,7 +452,7 @@
String8 values;
EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
- EXPECT_TRUE(values.empty());
+ EXPECT_EQ(0UL, values.length());
}
class DeviceHalAidlVendorParametersTest : public testing::Test {
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index 2854496..0cb654c 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -347,6 +347,45 @@
}
}
+TEST_P(libAudioHalEffectParamTest, deviceIndicationUpdate) {
+ for (auto& interface : mHalInterfaces) {
+ EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+
+ // output device
+ uint32_t deviceTypes = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BLE_SPEAKER;
+ status_t cmdStatus;
+ uint32_t replySize = sizeof(cmdStatus);
+ EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+ &replySize, &cmdStatus));
+ // input device
+ deviceTypes = AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_BLUETOOTH_BLE;
+ EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes,
+ &replySize, &cmdStatus));
+ }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioModeIndicationUpdate) {
+ for (auto& interface : mHalInterfaces) {
+ EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+ uint32_t mode = AUDIO_MODE_IN_CALL;
+ status_t cmdStatus;
+ uint32_t replySize = sizeof(cmdStatus);
+ EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_MODE, sizeof(uint32_t), &mode,
+ &replySize, &cmdStatus));
+ }
+}
+
+TEST_P(libAudioHalEffectParamTest, audioSourceIndicationUpdate) {
+ for (auto& interface : mHalInterfaces) {
+ EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+ uint32_t source = AUDIO_SOURCE_MIC;
+ status_t cmdStatus;
+ uint32_t replySize = sizeof(cmdStatus);
+ EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_SOURCE, sizeof(uint32_t), &source,
+ &replySize, &cmdStatus));
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(
libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
[](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
index f91e3ea..e9936a3 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -92,7 +92,7 @@
source = NuCachedSource2::Create(
mediaHTTP,
- cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ cacheConfig.empty() ? NULL : cacheConfig.c_str(),
disconnectAtHighwatermark);
} else if (!strncasecmp("data:", uri, 5)) {
source = DataURISource::Create(uri);
diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
index 58c1ce8..b1f2140 100644
--- a/media/libdatasource/MediaHTTP.cpp
+++ b/media/libdatasource/MediaHTTP.cpp
@@ -156,7 +156,7 @@
String8 MediaHTTP::getUri() {
if (mInitCheck != OK) {
- return String8::empty();
+ return String8();
}
String8 uri;
diff --git a/media/libdatasource/NuCachedSource2.cpp b/media/libdatasource/NuCachedSource2.cpp
index 6d63ffb..4e71d5f 100644
--- a/media/libdatasource/NuCachedSource2.cpp
+++ b/media/libdatasource/NuCachedSource2.cpp
@@ -225,7 +225,7 @@
// IMediaHTTPConnection::readAt and therefore call back into JAVA.
mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
- mName = String8::format("NuCachedSource2(%s)", mSource->toString().string());
+ mName = String8::format("NuCachedSource2(%s)", mSource->toString().c_str());
}
NuCachedSource2::~NuCachedSource2() {
@@ -765,7 +765,7 @@
headers->removeItemsAt(index);
- ALOGV("Using special cache config '%s'", cacheConfig->string());
+ ALOGV("Using special cache config '%s'", cacheConfig->c_str());
}
if ((index = headers->indexOfKey(
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 6834b7d..085a7e4 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -41,8 +41,8 @@
namespace android {
void initFrameInfo(HeifFrameInfo *info, const VideoFrame *videoFrame) {
- info->mWidth = videoFrame->mWidth;
- info->mHeight = videoFrame->mHeight;
+ info->mWidth = videoFrame->mDisplayWidth;
+ info->mHeight = videoFrame->mDisplayHeight;
info->mRotationAngle = videoFrame->mRotationAngle;
info->mBytesPerPixel = videoFrame->mBytesPerPixel;
info->mDurationUs = videoFrame->mDurationUs;
@@ -742,8 +742,11 @@
// Either document why it is safe in this case or address the
// issue (e.g. by copying).
VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->unsecurePointer());
- uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
- memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
+ uint8_t* src = videoFrame->getFlattenedData() +
+ (videoFrame->mRowBytes * (mCurScanline + videoFrame->mDisplayTop)) +
+ (videoFrame->mBytesPerPixel * videoFrame->mDisplayLeft);
+ mCurScanline++;
+ memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
return true;
}
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index eb436d1..8485ac0 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -304,7 +304,7 @@
}
for (size_t i = 0; i < tracks.size(); i++) {
const String8 desc = trackDescriptions.itemAt(i);
- str.appendFormat(" track {%s} ", desc.string());
+ str.appendFormat(" track {%s} ", desc.c_str());
wp<IMediaSource> wSource = tracks.itemAt(i);
if (wSource == NULL) {
str.append(": null\n");
@@ -339,7 +339,7 @@
if (source != NULL) {
instance.trackDescriptions.push_front(source->getFormat()->toString());
} else {
- instance.trackDescriptions.push_front(String8::empty());
+ instance.trackDescriptions.push_front(String8());
}
break;
}
@@ -386,7 +386,7 @@
}
}
}
- write(fd, out.string(), out.size());
+ write(fd, out.c_str(), out.size());
return OK;
}
diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp
index 8cbb4c2..b029b97 100644
--- a/media/libmedia/IMediaHTTPConnection.cpp
+++ b/media/libmedia/IMediaHTTPConnection.cpp
@@ -54,8 +54,8 @@
tmp = String16("");
if (headers != NULL) {
for (size_t i = 0; i < headers->size(); ++i) {
- String16 key(headers->keyAt(i).string());
- String16 val(headers->valueAt(i).string());
+ String16 key(headers->keyAt(i).c_str());
+ String16 val(headers->valueAt(i).c_str());
tmp.append(key);
tmp.append(String16(": "));
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 86427ed..cdb1837 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -218,7 +218,7 @@
} else {
mMetadata.replaceValueFor(keyCode, value);
}
- return mMetadata.valueFor(keyCode).string();
+ return mMetadata.valueFor(keyCode).c_str();
} else {
return NULL;
}
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index e191999..755a147 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -255,7 +255,7 @@
status_t setParameters(const String8& params)
{
- ALOGV("setParameter(%s)", params.string());
+ ALOGV("setParameter(%s)", params.c_str());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeString8(params);
@@ -275,7 +275,7 @@
status_t setClientName(const String16& clientName)
{
- ALOGV("setClientName(%s)", String8(clientName).string());
+ ALOGV("setClientName(%s)", String8(clientName).c_str());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeString16(clientName);
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index 37cb059..af25015 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -811,11 +811,11 @@
*/
// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
- t->mName = l.mName.string();
+ t->mName = l.mName.c_str();
t->mRoles.resize(l.mRoles.size());
size_t i = 0;
for (auto& role : l.mRoles) {
- t->mRoles[i++] = role.string();
+ t->mRoles[i++] = role.c_str();
}
return true;
}
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index bd06fb6..48f5e4b 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -472,7 +472,7 @@
}
status_t MediaRecorder::setParameters(const String8& params) {
- ALOGV("setParameters(%s)", params.string());
+ ALOGV("setParameters(%s)", params.c_str());
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
@@ -496,7 +496,7 @@
status_t ret = mMediaRecorder->setParameters(params);
if (OK != ret) {
- ALOGE("setParameters(%s) failed: %d", params.string(), ret);
+ ALOGE("setParameters(%s) failed: %d", params.c_str(), ret);
// Do not change our current state to MEDIA_RECORDER_ERROR, failures
// of the only currently supported parameters, "max-duration" and
// "max-filesize" are _not_ fatal.
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index c081629..f21ea53 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -96,7 +96,7 @@
mKeyValuePairs = keyValuePairs;
char *last;
- strcpy(str, keyValuePairs.string());
+ strcpy(str, keyValuePairs.c_str());
char *pair = strtok_r(str, ";", &last);
while (pair != NULL) {
if (strlen(pair) != 0) {
@@ -208,7 +208,7 @@
value = 0;
if (result == NO_ERROR) {
int val;
- if (sscanf(str8.string(), "%d", &val) == 1) {
+ if (sscanf(str8.c_str(), "%d", &val) == 1) {
value = val;
} else {
result = INVALID_OPERATION;
@@ -224,7 +224,7 @@
value = 0;
if (result == NO_ERROR) {
float val;
- if (sscanf(str8.string(), "%f", &val) == 1) {
+ if (sscanf(str8.c_str(), "%f", &val) == 1) {
value = val;
} else {
result = INVALID_OPERATION;
diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp
index 2240223..26fe306 100644
--- a/media/libmediametrics/MediaMetrics.cpp
+++ b/media/libmediametrics/MediaMetrics.cpp
@@ -87,7 +87,7 @@
}
void mediametrics_setString(mediametrics_handle_t handle, attr_t attr,
- const std::string &string) {
+ const std::string &string) {
mediametrics_setCString(handle, attr, string.c_str());
}
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 44e78d6..718f782 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -47,6 +47,7 @@
"framework-permission-aidl-cpp",
"libaudioclient_aidl_conversion",
"libbase",
+ "libbinder_ndk",
"libactivitymanager_aidl",
"libandroid_net",
"libaudioclient",
diff --git a/media/libmediaplayerservice/DeathNotifier.cpp b/media/libmediaplayerservice/DeathNotifier.cpp
index d13bdf5..ab22f67 100644
--- a/media/libmediaplayerservice/DeathNotifier.cpp
+++ b/media/libmediaplayerservice/DeathNotifier.cpp
@@ -31,6 +31,10 @@
DeathRecipient(Notify const& notify): mNotify{notify} {
}
+ void initNdk() {
+ mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
+ }
+
virtual void binderDied(wp<IBinder> const&) override {
mNotify();
}
@@ -39,8 +43,18 @@
mNotify();
}
+ static void OnBinderDied(void *cookie) {
+ DeathRecipient *thiz = (DeathRecipient *)cookie;
+ thiz->mNotify();
+ }
+
+ AIBinder_DeathRecipient *getNdkRecipient() {
+ return mNdkRecipient.get();;
+ }
+
private:
Notify mNotify;
+ ::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
};
DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
@@ -55,6 +69,14 @@
service->linkToDeath(mDeathRecipient, 0);
}
+DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
+ : mService{std::in_place_index<3>, service},
+ mDeathRecipient{new DeathRecipient(notify)} {
+ mDeathRecipient->initNdk();
+ AIBinder_linkToDeath(
+ service.get(), mDeathRecipient->getNdkRecipient(), mDeathRecipient.get());
+}
+
DeathNotifier::DeathNotifier(DeathNotifier&& other)
: mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
other.mService.emplace<0>();
@@ -71,6 +93,12 @@
case 2:
std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
break;
+ case 3:
+ AIBinder_unlinkToDeath(
+ std::get<3>(mService).get(),
+ mDeathRecipient->getNdkRecipient(),
+ mDeathRecipient.get());
+ break;
default:
CHECK(false) << "Corrupted service type during destruction.";
}
diff --git a/media/libmediaplayerservice/DeathNotifier.h b/media/libmediaplayerservice/DeathNotifier.h
index 7bc2611..24e45a3 100644
--- a/media/libmediaplayerservice/DeathNotifier.h
+++ b/media/libmediaplayerservice/DeathNotifier.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
#define ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
+#include <android/binder_auto_utils.h>
#include <android/hidl/base/1.0/IBase.h>
#include <binder/Binder.h>
#include <hidl/HidlSupport.h>
@@ -32,11 +33,12 @@
DeathNotifier(sp<IBinder> const& service, Notify const& notify);
DeathNotifier(sp<HBase> const& service, Notify const& notify);
+ DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify);
DeathNotifier(DeathNotifier&& other);
~DeathNotifier();
private:
- std::variant<std::monostate, sp<IBinder>, sp<HBase>> mService;
+ std::variant<std::monostate, sp<IBinder>, sp<HBase>, ::ndk::SpAIBinder> mService;
class DeathRecipient;
sp<DeathRecipient> mDeathRecipient;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 2e1fdcf..10a1da7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -237,7 +237,7 @@
if (hasFlattenedTag) {
// the tags are UTF16, convert to UTF8
String16 tags = parcel.readString16();
- ssize_t realTagSize = utf16_to_utf8_length(tags.string(), tags.size());
+ ssize_t realTagSize = utf16_to_utf8_length(tags.c_str(), tags.size());
if (realTagSize <= 0) {
strcpy(attributes->tags, "");
} else {
@@ -245,7 +245,7 @@
// copying array size -1, array for tags was calloc'd, no need to NULL-terminate it
size_t tagSize = realTagSize > AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 ?
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1 : realTagSize;
- utf16_to_utf8(tags.string(), tagSize, attributes->tags,
+ utf16_to_utf8(tags.c_str(), tagSize, attributes->tags,
sizeof(attributes->tags) / sizeof(attributes->tags[0]));
}
} else {
@@ -434,7 +434,7 @@
}
}
result.append("\n");
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
}
@@ -549,7 +549,7 @@
mAuxEffectId, mSendLevel);
result.append(buffer);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
if (mTrack != 0) {
mTrack->dump(fd, args);
}
@@ -584,7 +584,7 @@
} else {
result.append(" lock is taken, no dump from player and audio output\n");
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
if (p != NULL) {
p->dump(fd, args);
@@ -644,7 +644,7 @@
snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n",
c->mAttributionSource.pid);
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
result = "\n";
c->dump(fd, args);
@@ -746,7 +746,7 @@
result.append(s.c_str(), s.size());
}
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
@@ -927,10 +927,10 @@
{
for (std::shared_ptr<Codec2Client> const& client :
Codec2Client::CreateFromAllServices()) {
- sp<IBase> base = client->getBase();
- deathNotifiers.emplace_back(
- base, [l = wp<MediaPlayerBase>(p),
- name = std::string(client->getServiceName())]() {
+ sp<IBase> hidlBase = client->getHidlBase();
+ ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+ auto onBinderDied = [l = wp<MediaPlayerBase>(p),
+ name = std::string(client->getServiceName())]() {
sp<MediaPlayerBase> listener = l.promote();
if (listener) {
ALOGI("Codec2 service \"%s\" died. "
@@ -944,7 +944,12 @@
"without a death handler.",
name.c_str());
}
- });
+ };
+ if (hidlBase) {
+ deathNotifiers.emplace_back(hidlBase, onBinderDied);
+ } else if (aidlBase.get() != nullptr) {
+ deathNotifiers.emplace_back(aidlBase, onBinderDied);
+ }
}
}
}
@@ -1249,7 +1254,7 @@
const BufferingSettings& buffering)
{
ALOGV("[%d] setBufferingSettings{%s}",
- mConnId, buffering.toString().string());
+ mConnId, buffering.toString().c_str());
sp<MediaPlayerBase> p = getPlayer();
if (p == 0) return UNKNOWN_ERROR;
return p->setBufferingSettings(buffering);
@@ -1264,7 +1269,7 @@
status_t ret = p->getBufferingSettings(buffering);
if (ret == NO_ERROR) {
ALOGV("[%d] getBufferingSettings{%s}",
- mConnId, buffering->toString().string());
+ mConnId, buffering->toString().c_str());
} else {
ALOGE("[%d] getBufferingSettings returned %d", mConnId, ret);
}
@@ -2008,7 +2013,7 @@
String8 MediaPlayerService::AudioOutput::getParameters(const String8& keys)
{
Mutex::Autolock lock(mLock);
- if (mTrack == 0) return String8::empty();
+ if (mTrack == 0) return String8();
return mTrack->getParameters(keys);
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 58fc06d..ed3ec89 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -22,6 +22,7 @@
#include "MediaPlayerService.h"
#include "StagefrightRecorder.h"
+#include <android/binder_auto_utils.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <binder/IPCThreadState.h>
@@ -245,7 +246,7 @@
}
status_t MediaRecorderClient::setParameters(const String8& params) {
- ALOGV("setParameters(%s)", params.string());
+ ALOGV("setParameters(%s)", params.c_str());
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
@@ -490,9 +491,9 @@
{
for (std::shared_ptr<Codec2Client> const& client :
Codec2Client::CreateFromAllServices()) {
- sp<IBase> base = client->getBase();
- mDeathNotifiers.emplace_back(
- base, [l = wp<IMediaRecorderClient>(listener),
+ sp<IBase> hidlBase = client->getHidlBase();
+ ::ndk::SpAIBinder aidlBase = client->getAidlBase();
+ auto onBinderDied = [l = wp<IMediaRecorderClient>(listener),
name = std::string(client->getServiceName())]() {
sp<IMediaRecorderClient> listener = l.promote();
if (listener) {
@@ -507,7 +508,12 @@
"without a death handler",
name.c_str());
}
- });
+ };
+ if (hidlBase) {
+ mDeathNotifiers.emplace_back(hidlBase, onBinderDied);
+ } else if (aidlBase.get() != nullptr) {
+ mDeathNotifiers.emplace_back(aidlBase, onBinderDied);
+ }
}
}
}
@@ -519,7 +525,7 @@
}
status_t MediaRecorderClient::setClientName(const String16& clientName) {
- ALOGV("setClientName(%s)", String8(clientName).string());
+ ALOGV("setClientName(%s)", String8(clientName).c_str());
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index fb228ca..9e289d0 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -67,7 +67,7 @@
result.append(" MetadataRetrieverClient\n");
snprintf(buffer, 255, " pid(%d)\n", mPid);
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
write(fd, "\n", 1);
return NO_ERROR;
}
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index db979d7..605e659 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -472,7 +472,7 @@
return NULL;
}
- return mMetaData.valueAt(index).string();
+ return mMetaData.valueAt(index).c_str();
}
void StagefrightMetadataRetriever::parseColorAspects(const sp<MetaData>& meta) {
@@ -672,6 +672,18 @@
if (trackMeta->findInt32(kKeyWidth, &imageWidth)
&& trackMeta->findInt32(kKeyHeight, &imageHeight)) {
imagePrimary = imageCount;
+ int32_t displayLeft;
+ int32_t displayTop;
+ int32_t displayRight;
+ int32_t displayBottom;
+ if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop,
+ &displayRight, &displayBottom)
+ && displayLeft >= 0 && displayTop >= 0 && displayRight < imageWidth
+ && displayBottom < imageHeight && displayLeft <= displayRight
+ && displayTop <= displayBottom) {
+ imageWidth = displayRight - displayLeft + 1;
+ imageHeight = displayBottom - displayTop + 1;
+ }
} else {
ALOGE("primary image track ignored for missing dimensions");
}
@@ -692,7 +704,7 @@
// To save the language codes for all timed text tracks
// If multiple text tracks present, the format will look
// like "eng:chi"
- if (!timedTextLang.isEmpty()) {
+ if (!timedTextLang.empty()) {
mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index cb2007d..89348a4 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -519,7 +519,7 @@
// Trim both leading and trailing whitespace from the given string.
static void TrimString(String8 *s) {
size_t num_bytes = s->bytes();
- const char *data = s->string();
+ const char *data = s->c_str();
size_t leading_space = 0;
while (leading_space < num_bytes && isspace(data[leading_space])) {
@@ -531,7 +531,7 @@
--i;
}
- s->setTo(String8(&data[leading_space], i - leading_space));
+ *s = String8(&data[leading_space], i - leading_space);
}
status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
@@ -823,9 +823,9 @@
}
status_t StagefrightRecorder::setParamRtpLocalIp(const String8 &localIp) {
- ALOGV("setParamVideoLocalIp: %s", localIp.string());
+ ALOGV("setParamVideoLocalIp: %s", localIp.c_str());
- mLocalIp.setTo(localIp.string());
+ mLocalIp = localIp.c_str();
return OK;
}
@@ -837,9 +837,9 @@
}
status_t StagefrightRecorder::setParamRtpRemoteIp(const String8 &remoteIp) {
- ALOGV("setParamVideoRemoteIp: %s", remoteIp.string());
+ ALOGV("setParamVideoRemoteIp: %s", remoteIp.c_str());
- mRemoteIp.setTo(remoteIp.string());
+ mRemoteIp = remoteIp.c_str();
return OK;
}
@@ -929,197 +929,197 @@
}
status_t StagefrightRecorder::setLogSessionId(const String8 &log_session_id) {
- ALOGV("setLogSessionId: %s", log_session_id.string());
+ ALOGV("setLogSessionId: %s", log_session_id.c_str());
// TODO: validity check that log_session_id is a 32-byte hex digit.
- mLogSessionId.setTo(log_session_id.string());
+ mLogSessionId = log_session_id.c_str();
return OK;
}
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
- ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+ ALOGV("setParameter: key (%s) => value (%s)", key.c_str(), value.c_str());
if (key == "max-duration") {
int64_t max_duration_ms;
- if (safe_strtoi64(value.string(), &max_duration_ms)) {
+ if (safe_strtoi64(value.c_str(), &max_duration_ms)) {
return setParamMaxFileDurationUs(1000LL * max_duration_ms);
}
} else if (key == "max-filesize") {
int64_t max_filesize_bytes;
- if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
+ if (safe_strtoi64(value.c_str(), &max_filesize_bytes)) {
return setParamMaxFileSizeBytes(max_filesize_bytes);
}
} else if (key == "interleave-duration-us") {
int32_t durationUs;
- if (safe_strtoi32(value.string(), &durationUs)) {
+ if (safe_strtoi32(value.c_str(), &durationUs)) {
return setParamInterleaveDuration(durationUs);
}
} else if (key == "param-movie-time-scale") {
int32_t timeScale;
- if (safe_strtoi32(value.string(), &timeScale)) {
+ if (safe_strtoi32(value.c_str(), &timeScale)) {
return setParamMovieTimeScale(timeScale);
}
} else if (key == "param-use-64bit-offset") {
int32_t use64BitOffset;
- if (safe_strtoi32(value.string(), &use64BitOffset)) {
+ if (safe_strtoi32(value.c_str(), &use64BitOffset)) {
return setParam64BitFileOffset(use64BitOffset != 0);
}
} else if (key == "param-geotag-longitude") {
int64_t longitudex10000;
- if (safe_strtoi64(value.string(), &longitudex10000)) {
+ if (safe_strtoi64(value.c_str(), &longitudex10000)) {
return setParamGeoDataLongitude(longitudex10000);
}
} else if (key == "param-geotag-latitude") {
int64_t latitudex10000;
- if (safe_strtoi64(value.string(), &latitudex10000)) {
+ if (safe_strtoi64(value.c_str(), &latitudex10000)) {
return setParamGeoDataLatitude(latitudex10000);
}
} else if (key == "param-track-time-status") {
int64_t timeDurationUs;
- if (safe_strtoi64(value.string(), &timeDurationUs)) {
+ if (safe_strtoi64(value.c_str(), &timeDurationUs)) {
return setParamTrackTimeStatus(timeDurationUs);
}
} else if (key == "audio-param-sampling-rate") {
int32_t sampling_rate;
- if (safe_strtoi32(value.string(), &sampling_rate)) {
+ if (safe_strtoi32(value.c_str(), &sampling_rate)) {
return setParamAudioSamplingRate(sampling_rate);
}
} else if (key == "audio-param-number-of-channels") {
int32_t number_of_channels;
- if (safe_strtoi32(value.string(), &number_of_channels)) {
+ if (safe_strtoi32(value.c_str(), &number_of_channels)) {
return setParamAudioNumberOfChannels(number_of_channels);
}
} else if (key == "audio-param-encoding-bitrate") {
int32_t audio_bitrate;
- if (safe_strtoi32(value.string(), &audio_bitrate)) {
+ if (safe_strtoi32(value.c_str(), &audio_bitrate)) {
return setParamAudioEncodingBitRate(audio_bitrate);
}
} else if (key == "audio-param-time-scale") {
int32_t timeScale;
- if (safe_strtoi32(value.string(), &timeScale)) {
+ if (safe_strtoi32(value.c_str(), &timeScale)) {
return setParamAudioTimeScale(timeScale);
}
} else if (key == "video-param-encoding-bitrate") {
int32_t video_bitrate;
- if (safe_strtoi32(value.string(), &video_bitrate)) {
+ if (safe_strtoi32(value.c_str(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
} else if (key == "video-param-bitrate-mode") {
int32_t video_bitrate_mode;
- if (safe_strtoi32(value.string(), &video_bitrate_mode)) {
+ if (safe_strtoi32(value.c_str(), &video_bitrate_mode)) {
return setParamVideoBitRateMode(video_bitrate_mode);
}
} else if (key == "video-param-rotation-angle-degrees") {
int32_t degrees;
- if (safe_strtoi32(value.string(), °rees)) {
+ if (safe_strtoi32(value.c_str(), °rees)) {
return setParamVideoRotation(degrees);
}
} else if (key == "video-param-i-frames-interval") {
int32_t seconds;
- if (safe_strtoi32(value.string(), &seconds)) {
+ if (safe_strtoi32(value.c_str(), &seconds)) {
return setParamVideoIFramesInterval(seconds);
}
} else if (key == "video-param-encoder-profile") {
int32_t profile;
- if (safe_strtoi32(value.string(), &profile)) {
+ if (safe_strtoi32(value.c_str(), &profile)) {
return setParamVideoEncoderProfile(profile);
}
} else if (key == "video-param-encoder-level") {
int32_t level;
- if (safe_strtoi32(value.string(), &level)) {
+ if (safe_strtoi32(value.c_str(), &level)) {
return setParamVideoEncoderLevel(level);
}
} else if (key == "video-param-camera-id") {
int32_t cameraId;
- if (safe_strtoi32(value.string(), &cameraId)) {
+ if (safe_strtoi32(value.c_str(), &cameraId)) {
return setParamVideoCameraId(cameraId);
}
} else if (key == "video-param-time-scale") {
int32_t timeScale;
- if (safe_strtoi32(value.string(), &timeScale)) {
+ if (safe_strtoi32(value.c_str(), &timeScale)) {
return setParamVideoTimeScale(timeScale);
}
} else if (key == "time-lapse-enable") {
int32_t captureFpsEnable;
- if (safe_strtoi32(value.string(), &captureFpsEnable)) {
+ if (safe_strtoi32(value.c_str(), &captureFpsEnable)) {
return setParamCaptureFpsEnable(captureFpsEnable);
}
} else if (key == "time-lapse-fps") {
double fps;
- if (safe_strtod(value.string(), &fps)) {
+ if (safe_strtod(value.c_str(), &fps)) {
return setParamCaptureFps(fps);
}
} else if (key == "rtp-param-local-ip") {
return setParamRtpLocalIp(value);
} else if (key == "rtp-param-local-port") {
int32_t localPort;
- if (safe_strtoi32(value.string(), &localPort)) {
+ if (safe_strtoi32(value.c_str(), &localPort)) {
return setParamRtpLocalPort(localPort);
}
} else if (key == "rtp-param-remote-ip") {
return setParamRtpRemoteIp(value);
} else if (key == "rtp-param-remote-port") {
int32_t remotePort;
- if (safe_strtoi32(value.string(), &remotePort)) {
+ if (safe_strtoi32(value.c_str(), &remotePort)) {
return setParamRtpRemotePort(remotePort);
}
} else if (key == "rtp-param-self-id") {
int32_t selfID;
int64_t temp;
- if (safe_strtoi64(value.string(), &temp)) {
+ if (safe_strtoi64(value.c_str(), &temp)) {
selfID = static_cast<int32_t>(temp);
return setParamSelfID(selfID);
}
} else if (key == "rtp-param-opponent-id") {
int32_t opnId;
int64_t temp;
- if (safe_strtoi64(value.string(), &temp)) {
+ if (safe_strtoi64(value.c_str(), &temp)) {
opnId = static_cast<int32_t>(temp);
return setParamVideoOpponentID(opnId);
}
} else if (key == "rtp-param-payload-type") {
int32_t payloadType;
- if (safe_strtoi32(value.string(), &payloadType)) {
+ if (safe_strtoi32(value.c_str(), &payloadType)) {
return setParamPayloadType(payloadType);
}
} else if (key == "rtp-param-ext-cvo-extmap") {
int32_t extmap;
- if (safe_strtoi32(value.string(), &extmap)) {
+ if (safe_strtoi32(value.c_str(), &extmap)) {
return setRTPCVOExtMap(extmap);
}
} else if (key == "rtp-param-ext-cvo-degrees") {
int32_t degrees;
- if (safe_strtoi32(value.string(), °rees)) {
+ if (safe_strtoi32(value.c_str(), °rees)) {
return setRTPCVODegrees(degrees);
}
} else if (key == "video-param-request-i-frame") {
return requestIDRFrame();
} else if (key == "rtp-param-set-socket-dscp") {
int32_t dscp;
- if (safe_strtoi32(value.string(), &dscp)) {
+ if (safe_strtoi32(value.c_str(), &dscp)) {
return setParamRtpDscp(dscp);
}
} else if (key == "rtp-param-set-socket-ecn") {
int32_t targetEcn;
- if (safe_strtoi32(value.string(), &targetEcn)) {
+ if (safe_strtoi32(value.c_str(), &targetEcn)) {
return setParamRtpEcn(targetEcn);
}
} else if (key == "rtp-param-set-socket-network") {
int64_t networkHandle;
- if (safe_strtoi64(value.string(), &networkHandle)) {
+ if (safe_strtoi64(value.c_str(), &networkHandle)) {
return setSocketNetwork(networkHandle);
}
} else if (key == "log-session-id") {
return setLogSessionId(value);
} else {
- ALOGE("setParameter: failed to find key %s", key.string());
+ ALOGE("setParameter: failed to find key %s", key.c_str());
}
return BAD_VALUE;
}
status_t StagefrightRecorder::setParameters(const String8 ¶ms) {
- ALOGV("setParameters: %s", params.string());
- const char *cparams = params.string();
+ ALOGV("setParameters: %s", params.c_str());
+ const char *cparams = params.c_str();
const char *key_start = cparams;
for (;;) {
const char *equal_pos = strchr(key_start, '=');
@@ -1137,9 +1137,9 @@
const char *semicolon_pos = strchr(value_start, ';');
String8 value;
if (semicolon_pos == NULL) {
- value.setTo(value_start);
+ value = value_start;
} else {
- value.setTo(value_start, semicolon_pos - value_start);
+ value = String8(value_start, semicolon_pos - value_start);
}
if (setParameter(key, value) != OK) {
return BAD_VALUE;
@@ -2680,7 +2680,7 @@
result.append(buffer);
snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate);
result.append(buffer);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
return OK;
}
} // namespace android
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 017f403..b511372 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -35,6 +35,7 @@
shared_libs: [
"framework-permission-aidl-cpp",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libmedia",
"libstagefright",
@@ -173,6 +174,7 @@
"libnetd_client",
"libpowermanager",
"libstagefright_httplive",
+ "libaudiohal@7.0",
],
}
diff --git a/media/libmediaplayerservice/include/MediaPlayerInterface.h b/media/libmediaplayerservice/include/MediaPlayerInterface.h
index fb20aab..be1aa00 100644
--- a/media/libmediaplayerservice/include/MediaPlayerInterface.h
+++ b/media/libmediaplayerservice/include/MediaPlayerInterface.h
@@ -149,7 +149,7 @@
virtual bool needsTrailingPadding() { return true; }
virtual status_t setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; }
- virtual String8 getParameters(const String8& /* keys */) { return String8::empty(); }
+ virtual String8 getParameters(const String8& /* keys */) { return String8(); }
virtual media::VolumeShaper::Status applyVolumeShaper(
const sp<media::VolumeShaper::Configuration>& configuration,
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 1358faa..991c77b 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -270,7 +270,7 @@
}
ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
- mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
+ mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].c_str()));
if (mSources.size() == 0) {
ALOGE("b/23705695");
@@ -292,12 +292,12 @@
*buffering = mBufferingSettings;
}
- ALOGV("getBufferingSettings{%s}", buffering->toString().string());
+ ALOGV("getBufferingSettings{%s}", buffering->toString().c_str());
return OK;
}
status_t NuPlayer::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
- ALOGV("setBufferingSettings{%s}", buffering.toString().string());
+ ALOGV("setBufferingSettings{%s}", buffering.toString().c_str());
Mutex::Autolock _l(mLock);
mBufferingSettings = buffering;
@@ -1619,7 +1619,7 @@
return status;
}
ALOGV("prepareDrm: createCryptoAndPlugin succeeded for uuid: %s",
- DrmUUID::toHexString(uuid).string());
+ DrmUUID::toHexString(uuid).c_str());
*outCrypto = crypto;
// as long a there is an active crypto
@@ -1632,7 +1632,7 @@
}
// first mime in this list is either the video track, or the first audio track
- const char *mime = mMimes[0].string();
+ const char *mime = mMimes[0].c_str();
mIsSecure = crypto->requiresSecureDecoderComponent(mime);
ALOGV("prepareDrm: requiresSecureDecoderComponent mime: %s isSecure: %d",
mime, mIsSecure);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 485923f..a625893 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -370,7 +370,7 @@
}
void NuPlayer::setDataSourceAsync(const String8& rtpParams) {
- ALOGD("setDataSourceAsync for RTP = %s", rtpParams.string());
+ ALOGD("setDataSourceAsync for RTP = %s", rtpParams.c_str());
sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index a964d4f..8525192 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -89,8 +89,8 @@
drmSchemes.add(_uuid);
ALOGV("ParsePSSH[%zu]: %s: %s", numentries,
- _uuid.toHexString().string(),
- DrmUUID::arrayToHex(data, datalen).string()
+ _uuid.toHexString().c_str(),
+ DrmUUID::arrayToHex(data, datalen).c_str()
);
numentries++;
@@ -167,7 +167,7 @@
parcel->writeByteArray(psshsize, (const uint8_t*)pssh);
ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO PSSH: size: %zu %s", psshsize,
- DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string());
+ DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).c_str());
// 2) supportedDRMs
Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize);
@@ -177,7 +177,7 @@
parcel->writeByteArray(DrmUUID::UUID_SIZE, uuid.ptr());
ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO supportedScheme[%zu] %s", i,
- uuid.toHexString().string());
+ uuid.toHexString().c_str());
}
}
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index fd03150..9a33120 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -56,7 +56,7 @@
mReceivedFirstRTPPacket(false),
mPausing(false),
mPauseGeneration(0) {
- ALOGD("RTPSource initialized with rtpParams=%s", rtpParams.string());
+ ALOGD("RTPSource initialized with rtpParams=%s", rtpParams.c_str());
}
NuPlayer::RTPSource::~RTPSource() {
@@ -661,7 +661,7 @@
}
status_t NuPlayer::RTPSource::setParameter(const String8 &key, const String8 &value) {
- ALOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+ ALOGV("setParameter: key (%s) => value (%s)", key.c_str(), value.c_str());
bool isAudioKey = key.contains("audio");
TrackInfo *info = NULL;
@@ -684,12 +684,12 @@
if (key == "rtp-param-mime-type") {
info->mMimeType = value;
- const char *mime = value.string();
+ const char *mime = value.c_str();
const char *delimiter = strchr(mime, '/');
info->mCodecName = delimiter ? (delimiter + 1) : "<none>";
ALOGV("rtp-param-mime-type: mMimeType (%s) => mCodecName (%s)",
- info->mMimeType.string(), info->mCodecName.string());
+ info->mMimeType.c_str(), info->mCodecName.c_str());
} else if (key == "video-param-decoder-profile") {
info->mCodecProfile = atoi(value);
} else if (key == "video-param-decoder-level") {
@@ -732,8 +732,8 @@
}
status_t NuPlayer::RTPSource::setParameters(const String8 ¶ms) {
- ALOGV("setParameters: %s", params.string());
- const char *cparams = params.string();
+ ALOGV("setParameters: %s", params.c_str());
+ const char *cparams = params.c_str();
const char *key_start = cparams;
for (;;) {
const char *equal_pos = strchr(key_start, '=');
@@ -751,9 +751,9 @@
const char *semicolon_pos = strchr(value_start, ';');
String8 value;
if (semicolon_pos == NULL) {
- value.setTo(value_start);
+ value = value_start;
} else {
- value.setTo(value_start, semicolon_pos - value_start);
+ value = String8(value_start, semicolon_pos - value_start);
}
if (setParameter(key, value) != OK) {
return BAD_VALUE;
@@ -784,7 +784,7 @@
//static
void NuPlayer::RTPSource::TrimString(String8 *s) {
size_t num_bytes = s->bytes();
- const char *data = s->string();
+ const char *data = s->c_str();
size_t leading_space = 0;
while (leading_space < num_bytes && isspace(data[leading_space])) {
@@ -796,7 +796,7 @@
--i;
}
- s->setTo(String8(&data[leading_space], i - leading_space));
+ *s = String8(&data[leading_space], i - leading_space);
}
} // namespace android
diff --git a/media/libnblog/PerformanceAnalysis.cpp b/media/libnblog/PerformanceAnalysis.cpp
index e91a511..7982805 100644
--- a/media/libnblog/PerformanceAnalysis.cpp
+++ b/media/libnblog/PerformanceAnalysis.cpp
@@ -393,7 +393,7 @@
PerformanceAnalysis& curr = hash.second;
// write performance data to console
curr.reportPerformance(&body, thread.first, hash.first);
- if (!body.isEmpty()) {
+ if (!body.empty()) {
dumpLine(fd, indent, body);
body.clear();
}
@@ -409,7 +409,7 @@
// Writes a string into specified file descriptor
void dumpLine(int fd, int indent, const String8 &body) {
- dprintf(fd, "%.*s%s \n", indent, "", body.string());
+ dprintf(fd, "%.*s%s \n", indent, "", body.c_str());
}
} // namespace ReportPerformance
diff --git a/media/libnblog/Reader.cpp b/media/libnblog/Reader.cpp
index d6232d4..71ebfd1 100644
--- a/media/libnblog/Reader.cpp
+++ b/media/libnblog/Reader.cpp
@@ -282,8 +282,8 @@
default:
break;
}
- if (!body.isEmpty()) {
- dprintf(fd, "%.*s%s %s\n", (int)indent, "", timestamp.string(), body.string());
+ if (!body.empty()) {
+ dprintf(fd, "%.*s%s %s\n", (int)indent, "", timestamp.c_str(), body.c_str());
body.clear();
}
timestamp.clear();
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index a26fcbe..0af9d12 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -270,10 +270,10 @@
"SurfaceUtils.cpp",
"ThrottledSource.cpp",
"Utils.cpp",
- "VideoRenderQualityTracker.cpp",
"VideoFrameSchedulerBase.cpp",
"VideoFrameScheduler.cpp",
- ],
+ "VideoRenderQualityTracker.cpp",
+ ],
shared_libs: [
"libstagefright_framecapture_utils",
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index eb3cb45..ede4855 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -38,7 +38,7 @@
mName = String8::format("CallbackDataSource(%d->%d, %s)",
getpid(),
IPCThreadState::self()->getCallingPid(),
- mIDataSource->toString().string());
+ mIDataSource->toString().c_str());
}
@@ -120,7 +120,7 @@
TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
: mSource(source), mCachedOffset(0), mCachedSize(0) {
- mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
+ mName = String8::format("TinyCacheSource(%s)", mSource->toString().c_str());
}
status_t TinyCacheSource::initCheck() const {
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 57937f9..1a0bb7f 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -86,6 +86,22 @@
displayWidth = width;
displayHeight = height;
}
+ int32_t displayLeft = 0;
+ int32_t displayTop = 0;
+ int32_t displayRight;
+ int32_t displayBottom;
+ if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop, &displayRight,
+ &displayBottom)) {
+ if (displayLeft >= 0 && displayTop >= 0 && displayRight < width && displayBottom < height &&
+ displayLeft <= displayRight && displayTop <= displayBottom) {
+ displayWidth = displayRight - displayLeft + 1;
+ displayHeight = displayBottom - displayTop + 1;
+ } else {
+ // Crop rectangle is invalid, use the whole frame.
+ displayLeft = 0;
+ displayTop = 0;
+ }
+ }
if (allocRotated) {
if (rotationAngle == 90 || rotationAngle == 270) {
@@ -108,8 +124,8 @@
}
}
- VideoFrame frame(width, height, displayWidth, displayHeight,
- tileWidth, tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
+ VideoFrame frame(width, height, displayWidth, displayHeight, displayLeft, displayTop, tileWidth,
+ tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
size_t size = frame.getFlattenedSize();
sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2cd3768..e399cbe 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -612,7 +612,7 @@
result.append(buffer);
snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false");
result.append(buffer);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
(*it)->dump(fd, args);
@@ -634,7 +634,7 @@
result.append(buffer);
snprintf(buffer, SIZE, " duration encoded : %" PRId64 " us\n", mTrackDurationUs);
result.append(buffer);
- ::write(fd, result.string(), result.size());
+ ::write(fd, result.c_str(), result.size());
return OK;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index aeee3a8..d80cfa6 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -243,7 +243,7 @@
"android.media.mediacodec.judder-score-histogram-buckets";
// Freeze event
static const char *kCodecFreezeEventCount = "android.media.mediacodec.freeze-event-count";
-static const char *kFreezeEventKeyName = "freeze";
+static const char *kFreezeEventKeyName = "videofreeze";
static const char *kFreezeEventInitialTimeUs = "android.media.mediacodec.freeze.initial-time-us";
static const char *kFreezeEventDurationMs = "android.media.mediacodec.freeze.duration-ms";
static const char *kFreezeEventCount = "android.media.mediacodec.freeze.count";
@@ -255,7 +255,7 @@
"android.media.mediacodec.freeze.details-distance-ms";
// Judder event
static const char *kCodecJudderEventCount = "android.media.mediacodec.judder-event-count";
-static const char *kJudderEventKeyName = "judder";
+static const char *kJudderEventKeyName = "videojudder";
static const char *kJudderEventInitialTimeUs = "android.media.mediacodec.judder.initial-time-us";
static const char *kJudderEventDurationMs = "android.media.mediacodec.judder.duration-ms";
static const char *kJudderEventCount = "android.media.mediacodec.judder.count";
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2520e2a..1c72a65 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -242,22 +242,22 @@
continue;
}
void *libHandle = android_dlopen_ext(
- libPath.string(),
+ libPath.c_str(),
RTLD_NOW | RTLD_LOCAL, dlextinfo);
if (libHandle == nullptr) {
- ALOGI("dlopen(%s) reported error %s", libPath.string(), strerror(errno));
+ ALOGI("dlopen(%s) reported error %s", libPath.c_str(), strerror(errno));
continue;
}
GetExtractorDef getDef =
(GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
if (getDef == nullptr) {
- ALOGI("no sniffer found in %s", libPath.string());
+ ALOGI("no sniffer found in %s", libPath.c_str());
dlclose(libHandle);
continue;
}
- ALOGV("registering sniffer for %s", libPath.string());
+ ALOGV("registering sniffer for %s", libPath.c_str());
RegisterExtractor(
new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
}
@@ -387,7 +387,7 @@
out.append(" (no plugins registered)\n");
}
}
- write(fd, out.string(), out.size());
+ write(fd, out.c_str(), out.size());
return OK;
}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 28ca9ff..92ec56b 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -164,7 +164,7 @@
const char* NuMediaExtractor::getName() const {
Mutex::Autolock autoLock(mLock);
- return mImpl == nullptr ? nullptr : mName.string();
+ return mImpl == nullptr ? nullptr : mName.c_str();
}
static String8 arrayToString(const std::vector<uint8_t> &array) {
@@ -172,7 +172,7 @@
for (size_t i = 0; i < array.size(); i++) {
result.appendFormat("%02x ", array[i]);
}
- if (result.isEmpty()) {
+ if (result.empty()) {
result.append("(null)");
}
return result;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index f91a8b2..6c26c28 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -363,6 +363,7 @@
int32_t _g_u;
int32_t _g_v;
int32_t _b_u;
+ int32_t _c16; // 16 for limited range matrix, 0 for full rance
};
/*
@@ -425,18 +426,18 @@
*
* clip range 8-bit: [-277, 535], 10-bit: [-1111, 2155]
*/
-const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454 };
-const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516 };
-const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518 };
+const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454, 0 };
+const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516, 16 };
+const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518, 16 };
/**
* BT.709: K_R = 0.2126; K_B = 0.0722
*
* clip range 8-bit: [-289, 547], 10-bit: [-1159, 2202]
*/
-const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475 };
-const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541 };
-const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 290, 460, 55, 137, 542 };
+const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475, 0 };
+const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541, 16 };
+const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 299, 460, 55, 137, 542, 16 };
/**
* BT.2020: K_R = 0.2627; K_B = 0.0593
@@ -445,9 +446,9 @@
*
* This is the largest clip range.
*/
-const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482 };
-const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548 };
-const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550 };
+const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482, 0 };
+const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548, 16 };
+const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550, 16 };
constexpr int CLIP_RANGE_MIN_8BIT = -294;
constexpr int CLIP_RANGE_MAX_8BIT = 552;
@@ -781,7 +782,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+ signed _c16 = matrix->_c16;
uint8_t *kAdjustedClip = initClip();
@@ -1257,6 +1258,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
+ signed _c16 = matrix->_c16;
uint8_t *dst_ptr = (uint8_t *)dst.mBits
+ dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;
@@ -1275,13 +1277,12 @@
//TODO: optimize for chroma sampling, reading and writing multiple pixels
// within the same loop
- signed _c16 = 0;
+
void *kAdjustedClip = nullptr;
if (mSrcImage->getBitDepth() != ImageBitDepth8) {
ALOGE("BitDepth != 8 for MediaImage2");
return ERROR_UNSUPPORTED;
}
- _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
kAdjustedClip = initClip();
auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip);
@@ -1388,7 +1389,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0;
+ signed _c16 = matrix->_c16;
uint8_t *kAdjustedClip = initClip();
@@ -1463,7 +1464,7 @@
signed _neg_g_v = -matrix->_g_v;
signed _r_v = matrix->_r_v;
signed _y = matrix->_y;
- signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 64 : 0;
+ signed _c64 = matrix->_c16 * 4;
uint16_t *kAdjustedClip10bit = initClip10Bit();
@@ -1483,8 +1484,8 @@
for (size_t y = 0; y < src.cropHeight(); ++y) {
for (size_t x = 0; x < src.cropWidth(); x += 2) {
signed y1, y2, u, v;
- y1 = (src_y[x] >> 6) - _c16;
- y2 = (src_y[x + 1] >> 6) - _c16;
+ y1 = (src_y[x] >> 6) - _c64;
+ y2 = (src_y[x + 1] >> 6) - _c64;
u = int(src_uv[x] >> 6) - 512;
v = int(src_uv[x + 1] >> 6) - 512;
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 68f1de9..5ac1b9f 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -209,7 +209,7 @@
*out = buffer;
if (actualUrl != NULL) {
*actualUrl = mDataSource->getUri();
- if (actualUrl->isEmpty()) {
+ if (actualUrl->empty()) {
*actualUrl = url;
}
}
@@ -265,7 +265,7 @@
#endif
sp<M3UParser> playlist =
- new M3UParser(actualUrl.string(), buffer->data(), buffer->size());
+ new M3UParser(actualUrl.c_str(), buffer->data(), buffer->size());
if (playlist->initCheck() != OK) {
ALOGE("failed to parse .m3u8 playlist");
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index a464504..946d533 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -72,8 +72,8 @@
void setCrypto(const sp<ICrypto> &crypto) override;
void setDescrambler(const sp<IDescrambler> &descrambler) override;
- virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual status_t queueSecureInputBuffer(
+ status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ status_t queueSecureInputBuffer(
const sp<MediaCodecBuffer> &buffer,
bool secure,
const uint8_t *key,
@@ -83,10 +83,10 @@
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
AString *errorDetailMsg) override;
- virtual status_t attachBuffer(
+ status_t attachBuffer(
const std::shared_ptr<C2Buffer> &c2Buffer,
const sp<MediaCodecBuffer> &buffer) override;
- virtual status_t attachEncryptedBuffer(
+ status_t attachEncryptedBuffer(
const sp<hardware::HidlMemory> &memory,
bool secure,
const uint8_t *key,
@@ -98,12 +98,12 @@
size_t numSubSamples,
const sp<MediaCodecBuffer> &buffer,
AString* errorDetailMsg) override;
- virtual status_t renderOutputBuffer(
+ status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
- virtual void pollForRenderedBuffers() override;
- virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
- virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
- virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+ void pollForRenderedBuffers() override;
+ status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
+ void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
+ void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
// Methods below are interface for ACodec to use.
diff --git a/media/libstagefright/include/media/stagefright/MediaHistogram.h b/media/libstagefright/include/media/stagefright/MediaHistogram.h
index 50fa258..46ee288 100644
--- a/media/libstagefright/include/media/stagefright/MediaHistogram.h
+++ b/media/libstagefright/include/media/stagefright/MediaHistogram.h
@@ -29,11 +29,11 @@
public:
MediaHistogram();
void clear();
- bool setup(int bucketCount, T width, T floor = 0);
+ bool setup(size_t bucketCount, T width, T floor = 0);
bool setup(const std::vector<T> &bucketLimits);
void insert(T sample);
- size_t size();
- int64_t operator[](int);
+ size_t size() const;
+ int64_t operator[](int) const;
T getMin() const { return mMin; }
T getMax() const { return mMax; }
T getCount() const { return mCount; }
@@ -45,7 +45,7 @@
private:
MediaHistogram(const MediaHistogram &); // disallow
- bool allocate(int bucketCount, bool withBucketLimits);
+ void allocate(size_t bucketCount, bool withBucketLimits);
T mFloor, mCeiling, mWidth;
T mMin, mMax, mSum;
@@ -73,13 +73,12 @@
}
template<typename T>
-bool MediaHistogram<T>::setup(int bucketCount, T width, T floor) {
+bool MediaHistogram<T>::setup(size_t bucketCount, T width, T floor) {
if (bucketCount <= 0 || width <= 0) {
return false;
}
- if (!allocate(bucketCount, false)) {
- return false;
- }
+ allocate(bucketCount, false);
+
mWidth = width;
mFloor = floor;
mCeiling = floor + bucketCount * width;
@@ -92,14 +91,14 @@
if (bucketLimits.size() <= 1) {
return false;
}
- int bucketCount = bucketLimits.size() - 1;
- if (!allocate(bucketCount, true)) {
- return false;
- }
+ // The floor is the first bucket limit value, so offset by 1
+ size_t bucketCount = bucketLimits.size() - 1;
+ allocate(bucketCount, true);
mWidth = -1;
mFloor = bucketLimits[0];
- for (int i = 0; i < bucketCount; ++i) {
+ for (size_t i = 0; i < bucketCount; ++i) {
+ // The floor is the first bucket, so offset by 1
mBucketLimits[i] = bucketLimits[i + 1];
}
mCeiling = bucketLimits[bucketCount];
@@ -108,7 +107,7 @@
}
template<typename T>
-bool MediaHistogram<T>::allocate(int bucketCount, bool withBucketLimits) {
+void MediaHistogram<T>::allocate(size_t bucketCount, bool withBucketLimits) {
assert(bucketCount > 0);
if (bucketCount != mBuckets.size()) {
mBuckets = std::vector<T>(bucketCount, 0);
@@ -116,7 +115,6 @@
if (withBucketLimits && mBucketLimits.size() != bucketCount) {
mBucketLimits = std::vector<T>(bucketCount, 0);
}
- return true;
}
template<typename T>
@@ -128,8 +126,8 @@
mCount++;
mSum += sample;
- if (mMin > sample) mMin = sample;
- if (mMax < sample) mMax = sample;
+ mMin = std::min(mMin, sample);
+ mMax = std::max(mMax, sample);
if (sample < mFloor) {
mBelow++;
@@ -138,7 +136,7 @@
} else if (mWidth == -1) {
// A binary search might be more efficient for large number of buckets, but it is expected
// that there will never be a large amount of buckets, so keep the code simple.
- for (int slot = 0; slot < mBucketLimits.size(); ++slot) {
+ for (size_t slot = 0; slot < mBucketLimits.size(); ++slot) {
if (sample < mBucketLimits[slot]) {
mBuckets[slot]++;
break;
@@ -153,12 +151,12 @@
}
template<typename T>
-size_t MediaHistogram<T>::size() {
+size_t MediaHistogram<T>::size() const {
return mBuckets.size() + 1;
}
template<typename T>
-int64_t MediaHistogram<T>::operator[](int i) {
+int64_t MediaHistogram<T>::operator[](int i) const {
assert(i >= 0);
assert(i <= mBuckets.size());
if (i == mBuckets.size()) {
@@ -179,7 +177,7 @@
} else {
ss << mFloor << "," << mWidth << "," << mBelow << "{";
}
- for (int i = 0; i < mBuckets.size(); i++) {
+ for (size_t i = 0; i < mBuckets.size(); i++) {
if (i != 0) {
ss << ",";
}
@@ -194,12 +192,12 @@
std::stringstream ss("");
if (mWidth == -1) {
ss << mFloor;
- for (int i = 0; i < mBucketLimits.size(); ++i) {
+ for (size_t i = 0; i < mBucketLimits.size(); ++i) {
ss << ',' << mBucketLimits[i];
}
} else {
ss << mFloor;
- for (int i = 1; i <= mBuckets.size(); ++i) {
+ for (size_t i = 1; i <= mBuckets.size(); ++i) {
ss << ',' << (mFloor + i * mWidth);
}
}
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index d605cda..621d772 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -106,7 +106,7 @@
if (mMemory.get() == nullptr) {
ALOGE("Failed to allocate memory!");
}
- mName = String8::format("RemoteDataSource(%s)", mSource->toString().string());
+ mName = String8::format("RemoteDataSource(%s)", mSource->toString().c_str());
}
DISALLOW_EVIL_CONSTRUCTORS(RemoteDataSource);
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
index 0906433..b2d5a70 100644
--- a/media/libstagefright/omx/OMXStore.cpp
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -167,7 +167,7 @@
if (mPluginByComponentName.indexOfKey(name8) >= 0) {
ALOGE("A component of name '%s' already exists, ignoring this one.",
- name8.string());
+ name8.c_str());
continue;
}
@@ -263,7 +263,7 @@
const String8 &name8 = mPluginByComponentName.keyAt(index);
CHECK(size >= 1 + name8.size());
- strcpy(name, name8.string());
+ strcpy(name, name8.c_str());
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/omx/OmxGraphicBufferSource.cpp b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
index 33481e3..5d653bc 100644
--- a/media/libstagefright/omx/OmxGraphicBufferSource.cpp
+++ b/media/libstagefright/omx/OmxGraphicBufferSource.cpp
@@ -85,6 +85,18 @@
int32_t bufferCount,
uint32_t frameWidth,
uint32_t frameHeight,
+ uint32_t consumerUsage) {
+ uint64_t consumerUsage64 = static_cast<uint64_t>(consumerUsage);
+ return configure(omxNode, dataSpace, bufferCount,
+ frameWidth, frameHeight, consumerUsage64);
+}
+
+status_t OmxGraphicBufferSource::configure(
+ const sp<IOmxNodeWrapper>& omxNode,
+ int32_t dataSpace,
+ int32_t bufferCount,
+ uint32_t frameWidth,
+ uint32_t frameHeight,
uint64_t consumerUsage) {
if (omxNode == NULL) {
return BAD_VALUE;
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
index 1c3cb4e..a6e23ed 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/1.0/Conversion.h
@@ -540,11 +540,11 @@
*/
// convert: IOMX::ComponentInfo -> IOmx::ComponentInfo
inline bool convertTo(IOmx::ComponentInfo* t, IOMX::ComponentInfo const& l) {
- t->mName = l.mName.string();
+ t->mName = l.mName.c_str();
t->mRoles.resize(l.mRoles.size());
size_t i = 0;
for (auto& role : l.mRoles) {
- t->mRoles[i++] = role.string();
+ t->mRoles[i++] = role.c_str();
}
return true;
}
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
index a23efac..8b920c1 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OmxGraphicBufferSource.h
@@ -63,7 +63,19 @@
// ------------------------------
// Configure the buffer source to be used with an OMX node with the default
- // data space.
+ // data space.(32-bit consumerUsage flag, for vendor partition
+ // compatibility)
+ [[deprecated("use configure() with a 64-bit consumerUsage flag instead")]]
+ status_t configure(
+ const sp<IOmxNodeWrapper> &omxNode,
+ int32_t dataSpace,
+ int32_t bufferCount,
+ uint32_t frameWidth,
+ uint32_t frameHeight,
+ uint32_t consumerUsage);
+
+ // Configure the buffer source to be used with an OMX node with the default
+ // data space. (64-bit consumerUsage flag)
status_t configure(
const sp<IOmxNodeWrapper> &omxNode,
int32_t dataSpace,
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 039991c..b9bea1a 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -789,7 +789,7 @@
for (List<IOMX::ComponentInfo>::iterator it = componentInfos.begin();
it != componentInfos.end(); ++it) {
const IOMX::ComponentInfo &info = *it;
- const char *componentName = info.mName.string();
+ const char *componentName = info.mName.c_str();
if (strncmp(componentName, "OMX.google.", 11)) {
continue;
@@ -797,7 +797,7 @@
for (List<String8>::const_iterator role_it = info.mRoles.begin();
role_it != info.mRoles.end(); ++role_it) {
- const char *componentRole = (*role_it).string();
+ const char *componentRole = (*role_it).c_str();
err = test(componentName, componentRole);
diff --git a/media/libstagefright/renderfright/gl/GLExtensions.cpp b/media/libstagefright/renderfright/gl/GLExtensions.cpp
index 2924b0e..4717c68 100644
--- a/media/libstagefright/renderfright/gl/GLExtensions.cpp
+++ b/media/libstagefright/renderfright/gl/GLExtensions.cpp
@@ -68,19 +68,19 @@
}
char const* GLExtensions::getVendor() const {
- return mVendor.string();
+ return mVendor.c_str();
}
char const* GLExtensions::getRenderer() const {
- return mRenderer.string();
+ return mRenderer.c_str();
}
char const* GLExtensions::getVersion() const {
- return mVersion.string();
+ return mVersion.c_str();
}
char const* GLExtensions::getExtensions() const {
- return mExtensions.string();
+ return mExtensions.c_str();
}
void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExtensions) {
@@ -123,11 +123,11 @@
}
char const* GLExtensions::getEGLVersion() const {
- return mEGLVersion.string();
+ return mEGLVersion.c_str();
}
char const* GLExtensions::getEGLExtensions() const {
- return mEGLExtensions.string();
+ return mEGLExtensions.c_str();
}
} // namespace gl
diff --git a/media/libstagefright/renderfright/gl/ProgramCache.cpp b/media/libstagefright/renderfright/gl/ProgramCache.cpp
index af55172..350f0b7 100644
--- a/media/libstagefright/renderfright/gl/ProgramCache.cpp
+++ b/media/libstagefright/renderfright/gl/ProgramCache.cpp
@@ -62,7 +62,7 @@
return out;
}
friend inline Formatter& operator<<(Formatter& out, const String8& in) {
- return operator<<(out, in.string());
+ return operator<<(out, in.c_str());
}
friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
return (*func)(to);
@@ -778,7 +778,7 @@
// fragment shader
String8 fs = generateFragmentShader(needs);
- return std::make_unique<Program>(needs, vs.string(), fs.string());
+ return std::make_unique<Program>(needs, vs.c_str(), fs.c_str());
}
void ProgramCache::useProgram(EGLContext context, const Description& description) {
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 100c0cd..fc9f58e 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -203,12 +203,12 @@
seqNum, mNextExpectedSeqNo,
baseJbTimeMs, dynamicJbTimeMs, tryJbTimeMs, JITTER_MULTIPLE);
if (isSecondLineBroken) {
- ALOGE("%s", info.string());
+ ALOGE("%s", info.c_str());
printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
} else {
- ALOGW("%s", info.string());
+ ALOGW("%s", info.c_str());
}
}
diff --git a/media/libstagefright/rtsp/AHEVCAssembler.cpp b/media/libstagefright/rtsp/AHEVCAssembler.cpp
index 7b5c24a..06f19ab 100644
--- a/media/libstagefright/rtsp/AHEVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AHEVCAssembler.cpp
@@ -213,12 +213,12 @@
seqNum, mNextExpectedSeqNo,
baseJbTimeMs, dynamicJbTimeMs, tryJbTimeMs, JITTER_MULTIPLE);
if (isSecondLineBroken) {
- ALOGE("%s", info.string());
+ ALOGE("%s", info.c_str());
printNowTimeMs(startTimeMs, nowTimeMs, playedTimeMs);
printRTPTime(rtpTime, playedTimeRtp, expiredTimeRtp, isExpired);
} else {
- ALOGW("%s", info.string());
+ ALOGW("%s", info.c_str());
}
}
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index bc83410..bc57ef7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -1648,11 +1648,11 @@
memset(&mRTCPAddr6, 0, sizeof(mRTCPAddr6));
mLocalAddr6.sin6_family = AF_INET6;
- inet_pton(AF_INET6, localIp.string(), &mLocalAddr6.sin6_addr);
+ inet_pton(AF_INET6, localIp.c_str(), &mLocalAddr6.sin6_addr);
mLocalAddr6.sin6_port = htons((uint16_t)localPort);
mRTPAddr6.sin6_family = AF_INET6;
- inet_pton(AF_INET6, remoteIp.string(), &mRTPAddr6.sin6_addr);
+ inet_pton(AF_INET6, remoteIp.c_str(), &mRTPAddr6.sin6_addr);
mRTPAddr6.sin6_port = htons((uint16_t)remotePort);
mRTCPAddr6 = mRTPAddr6;
@@ -1663,11 +1663,11 @@
memset(&mRTCPAddr, 0, sizeof(mRTCPAddr));
mLocalAddr.sin_family = AF_INET;
- mLocalAddr.sin_addr.s_addr = inet_addr(localIp.string());
+ mLocalAddr.sin_addr.s_addr = inet_addr(localIp.c_str());
mLocalAddr.sin_port = htons((uint16_t)localPort);
mRTPAddr.sin_family = AF_INET;
- mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.string());
+ mRTPAddr.sin_addr.s_addr = inet_addr(remoteIp.c_str());
mRTPAddr.sin_port = htons((uint16_t)remotePort);
mRTCPAddr = mRTPAddr;
@@ -1680,9 +1680,9 @@
int sizeSockSt = mIsIPv6 ? sizeof(mLocalAddr6) : sizeof(mLocalAddr);
if (bind(mRTPSocket, localAddr, sizeSockSt) == -1) {
- ALOGE("failed to bind rtp %s:%d err=%s", localIp.string(), localPort, strerror(errno));
+ ALOGE("failed to bind rtp %s:%d err=%s", localIp.c_str(), localPort, strerror(errno));
} else {
- ALOGD("succeed to bind rtp %s:%d", localIp.string(), localPort);
+ ALOGD("succeed to bind rtp %s:%d", localIp.c_str(), localPort);
}
if (mIsIPv6)
@@ -1691,9 +1691,9 @@
mLocalAddr.sin_port = htons((uint16_t)(localPort + 1));
if (bind(mRTCPSocket, localAddr, sizeSockSt) == -1) {
- ALOGE("failed to bind rtcp %s:%d err=%s", localIp.string(), localPort + 1, strerror(errno));
+ ALOGE("failed to bind rtcp %s:%d err=%s", localIp.c_str(), localPort + 1, strerror(errno));
} else {
- ALOGD("succeed to bind rtcp %s:%d", localIp.string(), localPort + 1);
+ ALOGD("succeed to bind rtcp %s:%d", localIp.c_str(), localPort + 1);
}
}
diff --git a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
index b97f347..2016b2a 100644
--- a/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
+++ b/media/libstagefright/writer_fuzzers/WriterFuzzerBase.cpp
@@ -192,7 +192,9 @@
sp<MetaData> trackMeta = new MetaData;
convertMessageToMetaData(format, trackMeta);
mCurrentTrack[trackIndex] = new MediaAdapter(trackMeta);
- mWriter->addSource(mCurrentTrack[trackIndex]);
+ if (mWriter->addSource(mCurrentTrack[trackIndex]) != OK) {
+ mCurrentTrack[trackIndex] = nullptr;
+ }
}
void WriterFuzzerBase::start() {
@@ -202,13 +204,14 @@
void WriterFuzzerBase::sendBuffersToWriter(sp<MediaAdapter> ¤tTrack, int32_t trackIndex,
int32_t startFrameIndex, int32_t endFrameIndex) {
+ if (!mCurrentTrack[trackIndex]) {
+ return;
+ }
vector<FrameData> bufferInfo = mBufferSource->getFrameList(trackIndex);
for (int idx = startFrameIndex; idx < endFrameIndex; ++idx) {
sp<ABuffer> buffer = new ABuffer((void *)bufferInfo[idx].buf, bufferInfo[idx].size);
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[idx].timeUs);
@@ -219,8 +222,13 @@
sampleMetaData.setInt32(kKeyIsSyncFrame, true);
}
+ // Released in MediaAdapter::signalBufferReturned().
+ mediaBuffer->add_ref();
+
// This pushBuffer will wait until the mediaBuffer is consumed.
- currentTrack->pushBuffer(mediaBuffer);
+ if (currentTrack->pushBuffer(mediaBuffer) != OK) {
+ mediaBuffer->release();
+ }
}
}
diff --git a/media/module/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
index 4bb2215..82ddbc0 100644
--- a/media/module/bqhelper/GraphicBufferSource.cpp
+++ b/media/module/bqhelper/GraphicBufferSource.cpp
@@ -1150,6 +1150,18 @@
int32_t bufferCount,
uint32_t frameWidth,
uint32_t frameHeight,
+ uint32_t consumerUsage) {
+ uint64_t consumerUsage64 = static_cast<uint64_t>(consumerUsage);
+ return configure(component, dataSpace, bufferCount,
+ frameWidth, frameHeight, consumerUsage64);
+}
+
+status_t GraphicBufferSource::configure(
+ const sp<ComponentWrapper>& component,
+ int32_t dataSpace,
+ int32_t bufferCount,
+ uint32_t frameWidth,
+ uint32_t frameHeight,
uint64_t consumerUsage) {
if (component == NULL) {
return BAD_VALUE;
diff --git a/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
index 4e4fbfd..5225a48 100644
--- a/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
+++ b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
@@ -122,7 +122,19 @@
// ------------------------------
// Configure the buffer source to be used with a component with the default
- // data space.
+ // data space. (32-bit consumerUsage flag, for vendor partition
+ // compatibility)
+ [[deprecated("use configure() with a 64-bit consumerUsage flag instead")]]
+ status_t configure(
+ const sp<ComponentWrapper> &component,
+ int32_t dataSpace,
+ int32_t bufferCount,
+ uint32_t frameWidth,
+ uint32_t frameHeight,
+ uint32_t consumerUsage);
+
+ // Configure the buffer source to be used with a component with the default
+ // data space. (64-bit consumerUsage flag)
status_t configure(
const sp<ComponentWrapper> &component,
int32_t dataSpace,
diff --git a/media/module/extractors/mp3/MP3Extractor.cpp b/media/module/extractors/mp3/MP3Extractor.cpp
index 328b790..d0e9852 100644
--- a/media/module/extractors/mp3/MP3Extractor.cpp
+++ b/media/module/extractors/mp3/MP3Extractor.cpp
@@ -379,8 +379,8 @@
String8 commentdesc;
String8 commentvalue;
com->getString(&commentdesc, &commentvalue);
- const char * desc = commentdesc.string();
- const char * value = commentvalue.string();
+ const char * desc = commentdesc.c_str();
+ const char * value = commentvalue.c_str();
// first 3 characters are the language, which we don't care about
if(strlen(desc) > 3 && strcmp(desc + 3, "iTunSMPB") == 0) {
@@ -652,7 +652,7 @@
it->getString(&s);
delete it;
- AMediaFormat_setString(meta, kMap[i].key, s.string());
+ AMediaFormat_setString(meta, kMap[i].key, s.c_str());
}
size_t dataSize;
diff --git a/media/module/extractors/mp4/Android.bp b/media/module/extractors/mp4/Android.bp
index 540d75d..8072002 100644
--- a/media/module/extractors/mp4/Android.bp
+++ b/media/module/extractors/mp4/Android.bp
@@ -30,6 +30,7 @@
srcs: [
"AC4Parser.cpp",
+ "HeifCleanAperture.cpp",
"ItemTable.cpp",
"MPEG4Extractor.cpp",
"SampleIterator.cpp",
diff --git a/media/module/extractors/mp4/HeifCleanAperture.cpp b/media/module/extractors/mp4/HeifCleanAperture.cpp
new file mode 100644
index 0000000..f0a0867
--- /dev/null
+++ b/media/module/extractors/mp4/HeifCleanAperture.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <HeifCleanAperture.h>
+
+namespace android {
+namespace heif {
+namespace {
+
+// |a| and |b| hold int32_t values. The int64_t type is used so that we can negate INT32_MIN without
+// overflowing int32_t.
+int64_t calculateGreatestCommonDivisor(int64_t a, int64_t b) {
+ if (a < 0) {
+ a *= -1;
+ }
+ if (b < 0) {
+ b *= -1;
+ }
+ while (b != 0) {
+ int64_t r = a % b;
+ a = b;
+ b = r;
+ }
+ return a;
+}
+
+bool overflowsInt32(int64_t x) {
+ return (x < INT32_MIN) || (x > INT32_MAX);
+}
+
+Fraction calculateCenter(int32_t value) {
+ Fraction f(value, 2);
+ f.simplify();
+ return f;
+}
+
+} // namespace
+
+Fraction::Fraction(int32_t n, int32_t d) {
+ this->n = n;
+ this->d = d;
+}
+
+void Fraction::simplify() {
+ int64_t gcd = calculateGreatestCommonDivisor(n, d);
+ if (gcd > 1) {
+ n = static_cast<int32_t>(n / gcd);
+ d = static_cast<int32_t>(d / gcd);
+ }
+}
+
+bool Fraction::commonDenominator(Fraction* f) {
+ simplify();
+ f->simplify();
+ if (d == f->d) return true;
+ const int64_t this_d = d;
+ const int64_t fd = f->d;
+ const int64_t thisnNew = n * fd;
+ const int64_t thisdNew = d * fd;
+ const int64_t fnNew = f->n * this_d;
+ const int64_t fdNew = f->d * this_d;
+ if (overflowsInt32(thisnNew) || overflowsInt32(thisdNew) || overflowsInt32(fnNew) ||
+ overflowsInt32(fdNew)) {
+ return false;
+ }
+ n = static_cast<int32_t>(thisnNew);
+ d = static_cast<int32_t>(thisdNew);
+ f->n = static_cast<int32_t>(fnNew);
+ f->d = static_cast<int32_t>(fdNew);
+ return true;
+}
+
+bool Fraction::add(Fraction f) {
+ if (!commonDenominator(&f)) {
+ return false;
+ }
+
+ const int64_t result = static_cast<int64_t>(n) + f.n;
+ if (overflowsInt32(result)) {
+ return false;
+ }
+ n = static_cast<int32_t>(result);
+ simplify();
+ return true;
+}
+
+bool Fraction::subtract(Fraction f) {
+ if (!commonDenominator(&f)) {
+ return false;
+ }
+
+ const int64_t result = static_cast<int64_t>(n) - f.n;
+ if (overflowsInt32(result)) {
+ return false;
+ }
+ n = static_cast<int32_t>(result);
+ simplify();
+ return true;
+}
+
+bool convertCleanApertureToRect(uint32_t imageW, uint32_t imageH, const CleanAperture& clap,
+ int32_t* left, int32_t* top, int32_t* right, int32_t* bottom) {
+ // ISO/IEC 14496-12:2020, Section 12.1.4.1:
+ // For horizOff and vertOff, D shall be strictly positive and N may be
+ // positive or negative. For cleanApertureWidth and cleanApertureHeight,
+ // N shall be positive and D shall be strictly positive.
+ if (clap.width.d <= 0 || clap.height.d <= 0 || clap.horizOff.d <= 0 || clap.vertOff.d <= 0 ||
+ clap.width.n < 0 || clap.height.n < 0 || !clap.width.isInteger() ||
+ !clap.height.isInteger() || imageW > INT32_MAX || imageH > INT32_MAX) {
+ return false;
+ }
+
+ const int32_t clapW = clap.width.getInt32();
+ const int32_t clapH = clap.height.getInt32();
+ if (clapW == 0 || clapH == 0) {
+ return false;
+ }
+
+ Fraction centerX = calculateCenter(imageW);
+ Fraction centerY = calculateCenter(imageH);
+ Fraction halfW(clapW, 2);
+ Fraction halfH(clapH, 2);
+
+ if (!centerX.add(clap.horizOff) || !centerX.subtract(halfW) || !centerX.isInteger() ||
+ centerX.n < 0 || !centerY.add(clap.vertOff) || !centerY.subtract(halfH) ||
+ !centerY.isInteger() || centerY.n < 0) {
+ return false;
+ }
+
+ *left = centerX.getInt32();
+ *top = centerY.getInt32();
+ *right = *left + clapW;
+ *bottom = *top + clapH;
+
+ // Make sure that the crop rect is within the image bounds.
+ if (*left > (UINT32_MAX - clapW) || *right > imageW || *top > (UINT32_MAX - clapH) ||
+ *bottom > imageH) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace heif
+} // namespace android
diff --git a/media/module/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
index 444664c..cf3df62 100644
--- a/media/module/extractors/mp4/ItemTable.cpp
+++ b/media/module/extractors/mp4/ItemTable.cpp
@@ -19,6 +19,7 @@
#include <unordered_set>
+#include <HeifCleanAperture.h>
#include <ItemTable.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
@@ -47,7 +48,7 @@
ImageItem(uint32_t _type, uint32_t _id, bool _hidden) :
type(_type), itemId(_id), hidden(_hidden),
rows(0), columns(0), width(0), height(0), rotation(0),
- offset(0), size(0), nextTileIndex(0) {}
+ offset(0), size(0), seenClap(false), nextTileIndex(0) {}
bool isGrid() const {
return type == FOURCC("grid");
@@ -77,6 +78,8 @@
sp<ABuffer> hvcc;
sp<ABuffer> icc;
sp<ABuffer> av1c;
+ bool seenClap;
+ CleanAperture clap;
Vector<uint32_t> thumbnails;
Vector<uint32_t> dimgRefs;
@@ -833,6 +836,47 @@
return OK;
}
+struct ClapBox : public Box, public ItemProperty {
+ ClapBox(DataSourceHelper *source) :
+ Box(source, FOURCC("clap")), mSeen(false) {}
+
+ status_t parse(off64_t offset, size_t size) override;
+
+ void attachTo(ImageItem &image) const override {
+ image.seenClap = mSeen;
+ if (!mSeen) return;
+ image.clap = mClap;
+ }
+
+private:
+ bool mSeen;
+ CleanAperture mClap;
+};
+
+status_t ClapBox::parse(off64_t offset, size_t size) {
+ ALOGV("%s: offset %lld, size %zu", __FUNCTION__, (long long)offset, size);
+
+ if (size < 32) {
+ return ERROR_MALFORMED;
+ }
+ mSeen = true;
+ uint32_t values[8];
+ for (int i = 0; i < 8; ++i, offset += 4) {
+ if (!source()->getUInt32(offset, &values[i])) {
+ return ERROR_IO;
+ }
+ }
+ mClap.width.n = values[0];
+ mClap.width.d = values[1];
+ mClap.height.n = values[2];
+ mClap.height.d = values[3];
+ mClap.horizOff.n = values[4];
+ mClap.horizOff.d = values[5];
+ mClap.vertOff.n = values[6];
+ mClap.vertOff.d = values[7];
+ return OK;
+}
+
struct ColrBox : public Box, public ItemProperty {
ColrBox(DataSourceHelper *source) :
Box(source, FOURCC("colr")) {}
@@ -992,6 +1036,11 @@
itemProperty = new IrotBox(source());
break;
}
+ case FOURCC("clap"):
+ {
+ itemProperty = new ClapBox(source());
+ break;
+ }
case FOURCC("colr"):
{
itemProperty = new ColrBox(source());
@@ -1111,7 +1160,7 @@
}
buf.push_back(tmp);
if (tmp == 0) {
- out->setTo(buf.array());
+ *out = buf.array();
*offset = newOffset;
*size = stopOffset - newOffset;
@@ -1599,6 +1648,12 @@
AMediaFormat_setInt32(meta,
AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, image->width * image->height * 3 / 2);
+ int32_t left, top, right, bottom;
+ if (image->seenClap && convertCleanApertureToRect(image->width, image->height, image->clap,
+ &left, &top, &right, &bottom)) {
+ AMediaFormat_setRect(meta, AMEDIAFORMAT_KEY_DISPLAY_CROP, left, top, right - 1, bottom - 1);
+ }
+
if (!image->thumbnails.empty()) {
ssize_t thumbItemIndex = mItemIdToItemMap.indexOfKey(image->thumbnails[0]);
if (thumbItemIndex >= 0) {
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 184e4f4..9ab9f0f 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -847,7 +847,7 @@
struct tm* tm = gmtime(&time_1970);
if (tm != NULL &&
strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", tm) > 0) {
- s->setTo(tmp);
+ *s = tmp;
return true;
}
return false;
@@ -1794,7 +1794,7 @@
String8 mimeFormat(str + 8 + encoding_length + 1,
chunk_data_size - 8 - encoding_length - 1);
AMediaFormat_setString(mLastTrack->meta,
- AMEDIAFORMAT_KEY_MIME, mimeFormat.string());
+ AMEDIAFORMAT_KEY_MIME, mimeFormat.c_str());
}
break;
}
@@ -2813,7 +2813,7 @@
String8 s;
if (convertTimeToDate(creationTime, &s)) {
- AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DATE, s.string());
+ AMediaFormat_setString(mFileMetaData, AMEDIAFORMAT_KEY_DATE, s.c_str());
}
break;
@@ -4082,10 +4082,10 @@
buffer[size] = '\0';
switch (mPath[5]) {
case FOURCC("mean"):
- mLastCommentMean.setTo((const char *)buffer + 4);
+ mLastCommentMean = ((const char *)buffer + 4);
break;
case FOURCC("name"):
- mLastCommentName.setTo((const char *)buffer + 4);
+ mLastCommentName = ((const char *)buffer + 4);
break;
case FOURCC("data"):
if (size < 8) {
@@ -4094,7 +4094,7 @@
ALOGE("b/24346430");
return ERROR_MALFORMED;
}
- mLastCommentData.setTo((const char *)buffer + 8);
+ mLastCommentData = ((const char *)buffer + 8);
break;
}
@@ -4368,7 +4368,7 @@
} else {
// Convert from UTF-16 string to UTF-8 string.
String8 tmpUTF8str(framedata, len16);
- AMediaFormat_setString(mFileMetaData, metadataKey, tmpUTF8str.string());
+ AMediaFormat_setString(mFileMetaData, metadataKey, tmpUTF8str.c_str());
}
}
diff --git a/media/module/extractors/mp4/include/HeifCleanAperture.h b/media/module/extractors/mp4/include/HeifCleanAperture.h
new file mode 100644
index 0000000..930197d
--- /dev/null
+++ b/media/module/extractors/mp4/include/HeifCleanAperture.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HEIF_CLEAN_APERTURE_H_
+#define HEIF_CLEAN_APERTURE_H_
+
+#include <stdint.h>
+
+namespace android {
+namespace heif {
+
+struct Fraction {
+ Fraction() = default;
+ Fraction(int32_t n, int32_t d);
+
+ void simplify();
+ bool commonDenominator(Fraction* f);
+ bool add(Fraction f);
+ bool subtract(Fraction f);
+ bool isInteger() const { return n % d == 0; }
+ int32_t getInt32() const { return n / d; }
+ int32_t n;
+ int32_t d;
+};
+
+struct CleanAperture {
+ Fraction width;
+ Fraction height;
+ Fraction horizOff;
+ Fraction vertOff;
+};
+
+// Converts the CleanAperture value into a rectangle with bounds left, top, right and bottom.
+// Returns true on success, false otherwise.
+bool convertCleanApertureToRect(uint32_t imageW, uint32_t imageH, const CleanAperture& image,
+ int32_t* left, int32_t* top, int32_t* right, int32_t* bottom);
+
+} // namespace heif
+} // namespace android
+
+#endif // HEIF_CLEAN_APERTURE_H_
diff --git a/media/module/extractors/mp4/tests/Android.bp b/media/module/extractors/mp4/tests/Android.bp
new file mode 100644
index 0000000..252cec2
--- /dev/null
+++ b/media/module/extractors/mp4/tests/Android.bp
@@ -0,0 +1,24 @@
+package {
+ default_applicable_licenses: ["frameworks_av_media_extractors_mp4_license"],
+}
+
+cc_test_host {
+ name: "HeifCleanApertureUnitTest",
+ gtest: true,
+
+ srcs: ["HeifCleanApertureUnitTest.cpp"],
+
+ header_libs: [
+ "libmp4extractor_headers",
+ ],
+
+ static_libs: [
+ "libmp4extractor",
+ ],
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp b/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp
new file mode 100644
index 0000000..6a84ae3
--- /dev/null
+++ b/media/module/extractors/mp4/tests/HeifCleanApertureUnitTest.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <HeifCleanAperture.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+using android::heif::CleanAperture;
+using android::heif::convertCleanApertureToRect;
+using android::heif::Fraction;
+
+struct InvalidClapPropertyParam {
+ uint32_t width;
+ uint32_t height;
+ CleanAperture clap;
+};
+
+const InvalidClapPropertyParam kInvalidClapPropertyTestParams[] = {
+ // Zero or negative denominators.
+ {120, 160, {Fraction(96, 0), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, -1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 0), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, -1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 0), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, -1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 0)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, -1)}},
+ // Zero or negative clean aperture width or height.
+ {120, 160, {Fraction(-96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(0, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(-132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(0, 1), Fraction(0, 1), Fraction(0, 1)}},
+ // Clean aperture width or height is not an integer.
+ {120, 160, {Fraction(96, 5), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)}},
+ {120, 160, {Fraction(96, 1), Fraction(132, 5), Fraction(0, 1), Fraction(0, 1)}},
+ {722, 1024, {Fraction(385, 1), Fraction(330, 1), Fraction(103, 1), Fraction(-308, 1)}},
+ {1024, 722, {Fraction(330, 1), Fraction(385, 1), Fraction(-308, 1), Fraction(103, 1)}},
+};
+
+using InvalidClapPropertyTest = ::testing::TestWithParam<InvalidClapPropertyParam>;
+
+INSTANTIATE_TEST_SUITE_P(Parameterized, InvalidClapPropertyTest,
+ ::testing::ValuesIn(kInvalidClapPropertyTestParams));
+
+// Negative tests for the convertCleanApertureToRect() function.
+TEST_P(InvalidClapPropertyTest, ValidateClapProperty) {
+ const InvalidClapPropertyParam& param = GetParam();
+ int32_t left, top, right, bottom;
+ EXPECT_FALSE(convertCleanApertureToRect(param.width, param.height, param.clap, &left, &top,
+ &right, &bottom));
+}
+
+struct ValidClapPropertyParam {
+ uint32_t width;
+ uint32_t height;
+ CleanAperture clap;
+
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+};
+
+const ValidClapPropertyParam kValidClapPropertyTestParams[] = {
+ {120,
+ 160,
+ {Fraction(96, 1), Fraction(132, 1), Fraction(0, 1), Fraction(0, 1)},
+ 12,
+ 14,
+ 108,
+ 146},
+ {120,
+ 160,
+ {Fraction(60, 1), Fraction(80, 1), Fraction(-30, 1), Fraction(-40, 1)},
+ 0,
+ 0,
+ 60,
+ 80},
+};
+
+using ValidClapPropertyTest = ::testing::TestWithParam<ValidClapPropertyParam>;
+
+INSTANTIATE_TEST_SUITE_P(Parameterized, ValidClapPropertyTest,
+ ::testing::ValuesIn(kValidClapPropertyTestParams));
+
+// Positive tests for the convertCleanApertureToRect() function.
+TEST_P(ValidClapPropertyTest, ValidateClapProperty) {
+ const ValidClapPropertyParam& param = GetParam();
+ int32_t left, top, right, bottom;
+ EXPECT_TRUE(convertCleanApertureToRect(param.width, param.height, param.clap, &left, &top,
+ &right, &bottom));
+ EXPECT_EQ(left, param.left);
+ EXPECT_EQ(top, param.top);
+ EXPECT_EQ(right, param.right);
+ EXPECT_EQ(bottom, param.bottom);
+}
+
+} // namespace
diff --git a/media/module/foundation/ALooperRoster.cpp b/media/module/foundation/ALooperRoster.cpp
index 5625c7f..daa90be 100644
--- a/media/module/foundation/ALooperRoster.cpp
+++ b/media/module/foundation/ALooperRoster.cpp
@@ -180,7 +180,7 @@
}
s.append("\n");
}
- (void)write(fd, s.string(), s.size());
+ (void)write(fd, s.c_str(), s.size());
}
} // namespace android
diff --git a/media/module/foundation/AString.cpp b/media/module/foundation/AString.cpp
index a5e0ff8..2f8011d 100644
--- a/media/module/foundation/AString.cpp
+++ b/media/module/foundation/AString.cpp
@@ -70,7 +70,7 @@
: mData(NULL),
mSize(0),
mAllocSize(1) {
- setTo(from.string(), from.length());
+ setTo(from.c_str(), from.length());
}
AString::AString(const AString &from)
diff --git a/media/module/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp
index 3370748..60478c9 100644
--- a/media/module/foundation/MetaDataBase.cpp
+++ b/media/module/foundation/MetaDataBase.cpp
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <string.h>
+#include <mutex>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -78,6 +80,7 @@
struct MetaDataBase::MetaDataInternal {
+ std::mutex mLock;
KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
};
@@ -102,10 +105,12 @@
}
void MetaDataBase::clear() {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
mInternalData->mItems.clear();
}
bool MetaDataBase::remove(uint32_t key) {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -252,6 +257,7 @@
uint32_t key, uint32_t type, const void *data, size_t size) {
bool overwrote_existing = true;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
typed_data item;
@@ -269,6 +275,7 @@
bool MetaDataBase::findData(uint32_t key, uint32_t *type,
const void **data, size_t *size) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -283,6 +290,7 @@
}
bool MetaDataBase::hasData(uint32_t key) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -429,12 +437,13 @@
String8 MetaDataBase::toString() const {
String8 s;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
MakeFourCCString(key, cc);
const typed_data &item = mInternalData->mItems.valueAt(i);
- s.appendFormat("%s: %s", cc, item.asString(false).string());
+ s.appendFormat("%s: %s", cc, item.asString(false).c_str());
if (i != 0) {
s.append(", ");
}
@@ -443,18 +452,20 @@
}
void MetaDataBase::dumpToLog() const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
MakeFourCCString(key, cc);
const typed_data &item = mInternalData->mItems.valueAt(i);
- ALOGI("%s: %s", cc, item.asString(true /* verbose */).string());
+ ALOGI("%s: %s", cc, item.asString(true /* verbose */).c_str());
}
}
#if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
status_t MetaDataBase::writeToParcel(Parcel &parcel) {
status_t ret;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
size_t numItems = mInternalData->mItems.size();
ret = parcel.writeUint32(uint32_t(numItems));
if (ret) {
diff --git a/media/module/foundation/tests/Base64_test.cpp b/media/module/foundation/tests/Base64_test.cpp
index 7a4289e..a3f93d9 100644
--- a/media/module/foundation/tests/Base64_test.cpp
+++ b/media/module/foundation/tests/Base64_test.cpp
@@ -49,7 +49,7 @@
paddedText.append(kBase64Padding);
}
}
- sp<ABuffer> result = decodeBase64(AString(paddedText.string()));
+ sp<ABuffer> result = decodeBase64(AString(paddedText.c_str()));
ASSERT_EQ(AStringUtils::Compare(expected[i].c_str(),
reinterpret_cast<char*>(result->data()),
diff --git a/media/module/id3/ID3.cpp b/media/module/id3/ID3.cpp
index 1f3cad9..aaaeeaf 100644
--- a/media/module/id3/ID3.cpp
+++ b/media/module/id3/ID3.cpp
@@ -535,40 +535,40 @@
}
void ID3::Iterator::getID(String8 *id) const {
- id->setTo("");
+ *id = "";
if (mFrameData == NULL) {
return;
}
if (mParent.mVersion == ID3_V2_2) {
- id->setTo((const char *)&mParent.mData[mOffset], 3);
+ *id = String8((const char *)&mParent.mData[mOffset], 3);
} else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
- id->setTo((const char *)&mParent.mData[mOffset], 4);
+ *id = String8((const char *)&mParent.mData[mOffset], 4);
} else {
CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
switch (mOffset) {
case 3:
- id->setTo("TT2");
+ *id = "TT2";
break;
case 33:
- id->setTo("TP1");
+ *id = "TP1";
break;
case 63:
- id->setTo("TAL");
+ *id = "TAL";
break;
case 93:
- id->setTo("TYE");
+ *id = "TYE";
break;
case 97:
- id->setTo("COM");
+ *id = "COM";
break;
case 126:
- id->setTo("TRK");
+ *id = "TRK";
break;
case 127:
- id->setTo("TCO");
+ *id = "TCO";
break;
default:
CHECK(!"should not be here.");
@@ -590,7 +590,7 @@
// followed by more data. The data following the \0 can be retrieved by setting
// "otherdata" to true.
void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
- id->setTo("");
+ *id = "";
const uint8_t *frameData = mFrameData;
if (frameData == NULL) {
@@ -605,13 +605,13 @@
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d", (int)*frameData);
- id->setTo(tmp);
+ *id = tmp;
return;
}
// this is supposed to be ISO-8859-1, but pass it up as-is to the caller, who will figure
// out the real encoding
- id->setTo((const char*)frameData, mFrameSize);
+ *id = String8((const char*)frameData, mFrameSize);
return;
}
@@ -640,10 +640,10 @@
if (encoding == 0x00) {
// supposedly ISO 8859-1
- id->setTo((const char*)frameData + 1, n);
+ *id = String8((const char*)frameData + 1, n);
} else if (encoding == 0x03) {
// supposedly UTF-8
- id->setTo((const char *)(frameData + 1), n);
+ *id = String8((const char *)(frameData + 1), n);
} else if (encoding == 0x02) {
// supposedly UTF-16 BE, no byte order mark.
// API wants number of characters, not number of bytes...
@@ -662,7 +662,7 @@
framedata = framedatacopy;
}
#endif
- id->setTo(framedata, len);
+ *id = String8(framedata, len);
if (framedatacopy != NULL) {
delete[] framedatacopy;
}
@@ -715,13 +715,13 @@
for (int i = 0; i < len; i++) {
frame8[i] = framedata[i];
}
- id->setTo(frame8, len);
+ *id = String8(frame8, len);
delete [] frame8;
} else {
- id->setTo(framedata, len);
+ *id = String8(framedata, len);
}
} else {
- id->setTo(framedata, len);
+ *id = String8(framedata, len);
}
if (framedatacopy != NULL) {
@@ -948,7 +948,7 @@
const void *
ID3::getAlbumArt(size_t *length, String8 *mime) const {
*length = 0;
- mime->setTo("");
+ *mime = "";
Iterator it(
*this,
@@ -971,7 +971,7 @@
ALOGW("bogus album art size: mime");
return NULL;
}
- mime->setTo((const char *)&data[consumed]);
+ *mime = (const char *)&data[consumed];
consumed += mimeLen;
#if 0
@@ -1008,11 +1008,11 @@
}
if (!memcmp(&data[1], "PNG", 3)) {
- mime->setTo("image/png");
+ *mime = "image/png";
} else if (!memcmp(&data[1], "JPG", 3)) {
- mime->setTo("image/jpeg");
+ *mime = "image/jpeg";
} else if (!memcmp(&data[1], "-->", 3)) {
- mime->setTo("text/plain");
+ *mime = "text/plain";
} else {
return NULL;
}
diff --git a/media/module/id3/test/ID3Test.cpp b/media/module/id3/test/ID3Test.cpp
index a0a84ec..9da28d2 100644
--- a/media/module/id3/test/ID3Test.cpp
+++ b/media/module/id3/test/ID3Test.cpp
@@ -94,7 +94,7 @@
String8 text;
countTextFrames++;
it.getString(&text);
- ALOGV("Found text frame %s : %s \n", id.string(), text.string());
+ ALOGV("Found text frame %s : %s \n", id.c_str(), text.c_str());
}
it.next();
}
@@ -106,10 +106,10 @@
ASSERT_GT(id.length(), 0) << "Found an ID3 tag of 0 size";
it.getString(&text);
// if the tag has a value
- if (strcmp(text.string(), "")) {
+ if (strcmp(text.c_str(), "")) {
countTextFrames++;
ALOGV("ID: %s\n", id.c_str());
- ALOGV("Text string: %s\n", text.string());
+ ALOGV("Text string: %s\n", text.c_str());
}
it.next();
}
@@ -134,7 +134,7 @@
if (albumArtPresent) {
if (data) {
- ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+ ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str());
}
ASSERT_NE(data, nullptr) << "Expected album art, found none! " << path;
} else {
@@ -168,7 +168,7 @@
String8 mime;
const void *data = tag.getAlbumArt(&dataSize, &mime);
if (data) {
- ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.string());
+ ALOGV("Found album art: size = %zu mime = %s \n", dataSize, mime.c_str());
#if (LOG_NDEBUG == 0)
hexdump(data, dataSize > 128 ? 128 : dataSize);
#endif
diff --git a/media/module/id3/testid3.cpp b/media/module/id3/testid3.cpp
index 5cd51cf..e4f524b 100644
--- a/media/module/id3/testid3.cpp
+++ b/media/module/id3/testid3.cpp
@@ -90,9 +90,9 @@
String8 text;
it.getString(&text);
- printf(" found text frame '%s': %s\n", id.string(), text.string());
+ printf(" found text frame '%s': %s\n", id.c_str(), text.c_str());
} else {
- printf(" found frame '%s'.\n", id.string());
+ printf(" found frame '%s'.\n", id.c_str());
}
it.next();
@@ -104,7 +104,7 @@
if (data) {
printf("found album art: size=%zu mime='%s'\n", dataSize,
- mime.string());
+ mime.c_str());
hexdump(data, dataSize > 128 ? 128 : dataSize);
}
diff --git a/media/module/libmediatranscoding/TranscodingClientManager.cpp b/media/module/libmediatranscoding/TranscodingClientManager.cpp
index 6dbcaf9..18702a4 100644
--- a/media/module/libmediatranscoding/TranscodingClientManager.cpp
+++ b/media/module/libmediatranscoding/TranscodingClientManager.cpp
@@ -354,7 +354,7 @@
result.append(buffer);
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
bool TranscodingClientManager::isTrustedCaller(pid_t pid, uid_t uid) {
diff --git a/media/module/libmediatranscoding/TranscodingSessionController.cpp b/media/module/libmediatranscoding/TranscodingSessionController.cpp
index ea3e518..e9d19d3 100644
--- a/media/module/libmediatranscoding/TranscodingSessionController.cpp
+++ b/media/module/libmediatranscoding/TranscodingSessionController.cpp
@@ -421,7 +421,7 @@
dumpSession_l(session, result, true /*closedSession*/);
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
/*
diff --git a/media/module/service.mediatranscoding/MediaTranscodingService.cpp b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
index 2a20981..2c73f3e 100644
--- a/media/module/service.mediatranscoding/MediaTranscodingService.cpp
+++ b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
@@ -110,7 +110,7 @@
"Permission Denial: "
"can't dump MediaTranscodingService from pid=%d, uid=%d\n",
AIBinder_getCallingPid(), AIBinder_getCallingUid());
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return PERMISSION_DENIED;
}
}
@@ -120,7 +120,7 @@
snprintf(buffer, SIZE, "MediaTranscodingService: %p\n", this);
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
Vector<String16> args;
mClientManager->dumpAllClients(fd, args);
diff --git a/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
index 8e17f55..723bd77 100644
--- a/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
+++ b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
@@ -76,7 +76,7 @@
PermissionController pc;
uid = pc.getPackageUid(packageName, 0);
if (uid <= 0) {
- ALOGE("Unknown package: '%s'", String8(packageName).string());
+ ALOGE("Unknown package: '%s'", String8(packageName).c_str());
return BAD_VALUE;
}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
index f5faf77..83c6076 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
@@ -212,7 +212,7 @@
if (mFdp.ConsumeBool()) {
std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
android::String16 s(str.c_str());
- char16_t* data = const_cast<char16_t*>(s.string());
+ char16_t* data = const_cast<char16_t*>(s.c_str());
mtpDataPacket.putString(reinterpret_cast<uint16_t*>(data));
} else {
mtpDataPacket.putString(static_cast<uint16_t*>(nullptr));
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
index b4e659c..6300256 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -101,7 +101,7 @@
std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
android::String16 s(str.c_str());
if (mFdp.ConsumeBool()) {
- data = const_cast<char16_t*>(s.string());
+ data = const_cast<char16_t*>(s.c_str());
}
if (mFdp.ConsumeBool()) {
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 0f7d98b..7b19ac0 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -344,7 +344,7 @@
}
mCbLooper = new ALooper;
- mCbLooper->setName(consumerName.string());
+ mCbLooper->setName(consumerName.c_str());
res = mCbLooper->start(
/*runOnCallingThread*/false,
/*canCallJava*/ true,
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 0df7636..28a0233 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -478,7 +478,7 @@
*keyRequest = mObj->mKeyRequest.array();
*keyRequestSize = mObj->mKeyRequest.size();
if (defaultUrl != NULL)
- *defaultUrl = mObj->mDefaultUrl.string();
+ *defaultUrl = mObj->mDefaultUrl.c_str();
switch(requestType) {
case DrmPlugin::kKeyRequestType_Initial:
mObj->mkeyRequestType = KEY_REQUEST_TYPE_INITIAL;
@@ -606,8 +606,8 @@
}
for (size_t i = 0; i < mObj->mQueryResults.size(); i++) {
- keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).string();
- keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).string();
+ keyValuePairs[i].mKey = mObj->mQueryResults.keyAt(i).c_str();
+ keyValuePairs[i].mValue = mObj->mQueryResults.valueAt(i).c_str();
}
*numPairs = mObj->mQueryResults.size();
return AMEDIA_OK;
@@ -630,7 +630,7 @@
} else {
*provisionRequest = mObj->mProvisionRequest.array();
*provisionRequestSize = mObj->mProvisionRequest.size();
- *serverUrl = mObj->mProvisionUrl.string();
+ *serverUrl = mObj->mProvisionUrl.c_str();
}
return AMEDIA_OK;
}
@@ -714,7 +714,7 @@
mObj->mPropertyString);
if (status == OK) {
- *propertyValue = mObj->mPropertyString.string();
+ *propertyValue = mObj->mPropertyString.c_str();
} else {
*propertyValue = NULL;
}
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 66b5dec..161b5e3 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -142,7 +142,7 @@
}
ret.append("}");
mData->mDebug = ret;
- return mData->mDebug.string();
+ return mData->mDebug.c_str();
}
EXPORT
@@ -238,7 +238,7 @@
return false;
}
for (size_t i = 0; i < mData->mStringCache.size(); i++) {
- if (strcmp(mData->mStringCache.keyAt(i).string(), name) == 0) {
+ if (strcmp(mData->mStringCache.keyAt(i).c_str(), name) == 0) {
mData->mStringCache.removeItemsAt(i, 1);
break;
}
@@ -251,7 +251,7 @@
if (i < 0) {
return false;
}
- *out = mData->mStringCache.valueAt(i).string();
+ *out = mData->mStringCache.valueAt(i).c_str();
return true;
}
return false;
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 83b84e3..eef460f 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -403,7 +403,7 @@
PermissionController{}.getPackagesForUid(uid, str16PackageNames);
std::vector<std::string> packageNames;
for (const auto& str16PackageName : str16PackageNames) {
- packageNames.emplace_back(String8(str16PackageName).string());
+ packageNames.emplace_back(String8(str16PackageName).c_str());
}
if (packageNames.empty()) {
ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 761270b..8dbe067 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -23,7 +23,6 @@
#include "Configuration.h"
#include "AudioFlinger.h"
-#include "EffectConfiguration.h"
//#define BUFLOG_NDEBUG 0
#include <afutils/BufLog.h>
@@ -232,23 +231,6 @@
}
AudioFlinger::AudioFlinger()
- : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
- mPrimaryHardwareDev(NULL),
- mAudioHwDevs(NULL),
- mHardwareStatus(AUDIO_HW_IDLE),
- mMasterVolume(1.0f),
- mMasterMute(false),
- // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
- mMode(AUDIO_MODE_INVALID),
- mBtNrecIsOff(false),
- mIsLowRamDevice(true),
- mIsDeviceTypeKnown(false),
- mTotalMemory(0),
- mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
- mGlobalEffectEnableTime(0),
- mPatchCommandThread(sp<PatchCommandThread>::make()),
- mSystemReady(false),
- mBluetoothLatencyModesEnabled(true)
{
// Move the audio session unique ID generator start base as time passes to limit risk of
// generating the same ID again after an audioserver restart.
@@ -285,9 +267,6 @@
// in bad state, reset the state upon service start.
BatteryNotifier::getInstance().noteResetAudio();
- mDevicesFactoryHal = DevicesFactoryHalInterface::create();
- mEffectsFactoryHal = audioflinger::EffectConfiguration::getEffectsFactoryHal();
-
mMediaLogNotifier->run("MediaLogNotifier");
std::vector<pid_t> halPids;
mDevicesFactoryHal->getHalPids(&halPids);
@@ -695,7 +674,7 @@
result.appendFormat(" %7d %4d %7d %6u %s\n", r->mSessionid, r->mCnt, r->mPid,
r->mUid, info.package.c_str());
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
@@ -708,7 +687,7 @@
snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
dprintf(fd, "Vibrator infos(size=%zu):\n", mAudioVibratorInfos.size());
for (const auto& vibratorInfo : mAudioVibratorInfos) {
@@ -728,7 +707,7 @@
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
@@ -741,7 +720,7 @@
const bool hardwareLocked = afutils::dumpTryLock(mHardwareLock);
if (!hardwareLocked) {
String8 result(kHardwareLockedString);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
} else {
mHardwareLock.unlock();
}
@@ -751,20 +730,20 @@
// failed to lock - AudioFlinger is probably deadlocked
if (!locked) {
String8 result(kDeadlockedString);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
const bool clientLocked = afutils::dumpTryLock(mClientLock);
if (!clientLocked) {
String8 result(kClientLockedString);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
if (mEffectsFactoryHal != 0) {
mEffectsFactoryHal->dumpEffects(fd);
} else {
String8 result(kNoEffectsFactory);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
dumpClients(fd, args);
@@ -1329,7 +1308,7 @@
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
mHardwareStatus = AUDIO_HW_SET_MODE;
ret = dev->setMode(mode);
mHardwareStatus = AUDIO_HW_IDLE;
@@ -1366,7 +1345,7 @@
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
return INVALID_OPERATION;
@@ -1394,7 +1373,7 @@
if (mPrimaryHardwareDev == nullptr) {
return false;
}
- sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
if (primaryDev == nullptr) {
ALOGW("%s: no primary HAL device", __func__);
return false;
@@ -1775,7 +1754,7 @@
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
- ioHandle, keyValuePairs.string(),
+ ioHandle, keyValuePairs.c_str(),
IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
// check calling permissions
@@ -1786,7 +1765,7 @@
String8 filteredKeyValuePairs = keyValuePairs;
filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
- ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.string());
+ ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.c_str());
// AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
@@ -1861,7 +1840,7 @@
String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
{
ALOGVV("getParameters() io %d, keys %s, calling pid %d",
- ioHandle, keys.string(), IPCThreadState::self()->getCallingPid());
+ ioHandle, keys.c_str(), IPCThreadState::self()->getCallingPid());
Mutex::Autolock _l(mLock);
@@ -1912,7 +1891,7 @@
}
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
std::vector<audio_channel_mask_t> channelMasks = {channelMask};
if (channelMask != AUDIO_CHANNEL_IN_MONO) {
@@ -2003,7 +1982,7 @@
if (mPrimaryHardwareDev == nullptr) {
return INVALID_OPERATION;
}
- sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+ sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
ret = dev->setVoiceVolume(value);
mHardwareStatus = AUDIO_HW_IDLE;
@@ -2561,7 +2540,7 @@
if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
mPrimaryHardwareDev = audioDevice;
mHardwareStatus = AUDIO_HW_SET_MODE;
- mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+ mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -2695,7 +2674,7 @@
if (mPrimaryHardwareDev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
}
- dev = mPrimaryHardwareDev->hwDevice();
+ dev = mPrimaryHardwareDev.load()->hwDevice();
}
if (dev == nullptr) {
return AUDIO_HW_SYNC_INVALID;
@@ -2858,7 +2837,7 @@
deviceType,
flags,
halConfig,
- address.string());
+ address.c_str());
mHardwareStatus = AUDIO_HW_IDLE;
@@ -2967,7 +2946,7 @@
mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
mHardwareStatus = AUDIO_HW_SET_MODE;
- mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+ mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
} else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9aefb6b..6516756 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -20,6 +20,7 @@
// Classes and interfaces directly used.
#include "Client.h"
#include "DeviceEffectManager.h"
+#include "EffectConfiguration.h"
#include "IAfEffect.h"
#include "IAfPatchPanel.h"
#include "IAfThread.h"
@@ -459,7 +460,7 @@
static const int kPostTriggerSleepPeriod = 1000000;
};
- const sp<MediaLogNotifier> mMediaLogNotifier;
+ const sp<MediaLogNotifier> mMediaLogNotifier = sp<MediaLogNotifier>::make();
// Find io handle by session id.
// Preference is given to an io handle with a matching effect chain to session id.
@@ -571,13 +572,12 @@
// NOTE: If both mLock and mHardwareLock mutexes must be held,
// always take mLock before mHardwareLock
- // guarded by mHardwareLock
- AudioHwDevice* mPrimaryHardwareDev;
- DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs;
+ std::atomic<AudioHwDevice*> mPrimaryHardwareDev = nullptr;
+ DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs{nullptr /* defValue */};
- // These two fields are immutable after onFirstRef(), so no lock needed to access
- sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
- sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
+ const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
+ DevicesFactoryHalInterface::create();
+ /* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback; // set onFirstRef().
// for dump, indicates which hardware operation is currently in progress (but not stream ops)
enum hardware_call_state {
@@ -607,16 +607,15 @@
AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
};
- mutable hardware_call_state mHardwareStatus; // for dump only
-
+ mutable hardware_call_state mHardwareStatus = AUDIO_HW_IDLE; // for dump only
DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads;
stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
// member variables below are protected by mLock
- float mMasterVolume;
- bool mMasterMute;
- float mMasterBalance = 0.f;
+ float mMasterVolume = 1.f;
+ bool mMasterMute = false;
+ float mMasterBalance = 0.f;
// end of variables protected by mLock
DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads;
@@ -625,10 +624,10 @@
DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
// updated by atomic_fetch_add_explicit
- volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];
+ volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX]; // ctor init
- audio_mode_t mMode;
- std::atomic_bool mBtNrecIsOff;
+ std::atomic<audio_mode_t> mMode = AUDIO_MODE_INVALID;
+ std::atomic<bool> mBtNrecIsOff = false;
// protected by mLock
Vector<AudioSessionRef*> mAudioSessionRefs;
@@ -667,24 +666,25 @@
// though the variables are updated with mLock.
size_t getClientSharedHeapSize() const;
- std::atomic<bool> mIsLowRamDevice;
- bool mIsDeviceTypeKnown;
- int64_t mTotalMemory;
- std::atomic<size_t> mClientSharedHeapSize;
+ std::atomic<bool> mIsLowRamDevice = true;
+ bool mIsDeviceTypeKnown = false;
+ int64_t mTotalMemory = 0;
+ std::atomic<size_t> mClientSharedHeapSize = kMinimumClientSharedHeapSizeBytes;
static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
- nsecs_t mGlobalEffectEnableTime; // when a global effect was last enabled
+ nsecs_t mGlobalEffectEnableTime = 0; // when a global effect was last enabled
/* const */ sp<IAfPatchPanel> mPatchPanel;
- sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
+ const sp<EffectsFactoryHalInterface> mEffectsFactoryHal =
+ audioflinger::EffectConfiguration::getEffectsFactoryHal();
- const sp<PatchCommandThread> mPatchCommandThread;
+ const sp<PatchCommandThread> mPatchCommandThread = sp<PatchCommandThread>::make();
/* const */ sp<DeviceEffectManager> mDeviceEffectManager; // set onFirstRef
/* const */ sp<MelReporter> mMelReporter; // set onFirstRef
- bool mSystemReady;
- std::atomic_bool mAudioPolicyReady{};
+ bool mSystemReady = false;
+ std::atomic<bool> mAudioPolicyReady = false;
mediautils::UidInfo mUidInfo;
@@ -705,7 +705,7 @@
mediautils::atomic_sp<IAudioManager> mAudioManager;
// Bluetooth Variable latency control logic is enabled or disabled
- std::atomic_bool mBluetoothLatencyModesEnabled;
+ std::atomic<bool> mBluetoothLatencyModesEnabled = true;
};
// ----------------------------------------------------------------------------
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 681ec5f..588616d 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -206,17 +206,17 @@
const bool locked = afutils::dumpTryLock(mLock);
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
String8 heading("\nDevice Effects:\n");
- write(fd, heading.string(), heading.size());
+ write(fd, heading.c_str(), heading.size());
for (const auto& iter : mDeviceEffects) {
String8 outStr;
outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
for (const auto& effect : iter.second) {
- write(fd, outStr.string(), outStr.size());
+ write(fd, outStr.c_str(), outStr.size());
effect->dump2(fd, 4);
}
}
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index c3e1fba..22733a6 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -530,7 +530,7 @@
result.appendFormat("\t\t- apiVersion: %08X\n\t\t- flags: %08X (%s)\n",
mDescriptor.apiVersion,
mDescriptor.flags,
- effectFlagsToString(mDescriptor.flags).string());
+ effectFlagsToString(mDescriptor.flags).c_str());
result.appendFormat("\t\t- name: %s\n",
mDescriptor.name);
@@ -551,7 +551,7 @@
mLock.unlock();
}
- write(fd, result.string(), result.length());
+ write(fd, result.c_str(), result.length());
}
// ----------------------------------------------------------------------------
@@ -997,13 +997,6 @@
&size,
&cmdStatus);
}
-
- if (isVolumeControl()) {
- // Force initializing the volume as 0 for volume control effect for safer ramping
- uint32_t left = 0;
- uint32_t right = 0;
- setVolumeInternal(&left, &right, true /*controller*/);
- }
}
// mConfig.outputCfg.buffer.frameCount cannot be zero.
@@ -1660,7 +1653,7 @@
dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
- write(fd, result.string(), result.length());
+ write(fd, result.c_str(), result.length());
if (mEffectInterface != 0) {
dprintf(fd, "\tEffect ID %d HAL dump:\n", mId);
@@ -2129,7 +2122,7 @@
EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
audio_session_t sessionId)
: mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
- mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
+ mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
{
@@ -2367,6 +2360,15 @@
return NO_ERROR;
}
+std::optional<size_t> EffectChain::findVolumeControl_l(size_t from, size_t to) const {
+ for (size_t i = std::min(to, mEffects.size()); i > from; i--) {
+ if (mEffects[i - 1]->isVolumeControlEnabled()) {
+ return i - 1;
+ }
+ }
+ return std::nullopt;
+}
+
ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
// Insert effects are inserted at the end of mEffects vector as they are processed
// after track and auxiliary effects.
@@ -2536,29 +2538,38 @@
{
uint32_t newLeft = *left;
uint32_t newRight = *right;
- bool hasControl = false;
- int ctrlIdx = -1;
- size_t size = mEffects.size();
+ const size_t size = mEffects.size();
// first update volume controller
- for (size_t i = size; i > 0; i--) {
- if (mEffects[i - 1]->isVolumeControlEnabled()) {
- ctrlIdx = i - 1;
- hasControl = true;
- break;
- }
- }
+ const auto volumeControlIndex = findVolumeControl_l(0, size);
+ const int ctrlIdx = volumeControlIndex.value_or(-1);
+ const sp<IAfEffectModule> volumeControlEffect =
+ volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
+ const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
- if (!force && ctrlIdx == mVolumeCtrlIdx &&
+ if (!force && volumeControlEffect == cachedVolumeControlEffect &&
*left == mLeftVolume && *right == mRightVolume) {
- if (hasControl) {
+ if (volumeControlIndex.has_value()) {
*left = mNewLeftVolume;
*right = mNewRightVolume;
}
- return hasControl;
+ return volumeControlIndex.has_value();
}
- mVolumeCtrlIdx = ctrlIdx;
+ if (volumeControlEffect != cachedVolumeControlEffect) {
+ // The volume control effect is a new one. Set the old one as full volume. Set the new onw
+ // as zero for safe ramping.
+ if (cachedVolumeControlEffect != nullptr) {
+ uint32_t leftMax = 1 << 24;
+ uint32_t rightMax = 1 << 24;
+ cachedVolumeControlEffect->setVolume(&leftMax, &rightMax, true /*controller*/);
+ }
+ if (volumeControlEffect != nullptr) {
+ uint32_t leftZero = 0;
+ uint32_t rightZero = 0;
+ volumeControlEffect->setVolume(&leftZero, &rightZero, true /*controller*/);
+ }
+ }
mLeftVolume = newLeft;
mRightVolume = newRight;
@@ -2595,7 +2606,7 @@
setVolumeForOutput_l(*left, *right);
- return hasControl;
+ return volumeControlIndex.has_value();
}
// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held
@@ -2661,7 +2672,7 @@
(int)outBufferStr.size(), "Out buffer ");
result.appendFormat("\t%s %s %d\n",
inBufferStr.c_str(), outBufferStr.c_str(), mActiveTrackCnt);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
for (size_t i = 0; i < numEffects; ++i) {
sp<IAfEffectModule> effect = mEffects[i];
@@ -2674,7 +2685,7 @@
mLock.unlock();
}
} else {
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
}
@@ -3527,7 +3538,7 @@
const bool locked = afutils::dumpTryLock(mProxyLock);
if (!locked) {
String8 result("DeviceEffectProxy may be deadlocked\n");
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
String8 outStr;
@@ -3536,16 +3547,16 @@
} else {
outStr.appendFormat("%*sNO HAL Effect\n", spaces, "");
}
- write(fd, outStr.string(), outStr.size());
+ write(fd, outStr.c_str(), outStr.size());
outStr.clear();
outStr.appendFormat("%*sSub Effects:\n", spaces, "");
- write(fd, outStr.string(), outStr.size());
+ write(fd, outStr.c_str(), outStr.size());
outStr.clear();
for (const auto& iter : mEffectHandles) {
outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
- write(fd, outStr.string(), outStr.size());
+ write(fd, outStr.c_str(), outStr.size());
outStr.clear();
sp<IAfEffectBase> effect = iter.second->effect().promote();
if (effect != nullptr) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 79b4e63..aa5935a 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -622,6 +622,8 @@
ssize_t getInsertIndex(const effect_descriptor_t& desc);
+ std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const;
+
mutable Mutex mLock; // mutex protecting effect list
Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
audio_session_t mSessionId; // audio session ID
@@ -634,7 +636,6 @@
int32_t mTailBufferCount; // current effect tail buffer count
int32_t mMaxTailBuffers; // maximum effect tail buffers
- int mVolumeCtrlIdx; // index of insert effect having control over volume
uint32_t mLeftVolume; // previous volume on left channel
uint32_t mRightVolume; // previous volume on right channel
uint32_t mNewLeftVolume; // new volume on left channel
@@ -647,6 +648,8 @@
KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
const sp<EffectCallback> mEffectCallback;
+
+ wp<IAfEffectModule> mVolumeControlEffect;
};
class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 0ebb3eb..5dc2e8a 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -38,24 +38,21 @@
ndk::SpAIBinder soundDoseBinder;
if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) {
- ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL",
+ ALOGW("%s: HAL cannot provide sound dose interface for module %s",
__func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
if (soundDoseBinder == nullptr) {
- ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL",
+ ALOGW("%s: HAL doesn't implement a sound dose interface for module %s",
__func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
std::shared_ptr<ISoundDose> soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder);
- if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+ if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) {
ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
- activateInternalSoundDoseComputation();
return false;
}
@@ -73,7 +70,8 @@
mUseHalSoundDoseInterface = false;
}
- mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+ // reset the HAL interfaces and use internal MELs
+ mSoundDoseManager->resetHalSoundDoseInterfaces();
}
void MelReporter::onFirstRef() {
@@ -257,6 +255,9 @@
void MelReporter::stopInternalMelComputation() {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
+ if (mUseHalSoundDoseInterface) {
+ return;
+ }
mActiveMelPatches.clear();
mUseHalSoundDoseInterface = true;
}
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index f11a530..554272a 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -915,7 +915,7 @@
patchPanelDump += "\nPatches:\n";
headerPrinted = true;
}
- patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).string());
+ patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).c_str());
}
headerPrinted = false;
@@ -933,12 +933,12 @@
for (const auto& patch : module.second.sw_patches) {
moduleDump.appendFormat("%d ", patch);
}
- patchPanelDump.appendFormat("%s%s\n", indent, moduleDump.string());
+ patchPanelDump.appendFormat("%s%s\n", indent, moduleDump.c_str());
}
}
- if (!patchPanelDump.isEmpty()) {
- write(fd, patchPanelDump.string(), patchPanelDump.size());
+ if (!patchPanelDump.empty()) {
+ write(fd, patchPanelDump.c_str(), patchPanelDump.size());
}
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 5f54e11..3e5501f 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -62,8 +62,8 @@
wp<IAfThreadBase> mThread;
std::atomic_bool mHasOpPlayAudio;
- const AttributionSourceState mAttributionSource;
- const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
+ const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as
+ // int32_t
const int mId; // for logging purposes only
const uid_t mUid;
const String16 mPackageName;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a36494c..157764f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -570,7 +570,7 @@
" us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
" %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
" MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
- title.string(),
+ title.c_str(),
elapsed * .000000001, n, perLoop * .000001,
mean * .001,
stddev * .001,
@@ -696,7 +696,7 @@
status_t ThreadBase::setParameters(const String8& keyValuePairs)
{
- ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
+ ALOGV("ThreadBase::setParameters() %s", keyValuePairs.c_str());
Mutex::Autolock _l(mLock);
return sendSetParameterConfigEvent_l(keyValuePairs);
@@ -881,7 +881,7 @@
if (checkForNewParameter_l(data->mKeyValuePairs, event->mStatus)) {
configChanged = true;
mLocalLog.log("CFG_EVENT_SET_PARAMETER: (%s) configuration changed",
- data->mKeyValuePairs.string());
+ data->mKeyValuePairs.c_str());
}
} break;
case CFG_EVENT_CREATE_AUDIO_PATCH: {
@@ -1069,7 +1069,7 @@
dprintf(fd, " HAL buffer size: %zu bytes\n", mBufferSize);
dprintf(fd, " Channel count: %u\n", mChannelCount);
dprintf(fd, " Channel mask: 0x%08x (%s)\n", mChannelMask,
- channelMaskToString(mChannelMask, mType != RECORD).string());
+ channelMaskToString(mChannelMask, mType != RECORD).c_str());
dprintf(fd, " Processing format: 0x%x (%s)\n", mFormat,
IAfThreadBase::formatToString(mFormat).c_str());
dprintf(fd, " Processing frame size: %zu bytes\n", mFrameSize);
@@ -2005,7 +2005,7 @@
if (mLocalLog != nullptr) {
String8 result;
track->appendDump(result, false /* active */);
- mLocalLog->log("AT::%-10s(%p) %s", funcName, track.get(), result.string());
+ mLocalLog->log("AT::%-10s(%p) %s", funcName, track.get(), result.c_str());
}
}
@@ -2272,7 +2272,7 @@
}
}
result.append("\n");
- write(fd, result.string(), result.length());
+ write(fd, result.c_str(), result.length());
result.clear();
// These values are "raw"; they will wrap around. See prepareTracks_l() for a better way.
@@ -2318,7 +2318,7 @@
}
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
void PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
@@ -2966,7 +2966,7 @@
String8 result;
track->appendDump(result, false /* active */);
- mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
+ mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.c_str());
mTracks.remove(track);
{
@@ -4075,9 +4075,9 @@
releaseWakeLock_l();
// wait until we have something to do...
- ALOGV("%s going to sleep", myName.string());
+ ALOGV("%s going to sleep", myName.c_str());
mWaitWorkCV.wait(mLock);
- ALOGV("%s waking up", myName.string());
+ ALOGV("%s waking up", myName.c_str());
acquireWakeLock_l();
mMixerStatus = MIXER_IDLE;
@@ -9178,7 +9178,7 @@
{
String8 result;
track->appendDump(result, false /* active */);
- mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.string());
+ mLocalLog.log("removeTrack_l (%p) %s", track.get(), result.c_str());
mTracks.remove(track);
// need anything related to effects here?
@@ -9257,7 +9257,7 @@
}
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
void RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
@@ -10345,9 +10345,9 @@
}
// wait until we have something to do...
- ALOGV("%s going to sleep", myName.string());
+ ALOGV("%s going to sleep", myName.c_str());
mWaitWorkCV.wait(mLock);
- ALOGV("%s waking up", myName.string());
+ ALOGV("%s waking up", myName.c_str());
checkSilentMode_l();
@@ -10721,7 +10721,7 @@
} else {
dprintf(fd, "\n");
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
/* static */
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 79f75ca..18b6840 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -170,7 +170,7 @@
mKeyValuePairs(keyValuePairs) {}
virtual void dump(char *buffer, size_t size) {
- snprintf(buffer, size, "- KeyValue: %s\n", mKeyValuePairs.string());
+ snprintf(buffer, size, "- KeyValue: %s\n", mKeyValuePairs.c_str());
}
const String8 mKeyValuePairs;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ecea9eb..e93046e 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -568,9 +568,7 @@
getPackagesForUid(uid, packages);
if (isServiceUid(uid)) {
if (packages.isEmpty()) {
- ALOGD("OpPlayAudio: not muting track:%d usage:%d for service UID %d",
- id,
- attr.usage,
+ ALOGW("OpPlayAudio: not muting track:%d usage:%d for service UID %d", id, attr.usage,
uid);
return nullptr;
}
@@ -594,7 +592,6 @@
audio_usage_t usage, int id, uid_t uid)
: mThread(wp<IAfThreadBase>::fromExisting(thread)),
mHasOpPlayAudio(true),
- mAttributionSource(attributionSource),
mUsage((int32_t)usage),
mId(id),
mUid(uid),
@@ -614,10 +611,11 @@
// make sure not to broadcast the initial state since it is not needed and could
// cause a deadlock since this method can be called with the mThread->mLock held
checkPlayAudioForUsage(/*doBroadcast=*/false);
- if (mAttributionSource.packageName.has_value()) {
+ if (mPackageName.size()) {
mOpCallback = new PlayAudioOpCallback(this);
- mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
- mPackageName, mOpCallback);
+ mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, mPackageName, mOpCallback);
+ } else {
+ ALOGW("Skipping OpPlayAudioMonitor due to null package name");
}
}
@@ -628,16 +626,16 @@
// Note this method is never called (and never to be) for audio server / patch record track
// - not called from constructor due to check on UID,
// - not called from PlayAudioOpCallback because the callback is not installed in this case
-void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
-{
- const bool hasAppOps = mAttributionSource.packageName.has_value()
- && mAppOpsManager.checkAudioOpNoThrow(
- AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) ==
- AppOpsManager::MODE_ALLOWED;
+void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) {
+ const bool hasAppOps =
+ mPackageName.size() &&
+ mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid,
+ mPackageName) == AppOpsManager::MODE_ALLOWED;
bool shouldChange = !hasAppOps; // check if we need to update.
if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
- ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
+ ALOGI("OpPlayAudio: track:%d package:%s usage:%d %smuted", mId,
+ String8(mPackageName).string(), mUsage, hasAppOps ? "not " : "");
if (doBroadcast) {
auto thread = mThread.promote();
if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
@@ -655,11 +653,11 @@
void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
const String16& packageName) {
- // we only have uid, so we need to check all package names anyway
- UNUSED(packageName);
if (op != AppOpsManager::OP_PLAY_AUDIO) {
return;
}
+
+ ALOGI("%s OP_PLAY_AUDIO callback received for %s", __func__, String8(packageName).string());
sp<OpPlayAudioMonitor> monitor = mMonitor.promote();
if (monitor != NULL) {
monitor->checkPlayAudioForUsage(/*doBroadcast=*/true);
@@ -1640,22 +1638,18 @@
if (mMuteEventExtras == nullptr) {
mMuteEventExtras = std::make_unique<os::PersistableBundle>();
}
- mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey),
- static_cast<int>(muteState));
+ mMuteEventExtras->putInt(String16(kExtraPlayerEventMuteKey), static_cast<int>(muteState));
- result = audioManager->portEvent(mPortId,
- PLAYER_UPDATE_MUTED,
- mMuteEventExtras);
+ result = audioManager->portEvent(mPortId, PLAYER_UPDATE_MUTED, mMuteEventExtras);
}
if (result == OK) {
+ ALOGI("%s(%d): processed mute state for port ID %d from %d to %d", __func__, id(), mPortId,
+ int(muteState), int(mMuteState));
mMuteState = muteState;
} else {
- ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d",
- __func__,
- id(),
- mPortId,
- result);
+ ALOGW("%s(%d): cannot process mute state for port ID %d, status error %d", __func__, id(),
+ mPortId, result);
}
}
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 7accaf0..39c80d8 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -49,7 +49,7 @@
size_t channelCount, audio_format_t format) {
const std::lock_guard _l(mLock);
- if (mHalSoundDose != nullptr && mEnabledCsd) {
+ if (mHalSoundDose.size() > 0 && mEnabledCsd) {
ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
return nullptr;
}
@@ -82,20 +82,27 @@
return melProcessor;
}
-bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module,
+ const std::shared_ptr<ISoundDose> &halSoundDose) {
ALOGV("%s", __func__);
+ if (halSoundDose == nullptr) {
+ ALOGI("%s: passed ISoundDose object is null", __func__);
+ return false;
+ }
+
std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
{
const std::lock_guard _l(mLock);
- mHalSoundDose = halSoundDose;
- if (halSoundDose == nullptr) {
- ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+ if (mHalSoundDose.find(module) != mHalSoundDose.end()) {
+ ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__,
+ module.c_str());
return false;
}
+ mHalSoundDose[module] = halSoundDose;
- if (!mHalSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
+ if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) {
ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
__func__,
mRs2UpperBound);
@@ -121,16 +128,26 @@
return true;
}
+void SoundDoseManager::resetHalSoundDoseInterfaces() {
+ ALOGV("%s", __func__);
+
+ const std::lock_guard _l(mLock);
+ mHalSoundDose.clear();
+}
+
void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
ALOGV("%s", __func__);
const std::lock_guard _l(mLock);
- if (mHalSoundDose != nullptr) {
- // using the HAL sound dose interface
- if (!mHalSoundDose->setOutputRs2UpperBound(rs2Value).isOk()) {
- ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
- return;
+ if (mHalSoundDose.size() > 0) {
+ for (auto& halSoundDose : mHalSoundDose) {
+ // using the HAL sound dose interface
+ if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) {
+ ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value);
+ continue;
+ }
}
+
mRs2UpperBound = rs2Value;
return;
}
@@ -202,14 +219,16 @@
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
float in_currentDbA, const AudioDevice& in_audioDevice) {
- auto soundDoseManager = mSoundDoseManager.promote();
- if (soundDoseManager == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ sp<SoundDoseManager> soundDoseManager;
+ {
+ const std::lock_guard _l(mCbLock);
+ soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
}
- std::shared_ptr<ISoundDose> halSoundDose;
- soundDoseManager->getHalSoundDose(&halSoundDose);
- if(halSoundDose == nullptr) {
+ if (!soundDoseManager->useHalSoundDose()) {
ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
@@ -229,14 +248,16 @@
ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
const AudioDevice& in_audioDevice) {
- auto soundDoseManager = mSoundDoseManager.promote();
- if (soundDoseManager == nullptr) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ sp<SoundDoseManager> soundDoseManager;
+ {
+ const std::lock_guard _l(mCbLock);
+ soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
}
- std::shared_ptr<ISoundDose> halSoundDose;
- soundDoseManager->getHalSoundDose(&halSoundDose);
- if(halSoundDose == nullptr) {
+ if (!soundDoseManager->useHalSoundDose()) {
ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
@@ -509,7 +530,7 @@
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
// invalidate any HAL sound dose interface used
- setHalSoundDoseInterface(nullptr);
+ resetHalSoundDoseInterfaces();
const std::lock_guard _l(mLock);
mUseFrameworkMel = useFrameworkMel;
@@ -536,14 +557,12 @@
if (!mEnabledCsd) return false;
}
- std::shared_ptr<ISoundDose> halSoundDose;
- getHalSoundDose(&halSoundDose);
- return halSoundDose != nullptr;
+ return useHalSoundDose();
}
-void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
+bool SoundDoseManager::useHalSoundDose() const {
const std::lock_guard _l(mLock);
- *halSoundDose = mHalSoundDose;
+ return mHalSoundDose.size() > 0;
}
void SoundDoseManager::resetSoundDose() {
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 888561f..6e0bc34 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -94,12 +94,15 @@
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
/**
- * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
- * for using the internal MEL computation.
+ * Sets the HAL sound dose interface for a specific module to use for the MEL computation.
*
* @return true if setting the HAL sound dose value was successful, false otherwise.
*/
- bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+ bool setHalSoundDoseInterface(const std::string &module,
+ const std::shared_ptr<ISoundDose> &halSoundDose);
+
+ /** Reset all the stored HAL sound dose interface. */
+ void resetHalSoundDoseInterfaces();
/** Returns the cached audio port id from the active devices. */
audio_port_handle_t getIdForAudioDevice(
@@ -193,6 +196,7 @@
const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
wp<SoundDoseManager> mSoundDoseManager;
+ std::mutex mCbLock;
};
void resetSoundDose();
@@ -206,8 +210,11 @@
void setUseFrameworkMel(bool useFrameworkMel);
void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
bool isSoundDoseHalSupported() const;
- /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
- void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
+ /**
+ * Returns true if there is one active HAL sound dose interface or null if internal MEL
+ * computation is used.
+ **/
+ bool useHalSoundDose() const;
mutable std::mutex mLock;
@@ -241,10 +248,10 @@
sp<SoundDose> mSoundDose GUARDED_BY(mLock);
- std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+ std::unordered_map<std::string, std::shared_ptr<ISoundDose>> mHalSoundDose GUARDED_BY(mLock);
std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
- bool mUseFrameworkMel GUARDED_BY(mLock) = true;
+ bool mUseFrameworkMel GUARDED_BY(mLock) = false;
bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
bool mEnabledCsd GUARDED_BY(mLock) = true;
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 7d0b3a7..5f6dcb9 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -45,6 +45,8 @@
MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override));
};
+constexpr char kPrimaryModule[] = "primary";
+constexpr char kSecondaryModule[] = "secondary";
class SoundDoseManagerTest : public ::testing::Test {
protected:
@@ -52,17 +54,24 @@
mMelReporterCallback = sp<MelReporterCallback>::make();
mSoundDoseManager = sp<SoundDoseManager>::make(mMelReporterCallback);
mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+ mSecondaryHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound)
.WillByDefault([] (float rs2) {
EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
return ndk::ScopedAStatus::ok();
});
+ ON_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound)
+ .WillByDefault([] (float rs2) {
+ EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+ return ndk::ScopedAStatus::ok();
+ });
}
sp<MelReporterCallback> mMelReporterCallback;
sp<SoundDoseManager> mSoundDoseManager;
std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+ std::shared_ptr<HalSoundDoseMock> mSecondaryHalSoundDose;
};
TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
@@ -110,7 +119,7 @@
}
TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
- EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, nullptr));
}
TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
@@ -122,7 +131,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
@@ -139,8 +148,17 @@
EXPECT_NE(nullptr, callback);
return ndk::ScopedAStatus::ok();
});
+ EXPECT_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound).Times(1);
+ EXPECT_CALL(*mSecondaryHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kSecondaryModule,
+ mSecondaryHalSoundDose));
}
TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
@@ -154,7 +172,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
@@ -175,9 +193,9 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
- EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+ mSoundDoseManager->resetHalSoundDoseInterfaces();
AudioDevice audioDevice = {};
audioDevice.address.set<AudioDeviceAddress::id>("test");
@@ -197,7 +215,7 @@
return ndk::ScopedAStatus::ok();
});
- EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose));
EXPECT_NE(nullptr, halCallback);
AudioDevice audioDevice = {};
@@ -248,8 +266,7 @@
}
TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
- // TODO: for now dogfooding with internal MEL. Revert to false when using the HAL MELs
- EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel());
+ EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
}
TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStopsNonHeadphone) {
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index da0df5f..b954bfc 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -270,6 +270,10 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes) = 0;
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes) = 0;
+ virtual status_t updatePolicyMix(
+ const AudioMix& mix,
+ const std::vector<AudioMixMatchCriterion>& updatedCriteria) = 0;
+
virtual status_t setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices)
= 0;
virtual status_t removeUidDeviceAffinities(uid_t uid) = 0;
diff --git a/services/audiopolicy/TEST_MAPPING b/services/audiopolicy/TEST_MAPPING
index fa3a5d3..a2ebb8d 100644
--- a/services/audiopolicy/TEST_MAPPING
+++ b/services/audiopolicy/TEST_MAPPING
@@ -34,5 +34,18 @@
{
"name": "audiopolicy_tests"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "GtsGmscoreHostTestCases",
+ "options" : [
+ {
+ "include-filter": "com.google.android.gts.audio.AudioHostTest"
+ },
+ {
+ "include-filter": "com.google.android.gts.audio.AudioPolicyHostTest"
+ }
+ ]
+ }
]
}
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 7e29e10..b560bc4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -59,6 +59,8 @@
status_t unregisterMix(const AudioMix& mix);
+ status_t updateMix(const AudioMix& mix, const std::vector<AudioMixMatchCriterion>& newCriteria);
+
void closeOutput(sp<SwAudioOutputDescriptor> &desc);
/**
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index d40bbcb..c2e4b11 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -84,6 +84,7 @@
const AudioInputCollection *inputs, AudioPolicyClientInterface *mClientInterface);
void putOrphanEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
const AudioInputCollection *inputs, AudioPolicyClientInterface *clientInterface);
+ void putOrphanEffectsForIo(audio_io_handle_t srcIo);
/**
* @brief Checks if an effect session was already attached to an io handle and return it if
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index e994758..cf20260 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -43,7 +43,7 @@
HwModule(const char *name, uint32_t halVersion = 0);
~HwModule();
- const char *getName() const { return mName.string(); }
+ const char *getName() const { return mName.c_str(); }
const DeviceVector &getDeclaredDevices() const { return mDeclaredDevices; }
void setDeclaredDevices(const DeviceVector &devices);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 0f9cc89..a83e0af 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -21,6 +21,7 @@
#include <iterator>
#include <optional>
#include <regex>
+#include <vector>
#include "AudioPolicyMix.h"
#include "TypeConverter.h"
#include "HwModule.h"
@@ -138,7 +139,7 @@
dst->appendFormat("%*s- device type: %s\n", spaces, "", toString(mDeviceType).c_str());
- dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());
+ dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.c_str());
dst->appendFormat("%*s- output: %d\n", spaces, "",
mOutput == nullptr ? 0 : mOutput->mIoHandle);
@@ -186,7 +187,7 @@
&& mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0
&& is_mix_loopback(mix.mRouteFlags)) {
ALOGE("registerMix(): mix already registered for dev=0x%x addr=%s",
- mix.mDeviceType, mix.mDeviceAddress.string());
+ mix.mDeviceType, mix.mDeviceAddress.c_str());
return BAD_VALUE;
}
}
@@ -198,7 +199,7 @@
sp<AudioPolicyMix> policyMix = sp<AudioPolicyMix>::make(mix);
add(policyMix);
ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
- policyMix->mDeviceType, policyMix->mDeviceAddress.string());
+ policyMix->mDeviceType, policyMix->mDeviceAddress.c_str());
if (desc != nullptr) {
desc->mPolicyMix = policyMix;
@@ -214,14 +215,39 @@
if (mix.mDeviceType == registeredMix->mDeviceType
&& mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0) {
ALOGD("unregisterMix(): removing mix for dev=0x%x addr=%s",
- mix.mDeviceType, mix.mDeviceAddress.string());
+ mix.mDeviceType, mix.mDeviceAddress.c_str());
removeAt(i);
return NO_ERROR;
}
}
ALOGE("unregisterMix(): mix not registered for dev=0x%x addr=%s",
- mix.mDeviceType, mix.mDeviceAddress.string());
+ mix.mDeviceType, mix.mDeviceAddress.c_str());
+ return BAD_VALUE;
+}
+
+status_t AudioPolicyMixCollection::updateMix(
+ const AudioMix& mix, const std::vector<AudioMixMatchCriterion>& updatedCriteria) {
+ if (!areMixCriteriaConsistent(mix.mCriteria)) {
+ ALOGE("updateMix(): updated criteria are not consistent "
+ "(MATCH & EXCLUDE criteria of the same type)");
+ return BAD_VALUE;
+ }
+
+ for (size_t i = 0; i < size(); i++) {
+ const sp<AudioPolicyMix>& registeredMix = itemAt(i);
+ if (mix.mDeviceType == registeredMix->mDeviceType &&
+ mix.mDeviceAddress.compare(registeredMix->mDeviceAddress) == 0 &&
+ mix.mRouteFlags == registeredMix->mRouteFlags) {
+ registeredMix->mCriteria = updatedCriteria;
+ ALOGV("updateMix(): updated mix for dev=0x%x addr=%s", mix.mDeviceType,
+ mix.mDeviceAddress.string());
+ return NO_ERROR;
+ }
+ }
+
+ ALOGE("updateMix(): mix not registered for dev=0x%x addr=%s", mix.mDeviceType,
+ mix.mDeviceAddress.string());
return BAD_VALUE;
}
@@ -229,20 +255,20 @@
const String8& address, sp<AudioPolicyMix> &policyMix) const
{
- ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
+ ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.c_str());
for (ssize_t i = 0; i < size(); i++) {
// Workaround: when an in audio policy is registered, it opens an output
// that tries to find the audio policy, thus the device must be ignored.
if (itemAt(i)->mDeviceAddress.compare(address) == 0) {
policyMix = itemAt(i);
ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
- i, deviceType, address.string());
+ i, deviceType, address.c_str());
return NO_ERROR;
}
}
ALOGE("getAudioPolicyMix(): mix not registered for dev=0x%x addr=%s",
- deviceType, address.string());
+ deviceType, address.c_str());
return BAD_VALUE;
}
@@ -457,7 +483,7 @@
address->c_str(), attr.source);
for (size_t i = 0; i < size(); i++) {
const sp<AudioPolicyMix> audioPolicyMix = itemAt(i);
- ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.string());
+ ALOGV("\tmix %zu address=%s", i, audioPolicyMix->mDeviceAddress.c_str());
}
#endif
@@ -466,7 +492,7 @@
const sp<AudioPolicyMix>& registeredMix = itemAt(index);
if (address->compare(registeredMix->mDeviceAddress.c_str()) == 0) {
ALOGD("getInputMixForAttr found addr=%s dev=0x%x",
- registeredMix->mDeviceAddress.string(), registeredMix->mDeviceType);
+ registeredMix->mDeviceAddress.c_str(), registeredMix->mDeviceType);
break;
}
}
@@ -515,7 +541,7 @@
}
// check if this mix goes to a device in the list of devices
bool deviceMatch = false;
- const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+ const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.c_str());
for (size_t j = 0; j < devices.size(); j++) {
if (mixDevice.equals(devices[j])) {
deviceMatch = true;
@@ -571,7 +597,7 @@
}
}
if (ruleAllowsUid) {
- devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+ devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.c_str()));
}
}
return NO_ERROR;
@@ -606,7 +632,7 @@
}
// check if this mix goes to a device in the list of devices
bool deviceMatch = false;
- const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.string());
+ const AudioDeviceTypeAddr mixDevice(mix->mDeviceType, mix->mDeviceAddress.c_str());
for (size_t j = 0; j < devices.size(); j++) {
if (mixDevice.equals(devices[j])) {
deviceMatch = true;
@@ -668,7 +694,7 @@
}
}
if (ruleAllowsUserId) {
- devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string()));
+ devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.c_str()));
}
}
return NO_ERROR;
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index a909331..62e5bd4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -185,7 +185,7 @@
}
std::string descBaseDumpStr;
- DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.string(), verbose);
+ DeviceDescriptorBase::dump(&descBaseDumpStr, spaces, extraInfo.c_str(), verbose);
dst->append(descBaseDumpStr.c_str());
}
@@ -325,7 +325,7 @@
}
}
ALOGV("DeviceVector::%s() for type %08x address \"%s\" found %p format %08x",
- __func__, type, address.string(), device.get(), format);
+ __func__, type, address.c_str(), device.get(), format);
return device;
}
@@ -448,7 +448,7 @@
if (isEmpty()) {
return;
}
- dst->appendFormat("%*s%s devices (%zu):\n", spaces, "", tag.string(), size());
+ dst->appendFormat("%*s%s devices (%zu):\n", spaces, "", tag.c_str(), size());
for (size_t i = 0; i < size(); i++) {
const std::string prefix = base::StringPrintf("%*s %zu. ", spaces, "", i + 1);
dst->appendFormat("%s", prefix.c_str());
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 1f6946c..c85df0f 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -302,6 +302,17 @@
}
}
+void EffectDescriptorCollection::putOrphanEffectsForIo(audio_io_handle_t srcIo)
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<EffectDescriptor> effect = valueAt(i);
+ if (effect->mIo == srcIo) {
+ effect->mIo = AUDIO_IO_HANDLE_NONE;
+ effect->mIsOrphan = true;
+ }
+ }
+}
+
void EffectDescriptorCollection::putOrphanEffects(audio_session_t session,
audio_io_handle_t srcIo, const AudioInputCollection *inputs,
AudioPolicyClientInterface *clientInterface)
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 95f8d14..2c8e50b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -67,7 +67,7 @@
config->sample_rate));
sp<DeviceDescriptor> devDesc =
- new DeviceDescriptor(device, getTagForDevice(device), address.string());
+ new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@@ -135,7 +135,7 @@
config->sample_rate));
sp<DeviceDescriptor> devDesc =
- new DeviceDescriptor(device, getTagForDevice(device), address.string());
+ new DeviceDescriptor(device, getTagForDevice(device), address.c_str());
addDynamicDevice(devDesc);
// Reciprocally attach the device to the module
devDesc->attach(this);
@@ -375,7 +375,7 @@
if (allowToCreate) {
moduleDevice->attach(hwModule);
// Name may be overwritten, restored on detach.
- moduleDevice->setAddress(devAddress.string());
+ moduleDevice->setAddress(devAddress.c_str());
// Name may be overwritten, restored on detach.
moduleDevice->setName(name);
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 3d5c1d2..6f19a7a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -618,13 +618,15 @@
}
// Convert Sink name to port pointer
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
- if (sink == NULL && !mIgnoreVendorExtensions) {
- ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
- return BAD_VALUE;
- } else if (sink == NULL) {
- ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
- sinkAttr.c_str());
- return NO_INIT;
+ if (sink == NULL) {
+ if (!mIgnoreVendorExtensions) {
+ ALOGE("%s: no sink found with name \"%s\"", __func__, sinkAttr.c_str());
+ return BAD_VALUE;
+ } else {
+ ALOGW("%s: skipping route to sink \"%s\" as it likely has vendor extension type",
+ __func__, sinkAttr.c_str());
+ return NO_INIT;
+ }
}
route->setSink(sink);
@@ -641,12 +643,14 @@
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
- if (source == NULL && !mIgnoreVendorExtensions) {
- ALOGE("%s: no source found with name=%s", __func__, devTag);
- return BAD_VALUE;
- } else if (source == NULL) {
- ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
- devTag);
+ if (source == NULL) {
+ if (!mIgnoreVendorExtensions) {
+ ALOGE("%s: no source found with name \"%s\"", __func__, devTag);
+ return BAD_VALUE;
+ } else {
+ ALOGW("%s: skipping route source \"%s\" as it likely has vendor extension type",
+ __func__, devTag);
+ }
} else {
sources.add(source);
}
@@ -728,10 +732,16 @@
sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
- if (device == nullptr && mIgnoreVendorExtensions) {
- ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
- "extension type",
- reinterpret_cast<const char*>(attachedDevice.get()));
+ if (device == NULL) {
+ if (mIgnoreVendorExtensions) {
+ ALOGW("%s: skipped attached device \"%s\" because it likely uses a "
+ "vendor extension type",
+ __func__,
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ } else {
+ ALOGE("%s: got null device in %s, \"%s\"", __func__, child->name,
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ }
continue;
}
ctx->addDevice(device);
diff --git a/services/audiopolicy/config/Android.bp b/services/audiopolicy/config/Android.bp
index 671b30a..86600f4 100644
--- a/services/audiopolicy/config/Android.bp
+++ b/services/audiopolicy/config/Android.bp
@@ -112,3 +112,15 @@
name: "r_submix_audio_policy_configuration",
srcs: ["r_submix_audio_policy_configuration.xml"],
}
+filegroup {
+ name: "bluetooth_audio_policy_configuration_7_0",
+ srcs: ["bluetooth_audio_policy_configuration_7_0.xml"],
+}
+filegroup {
+ name: "bluetooth_with_le_audio_policy_configuration_7_0",
+ srcs: ["bluetooth_with_le_audio_policy_configuration_7_0.xml"],
+}
+filegroup {
+ name: "hearing_aid_audio_policy_configuration_7_0",
+ srcs: ["hearing_aid_audio_policy_configuration_7_0.xml"],
+}
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 15f7842..fa6be39 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -175,34 +175,37 @@
// - cannot route from voice call RX OR
// - audio HAL version is < 3.0 and TX device is on the primary HW module
if (getPhoneState() == AUDIO_MODE_IN_CALL) {
- audio_devices_t txDevice = AUDIO_DEVICE_NONE;
- sp<DeviceDescriptor> txDeviceDesc =
- getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
- if (txDeviceDesc != nullptr) {
- txDevice = txDeviceDesc->type();
- }
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
- LOG_ALWAYS_FATAL_IF(primaryOutput == nullptr, "Primary output not found");
- DeviceVector availPrimaryInputDevices =
- availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
+ if (primaryOutput != nullptr) {
+ audio_devices_t txDevice = AUDIO_DEVICE_NONE;
+ sp<DeviceDescriptor> txDeviceDesc =
+ getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+ if (txDeviceDesc != nullptr) {
+ txDevice = txDeviceDesc->type();
+ }
+ DeviceVector availPrimaryInputDevices =
+ availableInputDevices.getDevicesFromHwModule(
+ primaryOutput->getModuleHandle());
- // TODO: getPrimaryOutput return only devices from first module in
- // audio_policy_configuration.xml, hearing aid is not there, but it's
- // a primary device
- // FIXME: this is not the right way of solving this problem
- DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
- primaryOutput->supportedDevices().types());
- availPrimaryOutputDevices.add(
- availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
+ // TODO: getPrimaryOutput return only devices from first module in
+ // audio_policy_configuration.xml, hearing aid is not there, but it's
+ // a primary device
+ // FIXME: this is not the right way of solving this problem
+ DeviceVector availPrimaryOutputDevices = availableOutputDevices.getDevicesFromTypes(
+ primaryOutput->supportedDevices().types());
+ availPrimaryOutputDevices.add(
+ availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID));
- if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
- String8(""), AUDIO_FORMAT_DEFAULT) == nullptr) ||
- ((availPrimaryInputDevices.getDevice(
- txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
- (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
- availableOutputDevices = availPrimaryOutputDevices;
+ if ((availableInputDevices.getDevice(AUDIO_DEVICE_IN_TELEPHONY_RX,
+ String8(""), AUDIO_FORMAT_DEFAULT) == nullptr)
+ || ((availPrimaryInputDevices.getDevice(
+ txDevice, String8(""), AUDIO_FORMAT_DEFAULT) != nullptr) &&
+ (primaryOutput->getPolicyAudioPort()->getModuleVersionMajor() < 3))) {
+ availableOutputDevices = availPrimaryOutputDevices;
+ }
+ } else {
+ ALOGE("%s, STRATEGY_PHONE: Primary output not found", __func__);
}
-
}
// Do not use A2DP devices when in call but use them when not in call
// (e.g for voice mail playback)
@@ -595,8 +598,11 @@
if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
(availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX,
String8(""), AUDIO_FORMAT_DEFAULT)) == nullptr) {
- LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
- availableDevices = availablePrimaryDevices;
+ if (!availablePrimaryDevices.isEmpty()) {
+ availableDevices = availablePrimaryDevices;
+ } else {
+ ALOGE("%s, AUDIO_SOURCE_VOICE_COMMUNICATION: Primary devices not found", __func__);
+ }
}
if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
@@ -650,8 +656,11 @@
case AUDIO_SOURCE_HOTWORD:
// We should not use primary output criteria for Hotword but rather limit
// to devices attached to the same HW module as the build in mic
- LOG_ALWAYS_FATAL_IF(availablePrimaryDevices.isEmpty(), "Primary devices not found");
- availableDevices = availablePrimaryDevices;
+ if (!availablePrimaryDevices.isEmpty()) {
+ availableDevices = availablePrimaryDevices;
+ } else {
+ ALOGE("%s, AUDIO_SOURCE_HOTWORD: Primary devices not found", __func__);
+ }
if (audio_is_bluetooth_out_sco_device(commDeviceType)) {
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, String8(""), AUDIO_FORMAT_DEFAULT);
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 8793085..58fcb5c 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -661,7 +661,9 @@
}
AudioPolicyManagerFuzzerDPPlaybackReRouting::~AudioPolicyManagerFuzzerDPPlaybackReRouting() {
- mManager->stopInput(mPortId);
+ if (mManager) {
+ mManager->stopInput(mPortId);
+ }
}
bool AudioPolicyManagerFuzzerDPPlaybackReRouting::initialize() {
@@ -773,7 +775,9 @@
}
AudioPolicyManagerFuzzerDPMixRecordInjection::~AudioPolicyManagerFuzzerDPMixRecordInjection() {
- mManager->stopOutput(mPortId);
+ if (mManager) {
+ mManager->stopOutput(mPortId);
+ }
}
bool AudioPolicyManagerFuzzerDPMixRecordInjection::initialize() {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 884ad96..a72598e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "utils/Errors.h"
#define LOG_TAG "APM_AudioPolicyManager"
// Need to keep the log statements even in production builds
@@ -277,7 +278,7 @@
sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
if (policyMix != nullptr
&& policyMix->mMixType == MIX_TYPE_RECORDERS
- && device->address() == policyMix->mDeviceAddress.string()) {
+ && device->address() == policyMix->mDeviceAddress.c_str()) {
doCheckForDeviceAndOutputChanges = false;
break;
}
@@ -2242,7 +2243,7 @@
const char *address = NULL;
if (policyMix != nullptr) {
audio_devices_t newDeviceType;
- address = policyMix->mDeviceAddress.string();
+ address = policyMix->mDeviceAddress.c_str();
if ((policyMix->mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
newDeviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
} else {
@@ -3640,7 +3641,7 @@
}
if (mPolicyMixes.registerMix(mix, 0 /*output desc*/) != NO_ERROR) {
- ALOGE("Error registering mix %zu for address %s", i, address.string());
+ ALOGE("Error registering mix %zu for address %s", i, address.c_str());
res = INVALID_OPERATION;
break;
}
@@ -3657,16 +3658,16 @@
if ((res = setDeviceConnectionStateInt(deviceTypeToMakeAvailable,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
+ address.c_str(), "remote-submix", AUDIO_FORMAT_DEFAULT)) != NO_ERROR) {
ALOGE("Failed to set remote submix device available, type %u, address %s",
- mix.mDeviceType, address.string());
+ mix.mDeviceType, address.c_str());
break;
}
} else if ((mix.mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
String8 address = mix.mDeviceAddress;
audio_devices_t type = mix.mDeviceType;
ALOGV(" registerPolicyMixes() mix %zu of %zu is RENDER, dev=0x%X addr=%s",
- i, mixes.size(), type, address.string());
+ i, mixes.size(), type, address.c_str());
sp<DeviceDescriptor> device = mHwModules.getDeviceDescriptor(
mix.mDeviceType, mix.mDeviceAddress,
@@ -3684,7 +3685,7 @@
if (!desc->isDuplicated() && desc->supportedDevices().contains(device)) {
if (mPolicyMixes.registerMix(mix, desc) != NO_ERROR) {
ALOGE("Could not register mix RENDER, dev=0x%X addr=%s", type,
- address.string());
+ address.c_str());
res = INVALID_OPERATION;
} else {
foundOutput = true;
@@ -3701,7 +3702,7 @@
if (profile->isDirectOutput() && profile->supportsDevice(device)) {
if (mPolicyMixes.registerMix(mix, nullptr) != NO_ERROR) {
ALOGE("Could not register mix RENDER, dev=0x%X addr=%s", type,
- address.string());
+ address.c_str());
res = INVALID_OPERATION;
} else {
foundOutput = true;
@@ -3711,12 +3712,12 @@
}
if (res != NO_ERROR) {
ALOGE(" Error registering mix %zu for device 0x%X addr %s",
- i, type, address.string());
+ i, type, address.c_str());
res = INVALID_OPERATION;
break;
} else if (!foundOutput) {
ALOGE(" Output not found for mix %zu for device 0x%X addr %s",
- i, type, address.string());
+ i, type, address.c_str());
res = INVALID_OPERATION;
break;
} else {
@@ -3760,14 +3761,14 @@
}
for (auto device : {AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX}) {
- if (getDeviceConnectionState(device, address.string()) ==
+ if (getDeviceConnectionState(device, address.c_str()) ==
AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
res = setDeviceConnectionStateInt(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix",
+ address.c_str(), "remote-submix",
AUDIO_FORMAT_DEFAULT);
if (res != OK) {
ALOGE("Error making RemoteSubmix device unavailable for mix "
- "with type %d, address %s", device, address.string());
+ "with type %d, address %s", device, address.c_str());
}
}
}
@@ -3790,6 +3791,17 @@
return res;
}
+status_t AudioPolicyManager::updatePolicyMix(
+ const AudioMix& mix,
+ const std::vector<AudioMixMatchCriterion>& updatedCriteria) {
+ status_t res = mPolicyMixes.updateMix(mix, updatedCriteria);
+ if (res == NO_ERROR) {
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+ }
+ return res;
+}
+
void AudioPolicyManager::dumpManualSurroundFormats(String8 *dst) const
{
size_t i = 0;
@@ -4231,7 +4243,7 @@
{
String8 result;
dump(&result);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
@@ -6454,7 +6466,7 @@
}
ALOGV("opening output for device %08x with params %s profile %p name %s",
- deviceType, address.string(), profile.get(), profile->getName().c_str());
+ deviceType, address.c_str(), profile.get(), profile->getName().c_str());
desc = openOutputWithProfileAndDevice(profile, DeviceVector(device));
audio_io_handle_t output = desc == nullptr ? AUDIO_IO_HANDLE_NONE : desc->mIoHandle;
if (output == AUDIO_IO_HANDLE_NONE) {
@@ -6609,7 +6621,7 @@
if (status == NO_ERROR) {
const String8& address = String8(device->address().c_str());
- if (!address.isEmpty()) {
+ if (!address.empty()) {
char *param = audio_device_address_to_parameter(device->type(), address);
mpClientInterface->setParameters(input, String8(param));
free(param);
@@ -6769,6 +6781,7 @@
mpClientInterface->onAudioPatchListUpdate();
}
+ mEffects.putOrphanEffectsForIo(input);
inputDesc->close();
mInputs.removeItem(input);
@@ -7685,8 +7698,10 @@
const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false);
const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false);
const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false);
-
- if (volumeSource == a11yVolumeSrc
+ // Verify that the current volume source is not the ringer volume to prevent recursively
+ // calling to compute volume. This could happen in cases where a11y and ringer sounds belong
+ // to the same volume group.
+ if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc
&& (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) &&
mOutputs.isActive(ringVolumeSrc, 0)) {
auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING);
@@ -7749,8 +7764,12 @@
// when the phone is ringing we must consider that music could have been paused just before
// by the music application and behave as if music was active if the last music track was
// just stopped
- if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
- mLimitRingtoneVolume) {
+ // Verify that the current volume source is not the music volume to prevent recursively
+ // calling to compute volume. This could happen in cases where music and
+ // (alarm, ring, notification, system, etc.) sounds belong to the same volume group.
+ if (volumeSource != musicVolumeSrc &&
+ (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY)
+ || mLimitRingtoneVolume)) {
volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
DeviceTypeSet musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
@@ -8167,12 +8186,12 @@
if (profiles.hasDynamicFormat()) {
reply = mpClientInterface->getParameters(
ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
- ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
+ ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.c_str());
AudioParameter repliedParameters(reply);
FormatVector formats;
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
- formats = formatsFromString(reply.string());
+ formats = formatsFromString(reply.c_str());
} else if (devDesc->hasValidAudioProfile()) {
ALOGD("%s: using the device profiles", __func__);
formats = devDesc->getAudioProfiles().getSupportedFormats();
@@ -8199,11 +8218,11 @@
ioHandle,
requestedParameters.toString() + ";" +
AudioParameter::keyStreamSupportedSamplingRates);
- ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.string());
+ ALOGV("%s: supported sampling rates %s", __FUNCTION__, reply.c_str());
AudioParameter repliedParameters(reply);
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
- samplingRates = samplingRatesFromString(reply.string());
+ samplingRates = samplingRatesFromString(reply.c_str());
} else {
samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
}
@@ -8212,11 +8231,11 @@
reply = mpClientInterface->getParameters(ioHandle,
requestedParameters.toString() + ";" +
AudioParameter::keyStreamSupportedChannels);
- ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.string());
+ ALOGV("%s: supported channel masks %s", __FUNCTION__, reply.c_str());
AudioParameter repliedParameters(reply);
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
- channelMasks = channelMasksFromString(reply.string());
+ channelMasks = channelMasksFromString(reply.c_str());
} else {
channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
}
@@ -8350,7 +8369,7 @@
sp<DeviceDescriptor> device = devices.getDeviceForOpening();
const audio_devices_t deviceType = device->type();
const String8 &address = String8(device->address().c_str());
- if (!address.isEmpty()) {
+ if (!address.empty()) {
char *param = audio_device_address_to_parameter(deviceType, address.c_str());
mpClientInterface->setParameters(output, String8(param));
free(param);
@@ -8390,7 +8409,7 @@
desc->mPolicyMix = policyMix;
} else {
ALOGW("checkOutputsForDevice() cannot find policy for address %s",
- address.string());
+ address.c_str());
}
} else if (hasPrimaryOutput() && speaker != nullptr
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 509cc79..91fe1cc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -292,6 +292,9 @@
virtual status_t registerPolicyMixes(const Vector<AudioMix>& mixes);
virtual status_t unregisterPolicyMixes(Vector<AudioMix> mixes);
+ virtual status_t updatePolicyMix(
+ const AudioMix& mix,
+ const std::vector<AudioMixMatchCriterion>& updatedCriteria) override;
virtual status_t setUidDeviceAffinities(uid_t uid,
const AudioDeviceTypeAddrVector& devices);
virtual status_t removeUidDeviceAffinities(uid_t uid);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 13e682b..2874824 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -190,7 +190,7 @@
const String8& keyValuePairs,
int delay_ms)
{
- mAudioPolicyService->setParameters(io_handle, keyValuePairs.string(), delay_ms);
+ mAudioPolicyService->setParameters(io_handle, keyValuePairs.c_str(), delay_ms);
}
String8 AudioPolicyService::AudioPolicyClient::getParameters(audio_io_handle_t io_handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index a7b2a56..ce9fb92 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1764,6 +1764,22 @@
}
}
+Status AudioPolicyService::updatePolicyMixes(
+ const ::std::vector<::android::media::AudioMixUpdate>& updates) {
+ Mutex::Autolock _l(mLock);
+ for (const auto& update : updates) {
+ AudioMix mix = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_AudioMix(update.audioMix));
+ std::vector<AudioMixMatchCriterion> newCriteria =
+ VALUE_OR_RETURN_BINDER_STATUS(convertContainer<std::vector<AudioMixMatchCriterion>>(
+ update.newCriteria, aidl2legacy_AudioMixMatchCriterion));
+ int status;
+ if((status = mAudioPolicyManager->updatePolicyMix(mix, newCriteria)) != NO_ERROR) {
+ return binderStatusFromStatusT(status);
+ }
+ }
+ return binderStatusFromStatusT(NO_ERROR);
+}
+
Status AudioPolicyService::setUidDeviceAffinities(
int32_t uidAidl,
const std::vector<AudioDevice>& devicesAidl) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 72fa245..aa2b6f5 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -120,6 +120,7 @@
BINDER_METHOD_ENTRY(releaseSoundTriggerSession) \
BINDER_METHOD_ENTRY(getPhoneState) \
BINDER_METHOD_ENTRY(registerPolicyMixes) \
+BINDER_METHOD_ENTRY(updatePolicyMixes) \
BINDER_METHOD_ENTRY(setUidDeviceAffinities) \
BINDER_METHOD_ENTRY(removeUidDeviceAffinities) \
BINDER_METHOD_ENTRY(setUserIdDeviceAffinities) \
@@ -467,7 +468,7 @@
void AudioPolicyService::onDynamicPolicyMixStateUpdate(const String8& regId, int32_t state)
{
ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)",
- regId.string(), state);
+ regId.c_str(), state);
mOutputCommandThread->dynamicPolicyMixStateUpdateCommand(regId, state);
}
@@ -811,7 +812,7 @@
msg << std::endl;
result.append(msg.str().c_str());
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
mUidPolicy->dumpInternals(fd);
return NO_ERROR;
@@ -1205,19 +1206,19 @@
const bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result(kDeadlockedString);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
dumpInternals(fd);
String8 actPtr = String8::format("AudioCommandThread: %p\n", mAudioCommandThread.get());
- write(fd, actPtr.string(), actPtr.size());
+ write(fd, actPtr.c_str(), actPtr.size());
if (mAudioCommandThread != 0) {
mAudioCommandThread->dump(fd);
}
String8 octPtr = String8::format("OutputCommandThread: %p\n", mOutputCommandThread.get());
- write(fd, octPtr.string(), octPtr.size());
+ write(fd, octPtr.c_str(), octPtr.size());
if (mOutputCommandThread != 0) {
mOutputCommandThread->dump(fd);
}
@@ -1226,7 +1227,7 @@
mAudioPolicyManager->dump(fd);
} else {
String8 apmPtr = String8::format("AudioPolicyManager: %p\n", mAudioPolicyManager);
- write(fd, apmPtr.string(), apmPtr.size());
+ write(fd, apmPtr.c_str(), apmPtr.size());
}
mPackageManager.dump(fd);
@@ -1260,7 +1261,7 @@
IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return NO_ERROR;
}
@@ -1307,6 +1308,7 @@
case TRANSACTION_isStreamActiveRemotely:
case TRANSACTION_isSourceActive:
case TRANSACTION_registerPolicyMixes:
+ case TRANSACTION_updatePolicyMixes:
case TRANSACTION_setMasterMono:
case TRANSACTION_getSurroundFormats:
case TRANSACTION_getReportedSurroundFormats:
@@ -1439,8 +1441,8 @@
PermissionController pc;
uid = pc.getPackageUid(packageName, 0);
if (uid <= 0) {
- ALOGE("Unknown package: '%s'", String8(packageName).string());
- dprintf(err, "Unknown package: '%s'\n", String8(packageName).string());
+ ALOGE("Unknown package: '%s'", String8(packageName).c_str());
+ dprintf(err, "Unknown package: '%s'\n", String8(packageName).c_str());
return BAD_VALUE;
}
@@ -1459,7 +1461,7 @@
if (args[2] == String16("active")) {
active = true;
} else if ((args[2] != String16("idle"))) {
- ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
+ ALOGE("Expected active or idle but got: '%s'", String8(args[2]).c_str());
return BAD_VALUE;
}
@@ -1839,7 +1841,7 @@
snprintf(buffer, SIZE, "\tIs RTT Enabled: %s\n", (mRttEnabled ? "True":"False"));
result.append(buffer);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
}
// ----------- AudioPolicyService::SensorPrivacyService implementation ----------
@@ -1880,14 +1882,14 @@
AudioPolicyService::AudioCommandThread::~AudioCommandThread()
{
if (!mAudioCommands.isEmpty()) {
- release_wake_lock(mName.string());
+ release_wake_lock(mName.c_str());
}
mAudioCommands.clear();
}
void AudioPolicyService::AudioCommandThread::onFirstRef()
{
- run(mName.string(), ANDROID_PRIORITY_AUDIO);
+ run(mName.c_str(), ANDROID_PRIORITY_AUDIO);
}
bool AudioPolicyService::AudioCommandThread::threadLoop()
@@ -1924,7 +1926,7 @@
case SET_PARAMETERS: {
ParametersData *data = (ParametersData *)command->mParam.get();
ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
- data->mKeyValuePairs.string(), data->mIO);
+ data->mKeyValuePairs.c_str(), data->mIO);
mLock.unlock();
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
mLock.lock();
@@ -2033,7 +2035,7 @@
DynPolicyMixStateUpdateData *data =
(DynPolicyMixStateUpdateData *)command->mParam.get();
ALOGV("AudioCommandThread() processing dyn policy mix state update %s %d",
- data->mRegId.string(), data->mState);
+ data->mRegId.c_str(), data->mState);
svc = mService.promote();
if (svc == 0) {
break;
@@ -2158,7 +2160,7 @@
// release delayed commands wake lock as many times as we made the queue is
// empty during popping.
while (numTimesBecameEmpty--) {
- release_wake_lock(mName.string());
+ release_wake_lock(mName.c_str());
}
// At this stage we have either an empty command queue or the first command in the queue
@@ -2174,7 +2176,7 @@
}
// release delayed commands wake lock before quitting
if (!mAudioCommands.isEmpty()) {
- release_wake_lock(mName.string());
+ release_wake_lock(mName.c_str());
}
mLock.unlock();
return false;
@@ -2189,7 +2191,7 @@
const bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result2(kCmdDeadlockedString);
- write(fd, result2.string(), result2.size());
+ write(fd, result2.c_str(), result2.size());
}
snprintf(buffer, SIZE, "- Commands:\n");
@@ -2207,7 +2209,7 @@
result.append(" none\n");
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
dumpReleaseLock(mLock, locked);
@@ -2394,7 +2396,7 @@
data->mState = state;
command->mParam = data;
ALOGV("AudioCommandThread() sending dynamic policy mix (id=%s) state update to %d",
- regId.string(), state);
+ regId.c_str(), state);
sendCommand(command);
}
@@ -2491,7 +2493,7 @@
// acquire wake lock to make sure delayed commands are processed
if (mAudioCommands.isEmpty()) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.c_str());
}
// check same pending commands with later time stamps and eliminate them
@@ -2516,7 +2518,7 @@
ParametersData *data2 = (ParametersData *)command2->mParam.get();
if (data->mIO != data2->mIO) break;
ALOGV("Comparing parameter command %s to new command %s",
- data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+ data2->mKeyValuePairs.c_str(), data->mKeyValuePairs.c_str());
AudioParameter param = AudioParameter(data->mKeyValuePairs);
AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
for (size_t j = 0; j < param.size(); j++) {
@@ -2529,7 +2531,7 @@
param2.getAt(k, key2, value2);
if (key2 == key) {
param2.remove(key2);
- ALOGV("Filtering out parameter %s", key2.string());
+ ALOGV("Filtering out parameter %s", key2.c_str());
break;
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 94b48ea..ff29305 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -198,6 +198,8 @@
binder::Status getPhoneState(AudioMode* _aidl_return) override;
binder::Status registerPolicyMixes(const std::vector<media::AudioMix>& mixes,
bool registration) override;
+ binder::Status updatePolicyMixes(
+ const ::std::vector<::android::media::AudioMixUpdate>& updates) override;
binder::Status setUidDeviceAffinities(int32_t uid,
const std::vector<AudioDevice>& devices) override;
binder::Status removeUidDeviceAffinities(int32_t uid) override;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7a391b6..110e6bf 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -26,7 +26,9 @@
#define LOG_TAG "APM_Test"
#include <Serializer.h>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android/content/AttributionSourceState.h>
+#include <hardware/audio_effect.h>
#include <media/AudioPolicy.h>
#include <media/PatchBuilder.h>
#include <media/RecordingActivityTracker.h>
@@ -185,6 +187,7 @@
bool* isBitPerfect = nullptr);
void getInputForAttr(
const audio_attributes_t &attr,
+ audio_io_handle_t *input,
audio_session_t session,
audio_unique_id_t riid,
audio_port_handle_t *selectedDeviceId,
@@ -296,6 +299,7 @@
void AudioPolicyManagerTest::getInputForAttr(
const audio_attributes_t &attr,
+ audio_io_handle_t *input,
const audio_session_t session,
audio_unique_id_t riid,
audio_port_handle_t *selectedDeviceId,
@@ -304,7 +308,6 @@
int sampleRate,
audio_input_flags_t flags,
audio_port_handle_t *portId) {
- audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
config.sample_rate = sampleRate;
config.channel_mask = channelMask;
@@ -315,7 +318,7 @@
AudioPolicyInterface::input_type_t inputType;
AttributionSourceState attributionSource = createAttributionSourceState(/*uid=*/ 0);
ASSERT_EQ(OK, mManager->getInputForAttr(
- &attr, &input, riid, session, attributionSource, &config, flags,
+ &attr, input, riid, session, attributionSource, &config, flags,
selectedDeviceId, &inputType, portId));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
}
@@ -945,10 +948,13 @@
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_port_handle_t mixPortId = AUDIO_PORT_HANDLE_NONE;
audio_source_t source = AUDIO_SOURCE_VOICE_COMMUNICATION;
- audio_attributes_t attr = {
- AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000, AUDIO_INPUT_FLAG_VOIP_TX, &mixPortId));
+ audio_attributes_t attr = {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source,
+ AUDIO_FLAG_NONE, ""};
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1,
+ &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_MONO, 8000, AUDIO_INPUT_FLAG_VOIP_TX,
+ &mixPortId));
std::vector<audio_port_v7> ports;
ASSERT_NO_FATAL_FAILURE(
@@ -1708,10 +1714,11 @@
audio_attributes_t attr = {
AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
std::string tags = "addr=" + mMixAddress;
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- getInputForAttr(attr, param.session, mTracker->getRiid(), &selectedDeviceId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
- AUDIO_INPUT_FLAG_NONE, &mPortId);
+ getInputForAttr(attr, &input, param.session, mTracker->getRiid(),
+ &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &mPortId);
ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
ASSERT_EQ(extractionPort.id, selectedDeviceId);
@@ -2051,9 +2058,10 @@
audio_port_handle_t captureRoutedPortId = AUDIO_PORT_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
- getInputForAttr(param.attributes, param.session, mTracker->getRiid(), &captureRoutedPortId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
- AUDIO_INPUT_FLAG_NONE, &portId);
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ getInputForAttr(param.attributes, &input, param.session, mTracker->getRiid(),
+ &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &portId);
if (param.expected_match) {
EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
} else {
@@ -2236,9 +2244,10 @@
k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE);
} else if (audio_is_input_device(type)) {
RecordingActivityTracker tracker;
- getInputForAttr({}, AUDIO_SESSION_NONE, tracker.getRiid(), &routedPortId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
- AUDIO_INPUT_FLAG_NONE);
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ getInputForAttr({}, &input, AUDIO_SESSION_NONE, tracker.getRiid(), &routedPortId,
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate,
+ AUDIO_INPUT_FLAG_NONE);
}
ASSERT_EQ(devicePort.id, routedPortId);
@@ -2985,7 +2994,8 @@
audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
attr.source = source;
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
48000));
auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
@@ -3005,7 +3015,8 @@
mManager->setDevicesRoleForCapturePreset(source, role,
{preferredDevice->getDeviceTypeAddr()}));
selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+ input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
48000));
ASSERT_EQ(preferredDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3015,7 +3026,8 @@
ASSERT_EQ(NO_ERROR,
mManager->clearDevicesRoleForCapturePreset(source, role));
selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+ input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
48000));
ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3040,7 +3052,8 @@
audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
attr.source = source;
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
48000));
auto selectedDevice = availableDevices.getDeviceFromId(selectedDeviceId);
@@ -3052,9 +3065,10 @@
mManager->setDevicesRoleForCapturePreset(source, role,
{selectedDevice->getDeviceTypeAddr()}));
selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
- AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
- 48000));
+ input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1,
+ &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_STEREO, 48000));
ASSERT_NE(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
// After clearing disabled device for capture preset, the selected device for input should be
@@ -3062,7 +3076,8 @@
ASSERT_EQ(NO_ERROR,
mManager->clearDevicesRoleForCapturePreset(source, role));
selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
+ input = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &input, AUDIO_SESSION_NONE, 1, &selectedDeviceId,
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
48000));
ASSERT_EQ(selectedDevice, availableDevices.getDeviceFromId(selectedDeviceId));
@@ -3098,3 +3113,77 @@
DevicesRoleForCapturePresetParam({AUDIO_SOURCE_HOTWORD, DEVICE_ROLE_PREFERRED})
)
);
+
+
+const effect_descriptor_t TEST_EFFECT_DESC = {
+ {0xf2a4bb20, 0x0c3c, 0x11e3, 0x8b07, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xff93e360, 0x0c3c, 0x11e3, 0x8a97, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_PRE_PROC,
+ 0,
+ 1,
+ "APM test Effect",
+ "The Android Open Source Project",
+};
+
+class AudioPolicyManagerPreProcEffectTest : public AudioPolicyManagerTestWithConfigurationFile {
+};
+
+TEST_F(AudioPolicyManagerPreProcEffectTest, DeviceDisconnectWhileClientActive) {
+ const audio_source_t source = AUDIO_SOURCE_MIC;
+ const std::string address = "BUS00_MIC";
+ const std::string deviceName = "randomName";
+ audio_port_handle_t portId;
+ audio_devices_t type = AUDIO_DEVICE_IN_BUS;
+
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(type,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE, address.c_str(), deviceName.c_str(),
+ AUDIO_FORMAT_DEFAULT));
+ auto availableDevices = mManager->getAvailableInputDevices();
+ ASSERT_GT(availableDevices.size(), 1);
+
+ audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+ attr.source = source;
+ audio_session_t session = TEST_SESSION_ID;
+ audio_io_handle_t inputClientHandle = 777;
+ int effectId = 666;
+ audio_port_v7 devicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, type, address, &devicePort));
+
+ audio_port_handle_t routedPortId = devicePort.id;
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &inputClientHandle, session, 1, &routedPortId,
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ 48000, AUDIO_INPUT_FLAG_NONE, &portId));
+ ASSERT_EQ(devicePort.id, routedPortId);
+ auto selectedDevice = availableDevices.getDeviceFromId(routedPortId);
+ ASSERT_NE(nullptr, selectedDevice);
+
+ // Add a pre processing effect on the input client session
+ ASSERT_EQ(NO_ERROR, mManager->registerEffect(&TEST_EFFECT_DESC, inputClientHandle,
+ PRODUCT_STRATEGY_NONE, session, effectId));
+
+ ASSERT_EQ(NO_ERROR, mManager->startInput(portId));
+
+ // Force a device disconnection to close the input, no crash expected of APM
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
+
+ // Reconnect the device
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ type, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.c_str(), deviceName.c_str(), AUDIO_FORMAT_DEFAULT));
+
+ inputClientHandle += 1;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, type, address, &devicePort));
+ routedPortId = devicePort.id;
+
+ // Reconnect the client changing voluntarily the io, but keeping the session to get the
+ // effect attached again
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, &inputClientHandle, session, 1, &routedPortId,
+ AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+ 48000));
+
+ // unregister effect should succeed since effect shall have been restore on the client session
+ ASSERT_EQ(NO_ERROR, mManager->unregisterEffect(effectId));
+}
\ No newline at end of file
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 7ab9519..9e092c6 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -60,6 +60,11 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <mixPort name="mixport_bus_input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
@@ -84,6 +89,8 @@
</devicePort>
<devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source">
</devicePort>
+ <devicePort tagName="BUS Device In" type="AUDIO_DEVICE_IN_BUS" role="source" address="BUS00_MIC">
+ </devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Speaker"
@@ -102,6 +109,8 @@
sources="primary output,hifi_output"/>
<route type="mix" sink="USB Device Out"
sources="primary output,hifi_output,mmap_no_irq_out"/>
+ <route type="mix" sink="mixport_bus_input"
+ sources="BUS Device In"/>
</routes>
</module>
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 84dcf26..ea467e7 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -85,6 +85,7 @@
"android.hardware.common.fmq-V1-ndk",
"android.hardware.graphics.common-V4-ndk",
"media_permission-aidl-cpp",
+ "server_configurable_flags",
],
static_libs: [
@@ -105,12 +106,13 @@
"android.hardware.camera.provider@2.6",
"android.hardware.camera.provider@2.7",
"android.hardware.camera.provider-V2-ndk",
+ "camera_platform_flags_c_lib",
"libaidlcommonsupport",
+ "libbinderthreadstateutils",
+ "libcameraservice_device_independent",
"libdynamic_depth",
"libprocessinfoservice_aidl",
- "libbinderthreadstateutils",
"media_permission-aidl-cpp",
- "libcameraservice_device_independent",
],
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index ed321b6..c0194b9 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1388,7 +1388,7 @@
/*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true,
/*forceSlowJpegMode*/false, cameraIdStr, /*out*/ tmp)
).isOk()) {
- ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
+ ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().c_str());
}
return ret;
}
diff --git a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
index 402f8a2..954cb8b 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraDeviceUser.cpp
@@ -119,7 +119,7 @@
in_isRepeating, &submitInfo);
if (!ret.isOk()) {
ALOGE("%s: Failed submitRequestList to cameraservice: %s",
- __FUNCTION__, ret.toString8().string());
+ __FUNCTION__, ret.toString8().c_str());
return fromUStatus(ret);
}
mRequestId = submitInfo.mRequestId;
@@ -158,7 +158,7 @@
int32_t newStreamId;
UStatus ret = mDeviceRemote->createStream(outputConfig, &newStreamId);
if (!ret.isOk()) {
- ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().string());
+ ALOGE("%s: Failed to create stream: %s", __FUNCTION__, ret.toString8().c_str());
}
*_aidl_return = newStreamId;
return fromUStatus(ret);
@@ -170,7 +170,7 @@
UStatus ret = mDeviceRemote->createDefaultRequest(convertFromAidl(in_templateId),
&metadata);
if (!ret.isOk()) {
- ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().string());
+ ALOGE("%s: Failed to create default request: %s", __FUNCTION__, ret.toString8().c_str());
return fromUStatus(ret);
}
@@ -202,7 +202,7 @@
UStatus ret = mDeviceRemote->updateOutputConfiguration(in_streamId, outputConfig);
if (!ret.isOk()) {
ALOGE("%s: Failed to update output config for stream id: %d: %s",
- __FUNCTION__, in_streamId, ret.toString8().string());
+ __FUNCTION__, in_streamId, ret.toString8().c_str());
}
return fromUStatus(ret);
}
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index a62f6de..8cd7d1f 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -103,7 +103,7 @@
return fromSStatus(SStatus::ILLEGAL_ARGUMENT);
default:
ALOGE("Get camera characteristics from camera service failed: %s",
- ret.toString8().string());
+ ret.toString8().c_str());
return fromUStatus(ret);
}
}
@@ -313,7 +313,7 @@
}
vendorTagSections.resize(numSections);
for (size_t s = 0; s < numSections; s++) {
- vendorTagSections[s].sectionName = (*sectionNames)[s].string();
+ vendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
vendorTagSections[s].tags = tagsBySection[s];
}
SProviderIdAndVendorTagSections & prvdrIdAndVendorTagSection =
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 87a4420..b217476 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -188,7 +188,7 @@
SharedParameters::Lock l(mParameters);
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
- ALOGD("%s", l.mParameters.paramsFlattened.string());
+ ALOGD("%s", l.mParameters.paramsFlattened.c_str());
}
return OK;
@@ -247,7 +247,7 @@
result << fmt::sprintf(" GPS timestamp: %" PRId64 "\n",
p.gpsTimestamp);
result << fmt::sprintf(" GPS processing method: %s\n",
- p.gpsProcessingMethod.string());
+ p.gpsProcessingMethod.c_str());
}
result << " White balance mode: ";
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 13dcbaa..aa3d1bb 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -164,7 +164,7 @@
availablePreviewSizes[i].width,
availablePreviewSizes[i].height);
}
- ALOGV("Supported preview sizes are: %s", supportedPreviewSizes.string());
+ ALOGV("Supported preview sizes are: %s", supportedPreviewSizes.c_str());
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
supportedPreviewSizes);
@@ -175,7 +175,7 @@
availableVideoSizes[i].width,
availableVideoSizes[i].height);
}
- ALOGV("Supported video sizes are: %s", supportedVideoSizes.string());
+ ALOGV("Supported video sizes are: %s", supportedVideoSizes.c_str());
params.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
supportedVideoSizes);
}
@@ -315,7 +315,7 @@
fps);
ALOGV("%s: Supported preview frame rates: %s",
- __FUNCTION__, supportedPreviewFrameRates.string());
+ __FUNCTION__, supportedPreviewFrameRates.c_str());
}
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
supportedPreviewFrameRates);
@@ -2832,7 +2832,7 @@
String8 areasStr(areasCStr);
ssize_t areaStart = areasStr.find("(", 0) + 1;
while (areaStart != 0) {
- const char* area = areasStr.string() + areaStart;
+ const char* area = areasStr.c_str() + areaStart;
char *numEnd;
int vals[NUM_FIELDS];
for (size_t i = 0; i < NUM_FIELDS; i++) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 597b9aa..456d1be 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -3032,6 +3032,7 @@
mDoPause(false),
mPaused(true),
mNotifyPipelineDrain(false),
+ mPrevTriggers(0),
mFrameNumber(0),
mLatestRequestId(NAME_NOT_FOUND),
mLatestFailedRequestId(NAME_NOT_FOUND),
@@ -3041,7 +3042,6 @@
mAutoframingOverride(ANDROID_CONTROL_AUTOFRAMING_OFF),
mComposerOutput(false),
mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
- mCameraMuteChanged(false),
mSettingsOverride(ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF),
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
@@ -4239,7 +4239,6 @@
Mutex::Autolock l(mTriggerMutex);
if (muteMode != mCameraMute) {
mCameraMute = muteMode;
- mCameraMuteChanged = true;
}
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index a1e25fd..0229446 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1157,7 +1157,6 @@
camera_metadata_enum_android_control_autoframing_t mAutoframingOverride;
bool mComposerOutput;
int32_t mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
- bool mCameraMuteChanged;
int32_t mSettingsOverride; // -1 = use original, otherwise
// the settings override to use.
diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp
index ea1f2c1..bd78e0a 100644
--- a/services/camera/libcameraservice/device3/StatusTracker.cpp
+++ b/services/camera/libcameraservice/device3/StatusTracker.cpp
@@ -172,6 +172,7 @@
}
}
+ bool waitForIdleFence = false;
// After new pending states appear, or timeout, check if we're idle. Even
// with timeout, need to check to account for fences that may still be
// clearing out
@@ -196,6 +197,7 @@
ssize_t idx = mStates.indexOfKey(newState.id);
// Ignore notices for unknown components
if (idx >= 0) {
+ bool validFence = newState.fence != Fence::NO_FENCE;
// Update single component state
mStates.replaceValueAt(idx, newState.state);
mIdleFence = Fence::merge(String8("idleFence"),
@@ -204,6 +206,8 @@
ComponentState newState = getDeviceStateLocked();
if (newState != prevState) {
mStateTransitions.add(newState);
+ } else if (validFence && !waitForIdleFence) {
+ waitForIdleFence = true;
}
prevState = newState;
}
@@ -227,6 +231,13 @@
}
mStateTransitions.clear();
+ if (waitForIdleFence) {
+ auto ret = mIdleFence->wait(kWaitDuration);
+ if (ret == NO_ERROR) {
+ mComponentsChanged = true;
+ }
+ }
+
return true;
}
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index cd4a92c..5dbfb36 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -25,11 +25,11 @@
#include <gui/RingBufferConsumer.h>
#include <camera/StringUtils.h>
-#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
+#define BI_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
#undef assert
#define assert(x) ALOG_ASSERT((x), #x)
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 4f12933..94bf653 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -78,7 +78,7 @@
break;
default:
ALOGE("Get camera characteristics from camera service failed: %s",
- serviceRet.toString8().string());
+ serviceRet.toString8().c_str());
status = B2HStatus(serviceRet);
}
_hidl_cb(status, hidlMetadata);
@@ -307,7 +307,7 @@
}
hVendorTagSections.resize(numSections);
for (size_t s = 0; s < numSections; s++) {
- hVendorTagSections[s].sectionName = (*sectionNames)[s].string();
+ hVendorTagSections[s].sectionName = (*sectionNames)[s].c_str();
hVendorTagSections[s].tags = tagsBySection[s];
}
HProviderIdAndVendorTagSections &hProviderIdAndVendorTagSections =
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 902af66..abe5f16 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -107,7 +107,7 @@
if (args.size() > 0) {
const String8 arg0(args[0]);
- if (!strcmp(arg0.string(), "-r")) {
+ if (!strcmp(arg0.c_str(), "-r")) {
// needed because mReaders is protected by mLock
bool locked = dumpTryLock(mLock);
@@ -115,9 +115,9 @@
if (!locked) {
String8 result(kDeadlockedString);
if (fd >= 0) {
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
} else {
- ALOGW("%s:", result.string());
+ ALOGW("%s:", result.c_str());
}
return NO_ERROR;
}
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index af1372b..f81db53 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -278,14 +278,14 @@
} else if (args[i] == prefixOption) {
++i;
if (i < n) {
- prefix = String8(args[i]).string();
+ prefix = String8(args[i]).c_str();
}
} else if (args[i] == sinceOption) {
++i;
if (i < n) {
String8 value(args[i]);
char *endp;
- const char *p = value.string();
+ const char *p = value.c_str();
const auto sec = (int64_t)strtoll(p, &endp, 10);
if (endp == p || *endp != '\0' || sec == 0) {
sinceNs = 0;
@@ -524,8 +524,8 @@
"audiotrack",
// other media
"codec",
- "freeze",
- "judder",
+ "videofreeze",
+ "videojudder",
"extractor",
"mediadrm",
"mediaparser",
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index ea76bcd..5e3e654 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -187,10 +187,12 @@
const nsecs_t timestampNanos = MediaMetricsService::roundTime(item->getTimestamp());
AStatsEvent_writeInt64(event, timestampNanos);
- std::string packageName = item->getPkgName();
+ // packageName deprecated for calling_uid and statsd support as of U-QPR2
+ std::string packageName = "";
AStatsEvent_writeString(event, packageName.c_str());
- int64_t packageVersionCode = item->getPkgVersionCode();
+ // packageVersion depreccated for calling_uid and statsd support as of U-QPR2
+ int64_t packageVersionCode = 0;
AStatsEvent_writeInt64(event, packageVersionCode);
int64_t mediaApexVersion = 0;
@@ -654,6 +656,10 @@
}
AStatsEvent_writeInt32(event, componentColorFormat);
+ uid_t app_uid = item->getUid();
+ metrics_proto.set_caller_uid(app_uid);
+ AStatsEvent_writeInt32(event, app_uid);
+
int64_t firstRenderTimeUs = -1;
item->getInt64("android.media.mediacodec.first-render-time-us", &firstRenderTimeUs);
int64_t framesReleased = -1;
@@ -854,6 +860,7 @@
<< " original_qp_p_max:" << qpPMaxOri
<< " original_qp_b_min:" << qpBMinOri
<< " original_qp_b_max:" << qpBMaxOri
+ << " app_uid:" << app_uid
<< " }";
statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index dbde27c..5d1ba2b 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -164,7 +164,7 @@
static String8 getString(const std::vector<T>& items) {
String8 itemsStr;
for (size_t i = 0; i < items.size(); ++i) {
- itemsStr.appendFormat("%s ", toString(items[i]).string());
+ itemsStr.appendFormat("%s ", toString(items[i]).c_str());
}
return itemsStr;
}
@@ -272,7 +272,7 @@
"can't dump ResourceManagerService from pid=%d, uid=%d\n",
AIBinder_getCallingPid(),
AIBinder_getCallingUid());
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return PERMISSION_DENIED;
}
@@ -325,7 +325,7 @@
const ResourceList& resources = info.resources;
result.append(" Resources:\n");
for (auto it = resources.begin(); it != resources.end(); it++) {
- snprintf(buffer, SIZE, " %s\n", toString(it->second).string());
+ snprintf(buffer, SIZE, " %s\n", toString(it->second).c_str());
result.append(buffer);
}
}
@@ -339,7 +339,7 @@
result.append(" Events logs (most recent at top):\n");
result.append(serviceLog);
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return OK;
}
@@ -417,7 +417,7 @@
}
Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
- String8 log = String8::format("config(%s)", getString(policies).string());
+ String8 log = String8::format("config(%s)", getString(policies).c_str());
mServiceLog->add(log);
std::scoped_lock lock{mLock};
@@ -490,7 +490,7 @@
int64_t clientId = clientInfo.id;
const std::string& name = clientInfo.name;
String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
- pid, uid, (long long) clientId, getString(resources).string());
+ pid, uid, (long long) clientId, getString(resources).c_str());
mServiceLog->add(log);
std::scoped_lock lock{mLock};
@@ -552,7 +552,7 @@
int32_t uid = clientInfo.uid;
int64_t clientId = clientInfo.id;
String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
- pid, uid, (long long) clientId, getString(resources).string());
+ pid, uid, (long long) clientId, getString(resources).c_str());
mServiceLog->add(log);
std::scoped_lock lock{mLock};
@@ -679,7 +679,7 @@
int32_t callingPid = clientInfo.pid;
std::string clientName = clientInfo.name;
String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
- callingPid, clientInfo.uid, getString(resources).string());
+ callingPid, clientInfo.uid, getString(resources).c_str());
mServiceLog->add(log);
*_aidl_return = false;
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index ebe3903..6c5cecf 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -122,7 +122,7 @@
"can't dump ResourceManagerService from pid=%d, uid=%d\n",
AIBinder_getCallingPid(),
AIBinder_getCallingUid());
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return PERMISSION_DENIED;
}
@@ -138,7 +138,7 @@
String8 enabledEventsStr;
for (auto &event : sEvents) {
if (((uint64_t)observable.eventFilter & (uint64_t)event) != 0) {
- if (!enabledEventsStr.isEmpty()) {
+ if (!enabledEventsStr.empty()) {
enabledEventsStr.append("|");
}
enabledEventsStr.append(toString(event).c_str());
@@ -150,7 +150,7 @@
}
}
- write(fd, result.string(), result.size());
+ write(fd, result.c_str(), result.size());
return OK;
}
diff --git a/services/mediaresourcemanager/ServiceLog.cpp b/services/mediaresourcemanager/ServiceLog.cpp
index 791e797..132ed33 100644
--- a/services/mediaresourcemanager/ServiceLog.cpp
+++ b/services/mediaresourcemanager/ServiceLog.cpp
@@ -35,14 +35,14 @@
time_t now = time(0);
char buf[64];
strftime(buf, sizeof(buf), "%m-%d %T", localtime(&now));
- mLogs.add(String8::format("%s %s", buf, log.string()));
+ mLogs.add(String8::format("%s %s", buf, log.c_str()));
}
String8 ServiceLog::toString(const char *linePrefix) const {
Mutex::Autolock lock(mLock);
String8 result;
for (const auto& log : mLogs) {
- addLine(log.string(), linePrefix, &result);
+ addLine(log.c_str(), linePrefix, &result);
}
if (mLogs.size() == mMaxNum) {
addLine("...", linePrefix, &result);
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index f38a085..bbbc737 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -49,6 +49,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libresourcemanagerservice",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/services/mediaresourcemanager/test/ServiceLog_test.cpp b/services/mediaresourcemanager/test/ServiceLog_test.cpp
index 9172499..8556f2a 100644
--- a/services/mediaresourcemanager/test/ServiceLog_test.cpp
+++ b/services/mediaresourcemanager/test/ServiceLog_test.cpp
@@ -39,26 +39,26 @@
mServiceLog->add(String8("log1"));
logString = mServiceLog->toString();
EXPECT_TRUE(logString.contains("log1"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
static const char kTestLogPrefix[] = "testlogprefix: ";
logString = mServiceLog->toString(kTestLogPrefix);
EXPECT_TRUE(logString.contains(kTestLogPrefix));
EXPECT_TRUE(logString.contains("log1"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
mServiceLog->add(String8("log2"));
logString = mServiceLog->toString();
EXPECT_TRUE(logString.contains("log1"));
EXPECT_TRUE(logString.contains("log2"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
mServiceLog->add(String8("log3"));
logString = mServiceLog->toString();
EXPECT_TRUE(logString.contains("log1"));
EXPECT_TRUE(logString.contains("log2"));
EXPECT_TRUE(logString.contains("log3"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
mServiceLog->add(String8("log4"));
logString = mServiceLog->toString();
@@ -66,7 +66,7 @@
EXPECT_TRUE(logString.contains("log2"));
EXPECT_TRUE(logString.contains("log3"));
EXPECT_TRUE(logString.contains("log4"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
mServiceLog->add(String8("log5"));
logString = mServiceLog->toString();
@@ -75,7 +75,7 @@
EXPECT_TRUE(logString.contains("log3"));
EXPECT_TRUE(logString.contains("log4"));
EXPECT_TRUE(logString.contains("log5"));
- ALOGV("toString:\n%s", logString.string());
+ ALOGV("toString:\n%s", logString.c_str());
}
} // namespace android