Merge "Update version number to 220000000" into qt-dev
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index 4bcc2c6..df4dadb 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -78,6 +78,26 @@
.withSetter(ProfileLevelSetter, mSize)
.build());
+ mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
+ addParameter(
+ DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
+ .withDefault(mHdr10PlusInfoInput)
+ .withFields({
+ C2F(mHdr10PlusInfoInput, m.value).any(),
+ })
+ .withSetter(Hdr10PlusInfoInputSetter)
+ .build());
+
+ mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
+ addParameter(
+ DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
+ .withDefault(mHdr10PlusInfoOutput)
+ .withFields({
+ C2F(mHdr10PlusInfoOutput, m.value).any(),
+ })
+ .withSetter(Hdr10PlusInfoOutputSetter)
+ .build());
+
addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
.withDefault(new C2StreamMaxPictureSizeTuning::output(
0u, 320, 240))
@@ -203,6 +223,18 @@
return mDefaultColorAspects;
}
+ static C2R Hdr10PlusInfoInputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::input> &me) {
+ (void)mayBlock;
+ (void)me; // TODO: validate
+ return C2R::Ok();
+ }
+
+ static C2R Hdr10PlusInfoOutputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::output> &me) {
+ (void)mayBlock;
+ (void)me; // TODO: validate
+ return C2R::Ok();
+ }
+
private:
std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
@@ -211,6 +243,8 @@
std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+ std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
+ std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
};
C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
@@ -341,7 +375,8 @@
const std::shared_ptr<C2GraphicBlock>& block) {
std::shared_ptr<C2Buffer> buffer =
createGraphicBuffer(block, C2Rect(mWidth, mHeight));
- auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {
+ auto fillWork = [buffer, index, intf = this->mIntf](
+ const std::unique_ptr<C2Work>& work) {
uint32_t flags = 0;
if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
(c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
@@ -353,6 +388,28 @@
work->worklets.front()->output.buffers.push_back(buffer);
work->worklets.front()->output.ordinal = work->input.ordinal;
work->workletsProcessed = 1u;
+
+ for (const std::unique_ptr<C2Param> ¶m: work->input.configUpdate) {
+ if (param) {
+ C2StreamHdr10PlusInfo::input *hdr10PlusInfo =
+ C2StreamHdr10PlusInfo::input::From(param.get());
+
+ if (hdr10PlusInfo != nullptr) {
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ std::unique_ptr<C2Param> outParam = C2Param::CopyAsStream(
+ *param.get(), true /*output*/, param->stream());
+ c2_status_t err = intf->config(
+ { outParam.get() }, C2_MAY_BLOCK, &failures);
+ if (err == C2_OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(*outParam.get()));
+ } else {
+ ALOGE("finishWork: Config update size failed");
+ }
+ break;
+ }
+ }
+ }
};
if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
fillWork(work);
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 9290d74..063c537 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -812,19 +812,19 @@
ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
s_decode_op.u4_num_bytes_consumed);
}
- if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & 0xFF)) {
+ if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGE("allocation failure in decoder");
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & 0xFF)) {
+ } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & 0xFF)) {
+ } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGV("resolution changed");
drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
resetDecoder();
@@ -834,6 +834,12 @@
/* Decode header and get new dimensions */
setParams(mStride, IVD_DECODE_HEADER);
(void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
+ } else if (IS_IVD_FATAL_ERROR(s_decode_op.u4_error_code)) {
+ ALOGE("Fatal error in decoder 0x%x", s_decode_op.u4_error_code);
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
}
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index aa3ca61..58a86d8 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -38,7 +38,7 @@
#define DEFAULT_MAX_REORDER_FRM 0
#define DEFAULT_QP_MIN 10
#define DEFAULT_QP_MAX 40
-#define DEFAULT_MAX_BITRATE 20000000
+#define DEFAULT_MAX_BITRATE 240000000
#define DEFAULT_MAX_SRCH_RANGE_X 256
#define DEFAULT_MAX_SRCH_RANGE_Y 256
#define DEFAULT_MAX_FRAMERATE 120000
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index bb8dda0..5da59bd 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -806,19 +806,20 @@
TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
s_decode_op.u4_num_bytes_consumed);
- if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & 0xFF)) {
+ if (IVD_MEM_ALLOC_FAILED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGE("allocation failure in decoder");
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_decode_op.u4_error_code & 0xFF)) {
+ } else if (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED ==
+ (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGE("unsupported resolution : %dx%d", mWidth, mHeight);
mSignalledError = true;
work->workletsProcessed = 1u;
work->result = C2_CORRUPTED;
return;
- } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & 0xFF)) {
+ } else if (IVD_RES_CHANGED == (s_decode_op.u4_error_code & IVD_ERROR_MASK)) {
ALOGV("resolution changed");
drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
resetDecoder();
@@ -828,6 +829,12 @@
/* Decode header and get new dimensions */
setParams(mStride, IVD_DECODE_HEADER);
(void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
+ } else if (IS_IVD_FATAL_ERROR(s_decode_op.u4_error_code)) {
+ ALOGE("Fatal error in decoder 0x%x", s_decode_op.u4_error_code);
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
}
if (0 < s_decode_op.u4_pic_wd && 0 < s_decode_op.u4_pic_ht) {
if (mHeaderDecoded == false) {
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index a0b2443..f1020c3 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -194,12 +194,12 @@
return C2_BAD_VALUE;
}
- // Unconstrained VBR
- if (opus_multistream_encoder_ctl(mEncoder, OPUS_SET_VBR(0) != OPUS_OK)) {
+ // Constrained VBR
+ if (opus_multistream_encoder_ctl(mEncoder, OPUS_SET_VBR(1) != OPUS_OK)) {
ALOGE("failed to set vbr type");
return C2_BAD_VALUE;
}
- if (opus_multistream_encoder_ctl(mEncoder, OPUS_SET_VBR_CONSTRAINT(0) !=
+ if (opus_multistream_encoder_ctl(mEncoder, OPUS_SET_VBR_CONSTRAINT(1) !=
OPUS_OK)) {
ALOGE("failed to set vbr constraint");
return C2_BAD_VALUE;
diff --git a/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurface.h b/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurface.h
index b011a06..0a82a68 100644
--- a/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurface.h
+++ b/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurface.h
@@ -20,7 +20,6 @@
#include <memory>
#include <C2Component.h>
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
#include <media/stagefright/codec2/1.0/InputSurfaceConnection.h>
namespace android {
diff --git a/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h b/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h
index b24a416..5eae3af 100644
--- a/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h
+++ b/media/codec2/core/include/media/stagefright/codec2/1.0/InputSurfaceConnection.h
@@ -21,7 +21,6 @@
#include <C2Component.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
#include <media/stagefright/codec2/1.0/InputSurfaceConnection.h>
namespace android {
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index d6f84b4..1e0a190 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -23,7 +23,6 @@
#include <codec2/hidl/1.0/types.h>
#include <android-base/file.h>
-#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
#include <utils/Errors.h>
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
index 34ea959..29ed7ff 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/InputSurface.h
@@ -22,7 +22,6 @@
#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 <gui/IGraphicBufferProducer.h>
#include <hidl/Status.h>
#include <media/stagefright/bqhelper/GraphicBufferSource.h>
diff --git a/media/codec2/sfplugin/utils/Codec2Mapper.cpp b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
index d62944a..40160c7 100644
--- a/media/codec2/sfplugin/utils/Codec2Mapper.cpp
+++ b/media/codec2/sfplugin/utils/Codec2Mapper.cpp
@@ -379,11 +379,19 @@
ALookup<C2Config::profile_t, int32_t> sAv1Profiles = {
- { C2Config::PROFILE_AV1_0, AV1Profile0 },
- { C2Config::PROFILE_AV1_1, AV1Profile1 },
- { C2Config::PROFILE_AV1_2, AV1Profile2 },
+ // TODO: will need to disambiguate between Main8 and Main10
+ { C2Config::PROFILE_AV1_0, AV1ProfileMain8 },
+ { C2Config::PROFILE_AV1_0, AV1ProfileMain10 },
};
+ALookup<C2Config::profile_t, int32_t> sAv1HdrProfiles = {
+ { C2Config::PROFILE_AV1_0, AV1ProfileMain10 },
+ { C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10 },
+};
+
+ALookup<C2Config::profile_t, int32_t> sAv1Hdr10PlusProfiles = {
+ { C2Config::PROFILE_AV1_0, AV1ProfileMain10HDR10Plus },
+};
/**
* A helper that passes through vendor extension profile and level values.
@@ -590,6 +598,10 @@
};
struct Av1ProfileLevelMapper : ProfileLevelMapperHelper {
+ Av1ProfileLevelMapper(bool isHdr = false, bool isHdr10Plus = false) :
+ ProfileLevelMapperHelper(),
+ mIsHdr(isHdr), mIsHdr10Plus(isHdr10Plus) {}
+
virtual bool simpleMap(C2Config::level_t from, int32_t *to) {
return sAv1Levels.map(from, to);
}
@@ -597,11 +609,19 @@
return sAv1Levels.map(from, to);
}
virtual bool simpleMap(C2Config::profile_t from, int32_t *to) {
- return sAv1Profiles.map(from, to);
+ return mIsHdr10Plus ? sAv1Hdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sAv1HdrProfiles.map(from, to) :
+ sAv1Profiles.map(from, to);
}
virtual bool simpleMap(int32_t from, C2Config::profile_t *to) {
- return sAv1Profiles.map(from, to);
+ return mIsHdr10Plus ? sAv1Hdr10PlusProfiles.map(from, to) :
+ mIsHdr ? sAv1HdrProfiles.map(from, to) :
+ sAv1Profiles.map(from, to);
}
+
+private:
+ bool mIsHdr;
+ bool mIsHdr10Plus;
};
} // namespace
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 10c4dcc..f5dc838 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -26,6 +26,7 @@
#include <C2Config.h>
#include <C2PlatformStorePluginLoader.h>
#include <C2PlatformSupport.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <util/C2InterfaceHelper.h>
#include <dlfcn.h>
@@ -661,31 +662,37 @@
ALOGV("in %s", __func__);
ALOGV("loading dll");
mLibHandle = dlopen(libPath.c_str(), RTLD_NOW|RTLD_NODELETE);
- LOG_ALWAYS_FATAL_IF(mLibHandle == nullptr,
- "could not dlopen %s: %s", libPath.c_str(), dlerror());
+ if (mLibHandle == nullptr) {
+ LOG_ALWAYS_FATAL_IN_CHILD_PROC("could not dlopen %s: %s", libPath.c_str(), dlerror());
+ mInit = C2_CORRUPTED;
+ return mInit;
+ }
createFactory =
(C2ComponentFactory::CreateCodec2FactoryFunc)dlsym(mLibHandle, "CreateCodec2Factory");
- LOG_ALWAYS_FATAL_IF(createFactory == nullptr,
- "createFactory is null in %s", libPath.c_str());
+ if (createFactory == nullptr) {
+ LOG_ALWAYS_FATAL_IN_CHILD_PROC("createFactory is null in %s", libPath.c_str());
+ mInit = C2_CORRUPTED;
+ return mInit;
+ }
destroyFactory =
(C2ComponentFactory::DestroyCodec2FactoryFunc)dlsym(mLibHandle, "DestroyCodec2Factory");
- LOG_ALWAYS_FATAL_IF(destroyFactory == nullptr,
- "destroyFactory is null in %s", libPath.c_str());
+ if (destroyFactory == nullptr) {
+ LOG_ALWAYS_FATAL_IN_CHILD_PROC("destroyFactory is null in %s", libPath.c_str());
+ mInit = C2_CORRUPTED;
+ return mInit;
+ }
mComponentFactory = createFactory();
if (mComponentFactory == nullptr) {
ALOGD("could not create factory in %s", libPath.c_str());
mInit = C2_NO_MEMORY;
- } else {
- mInit = C2_OK;
- }
-
- if (mInit != C2_OK) {
return mInit;
}
+ mInit = C2_OK;
+
std::shared_ptr<C2ComponentInterface> intf;
c2_status_t res = createInterface(0, &intf);
if (res != C2_OK) {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 5a31c58..e1bfb62 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -338,13 +338,16 @@
return MEDIA_MIMETYPE_VIDEO_HEVC;
case FOURCC("ac-4"):
return MEDIA_MIMETYPE_AUDIO_AC4;
+ case FOURCC("Opus"):
+ return MEDIA_MIMETYPE_AUDIO_OPUS;
case FOURCC("twos"):
case FOURCC("sowt"):
return MEDIA_MIMETYPE_AUDIO_RAW;
case FOURCC("alac"):
return MEDIA_MIMETYPE_AUDIO_ALAC;
-
+ case FOURCC("fLaC"):
+ return MEDIA_MIMETYPE_AUDIO_FLAC;
case FOURCC("av01"):
return MEDIA_MIMETYPE_VIDEO_AV1;
case FOURCC(".mp3"):
@@ -1640,9 +1643,11 @@
case FOURCC("enca"):
case FOURCC("samr"):
case FOURCC("sawb"):
+ case FOURCC("Opus"):
case FOURCC("twos"):
case FOURCC("sowt"):
case FOURCC("alac"):
+ case FOURCC("fLaC"):
case FOURCC(".mp3"):
case 0x6D730055: // "ms U" mp3 audio
{
@@ -1729,6 +1734,47 @@
AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, num_channels);
AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
+ if (chunk_type == FOURCC("Opus")) {
+ uint8_t opusInfo[19];
+ data_offset += sizeof(buffer);
+ // Read Opus Header
+ if (mDataSource->readAt(
+ data_offset, opusInfo, sizeof(opusInfo)) < (ssize_t)sizeof(opusInfo)) {
+ return ERROR_IO;
+ }
+
+ // OpusHeader must start with this magic sequence
+ // http://wiki.xiph.org/OggOpus#ID_Header
+ strncpy((char *)opusInfo, "OpusHead", 8);
+
+ // Read Opus Specific Box values
+ size_t opusOffset = 10;
+ uint16_t pre_skip = U16_AT(&opusInfo[opusOffset]);
+ uint32_t sample_rate = U32_AT(&opusInfo[opusOffset + 2]);
+ uint16_t out_gain = U16_AT(&opusInfo[opusOffset + 6]);
+
+ // Convert Opus Specific Box values. ParseOpusHeader expects
+ // the values in LE, however MP4 stores these values as BE
+ // https://opus-codec.org/docs/opus_in_isobmff.html#4.3.2
+ memcpy(&opusInfo[opusOffset], &pre_skip, sizeof(pre_skip));
+ memcpy(&opusInfo[opusOffset + 2], &sample_rate, sizeof(sample_rate));
+ memcpy(&opusInfo[opusOffset + 6], &out_gain, sizeof(out_gain));
+
+ int64_t codecDelay = 6500000;
+ int64_t seekPreRollNs = 80000000; // Fixed 80 msec
+
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo));
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
+ AMediaFormat_setBuffer(mLastTrack->meta,
+ AMEDIAFORMAT_KEY_CSD_2, &seekPreRollNs, sizeof(seekPreRollNs));
+
+ data_offset += sizeof(opusInfo);
+ *offset = data_offset;
+ CHECK_EQ(*offset, stop_offset);
+ }
+
if (chunk_type == FOURCC("alac")) {
// See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
@@ -1766,6 +1812,29 @@
CHECK_EQ(*offset, stop_offset);
}
+ if (chunk_type == FOURCC("fLaC")) {
+
+ // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt
+ // 4 for mime, 4 for blockType and BlockLen, 34 for metadata
+ uint8_t flacInfo[4 + 4 + 34];
+ // skipping dFla, version
+ data_offset += sizeof(buffer) + 12;
+ size_t flacOffset = 4;
+ // Add flaC header mime type to CSD
+ strncpy((char *)flacInfo, "fLaC", 4);
+ if (mDataSource->readAt(
+ data_offset, flacInfo + flacOffset, sizeof(flacInfo) - flacOffset) <
+ (ssize_t)sizeof(flacInfo) - flacOffset) {
+ return ERROR_IO;
+ }
+ data_offset += sizeof(flacInfo) - flacOffset;
+
+ AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo,
+ sizeof(flacInfo));
+ *offset = data_offset;
+ CHECK_EQ(*offset, stop_offset);
+ }
+
while (*offset < stop_offset) {
status_t err = parseChunk(offset, depth + 1);
if (err != OK) {
diff --git a/media/libaaudio/src/binding/IAAudioService.cpp b/media/libaaudio/src/binding/IAAudioService.cpp
index 9b32543..97ad2b0 100644
--- a/media/libaaudio/src/binding/IAAudioService.cpp
+++ b/media/libaaudio/src/binding/IAAudioService.cpp
@@ -251,8 +251,15 @@
CHECK_INTERFACE(IAAudioService, data, reply);
sp<IAAudioClient> client = interface_cast<IAAudioClient>(
data.readStrongBinder());
- registerClient(client);
- return NO_ERROR;
+ // readStrongBinder() can return null
+ if (client.get() == nullptr) {
+ ALOGE("BnAAudioService::%s(REGISTER_CLIENT) client is NULL!", __func__);
+ android_errorWriteLog(0x534e4554, "116230453");
+ return DEAD_OBJECT;
+ } else {
+ registerClient(client);
+ return NO_ERROR;
+ }
} break;
case OPEN_STREAM: {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 0cce5bc..a1b04ca 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -177,7 +177,7 @@
}
// No lock here: worst case we remove a NULL callback which will be a nop
if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
}
IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
mAudioRecord.clear();
@@ -790,14 +790,13 @@
mAudioRecord = record;
mCblkMemory = output.cblk;
mBufferMemory = output.buffers;
- mPortId = output.portId;
IPCThreadState::self()->flushCommands();
mCblk = cblk;
// note that output.frameCount is the (possibly revised) value of mReqFrameCount
if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
- __func__, mPortId,
+ __func__, output.portId,
mReqFrameCount, output.frameCount);
}
@@ -805,19 +804,20 @@
// The computation is done on server side.
if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
- __func__, mPortId,
+ __func__, output.portId,
mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
}
mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
//mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
- if (mDeviceCallback != 0 && mInput != output.inputId) {
+ if (mDeviceCallback != 0) {
if (mInput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
}
- AudioSystem::addAudioDeviceCallback(this, output.inputId);
+ AudioSystem::addAudioDeviceCallback(this, output.inputId, output.portId);
}
+ mPortId = output.portId;
// We retain a copy of the I/O handle, but don't own the reference
mInput = output.inputId;
mRefreshRemaining = true;
@@ -1332,9 +1332,9 @@
if (mInput != AUDIO_IO_HANDLE_NONE) {
if (mDeviceCallback != 0) {
ALOGW("%s(%d): callback already present!", __func__, mPortId);
- AudioSystem::removeAudioDeviceCallback(this, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
}
- status = AudioSystem::addAudioDeviceCallback(this, mInput);
+ status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId);
}
mDeviceCallback = callback;
return status;
@@ -1354,7 +1354,7 @@
}
mDeviceCallback.clear();
if (mInput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mInput);
+ AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
}
return NO_ERROR;
}
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 47e2c28..d359f52 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -523,12 +523,10 @@
if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
- Vector<sp<AudioDeviceCallback>> callbacksToCall;
+ std::vector<sp<AudioDeviceCallback>> callbacksToCall;
{
Mutex::Autolock _l(mLock);
- bool deviceValidOrChanged = false;
- bool sendCallbacks = false;
- ssize_t ioIndex = -1;
+ auto callbacks = std::map<audio_port_handle_t, wp<AudioDeviceCallback>>();
switch (event) {
case AUDIO_OUTPUT_OPENED:
@@ -546,17 +544,11 @@
if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) {
deviceId = ioDesc->getDeviceId();
if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) {
- ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
- if (ioIndex >= 0) {
- sendCallbacks = true;
- deviceValidOrChanged = true;
+ auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
+ if (it != mAudioDeviceCallbacks.end()) {
+ callbacks = it->second;
}
}
- if (event == AUDIO_OUTPUT_REGISTERED || event == AUDIO_INPUT_REGISTERED) {
- ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
- sendCallbacks = (ioIndex >= 0)
- && !mAudioDeviceCallbackProxies.valueAt(ioIndex).notifiedOnce();
- }
}
ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x "
"frameCount %zu deviceId %d",
@@ -578,7 +570,7 @@
event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle);
mIoDescriptors.removeItem(ioDesc->mIoHandle);
- mAudioDeviceCallbackProxies.removeItem(ioDesc->mIoHandle);
+ mAudioDeviceCallbacks.erase(ioDesc->mIoHandle);
} break;
case AUDIO_OUTPUT_CONFIG_CHANGED:
@@ -593,10 +585,11 @@
mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
if (deviceId != ioDesc->getDeviceId()) {
- deviceValidOrChanged = true;
deviceId = ioDesc->getDeviceId();
- ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle);
- sendCallbacks = ioIndex >= 0;
+ auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
+ if (it != mAudioDeviceCallbacks.end()) {
+ callbacks = it->second;
+ }
}
ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x "
"channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d",
@@ -606,35 +599,40 @@
ioDesc->getDeviceId());
} break;
- }
-
- // sendCallbacks true => ioDesc->mIoHandle and deviceId are valid
- if (sendCallbacks) {
- AudioDeviceCallbackProxies &callbackProxies =
- mAudioDeviceCallbackProxies.editValueAt(ioIndex);
- for (size_t i = 0; i < callbackProxies.size(); ) {
- sp<AudioDeviceCallback> callback = callbackProxies[i]->callback();
- if (callback.get() != nullptr) {
- // Call the callback only if the device actually changed, the input or output
- // was opened or closed or the client was newly registered and the callback
- // was never called
- if (!callbackProxies[i]->notifiedOnce() || deviceValidOrChanged) {
- callbacksToCall.add(callback);
- callbackProxies[i]->setNotifiedOnce();
- }
- i++;
- } else {
- callbackProxies.removeAt(i);
+ case AUDIO_CLIENT_STARTED: {
+ sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle);
+ if (oldDesc == 0) {
+ ALOGW("ioConfigChanged() start client on unknown io! %d", ioDesc->mIoHandle);
+ break;
+ }
+ ALOGV("ioConfigChanged() AUDIO_CLIENT_STARTED io %d port %d num callbacks %zu",
+ ioDesc->mIoHandle, ioDesc->mPortId, mAudioDeviceCallbacks.size());
+ oldDesc->mPatch = ioDesc->mPatch;
+ auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle);
+ if (it != mAudioDeviceCallbacks.end()) {
+ auto cbks = it->second;
+ auto it2 = cbks.find(ioDesc->mPortId);
+ if (it2 != cbks.end()) {
+ callbacks.emplace(ioDesc->mPortId, it2->second);
+ deviceId = oldDesc->getDeviceId();
}
}
- callbackProxies.setNotifiedOnce();
+ } break;
+ }
+
+ for (auto wpCbk : callbacks) {
+ sp<AudioDeviceCallback> spCbk = wpCbk.second.promote();
+ if (spCbk != nullptr) {
+ callbacksToCall.push_back(spCbk);
+ }
}
}
// Callbacks must be called without mLock held. May lead to dead lock if calling for
// example getRoutedDevice that updates the device and tries to acquire mLock.
- for (size_t i = 0; i < callbacksToCall.size(); i++) {
- callbacksToCall[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+ for (auto cb : callbacksToCall) {
+ // If callbacksToCall is not empty, it implies ioDesc->mIoHandle and deviceId are valid
+ cb->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
}
}
@@ -687,51 +685,34 @@
}
status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
- const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
+ audio_port_handle_t portId)
{
+ ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId);
Mutex::Autolock _l(mLock);
- AudioDeviceCallbackProxies callbackProxies;
- ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo);
- if (ioIndex >= 0) {
- callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex);
+ auto& callbacks = mAudioDeviceCallbacks.emplace(audioIo, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>()).first->second;
+ auto result = callbacks.try_emplace(portId, callback);
+ if (!result.second) {
+ return INVALID_OPERATION;
}
-
- for (size_t cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) {
- sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback();
- if (cbk.get() == callback.unsafe_get()) {
- return INVALID_OPERATION;
- }
- }
- callbackProxies.add(new AudioDeviceCallbackProxy(callback));
- callbackProxies.resetNotifiedOnce();
- mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies);
return NO_ERROR;
}
status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
- const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback __unused, audio_io_handle_t audioIo,
+ audio_port_handle_t portId)
{
+ ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId);
Mutex::Autolock _l(mLock);
- ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo);
- if (ioIndex < 0) {
+ auto it = mAudioDeviceCallbacks.find(audioIo);
+ if (it == mAudioDeviceCallbacks.end()) {
return INVALID_OPERATION;
}
- AudioDeviceCallbackProxies callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex);
- size_t cbIndex;
- for (cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) {
- sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback();
- if (cbk.get() == callback.unsafe_get()) {
- break;
- }
- }
- if (cbIndex == callbackProxies.size()) {
+ if (it->second.erase(portId) == 0) {
return INVALID_OPERATION;
}
- callbackProxies.removeAt(cbIndex);
- if (callbackProxies.size() != 0) {
- mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies);
- } else {
- mAudioDeviceCallbackProxies.removeItem(audioIo);
+ if (it->second.size() == 0) {
+ mAudioDeviceCallbacks.erase(audioIo);
}
return NO_ERROR;
}
@@ -1271,13 +1252,14 @@
}
status_t AudioSystem::addAudioDeviceCallback(
- const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
+ audio_port_handle_t portId)
{
const sp<AudioFlingerClient> afc = getAudioFlingerClient();
if (afc == 0) {
return NO_INIT;
}
- status_t status = afc->addAudioDeviceCallback(callback, audioIo);
+ status_t status = afc->addAudioDeviceCallback(callback, audioIo, portId);
if (status == NO_ERROR) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af != 0) {
@@ -1288,13 +1270,14 @@
}
status_t AudioSystem::removeAudioDeviceCallback(
- const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
+ const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo,
+ audio_port_handle_t portId)
{
const sp<AudioFlingerClient> afc = getAudioFlingerClient();
if (afc == 0) {
return NO_INIT;
}
- return afc->removeAudioDeviceCallback(callback, audioIo);
+ return afc->removeAudioDeviceCallback(callback, audioIo, portId);
}
audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo)
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index bd48f56..4a80cd3 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -309,7 +309,7 @@
}
// No lock here: worst case we remove a NULL callback which will be a nop
if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
mAudioTrack.clear();
@@ -1495,7 +1495,6 @@
mAfFrameCount = output.afFrameCount;
mAfSampleRate = output.afSampleRate;
mAfLatency = output.afLatencyMs;
- mPortId = output.portId;
mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
@@ -1543,14 +1542,15 @@
mFlags = output.flags;
//mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
- if (mDeviceCallback != 0 && mOutput != output.outputId) {
+ if (mDeviceCallback != 0) {
if (mOutput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
- AudioSystem::addAudioDeviceCallback(this, output.outputId);
+ AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId);
callbackAdded = true;
}
+ mPortId = output.portId;
// We retain a copy of the I/O handle, but don't own the reference
mOutput = output.outputId;
mRefreshRemaining = true;
@@ -1615,7 +1615,7 @@
exit:
if (status != NO_ERROR && callbackAdded) {
// note: mOutput is always valid is callbackAdded is true
- AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
mStatus = status;
@@ -2144,9 +2144,27 @@
const nsecs_t timeNow = systemTime();
ns = max((nsecs_t)0, ns - (timeNow - timeAfterCallbacks));
}
- nsecs_t myns = framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed);
- if (ns < 0 /* NS_WHENEVER */ || myns < ns) {
- ns = myns;
+
+ // delayNs is first computed by the additional frames required in the buffer.
+ nsecs_t delayNs = framesToNanoseconds(
+ mRemainingFrames - avail, sampleRate, speed);
+
+ // afNs is the AudioFlinger mixer period in ns.
+ const nsecs_t afNs = framesToNanoseconds(mAfFrameCount, mAfSampleRate, speed);
+
+ // If the AudioTrack is double buffered based on the AudioFlinger mixer period,
+ // we may have a race if we wait based on the number of frames desired.
+ // This is a possible issue with resampling and AAudio.
+ //
+ // The granularity of audioflinger processing is one mixer period; if
+ // our wait time is less than one mixer period, wait at most half the period.
+ if (delayNs < afNs) {
+ delayNs = std::min(delayNs, afNs / 2);
+ }
+
+ // adjust our ns wait by delayNs.
+ if (ns < 0 /* NS_WHENEVER */ || delayNs < ns) {
+ ns = delayNs;
}
return ns;
}
@@ -2922,6 +2940,7 @@
status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
{
+
if (callback == 0) {
ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
return BAD_VALUE;
@@ -2935,9 +2954,9 @@
if (mOutput != AUDIO_IO_HANDLE_NONE) {
if (mDeviceCallback != 0) {
ALOGW("%s(%d): callback already present!", __func__, mPortId);
- AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
- status = AudioSystem::addAudioDeviceCallback(this, mOutput);
+ status = AudioSystem::addAudioDeviceCallback(this, mOutput, mPortId);
}
mDeviceCallback = callback;
return status;
@@ -2957,7 +2976,7 @@
}
mDeviceCallback.clear();
if (mOutput != AUDIO_IO_HANDLE_NONE) {
- AudioSystem::removeAudioDeviceCallback(this, mOutput);
+ AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
}
return NO_ERROR;
}
@@ -2979,6 +2998,7 @@
mRoutedDeviceId = deviceId;
}
}
+
if (callback.get() != nullptr) {
callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId);
}
diff --git a/media/libaudioclient/IAudioFlingerClient.cpp b/media/libaudioclient/IAudioFlingerClient.cpp
index b2dbc4c..47eb7dc 100644
--- a/media/libaudioclient/IAudioFlingerClient.cpp
+++ b/media/libaudioclient/IAudioFlingerClient.cpp
@@ -52,6 +52,7 @@
data.writeInt64(ioDesc->mFrameCount);
data.writeInt64(ioDesc->mFrameCountHAL);
data.writeInt32(ioDesc->mLatency);
+ data.writeInt32(ioDesc->mPortId);
remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -76,6 +77,7 @@
ioDesc->mFrameCount = data.readInt64();
ioDesc->mFrameCountHAL = data.readInt64();
ioDesc->mLatency = data.readInt32();
+ ioDesc->mPortId = data.readInt32();
ioConfigChanged(event, ioDesc);
return NO_ERROR;
} break;
diff --git a/media/libaudioclient/include/media/AudioIoDescriptor.h b/media/libaudioclient/include/media/AudioIoDescriptor.h
index 859f1a9..981d33a 100644
--- a/media/libaudioclient/include/media/AudioIoDescriptor.h
+++ b/media/libaudioclient/include/media/AudioIoDescriptor.h
@@ -28,6 +28,7 @@
AUDIO_INPUT_OPENED,
AUDIO_INPUT_CLOSED,
AUDIO_INPUT_CONFIG_CHANGED,
+ AUDIO_CLIENT_STARTED,
};
// audio input/output descriptor used to cache output configurations in client process to avoid
@@ -37,7 +38,7 @@
AudioIoDescriptor() :
mIoHandle(AUDIO_IO_HANDLE_NONE),
mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
- mFrameCount(0), mFrameCountHAL(0), mLatency(0)
+ mFrameCount(0), mFrameCountHAL(0), mLatency(0), mPortId(AUDIO_PORT_HANDLE_NONE)
{
memset(&mPatch, 0, sizeof(struct audio_patch));
}
@@ -66,6 +67,7 @@
size_t mFrameCount;
size_t mFrameCountHAL;
uint32_t mLatency; // only valid for output
+ audio_port_handle_t mPortId; // valid for event AUDIO_CLIENT_STARTED
};
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index d3035da..f79ec21 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -438,32 +438,12 @@
audio_port_handle_t deviceId) = 0;
};
- class AudioDeviceCallbackProxy : public RefBase
- {
- public:
-
- AudioDeviceCallbackProxy(wp<AudioDeviceCallback> callback)
- : mCallback(callback) {}
- ~AudioDeviceCallbackProxy() override {}
-
- sp<AudioDeviceCallback> callback() const { return mCallback.promote(); };
-
- bool notifiedOnce() const { return mNotifiedOnce; }
- void setNotifiedOnce() { mNotifiedOnce = true; }
- private:
- /**
- * @brief mNotifiedOnce it forces the callback to be called at least once when
- * registered with a VALID AudioDevice, and allows not to flood other listeners
- * on this iohandle that already know the valid device.
- */
- bool mNotifiedOnce = false;
- wp<AudioDeviceCallback> mCallback;
- };
-
static status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
- audio_io_handle_t audioIo);
+ audio_io_handle_t audioIo,
+ audio_port_handle_t portId);
static status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
- audio_io_handle_t audioIo);
+ audio_io_handle_t audioIo,
+ audio_port_handle_t portId);
static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -494,9 +474,11 @@
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
- audio_io_handle_t audioIo);
+ audio_io_handle_t audioIo,
+ audio_port_handle_t portId);
status_t removeAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
- audio_io_handle_t audioIo);
+ audio_io_handle_t audioIo,
+ audio_port_handle_t portId);
audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);
@@ -504,26 +486,8 @@
Mutex mLock;
DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> > mIoDescriptors;
- class AudioDeviceCallbackProxies : public Vector<sp<AudioDeviceCallbackProxy>>
- {
- public:
- /**
- * @brief notifiedOnce ensures that if a client adds a callback, it must at least be
- * called once with the device on which it will be routed to.
- * @return true if already notified or nobody waits for a callback, false otherwise.
- */
- bool notifiedOnce() const { return (size() == 0) || mNotifiedOnce; }
- void setNotifiedOnce() { mNotifiedOnce = true; }
- void resetNotifiedOnce() { mNotifiedOnce = false; }
- private:
- /**
- * @brief mNotifiedOnce it forces each callback to be called at least once when
- * registered with a VALID AudioDevice
- */
- bool mNotifiedOnce = false;
- };
- DefaultKeyedVector<audio_io_handle_t, AudioDeviceCallbackProxies>
- mAudioDeviceCallbackProxies;
+ std::map<audio_io_handle_t, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>>
+ mAudioDeviceCallbacks;
// cached values for recording getInputBufferSize() queries
size_t mInBuffSize; // zero indicates cache is invalid
uint32_t mInSamplingRate;
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index babda22..80e8f3a 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_UTILS_CONVERSION_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_UTILS_CONVERSION_H
#include <vector>
#include <list>
@@ -258,7 +258,12 @@
*/
// convert: Status -> status_t
inline status_t toStatusT(Return<Status> const& t) {
- return t.isOk() ? toStatusT(static_cast<Status>(t)) : UNKNOWN_ERROR;
+ if (t.isOk()) {
+ return toStatusT(static_cast<Status>(t));
+ } else if (t.isDeadObject()) {
+ return DEAD_OBJECT;
+ }
+ return UNKNOWN_ERROR;
}
/**
@@ -938,4 +943,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0_UTILS_CONVERSION_H
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3b87462..317b5ec 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2580,6 +2580,8 @@
layerParams.nPLayerCountActual = numLayers - numBLayers;
layerParams.nBLayerCountActual = numBLayers;
layerParams.bBitrateRatiosSpecified = OMX_FALSE;
+ layerParams.nLayerCountMax = numLayers;
+ layerParams.nBLayerCountMax = numBLayers;
err = mOMXNode->setParameter(
(OMX_INDEXTYPE)OMX_IndexParamAndroidVideoTemporalLayering,
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 2ca5eee..e56750b 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1110,6 +1110,9 @@
reset();
}
if (!isResourceError(err)) {
+ if (err == OK) {
+ disableLegacyBufferDropPostQ(surface);
+ }
break;
}
}
@@ -1175,7 +1178,11 @@
msg->setObject("surface", surface);
sp<AMessage> response;
- return PostAndAwaitResponse(msg, &response);
+ status_t result = PostAndAwaitResponse(msg, &response);
+ if (result == OK) {
+ disableLegacyBufferDropPostQ(surface);
+ }
+ return result;
}
status_t MediaCodec::createInputSurface(
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index d97591f..81d2abb 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -19,11 +19,11 @@
#include <utils/Log.h>
#include <android/dlext.h>
-#include <android-base/logging.h>
#include <binder/IPCThreadState.h>
#include <binder/PermissionCache.h>
#include <binder/IServiceManager.h>
#include <media/DataSource.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaExtractorFactory.h>
@@ -245,17 +245,21 @@
void *libHandle = android_dlopen_ext(
libPath.string(),
RTLD_NOW | RTLD_LOCAL, dlextinfo);
- CHECK(libHandle != nullptr)
- << "couldn't dlopen(" << libPath.string() << ") " << strerror(errno);
-
- GetExtractorDef getDef =
- (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
- CHECK(getDef != nullptr)
- << libPath.string() << " does not contain sniffer";
-
- ALOGV("registering sniffer for %s", libPath.string());
- RegisterExtractor(
- new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+ if (libHandle) {
+ GetExtractorDef getDef =
+ (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+ if (getDef) {
+ ALOGV("registering sniffer for %s", libPath.string());
+ RegisterExtractor(
+ new ExtractorPlugin(getDef(), libHandle, libPath), pluginList);
+ } else {
+ LOG_ALWAYS_FATAL_IN_CHILD_PROC("%s does not contain sniffer", libPath.string());
+ dlclose(libHandle);
+ }
+ } else {
+ LOG_ALWAYS_FATAL_IN_CHILD_PROC(
+ "couldn't dlopen(%s) %s", libPath.string(), strerror(errno));
+ }
}
closedir(libDir);
} else {
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 9e11a94..4c94baa 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -18,10 +18,13 @@
#define LOG_TAG "SurfaceUtils"
#include <utils/Log.h>
+#include <android/api-level.h>
#include <media/hardware/VideoAPI.h>
#include <media/stagefright/SurfaceUtils.h>
#include <gui/Surface.h>
+extern "C" int android_get_application_target_sdk_version();
+
namespace android {
status_t setNativeWindowSizeFormatAndUsage(
@@ -291,5 +294,28 @@
return err;
}
+
+status_t disableLegacyBufferDropPostQ(const sp<Surface> &surface) {
+ sp<IGraphicBufferProducer> igbp =
+ surface ? surface->getIGraphicBufferProducer() : nullptr;
+ if (igbp) {
+ int targetSdk = android_get_application_target_sdk_version();
+ // When the caller is not an app (e.g. MediaPlayer in mediaserver)
+ // targetSdk is __ANDROID_API_FUTURE__.
+ bool drop =
+ targetSdk < __ANDROID_API_Q__ ||
+ targetSdk == __ANDROID_API_FUTURE__;
+ if (!drop) {
+ status_t err = igbp->setLegacyBufferDrop(false);
+ if (err == NO_ERROR) {
+ ALOGD("legacy buffer drop disabled: target sdk (%d)",
+ targetSdk);
+ } else {
+ ALOGD("disabling legacy buffer drop failed: %d", err);
+ }
+ }
+ }
+ return NO_ERROR;
+}
} // namespace android
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/libstagefright/bqhelper/Android.bp
index 218fe15..db67034 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/libstagefright/bqhelper/Android.bp
@@ -6,10 +6,8 @@
},
double_loadable: true,
srcs: [
- "Conversion.cpp",
"FrameDropper.cpp",
"GraphicBufferSource.cpp",
- "WProducerListener.cpp",
],
export_include_dirs: [
@@ -27,7 +25,6 @@
shared_libs: [
"libbinder",
"libcutils",
- "libgui",
"libhidlbase",
"libhidlmemory",
"libhidltransport",
@@ -37,12 +34,25 @@
"libutils",
"android.hardware.graphics.bufferqueue@1.0",
+ // Following libs are from libgui_bufferqueue_static
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hidl.token@1.0-utils",
+ "libbase",
+ "libEGL",
+ "libhwbinder",
+ "libnativewindow",
+ "libvndksupport",
+ ],
+
+ static_libs: [
+ "libgui_bufferqueue_static"
],
export_shared_lib_headers: [
- "libgui",
"libhidlmemory",
"libstagefright_foundation",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
],
cflags: [
diff --git a/media/libstagefright/bqhelper/Conversion.cpp b/media/libstagefright/bqhelper/Conversion.cpp
deleted file mode 100644
index 91d7c74..0000000
--- a/media/libstagefright/bqhelper/Conversion.cpp
+++ /dev/null
@@ -1,1542 +0,0 @@
-/*
- * 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.
- */
-
-#include <media/stagefright/bqhelper/Conversion.h>
-
-namespace android {
-namespace conversion {
-
-// native_handle_t helper functions.
-
-/**
- * \brief Take an fd and create a native handle containing only the given fd.
- * The created handle will need to be deleted manually with
- * `native_handle_delete()`.
- *
- * \param[in] fd The source file descriptor (of type `int`).
- * \return The create `native_handle_t*` that contains the given \p fd. If the
- * supplied \p fd is negative, the created native handle will contain no file
- * descriptors.
- *
- * If the native handle cannot be created, the return value will be
- * `nullptr`.
- *
- * This function does not duplicate the file descriptor.
- */
-native_handle_t* native_handle_create_from_fd(int fd) {
- if (fd < 2) {
- return native_handle_create(0, 0);
- }
- native_handle_t* nh = native_handle_create(1, 0);
- if (nh == nullptr) {
- return nullptr;
- }
- nh->data[0] = fd;
- return nh;
-}
-
-/**
- * \brief Extract a file descriptor from a native handle.
- *
- * \param[in] nh The source `native_handle_t*`.
- * \param[in] index The index of the file descriptor in \p nh to read from. This
- * input has the default value of `0`.
- * \return The `index`-th file descriptor in \p nh. If \p nh does not have
- * enough file descriptors, the returned value will be `-1`.
- *
- * This function does not duplicate the file descriptor.
- */
-int native_handle_read_fd(native_handle_t const* nh, int index) {
- return ((nh == nullptr) || (nh->numFds == 0) ||
- (nh->numFds <= index) || (index < 0)) ?
- -1 : nh->data[index];
-}
-
-/**
- * Conversion functions
- * ====================
- *
- * There are two main directions of conversion:
- * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
- * input. The wrapper has type `TargetType`.
- * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
- * corresponds to the input. The lifetime of the output does not depend on the
- * lifetime of the input.
- * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
- * that cannot be copied and/or moved efficiently, or when there are multiple
- * output arguments.
- * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
- * `TargetType` that cannot be copied and/or moved efficiently, or when there
- * are multiple output arguments.
- *
- * `wrapIn()` and `convertTo()` functions will take output arguments before
- * input arguments. Some of these functions might return a value to indicate
- * success or error.
- *
- * In converting or wrapping something as a Treble type that contains a
- * `hidl_handle`, `native_handle_t*` will need to be created and returned as
- * an additional output argument, hence only `wrapIn()` or `convertTo()` would
- * be available. The caller must call `native_handle_delete()` to deallocate the
- * returned native handle when it is no longer needed.
- *
- * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
- * not perform duplication of file descriptors, while `toTargetType()` and
- * `convertTo()` do.
- */
-
-/**
- * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
- *
- * \param[in] t The source `Return<void>`.
- * \return The corresponding `status_t`.
- */
-// convert: Return<void> -> status_t
-status_t toStatusT(Return<void> const& t) {
- return t.isOk() ? OK : (t.isDeadObject() ? DEAD_OBJECT : UNKNOWN_ERROR);
-}
-
-/**
- * \brief Convert `Return<void>` to `binder::Status`.
- *
- * \param[in] t The source `Return<void>`.
- * \return The corresponding `binder::Status`.
- */
-// convert: Return<void> -> ::android::binder::Status
-::android::binder::Status toBinderStatus(
- Return<void> const& t) {
- return ::android::binder::Status::fromExceptionCode(
- toStatusT(t),
- t.description().c_str());
-}
-
-/**
- * \brief Wrap `native_handle_t*` in `hidl_handle`.
- *
- * \param[in] nh The source `native_handle_t*`.
- * \return The `hidl_handle` that points to \p nh.
- */
-// wrap: native_handle_t* -> hidl_handle
-hidl_handle inHidlHandle(native_handle_t const* nh) {
- return hidl_handle(nh);
-}
-
-/**
- * \brief Convert `int32_t` to `Dataspace`.
- *
- * \param[in] l The source `int32_t`.
- * \result The corresponding `Dataspace`.
- */
-// convert: int32_t -> Dataspace
-Dataspace toHardwareDataspace(int32_t l) {
- return static_cast<Dataspace>(l);
-}
-
-/**
- * \brief Convert `Dataspace` to `int32_t`.
- *
- * \param[in] t The source `Dataspace`.
- * \result The corresponding `int32_t`.
- */
-// convert: Dataspace -> int32_t
-int32_t toRawDataspace(Dataspace const& t) {
- return static_cast<int32_t>(t);
-}
-
-/**
- * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
- *
- * \param[in] l The pointer to the beginning of the opaque buffer.
- * \param[in] size The size of the buffer.
- * \return A `hidl_vec<uint8_t>` that points to the buffer.
- */
-// wrap: void*, size_t -> hidl_vec<uint8_t>
-hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size) {
- hidl_vec<uint8_t> t;
- t.setToExternal(static_cast<uint8_t*>(const_cast<void*>(l)), size, false);
- return t;
-}
-
-/**
- * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
- *
- * \param[in] l The pointer to the beginning of the opaque buffer.
- * \param[in] size The size of the buffer.
- * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
- */
-// convert: void*, size_t -> hidl_vec<uint8_t>
-hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size) {
- hidl_vec<uint8_t> t;
- t.resize(size);
- uint8_t const* src = static_cast<uint8_t const*>(l);
- std::copy(src, src + size, t.data());
- return t;
-}
-
-/**
- * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
- *
- * \param[out] t The wrapper of type `AnwBuffer`.
- * \param[in] l The source `GraphicBuffer`.
- */
-// wrap: GraphicBuffer -> AnwBuffer
-void wrapAs(AnwBuffer* t, GraphicBuffer const& l) {
- t->attr.width = l.getWidth();
- t->attr.height = l.getHeight();
- t->attr.stride = l.getStride();
- t->attr.format = static_cast<PixelFormat>(l.getPixelFormat());
- t->attr.layerCount = l.getLayerCount();
- t->attr.usage = l.getUsage();
- t->attr.id = l.getId();
- t->attr.generationNumber = l.getGenerationNumber();
- t->nativeHandle = hidl_handle(l.handle);
-}
-
-/**
- * \brief Convert `AnwBuffer` to `GraphicBuffer`.
- *
- * \param[out] l The destination `GraphicBuffer`.
- * \param[in] t The source `AnwBuffer`.
- *
- * This function will duplicate all file descriptors in \p t.
- */
-// convert: AnwBuffer -> GraphicBuffer
-// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
-bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
- native_handle_t* handle = t.nativeHandle == nullptr ?
- nullptr : native_handle_clone(t.nativeHandle);
-
- size_t const numInts = 12 + (handle ? handle->numInts : 0);
- int32_t* ints = new int32_t[numInts];
-
- size_t numFds = static_cast<size_t>(handle ? handle->numFds : 0);
- int* fds = new int[numFds];
-
- ints[0] = 'GBFR';
- ints[1] = static_cast<int32_t>(t.attr.width);
- ints[2] = static_cast<int32_t>(t.attr.height);
- ints[3] = static_cast<int32_t>(t.attr.stride);
- ints[4] = static_cast<int32_t>(t.attr.format);
- ints[5] = static_cast<int32_t>(t.attr.layerCount);
- ints[6] = static_cast<int32_t>(t.attr.usage);
- ints[7] = static_cast<int32_t>(t.attr.id >> 32);
- ints[8] = static_cast<int32_t>(t.attr.id & 0xFFFFFFFF);
- ints[9] = static_cast<int32_t>(t.attr.generationNumber);
- ints[10] = 0;
- ints[11] = 0;
- if (handle) {
- ints[10] = static_cast<int32_t>(handle->numFds);
- ints[11] = static_cast<int32_t>(handle->numInts);
- int* intsStart = handle->data + handle->numFds;
- std::copy(handle->data, intsStart, fds);
- std::copy(intsStart, intsStart + handle->numInts, &ints[12]);
- }
-
- void const* constBuffer = static_cast<void const*>(ints);
- size_t size = numInts * sizeof(int32_t);
- int const* constFds = static_cast<int const*>(fds);
- status_t status = l->unflatten(constBuffer, size, constFds, numFds);
-
- delete [] fds;
- delete [] ints;
- native_handle_delete(handle);
- return status == NO_ERROR;
-}
-
-/**
- * Conversion functions for types outside media
- * ============================================
- *
- * Some objects in libui and libgui that were made to go through binder calls do
- * not expose ways to read or write their fields to the public. To pass an
- * object of this kind through the HIDL boundary, translation functions need to
- * work around the access restriction by using the publicly available
- * `flatten()` and `unflatten()` functions.
- *
- * All `flatten()` and `unflatten()` overloads follow the same convention as
- * follows:
- *
- * status_t flatten(ObjectType const& object,
- * [OtherType const& other, ...]
- * void*& buffer, size_t& size,
- * int*& fds, size_t& numFds)
- *
- * status_t unflatten(ObjectType* object,
- * [OtherType* other, ...,]
- * void*& buffer, size_t& size,
- * int*& fds, size_t& numFds)
- *
- * The number of `other` parameters varies depending on the `ObjectType`. For
- * example, in the process of unflattening an object that contains
- * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
- * be created.
- *
- * The last four parameters always work the same way in all overloads of
- * `flatten()` and `unflatten()`:
- * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
- * `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
- * `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
- * size (in ints) of the fd buffer pointed to by `fds`.
- * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
- * from, `size` is the size (in bytes) of the non-fd buffer pointed to by
- * `buffer`, `fds` is the pointer to the fd buffer to be read from, and
- * `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
- * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
- * will be advanced, while `size` and `numFds` will be decreased to reflect
- * how much storage/data of the two buffers (fd and non-fd) have been used.
- * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
- * `numFds` are invalid.
- *
- * The return value of a successful `flatten()` or `unflatten()` call will be
- * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
- *
- * For each object type that supports flattening, there will be two accompanying
- * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
- * return the size of the non-fd buffer that the object will need for
- * flattening. `getFdCount()` will return the size of the fd buffer that the
- * object will need for flattening.
- *
- * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
- * `flatten()` and `unflatten()`, are similar to functions of the same name in
- * the abstract class `Flattenable`. The only difference is that functions in
- * this file are not member functions of the object type. For example, we write
- *
- * flatten(x, buffer, size, fds, numFds)
- *
- * instead of
- *
- * x.flatten(buffer, size, fds, numFds)
- *
- * because we cannot modify the type of `x`.
- *
- * There is one exception to the naming convention: `hidl_handle` that
- * represents a fence. The four functions for this "Fence" type have the word
- * "Fence" attched to their names because the object type, which is
- * `hidl_handle`, does not carry the special meaning that the object itself can
- * only contain zero or one file descriptor.
- */
-
-// Ref: frameworks/native/libs/ui/Fence.cpp
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten a fence.
- *
- * \param[in] fence The input fence of type `hidl_handle`.
- * \return The required size of the flat buffer.
- *
- * The current version of this function always returns 4, which is the number of
- * bytes required to store the number of file descriptors contained in the fd
- * part of the flat buffer.
- */
-size_t getFenceFlattenedSize(hidl_handle const& /* fence */) {
- return 4;
-};
-
-/**
- * \brief Return the number of file descriptors contained in a fence.
- *
- * \param[in] fence The input fence of type `hidl_handle`.
- * \return `0` if \p fence does not contain a valid file descriptor, or `1`
- * otherwise.
- */
-size_t getFenceFdCount(hidl_handle const& fence) {
- return native_handle_read_fd(fence) == -1 ? 0 : 1;
-}
-
-/**
- * \brief Unflatten `Fence` to `hidl_handle`.
- *
- * \param[out] fence The destination `hidl_handle`.
- * \param[out] nh The underlying native handle.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will point to a newly created
- * native handle, which needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < 4) {
- return NO_MEMORY;
- }
-
- uint32_t numFdsInHandle;
- FlattenableUtils::read(buffer, size, numFdsInHandle);
-
- if (numFdsInHandle > 1) {
- return BAD_VALUE;
- }
-
- if (numFds < numFdsInHandle) {
- return NO_MEMORY;
- }
-
- if (numFdsInHandle) {
- *nh = native_handle_create_from_fd(*fds);
- if (*nh == nullptr) {
- return NO_MEMORY;
- }
- *fence = *nh;
- ++fds;
- --numFds;
- } else {
- *nh = nullptr;
- *fence = hidl_handle();
- }
-
- return NO_ERROR;
-}
-
-/**
- * \brief Flatten `hidl_handle` as `Fence`.
- *
- * \param[in] t The source `hidl_handle`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t flattenFence(hidl_handle const& fence,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFenceFlattenedSize(fence) ||
- numFds < getFenceFdCount(fence)) {
- return NO_MEMORY;
- }
- // Cast to uint32_t since the size of a size_t can vary between 32- and
- // 64-bit processes
- FlattenableUtils::write(buffer, size,
- static_cast<uint32_t>(getFenceFdCount(fence)));
- int fd = native_handle_read_fd(fence);
- if (fd != -1) {
- *fds = fd;
- ++fds;
- --numFds;
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Wrap `Fence` in `hidl_handle`.
- *
- * \param[out] t The wrapper of type `hidl_handle`.
- * \param[out] nh The native handle pointed to by \p t.
- * \param[in] l The source `Fence`.
- *
- * On success, \p nh will hold a newly created native handle, which must be
- * deleted manually with `native_handle_delete()` afterwards.
- */
-// wrap: Fence -> hidl_handle
-bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l) {
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflattenFence(t, nh, constBuffer, size, constFds, numFds)
- != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-/**
- * \brief Convert `hidl_handle` to `Fence`.
- *
- * \param[out] l The destination `Fence`. `l` must not have been used
- * (`l->isValid()` must return `false`) before this function is called.
- * \param[in] t The source `hidl_handle`.
- *
- * If \p t contains a valid file descriptor, it will be duplicated.
- */
-// convert: hidl_handle -> Fence
-bool convertTo(Fence* l, hidl_handle const& t) {
- int fd = native_handle_read_fd(t);
- if (fd != -1) {
- fd = dup(fd);
- if (fd == -1) {
- return false;
- }
- }
- native_handle_t* nh = native_handle_create_from_fd(fd);
- if (nh == nullptr) {
- if (fd != -1) {
- close(fd);
- }
- return false;
- }
-
- size_t const baseSize = getFenceFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- native_handle_delete(nh);
- return false;
- }
-
- size_t const baseNumFds = getFenceFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- native_handle_delete(nh);
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (flattenFence(hidl_handle(nh), buffer, size, fds, numFds) != NO_ERROR) {
- native_handle_delete(nh);
- return false;
- }
- native_handle_delete(nh);
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `FenceTimeSnapshot`.
- *
- * \param[in] t The input `FenceTimeSnapshot`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(
- HGraphicBufferProducer::FenceTimeSnapshot const& t) {
- constexpr size_t min = sizeof(t.state);
- switch (t.state) {
- case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
- return min;
- case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
- return min + getFenceFlattenedSize(t.fence);
- case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
- return min + sizeof(
- ::android::FenceTime::Snapshot::signalTime);
- }
- return 0;
-}
-
-/**
- * \brief Return the number of file descriptors contained in
- * `FenceTimeSnapshot`.
- *
- * \param[in] t The input `FenceTimeSnapshot`.
- * \return The number of file descriptors contained in \p snapshot.
- */
-size_t getFdCount(
- HGraphicBufferProducer::FenceTimeSnapshot const& t) {
- return t.state ==
- HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE ?
- getFenceFdCount(t.fence) : 0;
-}
-
-/**
- * \brief Flatten `FenceTimeSnapshot`.
- *
- * \param[in] t The source `FenceTimeSnapshot`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate the file descriptor in `t.fence` if `t.state ==
- * FENCE`.
- */
-status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- switch (t.state) {
- case HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::EMPTY);
- return NO_ERROR;
- case HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::FENCE);
- return flattenFence(t.fence, buffer, size, fds, numFds);
- case HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME:
- FlattenableUtils::write(buffer, size,
- ::android::FenceTime::Snapshot::State::SIGNAL_TIME);
- FlattenableUtils::write(buffer, size, t.signalTimeNs);
- return NO_ERROR;
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Unflatten `FenceTimeSnapshot`.
- *
- * \param[out] t The destination `FenceTimeSnapshot`.
- * \param[out] nh The underlying native handle.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR` and the constructed snapshot contains a
- * file descriptor, \p nh will be created to hold that file descriptor. In this
- * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
- */
-status_t unflatten(
- HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < sizeof(t->state)) {
- return NO_MEMORY;
- }
-
- *nh = nullptr;
- ::android::FenceTime::Snapshot::State state;
- FlattenableUtils::read(buffer, size, state);
- switch (state) {
- case ::android::FenceTime::Snapshot::State::EMPTY:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::EMPTY;
- return NO_ERROR;
- case ::android::FenceTime::Snapshot::State::FENCE:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::FENCE;
- return unflattenFence(&t->fence, nh, buffer, size, fds, numFds);
- case ::android::FenceTime::Snapshot::State::SIGNAL_TIME:
- t->state = HGraphicBufferProducer::FenceTimeSnapshot::State::SIGNAL_TIME;
- if (size < sizeof(t->signalTimeNs)) {
- return NO_MEMORY;
- }
- FlattenableUtils::read(buffer, size, t->signalTimeNs);
- return NO_ERROR;
- }
- return NO_ERROR;
-}
-
-// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
-
-/**
- * \brief Return a lower bound on the size of the non-fd buffer required to
- * flatten `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return A lower bound on the size of the flat buffer.
- */
-constexpr size_t minFlattenedSize(
- HGraphicBufferProducer::FrameEventsDelta const& /* t */) {
- return sizeof(uint64_t) + // mFrameNumber
- sizeof(uint8_t) + // mIndex
- sizeof(uint8_t) + // mAddPostCompositeCalled
- sizeof(uint8_t) + // mAddRetireCalled
- sizeof(uint8_t) + // mAddReleaseCalled
- sizeof(nsecs_t) + // mPostedTime
- sizeof(nsecs_t) + // mRequestedPresentTime
- sizeof(nsecs_t) + // mLatchTime
- sizeof(nsecs_t) + // mFirstRefreshStartTime
- sizeof(nsecs_t); // mLastRefreshStartTime
-}
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(
- HGraphicBufferProducer::FrameEventsDelta const& t) {
- return minFlattenedSize(t) +
- getFlattenedSize(t.gpuCompositionDoneFence) +
- getFlattenedSize(t.displayPresentFence) +
- getFlattenedSize(t.displayRetireFence) +
- getFlattenedSize(t.releaseFence);
-};
-
-/**
- * \brief Return the number of file descriptors contained in
- * `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(
- HGraphicBufferProducer::FrameEventsDelta const& t) {
- return getFdCount(t.gpuCompositionDoneFence) +
- getFdCount(t.displayPresentFence) +
- getFdCount(t.displayRetireFence) +
- getFdCount(t.releaseFence);
-};
-
-/**
- * \brief Unflatten `FrameEventsDelta`.
- *
- * \param[out] t The destination `FrameEventsDelta`.
- * \param[out] nh The underlying array of native handles.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
- * populated with `nullptr` or newly created handles. Each non-null slot in \p
- * nh will need to be deleted manually with `native_handle_delete()`.
- */
-status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
- std::vector<native_handle_t*>* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < minFlattenedSize(*t)) {
- return NO_MEMORY;
- }
- FlattenableUtils::read(buffer, size, t->frameNumber);
-
- // These were written as uint8_t for alignment.
- uint8_t temp = 0;
- FlattenableUtils::read(buffer, size, temp);
- size_t index = static_cast<size_t>(temp);
- if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- t->index = static_cast<uint32_t>(index);
-
- FlattenableUtils::read(buffer, size, temp);
- t->addPostCompositeCalled = static_cast<bool>(temp);
- FlattenableUtils::read(buffer, size, temp);
- t->addRetireCalled = static_cast<bool>(temp);
- FlattenableUtils::read(buffer, size, temp);
- t->addReleaseCalled = static_cast<bool>(temp);
-
- FlattenableUtils::read(buffer, size, t->postedTimeNs);
- FlattenableUtils::read(buffer, size, t->requestedPresentTimeNs);
- FlattenableUtils::read(buffer, size, t->latchTimeNs);
- FlattenableUtils::read(buffer, size, t->firstRefreshStartTimeNs);
- FlattenableUtils::read(buffer, size, t->lastRefreshStartTimeNs);
- FlattenableUtils::read(buffer, size, t->dequeueReadyTime);
-
- // Fences
- HGraphicBufferProducer::FenceTimeSnapshot* tSnapshot[4];
- tSnapshot[0] = &t->gpuCompositionDoneFence;
- tSnapshot[1] = &t->displayPresentFence;
- tSnapshot[2] = &t->displayRetireFence;
- tSnapshot[3] = &t->releaseFence;
- nh->resize(4);
- for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
- status_t status = unflatten(
- tSnapshot[snapshotIndex], &((*nh)[snapshotIndex]),
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- while (snapshotIndex > 0) {
- --snapshotIndex;
- if ((*nh)[snapshotIndex] != nullptr) {
- native_handle_delete((*nh)[snapshotIndex]);
- }
- }
- return status;
- }
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Flatten `FrameEventsDelta`.
- *
- * \param[in] t The source `FrameEventsDelta`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate file descriptors contained in \p t.
- */
-// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
-// FrameEventsDelta::flatten
-status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t numFds) {
- // Check that t.index is within a valid range.
- if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
- || t.index > std::numeric_limits<uint8_t>::max()) {
- return BAD_VALUE;
- }
-
- FlattenableUtils::write(buffer, size, t.frameNumber);
-
- // These are static_cast to uint8_t for alignment.
- FlattenableUtils::write(buffer, size, static_cast<uint8_t>(t.index));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addPostCompositeCalled));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addRetireCalled));
- FlattenableUtils::write(
- buffer, size, static_cast<uint8_t>(t.addReleaseCalled));
-
- FlattenableUtils::write(buffer, size, t.postedTimeNs);
- FlattenableUtils::write(buffer, size, t.requestedPresentTimeNs);
- FlattenableUtils::write(buffer, size, t.latchTimeNs);
- FlattenableUtils::write(buffer, size, t.firstRefreshStartTimeNs);
- FlattenableUtils::write(buffer, size, t.lastRefreshStartTimeNs);
- FlattenableUtils::write(buffer, size, t.dequeueReadyTime);
-
- // Fences
- HGraphicBufferProducer::FenceTimeSnapshot const* tSnapshot[4];
- tSnapshot[0] = &t.gpuCompositionDoneFence;
- tSnapshot[1] = &t.displayPresentFence;
- tSnapshot[2] = &t.displayRetireFence;
- tSnapshot[3] = &t.releaseFence;
- for (size_t snapshotIndex = 0; snapshotIndex < 4; ++snapshotIndex) {
- status_t status = flatten(
- *(tSnapshot[snapshotIndex]), buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
-
-// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
- size_t size = 4 + // mDeltas.size()
- sizeof(t.compositorTiming);
- for (size_t i = 0; i < t.deltas.size(); ++i) {
- size += getFlattenedSize(t.deltas[i]);
- }
- return size;
-}
-
-/**
- * \brief Return the number of file descriptors contained in
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
- size_t numFds = 0;
- for (size_t i = 0; i < t.deltas.size(); ++i) {
- numFds += getFdCount(t.deltas[i]);
- }
- return numFds;
-}
-
-/**
- * \brief Unflatten `FrameEventHistoryDelta`.
- *
- * \param[out] t The destination `FrameEventHistoryDelta`.
- * \param[out] nh The underlying array of arrays of native handles.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
- * newly created handles. The second dimension of \p nh will be 4. Each non-null
- * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
- */
-status_t unflatten(
- HGraphicBufferProducer::FrameEventHistoryDelta* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < 4) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, t->compositorTiming);
-
- uint32_t deltaCount = 0;
- FlattenableUtils::read(buffer, size, deltaCount);
- if (static_cast<size_t>(deltaCount) >
- ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- t->deltas.resize(deltaCount);
- nh->resize(deltaCount);
- for (size_t deltaIndex = 0; deltaIndex < deltaCount; ++deltaIndex) {
- status_t status = unflatten(
- &(t->deltas[deltaIndex]), &((*nh)[deltaIndex]),
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Flatten `FrameEventHistoryDelta`.
- *
- * \param[in] t The source `FrameEventHistoryDelta`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate file descriptors contained in \p t.
- */
-status_t flatten(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, t.compositorTiming);
-
- FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.deltas.size()));
- for (size_t deltaIndex = 0; deltaIndex < t.deltas.size(); ++deltaIndex) {
- status_t status = flatten(t.deltas[deltaIndex], buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Wrap `::android::FrameEventHistoryData` in
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \param[out] nh The array of array of native handles that are referred to by
- * members of \p t.
- * \param[in] l The source `::android::FrameEventHistoryDelta`.
- *
- * On success, each member of \p nh will be either `nullptr` or a newly created
- * native handle. All the non-`nullptr` elements must be deleted individually
- * with `native_handle_delete()`.
- */
-bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- ::android::FrameEventHistoryDelta const& l) {
-
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-/**
- * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
- * `::android::FrameEventHistoryDelta`.
- *
- * \param[out] l The destination `::android::FrameEventHistoryDelta`.
- * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * This function will duplicate all file descriptors contained in \p t.
- */
-bool convertTo(
- ::android::FrameEventHistoryDelta* l,
- HGraphicBufferProducer::FrameEventHistoryDelta const& t) {
-
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = getFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = static_cast<int*>(baseFds.get());
- size_t numFds = baseNumFds;
- if (flatten(t, buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-// Ref: frameworks/native/libs/ui/Region.cpp
-
-/**
- * \brief Return the size of the buffer required to flatten `Region`.
- *
- * \param[in] t The input `Region`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(Region const& t) {
- return sizeof(uint32_t) + t.size() * sizeof(::android::Rect);
-}
-
-/**
- * \brief Unflatten `Region`.
- *
- * \param[out] t The destination `Region`.
- * \param[in,out] buffer The pointer to the flat buffer.
- * \param[in,out] size The size of the flat buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t unflatten(Region* t, void const*& buffer, size_t& size) {
- if (size < sizeof(uint32_t)) {
- return NO_MEMORY;
- }
-
- uint32_t numRects = 0;
- FlattenableUtils::read(buffer, size, numRects);
- if (size < numRects * sizeof(Rect)) {
- return NO_MEMORY;
- }
- if (numRects > (UINT32_MAX / sizeof(Rect))) {
- return NO_MEMORY;
- }
-
- t->resize(numRects);
- for (size_t r = 0; r < numRects; ++r) {
- ::android::Rect rect(::android::Rect::EMPTY_RECT);
- status_t status = rect.unflatten(buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::advance(buffer, size, sizeof(rect));
- (*t)[r] = Rect{
- static_cast<int32_t>(rect.left),
- static_cast<int32_t>(rect.top),
- static_cast<int32_t>(rect.right),
- static_cast<int32_t>(rect.bottom)};
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Flatten `Region`.
- *
- * \param[in] t The source `Region`.
- * \param[in,out] buffer The pointer to the flat buffer.
- * \param[in,out] size The size of the flat buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t flatten(Region const& t, void*& buffer, size_t& size) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, static_cast<uint32_t>(t.size()));
- for (size_t r = 0; r < t.size(); ++r) {
- ::android::Rect rect(
- static_cast<int32_t>(t[r].left),
- static_cast<int32_t>(t[r].top),
- static_cast<int32_t>(t[r].right),
- static_cast<int32_t>(t[r].bottom));
- status_t status = rect.flatten(buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::advance(buffer, size, sizeof(rect));
- }
- return NO_ERROR;
-}
-
-/**
- * \brief Convert `::android::Region` to `Region`.
- *
- * \param[out] t The destination `Region`.
- * \param[in] l The source `::android::Region`.
- */
-// convert: ::android::Region -> Region
-bool convertTo(Region* t, ::android::Region const& l) {
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- if (l.flatten(buffer, size) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- if (unflatten(t, constBuffer, size) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-/**
- * \brief Convert `Region` to `::android::Region`.
- *
- * \param[out] l The destination `::android::Region`.
- * \param[in] t The source `Region`.
- */
-// convert: Region -> ::android::Region
-bool convertTo(::android::Region* l, Region const& t) {
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- if (flatten(t, buffer, size) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- if (l->unflatten(constBuffer, size) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
-// BGraphicBufferProducer::QueueBufferInput
-
-/**
- * \brief Return a lower bound on the size of the buffer required to flatten
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return A lower bound on the size of the flat buffer.
- */
-constexpr size_t minFlattenedSize(
- HGraphicBufferProducer::QueueBufferInput const& /* t */) {
- return sizeof(int64_t) + // timestamp
- sizeof(int) + // isAutoTimestamp
- sizeof(android_dataspace) + // dataSpace
- sizeof(::android::Rect) + // crop
- sizeof(int) + // scalingMode
- sizeof(uint32_t) + // transform
- sizeof(uint32_t) + // stickyTransform
- sizeof(bool); // getFrameTimestamps
-}
-
-/**
- * \brief Return the size of the buffer required to flatten
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t) {
- return minFlattenedSize(t) +
- getFenceFlattenedSize(t.fence) +
- getFlattenedSize(t.surfaceDamage) +
- sizeof(HdrMetadata::validTypes);
-}
-
-/**
- * \brief Return the number of file descriptors contained in
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(
- HGraphicBufferProducer::QueueBufferInput const& t) {
- return getFenceFdCount(t.fence);
-}
-
-/**
- * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The native handle cloned from `t.fence`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate the file descriptor in `t.fence`. */
-status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
- native_handle_t** nh,
- void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (size < getFlattenedSize(t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::write(buffer, size, t.timestamp);
- FlattenableUtils::write(buffer, size, static_cast<int>(t.isAutoTimestamp));
- FlattenableUtils::write(buffer, size,
- static_cast<android_dataspace_t>(t.dataSpace));
- FlattenableUtils::write(buffer, size, ::android::Rect(
- static_cast<int32_t>(t.crop.left),
- static_cast<int32_t>(t.crop.top),
- static_cast<int32_t>(t.crop.right),
- static_cast<int32_t>(t.crop.bottom)));
- FlattenableUtils::write(buffer, size, static_cast<int>(t.scalingMode));
- FlattenableUtils::write(buffer, size, t.transform);
- FlattenableUtils::write(buffer, size, t.stickyTransform);
- FlattenableUtils::write(buffer, size, t.getFrameTimestamps);
-
- *nh = t.fence.getNativeHandle() == nullptr ?
- nullptr : native_handle_clone(t.fence);
- status_t status = flattenFence(hidl_handle(*nh), buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- status = flatten(t.surfaceDamage, buffer, size);
- if (status != NO_ERROR) {
- return status;
- }
- FlattenableUtils::write(buffer, size, decltype(HdrMetadata::validTypes)(0));
- return NO_ERROR;
-}
-
-/**
- * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The underlying native handle for `t->fence`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR` and `t->fence` contains a valid file
- * descriptor, \p nh will be a newly created native handle holding that file
- * descriptor. \p nh needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-status_t unflatten(
- HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds) {
- if (size < minFlattenedSize(*t)) {
- return NO_MEMORY;
- }
-
- FlattenableUtils::read(buffer, size, t->timestamp);
- int lIsAutoTimestamp;
- FlattenableUtils::read(buffer, size, lIsAutoTimestamp);
- t->isAutoTimestamp = static_cast<int32_t>(lIsAutoTimestamp);
- android_dataspace_t lDataSpace;
- FlattenableUtils::read(buffer, size, lDataSpace);
- t->dataSpace = static_cast<Dataspace>(lDataSpace);
- Rect lCrop;
- FlattenableUtils::read(buffer, size, lCrop);
- t->crop = Rect{
- static_cast<int32_t>(lCrop.left),
- static_cast<int32_t>(lCrop.top),
- static_cast<int32_t>(lCrop.right),
- static_cast<int32_t>(lCrop.bottom)};
- int lScalingMode;
- FlattenableUtils::read(buffer, size, lScalingMode);
- t->scalingMode = static_cast<int32_t>(lScalingMode);
- FlattenableUtils::read(buffer, size, t->transform);
- FlattenableUtils::read(buffer, size, t->stickyTransform);
- FlattenableUtils::read(buffer, size, t->getFrameTimestamps);
-
- status_t status = unflattenFence(&(t->fence), nh,
- buffer, size, fds, numFds);
- if (status != NO_ERROR) {
- return status;
- }
- // HdrMetadata ignored
- return unflatten(&(t->surfaceDamage), buffer, size);
-}
-
-/**
- * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The underlying native handle for `t->fence`.
- * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
- *
- * If the return value is `true` and `t->fence` contains a valid file
- * descriptor, \p nh will be a newly created native handle holding that file
- * descriptor. \p nh needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-bool wrapAs(
- HGraphicBufferProducer::QueueBufferInput* t,
- native_handle_t** nh,
- BGraphicBufferProducer::QueueBufferInput const& l) {
-
- size_t const baseSize = l.getFlattenedSize();
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = l.getFdCount();
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- if (l.flatten(buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (unflatten(t, nh, constBuffer, size, constFds, numFds) != NO_ERROR) {
- return false;
- }
-
- return true;
-}
-
-/**
- * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
- * `BGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
- *
- * If `t.fence` has a valid file descriptor, it will be duplicated.
- */
-bool convertTo(
- BGraphicBufferProducer::QueueBufferInput* l,
- HGraphicBufferProducer::QueueBufferInput const& t) {
-
- size_t const baseSize = getFlattenedSize(t);
- std::unique_ptr<uint8_t[]> baseBuffer(
- new (std::nothrow) uint8_t[baseSize]);
- if (!baseBuffer) {
- return false;
- }
-
- size_t const baseNumFds = getFdCount(t);
- std::unique_ptr<int[]> baseFds(
- new (std::nothrow) int[baseNumFds]);
- if (!baseFds) {
- return false;
- }
-
- void* buffer = static_cast<void*>(baseBuffer.get());
- size_t size = baseSize;
- int* fds = baseFds.get();
- size_t numFds = baseNumFds;
- native_handle_t* nh;
- if (flatten(t, &nh, buffer, size, fds, numFds) != NO_ERROR) {
- return false;
- }
-
- void const* constBuffer = static_cast<void const*>(baseBuffer.get());
- size = baseSize;
- int const* constFds = static_cast<int const*>(baseFds.get());
- numFds = baseNumFds;
- if (l->unflatten(constBuffer, size, constFds, numFds) != NO_ERROR) {
- if (nh != nullptr) {
- native_handle_close(nh);
- native_handle_delete(nh);
- }
- return false;
- }
-
- native_handle_delete(nh);
- return true;
-}
-
-// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
-// BGraphicBufferProducer::QueueBufferOutput
-
-/**
- * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
- * `HGraphicBufferProducer::QueueBufferOutput`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::QueueBufferOutput`.
- * \param[out] nh The array of array of native handles that are referred to by
- * members of \p t.
- * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
- *
- * On success, each member of \p nh will be either `nullptr` or a newly created
- * native handle. All the non-`nullptr` elements must be deleted individually
- * with `native_handle_delete()`.
- */
-// wrap: BGraphicBufferProducer::QueueBufferOutput ->
-// HGraphicBufferProducer::QueueBufferOutput
-bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- BGraphicBufferProducer::QueueBufferOutput const& l) {
- if (!wrapAs(&(t->frameTimestamps), nh, l.frameTimestamps)) {
- return false;
- }
- t->width = l.width;
- t->height = l.height;
- t->transformHint = l.transformHint;
- t->numPendingBuffers = l.numPendingBuffers;
- t->nextFrameNumber = l.nextFrameNumber;
- t->bufferReplaced = l.bufferReplaced;
- return true;
-}
-
-/**
- * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
- * `BGraphicBufferProducer::QueueBufferOutput`.
- *
- * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
- *
- * This function will duplicate all file descriptors contained in \p t.
- */
-// convert: HGraphicBufferProducer::QueueBufferOutput ->
-// BGraphicBufferProducer::QueueBufferOutput
-bool convertTo(
- BGraphicBufferProducer::QueueBufferOutput* l,
- HGraphicBufferProducer::QueueBufferOutput const& t) {
- if (!convertTo(&(l->frameTimestamps), t.frameTimestamps)) {
- return false;
- }
- l->width = t.width;
- l->height = t.height;
- l->transformHint = t.transformHint;
- l->numPendingBuffers = t.numPendingBuffers;
- l->nextFrameNumber = t.nextFrameNumber;
- l->bufferReplaced = t.bufferReplaced;
- return true;
-}
-
-/**
- * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
- * `HGraphicBufferProducer::DisconnectMode`.
- *
- * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
- * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
- */
-HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
- BGraphicBufferProducer::DisconnectMode l) {
- switch (l) {
- case BGraphicBufferProducer::DisconnectMode::Api:
- return HGraphicBufferProducer::DisconnectMode::API;
- case BGraphicBufferProducer::DisconnectMode::AllLocal:
- return HGraphicBufferProducer::DisconnectMode::ALL_LOCAL;
- }
- return HGraphicBufferProducer::DisconnectMode::API;
-}
-
-/**
- * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
- * `BGraphicBufferProducer::DisconnectMode`.
- *
- * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
- * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
- */
-BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
- HGraphicBufferProducer::DisconnectMode t) {
- switch (t) {
- case HGraphicBufferProducer::DisconnectMode::API:
- return BGraphicBufferProducer::DisconnectMode::Api;
- case HGraphicBufferProducer::DisconnectMode::ALL_LOCAL:
- return BGraphicBufferProducer::DisconnectMode::AllLocal;
- }
- return BGraphicBufferProducer::DisconnectMode::Api;
-}
-
-} // namespace conversion
-} // namespace android
-
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
index 68abcb5..59317e7 100644
--- a/media/libstagefright/bqhelper/GraphicBufferSource.cpp
+++ b/media/libstagefright/bqhelper/GraphicBufferSource.cpp
@@ -32,7 +32,11 @@
#include <media/hardware/MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IGraphicBufferConsumer.h>
#include <media/hardware/HardwareAPI.h>
#include <inttypes.h>
@@ -389,6 +393,18 @@
}
}
+sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const {
+ return mProducer;
+}
+
+sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>
+GraphicBufferSource::getHGraphicBufferProducer_V1_0() const {
+ using TWGraphicBufferProducer = ::android::TWGraphicBufferProducer<
+ ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>;
+
+ return new TWGraphicBufferProducer(getIGraphicBufferProducer());
+}
+
sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
GraphicBufferSource::getHGraphicBufferProducer() const {
return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
diff --git a/media/libstagefright/bqhelper/WProducerListener.cpp b/media/libstagefright/bqhelper/WProducerListener.cpp
deleted file mode 100644
index 2ca13be..0000000
--- a/media/libstagefright/bqhelper/WProducerListener.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <media/stagefright/bqhelper/WProducerListener.h>
-
-namespace android {
-
-// TWProducerListener
-TWProducerListener::TWProducerListener(
- sp<BProducerListener> const& base):
- mBase(base) {
-}
-
-Return<void> TWProducerListener::onBufferReleased() {
- mBase->onBufferReleased();
- return Void();
-}
-
-Return<bool> TWProducerListener::needsReleaseNotify() {
- return mBase->needsReleaseNotify();
-}
-
-// LWProducerListener
-LWProducerListener::LWProducerListener(
- sp<HProducerListener> const& base):
- mBase(base) {
-}
-
-void LWProducerListener::onBufferReleased() {
- mBase->onBufferReleased();
-}
-
-bool LWProducerListener::needsReleaseNotify() {
- return static_cast<bool>(mBase->needsReleaseNotify());
-}
-
-} // namespace android
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h
deleted file mode 100644
index 60d8c1e..0000000
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/Conversion.h
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Copyright 2016, 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 MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
-#define MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
-
-#include <vector>
-#include <list>
-
-#include <unistd.h>
-
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <hidlmemory/mapping.h>
-
-#include <binder/Binder.h>
-#include <binder/Status.h>
-#include <ui/FenceTime.h>
-#include <cutils/native_handle.h>
-#include <gui/IGraphicBufferProducer.h>
-
-#include <media/hardware/VideoAPI.h>
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
-
-namespace android {
-namespace conversion {
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-using ::android::status_t;
-
-using ::android::String8;
-
-using ::android::hardware::media::V1_0::Rect;
-using ::android::hardware::media::V1_0::Region;
-
-using ::android::hardware::graphics::common::V1_0::Dataspace;
-
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-
-using ::android::hardware::media::V1_0::AnwBuffer;
-using ::android::GraphicBuffer;
-
-typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
- HGraphicBufferProducer;
-typedef ::android::IGraphicBufferProducer
- BGraphicBufferProducer;
-
-// native_handle_t helper functions.
-
-/**
- * \brief Take an fd and create a native handle containing only the given fd.
- * The created handle will need to be deleted manually with
- * `native_handle_delete()`.
- *
- * \param[in] fd The source file descriptor (of type `int`).
- * \return The create `native_handle_t*` that contains the given \p fd. If the
- * supplied \p fd is negative, the created native handle will contain no file
- * descriptors.
- *
- * If the native handle cannot be created, the return value will be
- * `nullptr`.
- *
- * This function does not duplicate the file descriptor.
- */
-native_handle_t* native_handle_create_from_fd(int fd);
-
-/**
- * \brief Extract a file descriptor from a native handle.
- *
- * \param[in] nh The source `native_handle_t*`.
- * \param[in] index The index of the file descriptor in \p nh to read from. This
- * input has the default value of `0`.
- * \return The `index`-th file descriptor in \p nh. If \p nh does not have
- * enough file descriptors, the returned value will be `-1`.
- *
- * This function does not duplicate the file descriptor.
- */
-int native_handle_read_fd(native_handle_t const* nh, int index = 0);
-
-/**
- * Conversion functions
- * ====================
- *
- * There are two main directions of conversion:
- * - `inTargetType(...)`: Create a wrapper whose lifetime depends on the
- * input. The wrapper has type `TargetType`.
- * - `toTargetType(...)`: Create a standalone object of type `TargetType` that
- * corresponds to the input. The lifetime of the output does not depend on the
- * lifetime of the input.
- * - `wrapIn(TargetType*, ...)`: Same as `inTargetType()`, but for `TargetType`
- * that cannot be copied and/or moved efficiently, or when there are multiple
- * output arguments.
- * - `convertTo(TargetType*, ...)`: Same as `toTargetType()`, but for
- * `TargetType` that cannot be copied and/or moved efficiently, or when there
- * are multiple output arguments.
- *
- * `wrapIn()` and `convertTo()` functions will take output arguments before
- * input arguments. Some of these functions might return a value to indicate
- * success or error.
- *
- * In converting or wrapping something as a Treble type that contains a
- * `hidl_handle`, `native_handle_t*` will need to be created and returned as
- * an additional output argument, hence only `wrapIn()` or `convertTo()` would
- * be available. The caller must call `native_handle_delete()` to deallocate the
- * returned native handle when it is no longer needed.
- *
- * For types that contain file descriptors, `inTargetType()` and `wrapAs()` do
- * not perform duplication of file descriptors, while `toTargetType()` and
- * `convertTo()` do.
- */
-
-/**
- * \brief Convert `Return<void>` to `binder::Status`.
- *
- * \param[in] t The source `Return<void>`.
- * \return The corresponding `binder::Status`.
- */
-// convert: Return<void> -> ::android::binder::Status
-::android::binder::Status toBinderStatus(Return<void> const& t);
-
-/**
- * \brief Convert `Return<void>` to `status_t`. This is for legacy binder calls.
- *
- * \param[in] t The source `Return<void>`.
- * \return The corresponding `status_t`.
- */
-// convert: Return<void> -> status_t
-status_t toStatusT(Return<void> const& t);
-
-/**
- * \brief Wrap `native_handle_t*` in `hidl_handle`.
- *
- * \param[in] nh The source `native_handle_t*`.
- * \return The `hidl_handle` that points to \p nh.
- */
-// wrap: native_handle_t* -> hidl_handle
-hidl_handle inHidlHandle(native_handle_t const* nh);
-
-/**
- * \brief Convert `int32_t` to `Dataspace`.
- *
- * \param[in] l The source `int32_t`.
- * \result The corresponding `Dataspace`.
- */
-// convert: int32_t -> Dataspace
-Dataspace toHardwareDataspace(int32_t l);
-
-/**
- * \brief Convert `Dataspace` to `int32_t`.
- *
- * \param[in] t The source `Dataspace`.
- * \result The corresponding `int32_t`.
- */
-// convert: Dataspace -> int32_t
-int32_t toRawDataspace(Dataspace const& t);
-
-/**
- * \brief Wrap an opaque buffer inside a `hidl_vec<uint8_t>`.
- *
- * \param[in] l The pointer to the beginning of the opaque buffer.
- * \param[in] size The size of the buffer.
- * \return A `hidl_vec<uint8_t>` that points to the buffer.
- */
-// wrap: void*, size_t -> hidl_vec<uint8_t>
-hidl_vec<uint8_t> inHidlBytes(void const* l, size_t size);
-
-/**
- * \brief Create a `hidl_vec<uint8_t>` that is a copy of an opaque buffer.
- *
- * \param[in] l The pointer to the beginning of the opaque buffer.
- * \param[in] size The size of the buffer.
- * \return A `hidl_vec<uint8_t>` that is a copy of the input buffer.
- */
-// convert: void*, size_t -> hidl_vec<uint8_t>
-hidl_vec<uint8_t> toHidlBytes(void const* l, size_t size);
-
-/**
- * \brief Wrap `GraphicBuffer` in `AnwBuffer`.
- *
- * \param[out] t The wrapper of type `AnwBuffer`.
- * \param[in] l The source `GraphicBuffer`.
- */
-// wrap: GraphicBuffer -> AnwBuffer
-void wrapAs(AnwBuffer* t, GraphicBuffer const& l);
-
-/**
- * \brief Convert `AnwBuffer` to `GraphicBuffer`.
- *
- * \param[out] l The destination `GraphicBuffer`.
- * \param[in] t The source `AnwBuffer`.
- *
- * This function will duplicate all file descriptors in \p t.
- */
-// convert: AnwBuffer -> GraphicBuffer
-// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
-bool convertTo(GraphicBuffer* l, AnwBuffer const& t);
-
-/**
- * Conversion functions for types outside media
- * ============================================
- *
- * Some objects in libui and libgui that were made to go through binder calls do
- * not expose ways to read or write their fields to the public. To pass an
- * object of this kind through the HIDL boundary, translation functions need to
- * work around the access restriction by using the publicly available
- * `flatten()` and `unflatten()` functions.
- *
- * All `flatten()` and `unflatten()` overloads follow the same convention as
- * follows:
- *
- * status_t flatten(ObjectType const& object,
- * [OtherType const& other, ...]
- * void*& buffer, size_t& size,
- * int*& fds, size_t& numFds)
- *
- * status_t unflatten(ObjectType* object,
- * [OtherType* other, ...,]
- * void*& buffer, size_t& size,
- * int*& fds, size_t& numFds)
- *
- * The number of `other` parameters varies depending on the `ObjectType`. For
- * example, in the process of unflattening an object that contains
- * `hidl_handle`, `other` is needed to hold `native_handle_t` objects that will
- * be created.
- *
- * The last four parameters always work the same way in all overloads of
- * `flatten()` and `unflatten()`:
- * - For `flatten()`, `buffer` is the pointer to the non-fd buffer to be filled,
- * `size` is the size (in bytes) of the non-fd buffer pointed to by `buffer`,
- * `fds` is the pointer to the fd buffer to be filled, and `numFds` is the
- * size (in ints) of the fd buffer pointed to by `fds`.
- * - For `unflatten()`, `buffer` is the pointer to the non-fd buffer to be read
- * from, `size` is the size (in bytes) of the non-fd buffer pointed to by
- * `buffer`, `fds` is the pointer to the fd buffer to be read from, and
- * `numFds` is the size (in ints) of the fd buffer pointed to by `fds`.
- * - After a successful call to `flatten()` or `unflatten()`, `buffer` and `fds`
- * will be advanced, while `size` and `numFds` will be decreased to reflect
- * how much storage/data of the two buffers (fd and non-fd) have been used.
- * - After an unsuccessful call, the values of `buffer`, `size`, `fds` and
- * `numFds` are invalid.
- *
- * The return value of a successful `flatten()` or `unflatten()` call will be
- * `OK` (also aliased as `NO_ERROR`). Any other values indicate a failure.
- *
- * For each object type that supports flattening, there will be two accompanying
- * functions: `getFlattenedSize()` and `getFdCount()`. `getFlattenedSize()` will
- * return the size of the non-fd buffer that the object will need for
- * flattening. `getFdCount()` will return the size of the fd buffer that the
- * object will need for flattening.
- *
- * The set of these four functions, `getFlattenedSize()`, `getFdCount()`,
- * `flatten()` and `unflatten()`, are similar to functions of the same name in
- * the abstract class `Flattenable`. The only difference is that functions in
- * this file are not member functions of the object type. For example, we write
- *
- * flatten(x, buffer, size, fds, numFds)
- *
- * instead of
- *
- * x.flatten(buffer, size, fds, numFds)
- *
- * because we cannot modify the type of `x`.
- *
- * There is one exception to the naming convention: `hidl_handle` that
- * represents a fence. The four functions for this "Fence" type have the word
- * "Fence" attched to their names because the object type, which is
- * `hidl_handle`, does not carry the special meaning that the object itself can
- * only contain zero or one file descriptor.
- */
-
-// Ref: frameworks/native/libs/ui/Fence.cpp
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten a fence.
- *
- * \param[in] fence The input fence of type `hidl_handle`.
- * \return The required size of the flat buffer.
- *
- * The current version of this function always returns 4, which is the number of
- * bytes required to store the number of file descriptors contained in the fd
- * part of the flat buffer.
- */
-size_t getFenceFlattenedSize(hidl_handle const& fence);
-
-/**
- * \brief Return the number of file descriptors contained in a fence.
- *
- * \param[in] fence The input fence of type `hidl_handle`.
- * \return `0` if \p fence does not contain a valid file descriptor, or `1`
- * otherwise.
- */
-size_t getFenceFdCount(hidl_handle const& fence);
-
-/**
- * \brief Unflatten `Fence` to `hidl_handle`.
- *
- * \param[out] fence The destination `hidl_handle`.
- * \param[out] nh The underlying native handle.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will point to a newly created
- * native handle, which needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-status_t unflattenFence(hidl_handle* fence, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
-
-/**
- * \brief Flatten `hidl_handle` as `Fence`.
- *
- * \param[in] t The source `hidl_handle`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t flattenFence(hidl_handle const& fence,
- void*& buffer, size_t& size, int*& fds, size_t& numFds);
-
-/**
- * \brief Wrap `Fence` in `hidl_handle`.
- *
- * \param[out] t The wrapper of type `hidl_handle`.
- * \param[out] nh The native handle pointed to by \p t.
- * \param[in] l The source `Fence`.
- *
- * On success, \p nh will hold a newly created native handle, which must be
- * deleted manually with `native_handle_delete()` afterwards.
- */
-// wrap: Fence -> hidl_handle
-bool wrapAs(hidl_handle* t, native_handle_t** nh, Fence const& l);
-
-/**
- * \brief Convert `hidl_handle` to `Fence`.
- *
- * \param[out] l The destination `Fence`. `l` must not have been used
- * (`l->isValid()` must return `false`) before this function is called.
- * \param[in] t The source `hidl_handle`.
- *
- * If \p t contains a valid file descriptor, it will be duplicated.
- */
-// convert: hidl_handle -> Fence
-bool convertTo(Fence* l, hidl_handle const& t);
-
-// Ref: frameworks/native/libs/ui/FenceTime.cpp: FenceTime::Snapshot
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `FenceTimeSnapshot`.
- *
- * \param[in] t The input `FenceTimeSnapshot`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(HGraphicBufferProducer::FenceTimeSnapshot const& t);
-
-/**
- * \brief Return the number of file descriptors contained in
- * `FenceTimeSnapshot`.
- *
- * \param[in] t The input `FenceTimeSnapshot`.
- * \return The number of file descriptors contained in \p snapshot.
- */
-size_t getFdCount(HGraphicBufferProducer::FenceTimeSnapshot const& t);
-
-/**
- * \brief Flatten `FenceTimeSnapshot`.
- *
- * \param[in] t The source `FenceTimeSnapshot`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate the file descriptor in `t.fence` if `t.state ==
- * FENCE`.
- */
-status_t flatten(HGraphicBufferProducer::FenceTimeSnapshot const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds);
-
-/**
- * \brief Unflatten `FenceTimeSnapshot`.
- *
- * \param[out] t The destination `FenceTimeSnapshot`.
- * \param[out] nh The underlying native handle.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR` and the constructed snapshot contains a
- * file descriptor, \p nh will be created to hold that file descriptor. In this
- * case, \p nh needs to be deleted with `native_handle_delete()` afterwards.
- */
-status_t unflatten(
- HGraphicBufferProducer::FenceTimeSnapshot* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
-
-// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventsDelta
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(HGraphicBufferProducer::FrameEventsDelta const& t);
-
-/**
- * \brief Return the number of file descriptors contained in
- * `FrameEventsDelta`.
- *
- * \param[in] t The input `FrameEventsDelta`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(HGraphicBufferProducer::FrameEventsDelta const& t);
-
-/**
- * \brief Unflatten `FrameEventsDelta`.
- *
- * \param[out] t The destination `FrameEventsDelta`.
- * \param[out] nh The underlying array of native handles.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will have length 4, and it will be
- * populated with `nullptr` or newly created handles. Each non-null slot in \p
- * nh will need to be deleted manually with `native_handle_delete()`.
- */
-status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
- std::vector<native_handle_t*>* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
-
-/**
- * \brief Flatten `FrameEventsDelta`.
- *
- * \param[in] t The source `FrameEventsDelta`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate file descriptors contained in \p t.
- */
-// Ref: frameworks/native/libs/gui/FrameTimestamp.cpp:
-// FrameEventsDelta::flatten
-status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t numFds);
-
-// Ref: frameworks/native/libs/gui/FrameTimestamps.cpp: FrameEventHistoryDelta
-
-/**
- * \brief Return the size of the non-fd buffer required to flatten
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t);
-
-/**
- * \brief Return the number of file descriptors contained in
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[in] t The input `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t);
-
-/**
- * \brief Unflatten `FrameEventHistoryDelta`.
- *
- * \param[out] t The destination `FrameEventHistoryDelta`.
- * \param[out] nh The underlying array of arrays of native handles.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR`, \p nh will be populated with `nullptr` or
- * newly created handles. The second dimension of \p nh will be 4. Each non-null
- * slot in \p nh will need to be deleted manually with `native_handle_delete()`.
- */
-status_t unflatten(
- HGraphicBufferProducer::FrameEventHistoryDelta* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
-
-/**
- * \brief Flatten `FrameEventHistoryDelta`.
- *
- * \param[in] t The source `FrameEventHistoryDelta`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate file descriptors contained in \p t.
- */
-status_t flatten(
- HGraphicBufferProducer::FrameEventHistoryDelta const& t,
- void*& buffer, size_t& size, int*& fds, size_t& numFds);
-
-/**
- * \brief Wrap `::android::FrameEventHistoryData` in
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::FrameEventHistoryDelta`.
- * \param[out] nh The array of array of native handles that are referred to by
- * members of \p t.
- * \param[in] l The source `::android::FrameEventHistoryDelta`.
- *
- * On success, each member of \p nh will be either `nullptr` or a newly created
- * native handle. All the non-`nullptr` elements must be deleted individually
- * with `native_handle_delete()`.
- */
-bool wrapAs(HGraphicBufferProducer::FrameEventHistoryDelta* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- ::android::FrameEventHistoryDelta const& l);
-
-/**
- * \brief Convert `HGraphicBufferProducer::FrameEventHistoryDelta` to
- * `::android::FrameEventHistoryDelta`.
- *
- * \param[out] l The destination `::android::FrameEventHistoryDelta`.
- * \param[in] t The source `HGraphicBufferProducer::FrameEventHistoryDelta`.
- *
- * This function will duplicate all file descriptors contained in \p t.
- */
-bool convertTo(
- ::android::FrameEventHistoryDelta* l,
- HGraphicBufferProducer::FrameEventHistoryDelta const& t);
-
-// Ref: frameworks/native/libs/ui/Region.cpp
-
-/**
- * \brief Return the size of the buffer required to flatten `Region`.
- *
- * \param[in] t The input `Region`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(Region const& t);
-
-/**
- * \brief Unflatten `Region`.
- *
- * \param[out] t The destination `Region`.
- * \param[in,out] buffer The pointer to the flat buffer.
- * \param[in,out] size The size of the flat buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t unflatten(Region* t, void const*& buffer, size_t& size);
-
-/**
- * \brief Flatten `Region`.
- *
- * \param[in] t The source `Region`.
- * \param[in,out] buffer The pointer to the flat buffer.
- * \param[in,out] size The size of the flat buffer.
- * \return `NO_ERROR` on success; other value on failure.
- */
-status_t flatten(Region const& t, void*& buffer, size_t& size);
-
-/**
- * \brief Convert `::android::Region` to `Region`.
- *
- * \param[out] t The destination `Region`.
- * \param[in] l The source `::android::Region`.
- */
-// convert: ::android::Region -> Region
-bool convertTo(Region* t, ::android::Region const& l);
-
-/**
- * \brief Convert `Region` to `::android::Region`.
- *
- * \param[out] l The destination `::android::Region`.
- * \param[in] t The source `Region`.
- */
-// convert: Region -> ::android::Region
-bool convertTo(::android::Region* l, Region const& t);
-
-// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
-// BGraphicBufferProducer::QueueBufferInput
-
-/**
- * \brief Return the size of the buffer required to flatten
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return The required size of the flat buffer.
- */
-size_t getFlattenedSize(HGraphicBufferProducer::QueueBufferInput const& t);
-
-/**
- * \brief Return the number of file descriptors contained in
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The input `HGraphicBufferProducer::QueueBufferInput`.
- * \return The number of file descriptors contained in \p t.
- */
-size_t getFdCount(
- HGraphicBufferProducer::QueueBufferInput const& t);
-/**
- * \brief Flatten `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The native handle cloned from `t.fence`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * This function will duplicate the file descriptor in `t.fence`. */
-status_t flatten(HGraphicBufferProducer::QueueBufferInput const& t,
- native_handle_t** nh,
- void*& buffer, size_t& size, int*& fds, size_t& numFds);
-
-/**
- * \brief Unflatten `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] t The destination `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The underlying native handle for `t->fence`.
- * \param[in,out] buffer The pointer to the flat non-fd buffer.
- * \param[in,out] size The size of the flat non-fd buffer.
- * \param[in,out] fds The pointer to the flat fd buffer.
- * \param[in,out] numFds The size of the flat fd buffer.
- * \return `NO_ERROR` on success; other value on failure.
- *
- * If the return value is `NO_ERROR` and `t->fence` contains a valid file
- * descriptor, \p nh will be a newly created native handle holding that file
- * descriptor. \p nh needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-status_t unflatten(
- HGraphicBufferProducer::QueueBufferInput* t, native_handle_t** nh,
- void const*& buffer, size_t& size, int const*& fds, size_t& numFds);
-
-/**
- * \brief Wrap `BGraphicBufferProducer::QueueBufferInput` in
- * `HGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::QueueBufferInput`.
- * \param[out] nh The underlying native handle for `t->fence`.
- * \param[in] l The source `BGraphicBufferProducer::QueueBufferInput`.
- *
- * If the return value is `true` and `t->fence` contains a valid file
- * descriptor, \p nh will be a newly created native handle holding that file
- * descriptor. \p nh needs to be deleted with `native_handle_delete()`
- * afterwards.
- */
-bool wrapAs(
- HGraphicBufferProducer::QueueBufferInput* t,
- native_handle_t** nh,
- BGraphicBufferProducer::QueueBufferInput const& l);
-
-/**
- * \brief Convert `HGraphicBufferProducer::QueueBufferInput` to
- * `BGraphicBufferProducer::QueueBufferInput`.
- *
- * \param[out] l The destination `BGraphicBufferProducer::QueueBufferInput`.
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferInput`.
- *
- * If `t.fence` has a valid file descriptor, it will be duplicated.
- */
-bool convertTo(
- BGraphicBufferProducer::QueueBufferInput* l,
- HGraphicBufferProducer::QueueBufferInput const& t);
-
-// Ref: frameworks/native/libs/gui/BGraphicBufferProducer.cpp:
-// BGraphicBufferProducer::QueueBufferOutput
-
-/**
- * \brief Wrap `BGraphicBufferProducer::QueueBufferOutput` in
- * `HGraphicBufferProducer::QueueBufferOutput`.
- *
- * \param[out] t The wrapper of type
- * `HGraphicBufferProducer::QueueBufferOutput`.
- * \param[out] nh The array of array of native handles that are referred to by
- * members of \p t.
- * \param[in] l The source `BGraphicBufferProducer::QueueBufferOutput`.
- *
- * On success, each member of \p nh will be either `nullptr` or a newly created
- * native handle. All the non-`nullptr` elements must be deleted individually
- * with `native_handle_delete()`.
- */
-// wrap: BGraphicBufferProducer::QueueBufferOutput ->
-// HGraphicBufferProducer::QueueBufferOutput
-bool wrapAs(HGraphicBufferProducer::QueueBufferOutput* t,
- std::vector<std::vector<native_handle_t*> >* nh,
- BGraphicBufferProducer::QueueBufferOutput const& l);
-
-/**
- * \brief Convert `HGraphicBufferProducer::QueueBufferOutput` to
- * `BGraphicBufferProducer::QueueBufferOutput`.
- *
- * \param[out] l The destination `BGraphicBufferProducer::QueueBufferOutput`.
- * \param[in] t The source `HGraphicBufferProducer::QueueBufferOutput`.
- *
- * This function will duplicate all file descriptors contained in \p t.
- */
-// convert: HGraphicBufferProducer::QueueBufferOutput ->
-// BGraphicBufferProducer::QueueBufferOutput
-bool convertTo(
- BGraphicBufferProducer::QueueBufferOutput* l,
- HGraphicBufferProducer::QueueBufferOutput const& t);
-
-/**
- * \brief Convert `BGraphicBufferProducer::DisconnectMode` to
- * `HGraphicBufferProducer::DisconnectMode`.
- *
- * \param[in] l The source `BGraphicBufferProducer::DisconnectMode`.
- * \return The corresponding `HGraphicBufferProducer::DisconnectMode`.
- */
-HGraphicBufferProducer::DisconnectMode toHidlDisconnectMode(
- BGraphicBufferProducer::DisconnectMode l);
-
-/**
- * \brief Convert `HGraphicBufferProducer::DisconnectMode` to
- * `BGraphicBufferProducer::DisconnectMode`.
- *
- * \param[in] l The source `HGraphicBufferProducer::DisconnectMode`.
- * \return The corresponding `BGraphicBufferProducer::DisconnectMode`.
- */
-BGraphicBufferProducer::DisconnectMode toGuiDisconnectMode(
- HGraphicBufferProducer::DisconnectMode t);
-
-} // namespace conversion
-} // namespace android
-
-#endif // MEDIA_STAGEFRIGHT_BQHELPER_CONVERSION_H_
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
index bf329b9..b4c4d4a 100644
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
+++ b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
@@ -19,8 +19,6 @@
#define GRAPHIC_BUFFER_SOURCE_H_
#include <binder/Status.h>
-#include <gui/BufferQueue.h>
-#include <gui/IGraphicBufferProducer.h>
#include <utils/RefBase.h>
#include <media/hardware/VideoAPI.h>
@@ -28,13 +26,17 @@
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/bqhelper/ComponentWrapper.h>
+#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
+#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
namespace android {
using ::android::binder::Status;
struct FrameDropper;
-
+class BufferItem;
+class IGraphicBufferProducer;
+class IGraphicBufferConsumer;
/*
* This class is used to feed codecs from a Surface via BufferQueue or
* HW producer.
@@ -82,9 +84,12 @@
// Returns the handle to the producer side of the BufferQueue. Buffers
// queued on this will be received by GraphicBufferSource.
- sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
- return mProducer;
- }
+ sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
+ // Returns the handle to the bufferqueue HAL (V1_0) producer side of the BufferQueue.
+ // Buffers queued on this will be received by GraphicBufferSource.
+ sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>
+ getHGraphicBufferProducer_V1_0() const;
// Returns the handle to the bufferqueue HAL producer side of the BufferQueue.
// Buffers queued on this will be received by GraphicBufferSource.
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WGraphicBufferProducer.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WGraphicBufferProducer.h
deleted file mode 100644
index 8ddf20f..0000000
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WGraphicBufferProducer.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
- * Copyright 2016, 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 MEDIA_STAGEFRIGHT_WGRAPHICBUFFERPRODUCER_H_
-#define MEDIA_STAGEFRIGHT_WGRAPHICBUFFERPRODUCER_H_
-
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-#include <binder/Binder.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IProducerListener.h>
-#include <media/stagefright/bqhelper/Conversion.h>
-#include <media/stagefright/bqhelper/WProducerListener.h>
-#include <system/window.h>
-
-#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
-
-namespace android {
-
-using ::android::hardware::media::V1_0::AnwBuffer;
-using ::android::hidl::base::V1_0::IBase;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_handle;
-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::sp;
-
-typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IGraphicBufferProducer HGraphicBufferProducer;
-typedef ::android::hardware::graphics::bufferqueue::V1_0::
- IProducerListener HProducerListener;
-
-typedef ::android::IGraphicBufferProducer BGraphicBufferProducer;
-typedef ::android::IProducerListener BProducerListener;
-using ::android::BnGraphicBufferProducer;
-
-#ifndef LOG
-struct LOG_dummy {
- template <typename T>
- LOG_dummy& operator<< (const T&) { return *this; }
-};
-
-#define LOG(x) LOG_dummy()
-#endif
-
-// Instantiate only if HGraphicBufferProducer is base of BASE.
-template <typename BASE,
- typename = typename std::enable_if<std::is_base_of<HGraphicBufferProducer, BASE>::value>::type>
-struct TWGraphicBufferProducer : public BASE {
- TWGraphicBufferProducer(sp<BGraphicBufferProducer> const& base) : mBase(base) {}
- Return<void> requestBuffer(int32_t slot, HGraphicBufferProducer::requestBuffer_cb _hidl_cb) override {
- sp<GraphicBuffer> buf;
- status_t status = mBase->requestBuffer(slot, &buf);
- AnwBuffer anwBuffer;
- if (buf != nullptr) {
- ::android::conversion::wrapAs(&anwBuffer, *buf);
- }
- _hidl_cb(static_cast<int32_t>(status), anwBuffer);
- return Void();
- }
-
- Return<int32_t> setMaxDequeuedBufferCount(int32_t maxDequeuedBuffers) override {
- return static_cast<int32_t>(mBase->setMaxDequeuedBufferCount(
- static_cast<int>(maxDequeuedBuffers)));
- }
-
- Return<int32_t> setAsyncMode(bool async) override {
- return static_cast<int32_t>(mBase->setAsyncMode(async));
- }
-
- Return<void> dequeueBuffer(
- uint32_t width, uint32_t height,
- ::android::hardware::graphics::common::V1_0::PixelFormat format, uint32_t usage,
- bool getFrameTimestamps, HGraphicBufferProducer::dequeueBuffer_cb _hidl_cb) override {
- int slot;
- sp<Fence> fence;
- ::android::FrameEventHistoryDelta outTimestamps;
- status_t status = mBase->dequeueBuffer(
- &slot, &fence, width, height,
- static_cast<::android::PixelFormat>(format), usage, nullptr,
- getFrameTimestamps ? &outTimestamps : nullptr);
- hidl_handle tFence;
- HGraphicBufferProducer::FrameEventHistoryDelta tOutTimestamps;
-
- native_handle_t* nh = nullptr;
- if ((fence == nullptr) || !::android::conversion::wrapAs(&tFence, &nh, *fence)) {
- LOG(ERROR) << "TWGraphicBufferProducer::dequeueBuffer - "
- "Invalid output fence";
- _hidl_cb(static_cast<int32_t>(status),
- static_cast<int32_t>(slot),
- tFence,
- tOutTimestamps);
- return Void();
- }
- std::vector<std::vector<native_handle_t*> > nhAA;
- if (getFrameTimestamps && !::android::conversion::wrapAs(&tOutTimestamps, &nhAA, outTimestamps)) {
- LOG(ERROR) << "TWGraphicBufferProducer::dequeueBuffer - "
- "Invalid output timestamps";
- _hidl_cb(static_cast<int32_t>(status),
- static_cast<int32_t>(slot),
- tFence,
- tOutTimestamps);
- native_handle_delete(nh);
- return Void();
- }
-
- _hidl_cb(static_cast<int32_t>(status),
- static_cast<int32_t>(slot),
- tFence,
- tOutTimestamps);
- native_handle_delete(nh);
- if (getFrameTimestamps) {
- for (auto& nhA : nhAA) {
- for (auto& handle : nhA) {
- native_handle_delete(handle);
- }
- }
- }
- return Void();
- }
-
- Return<int32_t> detachBuffer(int32_t slot) override {
- return static_cast<int32_t>(mBase->detachBuffer(slot));
- }
-
- Return<void> detachNextBuffer(HGraphicBufferProducer::detachNextBuffer_cb _hidl_cb) override {
- sp<GraphicBuffer> outBuffer;
- sp<Fence> outFence;
- status_t status = mBase->detachNextBuffer(&outBuffer, &outFence);
- AnwBuffer tBuffer;
- hidl_handle tFence;
-
- if (outBuffer == nullptr) {
- LOG(ERROR) << "TWGraphicBufferProducer::detachNextBuffer - "
- "Invalid output buffer";
- _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
- return Void();
- }
- ::android::conversion::wrapAs(&tBuffer, *outBuffer);
- native_handle_t* nh = nullptr;
- if ((outFence != nullptr) && !::android::conversion::wrapAs(&tFence, &nh, *outFence)) {
- LOG(ERROR) << "TWGraphicBufferProducer::detachNextBuffer - "
- "Invalid output fence";
- _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
- return Void();
- }
-
- _hidl_cb(static_cast<int32_t>(status), tBuffer, tFence);
- native_handle_delete(nh);
- return Void();
- }
-
- Return<void> attachBuffer(const AnwBuffer& buffer, HGraphicBufferProducer::attachBuffer_cb _hidl_cb) override {
- int outSlot;
- sp<GraphicBuffer> lBuffer = new GraphicBuffer();
- if (!::android::conversion::convertTo(lBuffer.get(), buffer)) {
- LOG(ERROR) << "TWGraphicBufferProducer::attachBuffer - "
- "Invalid input native window buffer";
- _hidl_cb(static_cast<int32_t>(BAD_VALUE), -1);
- return Void();
- }
- status_t status = mBase->attachBuffer(&outSlot, lBuffer);
-
- _hidl_cb(static_cast<int32_t>(status), static_cast<int32_t>(outSlot));
- return Void();
- }
-
- Return<void> queueBuffer(
- int32_t slot, const HGraphicBufferProducer::QueueBufferInput& input,
- HGraphicBufferProducer::queueBuffer_cb _hidl_cb) override {
- HGraphicBufferProducer::QueueBufferOutput tOutput;
- BGraphicBufferProducer::QueueBufferInput lInput(
- 0, false, HAL_DATASPACE_UNKNOWN,
- ::android::Rect(0, 0, 1, 1),
- NATIVE_WINDOW_SCALING_MODE_FREEZE,
- 0, ::android::Fence::NO_FENCE);
- if (!::android::conversion::convertTo(&lInput, input)) {
- LOG(ERROR) << "TWGraphicBufferProducer::queueBuffer - "
- "Invalid input";
- _hidl_cb(static_cast<int32_t>(BAD_VALUE), tOutput);
- return Void();
- }
- BGraphicBufferProducer::QueueBufferOutput lOutput;
- status_t status = mBase->queueBuffer(
- static_cast<int>(slot), lInput, &lOutput);
-
- std::vector<std::vector<native_handle_t*> > nhAA;
- if (!::android::conversion::wrapAs(&tOutput, &nhAA, lOutput)) {
- LOG(ERROR) << "TWGraphicBufferProducer::queueBuffer - "
- "Invalid output";
- _hidl_cb(static_cast<int32_t>(BAD_VALUE), tOutput);
- return Void();
- }
-
- _hidl_cb(static_cast<int32_t>(status), tOutput);
- for (auto& nhA : nhAA) {
- for (auto& nh : nhA) {
- native_handle_delete(nh);
- }
- }
- return Void();
- }
-
- Return<int32_t> cancelBuffer(int32_t slot, const hidl_handle& fence) override {
- sp<Fence> lFence = new Fence();
- if (!::android::conversion::convertTo(lFence.get(), fence)) {
- LOG(ERROR) << "TWGraphicBufferProducer::cancelBuffer - "
- "Invalid input fence";
- return static_cast<int32_t>(BAD_VALUE);
- }
- return static_cast<int32_t>(mBase->cancelBuffer(static_cast<int>(slot), lFence));
- }
-
- Return<void> query(int32_t what, HGraphicBufferProducer::query_cb _hidl_cb) override {
- int lValue;
- int lReturn = mBase->query(static_cast<int>(what), &lValue);
- _hidl_cb(static_cast<int32_t>(lReturn), static_cast<int32_t>(lValue));
- return Void();
- }
-
- Return<void> connect(const sp<HProducerListener>& listener,
- int32_t api, bool producerControlledByApp,
- HGraphicBufferProducer::connect_cb _hidl_cb) override {
- sp<BProducerListener> lListener = listener == nullptr ?
- nullptr : new LWProducerListener(listener);
- BGraphicBufferProducer::QueueBufferOutput lOutput;
- status_t status = mBase->connect(lListener,
- static_cast<int>(api),
- producerControlledByApp,
- &lOutput);
-
- HGraphicBufferProducer::QueueBufferOutput tOutput;
- std::vector<std::vector<native_handle_t*> > nhAA;
- if (!::android::conversion::wrapAs(&tOutput, &nhAA, lOutput)) {
- LOG(ERROR) << "TWGraphicBufferProducer::connect - "
- "Invalid output";
- _hidl_cb(static_cast<int32_t>(status), tOutput);
- return Void();
- }
-
- _hidl_cb(static_cast<int32_t>(status), tOutput);
- for (auto& nhA : nhAA) {
- for (auto& nh : nhA) {
- native_handle_delete(nh);
- }
- }
- return Void();
- }
-
- Return<int32_t> disconnect(
- int32_t api,
- HGraphicBufferProducer::DisconnectMode mode) override {
- return static_cast<int32_t>(mBase->disconnect(
- static_cast<int>(api),
- ::android::conversion::toGuiDisconnectMode(mode)));
- }
-
- Return<int32_t> setSidebandStream(const hidl_handle& stream) override {
- return static_cast<int32_t>(mBase->setSidebandStream(NativeHandle::create(
- stream ? native_handle_clone(stream) : NULL, true)));
- }
-
- Return<void> allocateBuffers(
- uint32_t width, uint32_t height,
- ::android::hardware::graphics::common::V1_0::PixelFormat format,
- uint32_t usage) override {
- mBase->allocateBuffers(
- width, height,
- static_cast<::android::PixelFormat>(format),
- usage);
- return Void();
- }
-
- Return<int32_t> allowAllocation(bool allow) override {
- return static_cast<int32_t>(mBase->allowAllocation(allow));
- }
-
- Return<int32_t> setGenerationNumber(uint32_t generationNumber) override {
- return static_cast<int32_t>(mBase->setGenerationNumber(generationNumber));
- }
-
- Return<void> getConsumerName(HGraphicBufferProducer::getConsumerName_cb _hidl_cb) override {
- _hidl_cb(mBase->getConsumerName().string());
- return Void();
- }
-
- Return<int32_t> setSharedBufferMode(bool sharedBufferMode) override {
- return static_cast<int32_t>(mBase->setSharedBufferMode(sharedBufferMode));
- }
-
- Return<int32_t> setAutoRefresh(bool autoRefresh) override {
- return static_cast<int32_t>(mBase->setAutoRefresh(autoRefresh));
- }
-
- Return<int32_t> setDequeueTimeout(int64_t timeoutNs) override {
- return static_cast<int32_t>(mBase->setDequeueTimeout(timeoutNs));
- }
-
- Return<void> getLastQueuedBuffer(HGraphicBufferProducer::getLastQueuedBuffer_cb _hidl_cb) override {
- sp<GraphicBuffer> lOutBuffer = new GraphicBuffer();
- sp<Fence> lOutFence = new Fence();
- float lOutTransformMatrix[16];
- status_t status = mBase->getLastQueuedBuffer(
- &lOutBuffer, &lOutFence, lOutTransformMatrix);
-
- AnwBuffer tOutBuffer;
- if (lOutBuffer != nullptr) {
- ::android::conversion::wrapAs(&tOutBuffer, *lOutBuffer);
- }
- hidl_handle tOutFence;
- native_handle_t* nh = nullptr;
- if ((lOutFence == nullptr) || !::android::conversion::wrapAs(&tOutFence, &nh, *lOutFence)) {
- LOG(ERROR) << "TWGraphicBufferProducer::getLastQueuedBuffer - "
- "Invalid output fence";
- _hidl_cb(static_cast<int32_t>(status),
- tOutBuffer,
- tOutFence,
- hidl_array<float, 16>());
- return Void();
- }
- hidl_array<float, 16> tOutTransformMatrix(lOutTransformMatrix);
-
- _hidl_cb(static_cast<int32_t>(status), tOutBuffer, tOutFence, tOutTransformMatrix);
- native_handle_delete(nh);
- return Void();
- }
-
- Return<void> getFrameTimestamps(HGraphicBufferProducer::getFrameTimestamps_cb _hidl_cb) override {
- ::android::FrameEventHistoryDelta lDelta;
- mBase->getFrameTimestamps(&lDelta);
-
- HGraphicBufferProducer::FrameEventHistoryDelta tDelta;
- std::vector<std::vector<native_handle_t*> > nhAA;
- if (!::android::conversion::wrapAs(&tDelta, &nhAA, lDelta)) {
- LOG(ERROR) << "TWGraphicBufferProducer::getFrameTimestamps - "
- "Invalid output frame timestamps";
- _hidl_cb(tDelta);
- return Void();
- }
-
- _hidl_cb(tDelta);
- for (auto& nhA : nhAA) {
- for (auto& nh : nhA) {
- native_handle_delete(nh);
- }
- }
- return Void();
- }
-
- Return<void> getUniqueId(HGraphicBufferProducer::getUniqueId_cb _hidl_cb) override {
- uint64_t outId;
- status_t status = mBase->getUniqueId(&outId);
- _hidl_cb(static_cast<int32_t>(status), outId);
- return Void();
- }
-
-private:
- sp<BGraphicBufferProducer> mBase;
-};
-
-} // namespace android
-
-#endif // MEDIA_STAGEFRIGHT_WGRAPHICBUFFERPRODUCER_H_
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WProducerListener.h b/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WProducerListener.h
deleted file mode 100644
index febba87..0000000
--- a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/WProducerListener.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2016, 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 MEDIA_STAGEFRIGHT_WPRODUCERLISTENER_H_
-#define MEDIA_STAGEFRIGHT_WPRODUCERLISTENER_H_
-
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-#include <binder/IBinder.h>
-#include <gui/IProducerListener.h>
-
-#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
-
-namespace android {
-
-using ::android::hidl::base::V1_0::IBase;
-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::sp;
-
-typedef ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener
- HProducerListener;
-typedef ::android::IProducerListener
- BProducerListener;
-using ::android::BnProducerListener;
-
-struct TWProducerListener : public HProducerListener {
- sp<BProducerListener> mBase;
- TWProducerListener(sp<BProducerListener> const& base);
- Return<void> onBufferReleased() override;
- Return<bool> needsReleaseNotify() override;
-};
-
-class LWProducerListener : public BnProducerListener {
-public:
- sp<HProducerListener> mBase;
- LWProducerListener(sp<HProducerListener> const& base);
- void onBufferReleased() override;
- bool needsReleaseNotify() override;
-};
-
-} // namespace android
-
-#endif // MEDIA_STAGEFRIGHT_WPRODUCERLISTENER_H_
diff --git a/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp b/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
index b80555b..c0e4c51 100644
--- a/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
+++ b/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
@@ -131,7 +131,7 @@
int16 lo, hi;
L_tmp = ((int32)x_hi[0]) << 16;
- L_tmp += ((int32)x_lo[0]) << 4;
+ L_tmp += (((int32)x_lo[0]) << 4) & 0xFFFF;
L_tmp = shl_int32(L_tmp, 3);
L_tmp = fxp_mac_16by16(*mem, mu, L_tmp),
@@ -144,7 +144,7 @@
for (i = 1; i < L - 1; i++)
{
L_tmp = ((int32)hi) << 16;
- L_tmp += ((int32)lo) << 4;
+ L_tmp += (((int32)lo) << 4) & 0xFFFF;
L_tmp = shl_int32(L_tmp, 3);
L_tmp = fxp_mac_16by16(y[i - 1], mu, L_tmp),
L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
@@ -153,7 +153,7 @@
hi = x_hi[i+1];
}
L_tmp = ((int32)hi) << 16;
- L_tmp += ((int32)lo) << 4;
+ L_tmp += (((int32)lo) << 4) & 0xFFFF;
L_tmp = shl_int32(L_tmp, 3);
L_tmp = fxp_mac_16by16(y[i - 1], mu, L_tmp),
L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index bf5e243..5a4b2f8 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -580,7 +580,7 @@
status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
bool unsupportedResolution =
- (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
+ (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
/* Check for unsupported dimensions */
if (unsupportedResolution) {
@@ -590,7 +590,7 @@
return;
}
- bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
+ bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
if (allocationFailed) {
ALOGE("Allocation failure in decoder");
notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
@@ -598,7 +598,14 @@
return;
}
- bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
+ if (IS_IVD_FATAL_ERROR(s_dec_op.u4_error_code)) {
+ ALOGE("Fatal Error : 0x%x", s_dec_op.u4_error_code);
+ notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
getVUIParams();
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
index 8253b7d..6d2e084 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.h
@@ -36,7 +36,7 @@
#define DEFAULT_MAX_REORDER_FRM 0
#define DEFAULT_QP_MIN 10
#define DEFAULT_QP_MAX 40
-#define DEFAULT_MAX_BITRATE 20000000
+#define DEFAULT_MAX_BITRATE 240000000
#define DEFAULT_MAX_SRCH_RANGE_X 256
#define DEFAULT_MAX_SRCH_RANGE_Y 256
#define DEFAULT_MAX_FRAMERATE 120000
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index bb7d361..f6ae1f4 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -569,7 +569,7 @@
status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
bool unsupportedResolution =
- (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
+ (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
/* Check for unsupported dimensions */
if (unsupportedResolution) {
@@ -579,7 +579,8 @@
return;
}
- bool allocationFailed = (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & 0xFF));
+ bool allocationFailed =
+ (IVD_MEM_ALLOC_FAILED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
if (allocationFailed) {
ALOGE("Allocation failure in decoder");
notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
@@ -587,7 +588,14 @@
return;
}
- bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
+ if (IS_IVD_FATAL_ERROR(s_dec_op.u4_error_code)) {
+ ALOGE("Fatal Error : 0x%x", s_dec_op.u4_error_code);
+ notify(OMX_EventError, OMX_ErrorUnsupportedSetting, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & IVD_ERROR_MASK));
getVUIParams();
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
index a8b88fd..180694b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
@@ -123,6 +123,15 @@
#define TRESPASS_DBG(...)
#endif
+#ifndef LOG_ALWAYS_FATAL_IN_CHILD_PROC
+#define LOG_ALWAYS_FATAL_IN_CHILD_PROC(...) \
+ do { \
+ if (fork() == 0) { \
+ LOG_ALWAYS_FATAL(__VA_ARGS__); \
+ } \
+ } while (false)
+#endif
+
struct ADebug {
enum Level {
kDebugNone, // no debug
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index c84614a..50d7724 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -356,16 +356,18 @@
}
}
-constexpr int32_t AV1Profile0 = 0x01;
-constexpr int32_t AV1Profile1 = 0x02;
-constexpr int32_t AV1Profile2 = 0x04;
+constexpr int32_t AV1ProfileMain8 = 0x1;
+constexpr int32_t AV1ProfileMain10 = 0x2;
+constexpr int32_t AV1ProfileMain10HDR10 = 0x1000;
+constexpr int32_t AV1ProfileMain10HDR10Plus = 0x2000;
inline static const char *asString_AV1Profile(int32_t i, const char *def = "??") {
switch (i) {
- case AV1Profile0: return "0";
- case AV1Profile1: return "1";
- case AV1Profile2: return "2";
- default: return def;
+ case AV1ProfileMain8: return "Main8";
+ case AV1ProfileMain10: return "Main10HDR";
+ case AV1ProfileMain10HDR10: return "Main10HDR10";
+ case AV1ProfileMain10HDR10Plus: return "Main10HDRPlus";
+ default: return def;
}
}
diff --git a/media/libstagefright/include/media/stagefright/SurfaceUtils.h b/media/libstagefright/include/media/stagefright/SurfaceUtils.h
index 689e458..ae55c65 100644
--- a/media/libstagefright/include/media/stagefright/SurfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/SurfaceUtils.h
@@ -19,8 +19,10 @@
#define SURFACE_UTILS_H_
#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
struct ANativeWindow;
+class Surface;
namespace android {
@@ -40,6 +42,15 @@
status_t nativeWindowConnect(ANativeWindow *surface, const char *reason);
status_t nativeWindowDisconnect(ANativeWindow *surface, const char *reason);
+/**
+ * Disable buffer dropping behavior of BufferQueue if target sdk of application
+ * is Q or later. If the caller is not an app (e.g. MediaPlayer in mediaserver)
+ * retain buffer dropping behavior.
+ *
+ * @return NO_ERROR
+ */
+status_t disableLegacyBufferDropPostQ(const sp<Surface> &surface);
+
} // namespace android
#endif // SURFACE_UTILS_H_
diff --git a/media/libstagefright/omx/1.0/Omx.cpp b/media/libstagefright/omx/1.0/Omx.cpp
index 121bb1a..bb79f54 100644
--- a/media/libstagefright/omx/1.0/Omx.cpp
+++ b/media/libstagefright/omx/1.0/Omx.cpp
@@ -18,7 +18,6 @@
#include <list>
#include <android-base/logging.h>
-#include <gui/IGraphicBufferProducer.h>
#include <media/openmax/OMX_Core.h>
#include <media/openmax/OMX_AsString.h>
@@ -28,7 +27,6 @@
#include <media/stagefright/omx/1.0/WOmxNode.h>
#include <media/stagefright/omx/1.0/WOmxObserver.h>
-#include <media/stagefright/omx/1.0/WGraphicBufferProducer.h>
#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
#include <media/stagefright/omx/1.0/Conversion.h>
#include <media/stagefright/omx/1.0/Omx.h>
@@ -146,8 +144,6 @@
}
Return<void> Omx::createInputSurface(createInputSurface_cb _hidl_cb) {
- sp<::android::IGraphicBufferProducer> bufferProducer;
-
sp<OmxGraphicBufferSource> graphicBufferSource = new OmxGraphicBufferSource();
status_t err = graphicBufferSource->initCheck();
if (err != OK) {
@@ -157,10 +153,9 @@
_hidl_cb(toStatus(err), nullptr, nullptr);
return Void();
}
- bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
_hidl_cb(toStatus(OK),
- new TWGraphicBufferProducer(bufferProducer),
+ graphicBufferSource->getHGraphicBufferProducer_V1_0(),
new TWGraphicBufferSource(graphicBufferSource));
return Void();
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index d7aacff..ddb4ba0 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -33,12 +33,13 @@
#include <binder/IMemory.h>
#include <cutils/properties.h>
-#include <gui/BufferQueue.h>
#include <media/hardware/HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaErrors.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Fence.h>
#include <utils/misc.h>
#include <utils/NativeHandle.h>
#include <media/OMXBuffer.h>
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 0f229f7..9669677 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
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+#ifndef ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
+#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
#include <vector>
#include <list>
@@ -29,15 +29,15 @@
#include <binder/Binder.h>
#include <binder/Status.h>
+#include <ui/BufferQueueDefs.h>
#include <ui/FenceTime.h>
#include <cutils/native_handle.h>
-#include <gui/IGraphicBufferProducer.h>
#include <media/OMXFenceParcelable.h>
#include <media/OMXBuffer.h>
+#include <media/omx/1.0/Conversion.h>
#include <media/hardware/VideoAPI.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/bqhelper/Conversion.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
@@ -99,16 +99,9 @@
typedef ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer
HGraphicBufferProducer;
-typedef ::android::IGraphicBufferProducer
- BGraphicBufferProducer;
-// We want to use all functions declared in ::android::conversion
-using namespace ::android::conversion;
-
-// Now specifically inject these two functions here, because we're going to
-// declare functions with the same name in this namespace.
-using ::android::conversion::convertTo;
-using ::android::conversion::toStatusT;
+// Use the conversion functions from libmedia_omx so that we don't need libgui
+using namespace ::android::hardware::media::omx::V1_0::utils;
/**
* Conversion functions
@@ -143,62 +136,6 @@
*/
/**
- * \brief Convert `Status` to `status_t`. This is for legacy binder calls.
- *
- * \param[in] t The source `Status`.
- * \return the corresponding `status_t`.
- */
-// convert: Status -> status_t
-inline status_t toStatusT(Status const& t) {
- switch (t) {
- case Status::NO_ERROR:
- case Status::NAME_NOT_FOUND:
- case Status::WOULD_BLOCK:
- case Status::NO_MEMORY:
- case Status::ALREADY_EXISTS:
- case Status::NO_INIT:
- case Status::BAD_VALUE:
- case Status::DEAD_OBJECT:
- case Status::INVALID_OPERATION:
- case Status::TIMED_OUT:
- case Status::ERROR_UNSUPPORTED:
- case Status::UNKNOWN_ERROR:
- case Status::RELEASE_ALL_BUFFERS:
- return static_cast<status_t>(t);
- case Status::BUFFER_NEEDS_REALLOCATION:
- return NOT_ENOUGH_DATA;
- default:
- ALOGW("Unrecognized status value: %" PRId32, static_cast<int32_t>(t));
- return static_cast<status_t>(t);
- }
-}
-
-/**
- * \brief Convert `Return<Status>` to `status_t`. This is for legacy binder
- * calls.
- *
- * \param[in] t The source `Return<Status>`.
- * \return The corresponding `status_t`.
- *
- * This function first check if \p t has a transport error. If it does, then the
- * return value is the transport error code. Otherwise, the return value is
- * converted from `Status` contained inside \p t.
- *
- * Note:
- * - This `Status` is omx-specific. It is defined in `types.hal`.
- * - The name of this function is not `convert`.
- */
-// convert: Status -> status_t
-inline status_t toStatusT(Return<Status> const& t) {
- if (t.isOk()) {
- return toStatusT(static_cast<Status>(t));
- } else if (t.isDeadObject()) {
- return DEAD_OBJECT;
- }
- return UNKNOWN_ERROR;
-}
-
-/**
* \brief Convert `status_t` to `Status`.
*
* \param[in] l The source `status_t`.
@@ -219,8 +156,8 @@
case TIMED_OUT:
case ERROR_UNSUPPORTED:
case UNKNOWN_ERROR:
- case IGraphicBufferProducer::RELEASE_ALL_BUFFERS:
- case IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION:
+ case BufferQueueDefs::RELEASE_ALL_BUFFERS:
+ case BufferQueueDefs::BUFFER_NEEDS_REALLOCATION:
return static_cast<Status>(l);
case NOT_ENOUGH_DATA:
return Status::BUFFER_NEEDS_REALLOCATION;
@@ -572,7 +509,8 @@
anwBuffer.nativeHandle = t.nativeHandle;
anwBuffer.attr = t.attr.anwBuffer;
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
- if (!convertTo(graphicBuffer.get(), anwBuffer)) {
+ if (!::android::hardware::media::omx::V1_0::utils::convertTo(
+ graphicBuffer.get(), anwBuffer)) {
return false;
}
*l = OMXBuffer(graphicBuffer);
@@ -756,4 +694,4 @@
} // namespace hardware
} // namespace android
-#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0__CONVERSION_H
+#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0_IMPL_CONVERSION_H
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferProducer.h b/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferProducer.h
deleted file mode 100644
index 322a699..0000000
--- a/media/libstagefright/omx/include/media/stagefright/omx/1.0/WGraphicBufferProducer.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERPRODUCER_H
-#define ANDROID_HARDWARE_MEDIA_OMX_V1_0_WGRAPHICBUFFERPRODUCER_H
-
-#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace omx {
-namespace V1_0 {
-namespace implementation {
-
-using TWGraphicBufferProducer = ::android::TWGraphicBufferProducer<
- ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>;
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace omx
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_MEDIA_OMX_V1_0_WOMXBUFFERPRODUCER_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0f03b7e..5e5ea11 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -701,8 +701,8 @@
updatePid = true;
}
pid_t clientPid = input.clientInfo.clientPid;
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
if (updatePid) {
- const pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW_IF(clientPid != -1 && clientPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
__func__, callingUid, callingPid, clientPid);
@@ -787,7 +787,8 @@
&output.frameCount, &output.notificationFrameCount,
input.notificationsPerBuffer, input.speed,
input.sharedBuffer, sessionId, &output.flags,
- input.clientInfo.clientTid, clientUid, &lStatus, portId);
+ callingPid, input.clientInfo.clientTid, clientUid,
+ &lStatus, portId);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (track == 0));
// we don't abort yet if lStatus != NO_ERROR; there is still work to be done regardless
@@ -1841,8 +1842,8 @@
updatePid = true;
}
pid_t clientPid = input.clientInfo.clientPid;
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
if (updatePid) {
- const pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW_IF(clientPid != -1 && clientPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
__func__, callingUid, callingPid, clientPid);
@@ -1919,7 +1920,7 @@
input.config.format, input.config.channel_mask,
&output.frameCount, sessionId,
&output.notificationFrameCount,
- clientUid, &output.flags,
+ callingPid, clientUid, &output.flags,
input.clientInfo.clientTid,
&lStatus, portId);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index 968d5aa..b83f6b5 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -31,6 +31,7 @@
bool isOut,
uid_t uid,
pid_t pid,
+ pid_t creatorPid,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
virtual ~MmapTrack();
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 56be433..bb97f8d 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -69,6 +69,7 @@
size_t bufferSize,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t uid,
audio_output_flags_t flags,
track_type type,
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index ec1f86c..08660dd 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -32,6 +32,7 @@
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t uid,
audio_input_flags_t flags,
track_type type,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fd29f31..7daa929 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -566,14 +566,16 @@
return status;
}
-void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event, pid_t pid)
+void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId)
{
Mutex::Autolock _l(mLock);
- sendIoConfigEvent_l(event, pid);
+ sendIoConfigEvent_l(event, pid, portId);
}
// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid)
+void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId)
{
// The audio statistics history is exponentially weighted to forget events
// about five or more seconds in the past. In order to have
@@ -584,7 +586,7 @@
mProcessTimeMs.reset();
mTimestampVerifier.discontinuity();
- sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid);
+ sp<ConfigEvent> configEvent = (ConfigEvent *)new IoConfigEvent(event, pid, portId);
sendConfigEvent_l(configEvent);
}
@@ -667,7 +669,7 @@
} break;
case CFG_EVENT_IO: {
IoConfigEventData *data = (IoConfigEventData *)event->mData.get();
- ioConfigChanged(data->mEvent, data->mPid);
+ ioConfigChanged(data->mEvent, data->mPid, data->mPortId);
} break;
case CFG_EVENT_SET_PARAMETER: {
SetParameterConfigEventData *data = (SetParameterConfigEventData *)event->mData.get();
@@ -1952,6 +1954,7 @@
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
audio_output_flags_t *flags,
+ pid_t creatorPid,
pid_t tid,
uid_t uid,
status_t *status,
@@ -2235,7 +2238,7 @@
track = new Track(this, client, streamType, attr, sampleRate, format,
channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
- sessionId, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
+ sessionId, creatorPid, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
if (lStatus != NO_ERROR) {
@@ -2391,6 +2394,7 @@
// to track the speaker usage
addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
#endif
+ sendIoConfigEvent_l(AUDIO_CLIENT_STARTED, track->creatorPid(), track->portId());
}
// set retry count for buffer fill
@@ -2499,7 +2503,8 @@
return mOutput->stream->selectPresentation(presentationId, programId);
}
-void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
+void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId) {
sp<AudioIoDescriptor> desc = new AudioIoDescriptor();
ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
@@ -2518,7 +2523,10 @@
desc->mFrameCountHAL = mFrameCount;
desc->mLatency = latency_l();
break;
-
+ case AUDIO_CLIENT_STARTED:
+ desc->mPatch = mPatch;
+ desc->mPortId = portId;
+ break;
case AUDIO_OUTPUT_CLOSED:
default:
break;
@@ -3268,6 +3276,8 @@
cpuStats.sample(myName);
Vector< sp<EffectChain> > effectChains;
+ audio_session_t activeHapticSessionId = AUDIO_SESSION_NONE;
+ std::vector<sp<Track>> activeTracks;
// If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
//
@@ -3541,6 +3551,25 @@
// during mixing and effect process as the audio buffers could be deleted
// or modified if an effect is created or deleted
lockEffectChains_l(effectChains);
+
+ // Determine which session to pick up haptic data.
+ // This must be done under the same lock as prepareTracks_l().
+ // TODO: Write haptic data directly to sink buffer when mixing.
+ if (mHapticChannelCount > 0 && effectChains.size() > 0) {
+ for (const auto& track : mActiveTracks) {
+ if (track->getHapticPlaybackEnabled()) {
+ activeHapticSessionId = track->sessionId();
+ break;
+ }
+ }
+ }
+
+ // Acquire a local copy of active tracks with lock (release w/o lock).
+ //
+ // Control methods on the track acquire the ThreadBase lock (e.g. start()
+ // stop(), pause(), etc.), but the threadLoop is entitled to call audio
+ // data / buffer methods on tracks from activeTracks without the ThreadBase lock.
+ activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());
} // mLock scope ends
if (mBytesRemaining == 0) {
@@ -3555,6 +3584,13 @@
threadLoop_sleepTime();
if (mSleepTimeUs == 0) {
mCurrentWriteLength = mSinkBufferSize;
+
+ // Tally underrun frames as we are inserting 0s here.
+ for (const auto& track : activeTracks) {
+ if (track->mFillingUpStatus == Track::FS_ACTIVE) {
+ track->mAudioTrackServerProxy->tallyUnderrunFrames(mNormalFrameCount);
+ }
+ }
}
}
// Either threadLoop_mix() or threadLoop_sleepTime() should have set
@@ -3613,20 +3649,11 @@
// only process effects if we're going to write
if (mSleepTimeUs == 0 && mType != OFFLOAD) {
- audio_session_t activeHapticId = AUDIO_SESSION_NONE;
- if (mHapticChannelCount > 0 && effectChains.size() > 0) {
- for (auto track : mActiveTracks) {
- if (track->getHapticPlaybackEnabled()) {
- activeHapticId = track->sessionId();
- break;
- }
- }
- }
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
// TODO: Write haptic data directly to sink buffer when mixing.
- if (activeHapticId != AUDIO_SESSION_NONE
- && activeHapticId == effectChains[i]->sessionId()) {
+ if (activeHapticSessionId != AUDIO_SESSION_NONE
+ && activeHapticSessionId == effectChains[i]->sessionId()) {
// Haptic data is active in this case, copy it directly from
// in buffer to out buffer.
const size_t audioBufferSize = mNormalFrameCount
@@ -7405,6 +7432,7 @@
size_t *pFrameCount,
audio_session_t sessionId,
size_t *pNotificationFrameCount,
+ pid_t creatorPid,
uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
@@ -7542,7 +7570,7 @@
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
- nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, uid,
+ nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid, uid,
*flags, TrackBase::TYPE_DEFAULT, portId);
lStatus = track->initCheck();
@@ -7650,6 +7678,8 @@
recordTrack->clearSyncStartEvent();
return status;
}
+ sendIoConfigEvent_l(
+ AUDIO_CLIENT_STARTED, recordTrack->creatorPid(), recordTrack->portId());
}
// Catch up with current buffer indices if thread is already running.
// This is what makes a new client discard all buffered data. If the track's mRsmpInFront
@@ -8131,7 +8161,8 @@
return String8();
}
-void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
+void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId) {
sp<AudioIoDescriptor> desc = new AudioIoDescriptor();
desc->mIoHandle = mId;
@@ -8148,7 +8179,10 @@
desc->mFrameCountHAL = mFrameCount;
desc->mLatency = 0;
break;
-
+ case AUDIO_CLIENT_STARTED:
+ desc->mPatch = mPatch;
+ desc->mPortId = portId;
+ break;
case AUDIO_INPUT_CLOSED:
default:
break;
@@ -8606,7 +8640,8 @@
// Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
- isOutput(), client.clientUid, client.clientPid, portId);
+ isOutput(), client.clientUid, client.clientPid,
+ IPCThreadState::self()->getCallingPid(), portId);
if (isOutput()) {
// force volume update when a new track is added
@@ -8832,7 +8867,8 @@
return String8();
}
-void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
+void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId __unused) {
sp<AudioIoDescriptor> desc = new AudioIoDescriptor();
desc->mIoHandle = mId;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 37b2d08..336c2b4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -103,8 +103,9 @@
class IoConfigEventData : public ConfigEventData {
public:
- IoConfigEventData(audio_io_config_event event, pid_t pid) :
- mEvent(event), mPid(pid) {}
+ IoConfigEventData(audio_io_config_event event, pid_t pid,
+ audio_port_handle_t portId) :
+ mEvent(event), mPid(pid), mPortId(portId) {}
virtual void dump(char *buffer, size_t size) {
snprintf(buffer, size, "IO event: event %d\n", mEvent);
@@ -112,13 +113,14 @@
const audio_io_config_event mEvent;
const pid_t mPid;
+ const audio_port_handle_t mPortId;
};
class IoConfigEvent : public ConfigEvent {
public:
- IoConfigEvent(audio_io_config_event event, pid_t pid) :
+ IoConfigEvent(audio_io_config_event event, pid_t pid, audio_port_handle_t portId) :
ConfigEvent(CFG_EVENT_IO) {
- mData = new IoConfigEventData(event, pid);
+ mData = new IoConfigEventData(event, pid, portId);
}
virtual ~IoConfigEvent() {}
};
@@ -260,13 +262,16 @@
status_t& status) = 0;
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
- virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0) = 0;
+ virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from
// processConfigEvents_l().
status_t sendConfigEvent_l(sp<ConfigEvent>& event);
- void sendIoConfigEvent(audio_io_config_event event, pid_t pid = 0);
- void sendIoConfigEvent_l(audio_io_config_event event, pid_t pid = 0);
+ void sendIoConfigEvent(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+ void sendIoConfigEvent_l(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp);
void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp);
status_t sendSetParameterConfigEvent_l(const String8& keyValuePair);
@@ -802,6 +807,7 @@
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
audio_output_flags_t *flags,
+ pid_t creatorPid,
pid_t tid,
uid_t uid,
status_t *status /*non-NULL*/,
@@ -825,7 +831,8 @@
{ return android_atomic_acquire_load(&mSuspended) > 0; }
virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0);
+ virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::PlaybackThread::Track::Track().
@@ -1540,6 +1547,7 @@
size_t *pFrameCount,
audio_session_t sessionId,
size_t *pNotificationFrameCount,
+ pid_t creatorPid,
uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
@@ -1562,7 +1570,8 @@
status_t& status);
virtual void cacheParameters_l() {}
virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0);
+ virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle);
virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle);
@@ -1743,7 +1752,8 @@
virtual bool checkForNewParameter_l(const String8& keyValuePair,
status_t& status);
virtual String8 getParameters(const String8& keys);
- virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0);
+ virtual void ioConfigChanged(audio_io_config_event event, pid_t pid = 0,
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
void readHalParameters_l();
virtual void cacheParameters_l() {}
virtual status_t createAudioPatch_l(const struct audio_patch *patch,
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 4402d99..8f720b5 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -64,6 +64,7 @@
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t uid,
bool isOut,
alloc_type alloc = ALLOC_CBLK,
@@ -79,6 +80,8 @@
audio_track_cblk_t* cblk() const { return mCblk; }
audio_session_t sessionId() const { return mSessionId; }
uid_t uid() const { return mUid; }
+ pid_t creatorPid() const { return mCreatorPid; }
+
audio_port_handle_t portId() const { return mPortId; }
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
@@ -310,6 +313,8 @@
std::atomic<bool> mServerLatencyFromTrack{}; // latency from track or server timestamp.
std::atomic<double> mServerLatencyMs{}; // last latency pushed from server thread.
std::atomic<FrameTime> mKernelFrameTime{}; // last frame time on kernel side.
+ const pid_t mCreatorPid; // can be different from mclient->pid() for instance
+ // when created by NuPlayer on behalf of a client
};
// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 8d59431..e1f00c1 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -73,6 +73,7 @@
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t clientUid,
bool isOut,
alloc_type alloc,
@@ -101,7 +102,8 @@
mType(type),
mThreadIoHandle(thread ? thread->id() : AUDIO_IO_HANDLE_NONE),
mPortId(portId),
- mIsInvalid(false)
+ mIsInvalid(false),
+ mCreatorPid(creatorPid)
{
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
if (!isAudioServerOrMediaServerUid(callingUid) || clientUid == AUDIO_UID_INVALID) {
@@ -485,6 +487,7 @@
size_t bufferSize,
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t uid,
audio_output_flags_t flags,
track_type type,
@@ -492,7 +495,7 @@
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
(sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
(sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
- sessionId, uid, true /*isOut*/,
+ sessionId, creatorPid, uid, true /*isOut*/,
(type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
type, portId),
mFillingUpStatus(FS_INVALID),
@@ -1543,7 +1546,7 @@
audio_attributes_t{} /* currently unused for output track */,
sampleRate, format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
- AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
+ AUDIO_SESSION_NONE, getpid(), uid, AUDIO_OUTPUT_FLAG_NONE,
TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread)
{
@@ -1772,7 +1775,7 @@
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
- AUDIO_SESSION_NONE, AID_AUDIOSERVER, flags, TYPE_PATCH),
+ AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER, flags, TYPE_PATCH),
PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
*playbackThread, timeout)
{
@@ -1927,12 +1930,14 @@
void *buffer,
size_t bufferSize,
audio_session_t sessionId,
+ pid_t creatorPid,
uid_t uid,
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId)
: TrackBase(thread, client, attr, sampleRate, format,
- channelMask, frameCount, buffer, bufferSize, sessionId, uid, false /*isOut*/,
+ channelMask, frameCount, buffer, bufferSize, sessionId,
+ creatorPid, uid, false /*isOut*/,
(type == TYPE_DEFAULT) ?
((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
((buffer == NULL) ? ALLOC_LOCAL : ALLOC_NONE),
@@ -2242,7 +2247,7 @@
: RecordTrack(recordThread, NULL,
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
- buffer, bufferSize, AUDIO_SESSION_NONE, AID_AUDIOSERVER,
+ buffer, bufferSize, AUDIO_SESSION_NONE, getpid(), AID_AUDIOSERVER,
flags, TYPE_PATCH),
PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true),
*recordThread, timeout)
@@ -2310,11 +2315,12 @@
bool isOut,
uid_t uid,
pid_t pid,
+ pid_t creatorPid,
audio_port_handle_t portId)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
- sessionId, uid, isOut,
+ sessionId, creatorPid, uid, isOut,
ALLOC_NONE,
TYPE_DEFAULT, portId),
mPid(pid), mSilenced(false), mSilencedNotified(false)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c0ca440..6f62b90 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -3003,22 +3003,11 @@
status_t AudioPolicyManager::removeUidDeviceAffinities(uid_t uid) {
ALOGV("%s() uid=%d", __FUNCTION__, uid);
- Vector<AudioDeviceTypeAddr> devices;
- status_t res = mPolicyMixes.getDevicesForUid(uid, devices);
- if (res == NO_ERROR) {
- // reevaluate outputs for all found devices
- for (size_t i = 0; i < devices.size(); i++) {
- sp<DeviceDescriptor> devDesc = mHwModules.getDeviceDescriptor(
- devices[i].mType, devices[i].mAddress, String8(),
- AUDIO_FORMAT_DEFAULT);
- SortedVector<audio_io_handle_t> outputs;
- if (checkOutputsForDevice(devDesc, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputs) != NO_ERROR) {
- ALOGE("%s() error in checkOutputsForDevice for device=%08x addr=%s",
- __FUNCTION__, devices[i].mType, devices[i].mAddress.string());
- return INVALID_OPERATION;
- }
- }
+ status_t res = mPolicyMixes.removeUidDeviceAffinities(uid);
+ if (res != NO_ERROR) {
+ ALOGE("%s() Could not remove all device affinities fo uid = %d",
+ __FUNCTION__, uid);
+ return INVALID_OPERATION;
}
return res;
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
index 02cedba..f75515a 100644
--- a/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-arm.policy
@@ -61,3 +61,24 @@
restart_syscall: 1
rt_sigreturn: 1
getrandom: 1
+madvise: 1
+
+# crash dump policy additions
+sigreturn: 1
+clock_gettime: 1
+futex: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
+#mprotect: arg2 in 0x1|0x2
+#mmap2: arg2 in 0x1|0x2
+geteuid32: 1
+getgid32: 1
+getegid32: 1
+getgroups32: 1
diff --git a/services/oboeservice/AAudioClientTracker.cpp b/services/oboeservice/AAudioClientTracker.cpp
index 83704ba..8572561 100644
--- a/services/oboeservice/AAudioClientTracker.cpp
+++ b/services/oboeservice/AAudioClientTracker.cpp
@@ -67,6 +67,12 @@
const sp<IAAudioClient>& client) {
ALOGV("registerClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
+ if (client.get() == nullptr) {
+ ALOGE("AAudioClientTracker::%s() client is NULL!", __func__);
+ android_errorWriteLog(0x534e4554, "116230453");
+ return AAUDIO_ERROR_NULL;
+ }
+
std::lock_guard<std::mutex> lock(mLock);
if (mNotificationClients.count(pid) == 0) {
sp<NotificationClient> notificationClient = new NotificationClient(pid);