Merge "AudioPolicyManager volume init on invalid min/max" into tm-dev
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 74e3223..f7989bd 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -208,7 +208,11 @@
}
status_t DrmManager::loadPlugIns() {
+#if __LP64__
+ String8 pluginDirPath("/system/lib64/drm");
+#else
String8 pluginDirPath("/system/lib/drm");
+#endif
loadPlugIns(pluginDirPath);
return DRM_NO_ERROR;
}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
index 02ac943..b82d996 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
@@ -144,7 +144,6 @@
"libclearkeydevicefiles-protos",
"libjsmn",
"libprotobuf-cpp-lite",
- "libutils",
],
shared_libs: [
"android.hidl.allocator@1.0",
@@ -157,6 +156,7 @@
"libhidlbase",
"libhidlmemory",
"liblog",
+ "libutils",
],
fuzz_config: {
cc: [
diff --git a/drm/mediadrm/plugins/clearkey/service-lazy.mk b/drm/mediadrm/plugins/clearkey/service-lazy.mk
new file mode 100644
index 0000000..0d16f4c
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/service-lazy.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2022 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.
+#
+PRODUCT_PACKAGES += android.hardware.drm-service-lazy.clearkey
diff --git a/drm/mediadrm/plugins/clearkey/service.mk b/drm/mediadrm/plugins/clearkey/service.mk
new file mode 100644
index 0000000..15988fb
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/service.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2022 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.
+#
+PRODUCT_PACKAGES += android.hardware.drm-service.clearkey
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index c7985ca..3b0e949 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -261,8 +261,7 @@
CREATE_DUMP_FILE(mInFile);
CREATE_DUMP_FILE(mOutFile);
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
C2SoftAomDec::~C2SoftAomDec() {
@@ -463,19 +462,17 @@
int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
if (inSize) {
uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
- int32_t decodeTime = 0;
- int32_t delay = 0;
DUMP_TO_FILE(mOutFile, bitstream, inSize);
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
+ mTimeStart = systemTime();
+ nsecs_t delay = mTimeStart - mTimeEnd;
aom_codec_err_t err =
aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
+ mTimeEnd = systemTime();
+ nsecs_t decodeTime = mTimeEnd - mTimeStart;
+ ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
if (err != AOM_CODEC_OK) {
ALOGE("av1 decoder failed to decode frame err: %d", err);
diff --git a/media/codec2/components/aom/C2SoftAomDec.h b/media/codec2/components/aom/C2SoftAomDec.h
index 4c82647..8b953fe 100644
--- a/media/codec2/components/aom/C2SoftAomDec.h
+++ b/media/codec2/components/aom/C2SoftAomDec.h
@@ -17,15 +17,12 @@
#ifndef ANDROID_C2_SOFT_AV1_DEC_H_
#define ANDROID_C2_SOFT_AV1_DEC_H_
+#include <inttypes.h>
+
#include <SimpleC2Component.h>
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
namespace android {
struct C2SoftAomDec : public SimpleC2Component {
@@ -60,8 +57,8 @@
char mOutFile[200];
#endif /* FILE_DUMP_ENABLE */
- struct timeval mTimeStart; // Time at the start of decode()
- struct timeval mTimeEnd; // Time at the end of decode()
+ nsecs_t mTimeStart = 0; // Time at the start of decode()
+ nsecs_t mTimeEnd = 0; // Time at the end of decode()
status_t initDecoder();
status_t destroyDecoder();
@@ -85,14 +82,13 @@
#define OUTPUT_DUMP_EXT "av1"
#define GENERATE_FILE_NAMES() \
{ \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
+ nsecs_t now = systemTime(); \
ALOGD("GENERATE_FILE_NAMES"); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, mTimeStart.tv_sec, \
- mTimeStart.tv_usec, INPUT_DUMP_EXT); \
+ sprintf(mInFile, "%s_%" PRId64 ".%s", INPUT_DUMP_PATH, \
+ now, INPUT_DUMP_EXT); \
strcpy(mOutFile, ""); \
- sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, OUTPUT_DUMP_EXT); \
+ sprintf(mOutFile, "%s_%" PRId64 ".%s", OUTPUT_DUMP_PATH, \
+ now, OUTPUT_DUMP_EXT); \
}
#define CREATE_DUMP_FILE(m_filename) \
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index cc4517d..953afc5 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -670,8 +670,7 @@
void C2SoftAvcDec::resetPlugin() {
mSignalledOutputEos = false;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
status_t C2SoftAvcDec::deleteDecoder() {
@@ -866,14 +865,13 @@
setParams(mStride, IVD_DECODE_HEADER);
}
- WORD32 delay;
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
+ mTimeStart = systemTime();
+ nsecs_t delay = mTimeStart - mTimeEnd;
(void) ivdec_api_function(mDecHandle, &s_h264d_decode_ip, &s_h264d_decode_op);
- WORD32 decodeTime;
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
+
+ mTimeEnd = systemTime();
+ nsecs_t decodeTime = mTimeEnd - mTimeStart;
+ ALOGV("decodeTime=%" PRId64 " delay=%" PRId64 " numBytes=%6d", decodeTime, delay,
ps_decode_op->u4_num_bytes_consumed);
}
if (IVD_MEM_ALLOC_FAILED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
diff --git a/media/codec2/components/avc/C2SoftAvcDec.h b/media/codec2/components/avc/C2SoftAvcDec.h
index 59d5184..36a463e 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.h
+++ b/media/codec2/components/avc/C2SoftAvcDec.h
@@ -18,6 +18,7 @@
#define ANDROID_C2_SOFT_AVC_DEC_H_
#include <sys/time.h>
+#include <inttypes.h>
#include <media/stagefright/foundation/ColorUtils.h>
@@ -43,19 +44,15 @@
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
#ifdef FILE_DUMP_ENABLE
#define INPUT_DUMP_PATH "/sdcard/clips/avcd_input"
#define INPUT_DUMP_EXT "h264"
#define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
+ nsecs_t now = systemTime(); \
strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
+ sprintf(mInFile, "%s_%" PRId64 "d.%s", \
+ INPUT_DUMP_PATH, now, \
INPUT_DUMP_EXT); \
}
#define CREATE_DUMP_FILE(m_filename) { \
@@ -183,8 +180,8 @@
} mBitstreamColorAspects;
// profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
+ nsecs_t mTimeStart = 0;
+ nsecs_t mTimeEnd = 0;
#ifdef FILE_DUMP_ENABLE
char mInFile[200];
#endif /* FILE_DUMP_ENABLE */
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index d65ffa5..4ffcd59 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -656,8 +656,7 @@
mEntropyMode = DEFAULT_ENTROPY_MODE;
mBframes = DEFAULT_B_FRAMES;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
c2_status_t C2SoftAvcEnc::setDimensions() {
@@ -1650,8 +1649,7 @@
work->worklets.front()->output.flags = work->input.flags;
IV_STATUS_T status;
- WORD32 timeDelay = 0;
- WORD32 timeTaken = 0;
+ nsecs_t timeDelay = 0;
uint64_t workIndex = work->input.ordinal.frameIndex.peekull();
// Initialize encoder if not already initialized
@@ -1817,10 +1815,10 @@
// mInFile, s_encode_ip.s_inp_buf.apv_bufs[0],
// (mHeight * mStride * 3 / 2));
- GETTIME(&mTimeStart, nullptr);
/* Compute time elapsed between end of previous decode()
* to start of current decode() */
- TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
+ mTimeStart = systemTime();
+ timeDelay = mTimeStart - mTimeEnd;
status = ive_api_function(mCodecCtx, &s_video_encode_ip, &s_video_encode_op);
if (IV_SUCCESS != status) {
@@ -1844,11 +1842,11 @@
mBuffers[ps_encode_ip->s_inp_buf.apv_bufs[0]] = inputBuffer;
}
- GETTIME(&mTimeEnd, nullptr);
/* Compute time taken for decode() */
- TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
+ mTimeEnd = systemTime();
+ nsecs_t timeTaken = mTimeEnd - mTimeStart;
- ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", timeTaken, timeDelay,
+ ALOGV("timeTaken=%" PRId64 "d delay=%" PRId64 " numBytes=%6d", timeTaken, timeDelay,
ps_encode_op->s_out_buf.u4_bytes);
void *freed = ps_encode_op->s_inp_buf.apv_bufs[0];
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index 1fecd9e..293867d 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -18,6 +18,7 @@
#define ANDROID_C2_SOFT_AVC_ENC_H__
#include <map>
+#include <inttypes.h>
#include <utils/Vector.h>
@@ -115,14 +116,6 @@
/** Used to remove warnings about unused parameters */
#define UNUSED(x) ((void)(x))
-/** Get time */
-#define GETTIME(a, b) gettimeofday(a, b);
-
-/** Compute difference between start and end */
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
#define ive_aligned_malloc(alignment, size) memalign(alignment, size)
#define ive_aligned_free(buf) free(buf)
@@ -148,6 +141,7 @@
virtual ~C2SoftAvcEnc();
private:
+ // RBE What does OMX have to do with the c2 plugin?
// OMX input buffer's timestamp and flags
typedef struct {
int64_t mTimeUs;
@@ -158,8 +152,8 @@
int32_t mStride;
- struct timeval mTimeStart; // Time at the start of decode()
- struct timeval mTimeEnd; // Time at the end of decode()
+ nsecs_t mTimeStart = 0; // Time at the start of decode()
+ nsecs_t mTimeEnd = 0; // Time at the end of decode()
#ifdef FILE_DUMP_ENABLE
char mInFile[200];
@@ -259,14 +253,14 @@
#define OUTPUT_DUMP_EXT "h264"
#define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
+ nsecs_t now = systemTime(); \
strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
+ sprintf(mInFile, "%s_%" PRId64 "d.%s", \
+ INPUT_DUMP_PATH, now, \
INPUT_DUMP_EXT); \
strcpy(mOutFile, ""); \
- sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH,\
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
+ sprintf(mOutFile, "%s_%" PRId64 "d.%s", \
+ OUTPUT_DUMP_PATH, now, \
OUTPUT_DUMP_EXT); \
}
diff --git a/media/codec2/components/base/SimpleC2Interface.cpp b/media/codec2/components/base/SimpleC2Interface.cpp
index 29740d1..993e602 100644
--- a/media/codec2/components/base/SimpleC2Interface.cpp
+++ b/media/codec2/components/base/SimpleC2Interface.cpp
@@ -28,6 +28,14 @@
/* SimpleInterface */
+static C2R SubscribedParamIndicesSetter(
+ bool mayBlock, C2InterfaceHelper::C2P<C2SubscribedParamIndicesTuning> &me) {
+ (void)mayBlock;
+ (void)me;
+
+ return C2R::Ok();
+}
+
SimpleInterface<void>::BaseParams::BaseParams(
const std::shared_ptr<C2ReflectorHelper> &reflector,
C2String name,
@@ -186,7 +194,7 @@
.withDefault(C2SubscribedParamIndicesTuning::AllocShared(0u))
.withFields({ C2F(mSubscribedParamIndices, m.values[0]).any(),
C2F(mSubscribedParamIndices, m.values).any() })
- .withSetter(Setter<C2SubscribedParamIndicesTuning>::NonStrictValuesWithNoDeps)
+ .withSetter(SubscribedParamIndicesSetter)
.build());
/* TODO
diff --git a/media/codec2/components/base/include/SimpleC2Interface.h b/media/codec2/components/base/include/SimpleC2Interface.h
index 2051d3d..916f392 100644
--- a/media/codec2/components/base/include/SimpleC2Interface.h
+++ b/media/codec2/components/base/include/SimpleC2Interface.h
@@ -209,6 +209,7 @@
return me.F(me.v.value).validatePossible(me.v.value);
}
+ // TODO(b/230146771): fix crash
static C2R NonStrictValuesWithNoDeps(
bool mayBlock, C2InterfaceHelper::C2P<type> &me) {
(void)mayBlock;
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index c4cbb78..f5c8138 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -342,8 +342,7 @@
std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
mIntf(intfImpl),
mCodecCtx(nullptr) {
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
C2SoftGav1Dec::~C2SoftGav1Dec() { onRelease(); }
@@ -514,19 +513,17 @@
int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
if (inSize) {
uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
- int32_t decodeTime = 0;
- int32_t delay = 0;
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
+ mTimeStart = systemTime();
+ nsecs_t delay = mTimeStart - mTimeEnd;
const Libgav1StatusCode status =
mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
/*buffer_private_data=*/nullptr);
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
+ mTimeEnd = systemTime();
+ nsecs_t decodeTime = mTimeEnd - mTimeStart;
+ ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
if (status != kLibgav1StatusOk) {
ALOGE("av1 decoder failed to decode frame. status: %d.", status);
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index a69a863..4b13fef 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_C2_SOFT_GAV1_DEC_H_
#define ANDROID_C2_SOFT_GAV1_DEC_H_
+#include <inttypes.h>
+
#include <media/stagefright/foundation/ColorUtils.h>
#include <SimpleC2Component.h>
@@ -24,11 +26,6 @@
#include "libgav1/src/gav1/decoder.h"
#include "libgav1/src/gav1/decoder_settings.h"
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
namespace android {
struct C2SoftGav1Dec : public SimpleC2Component {
@@ -81,8 +78,8 @@
}
} mBitstreamColorAspects;
- struct timeval mTimeStart; // Time at the start of decode()
- struct timeval mTimeEnd; // Time at the end of decode()
+ nsecs_t mTimeStart = 0; // Time at the start of decode()
+ nsecs_t mTimeEnd = 0; // Time at the end of decode()
bool initDecoder();
void getVuiParams(const libgav1::DecoderBuffer *buffer);
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 2a6adca..5a660c5 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -663,8 +663,7 @@
void C2SoftHevcDec::resetPlugin() {
mSignalledOutputEos = false;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
status_t C2SoftHevcDec::deleteDecoder() {
@@ -858,14 +857,13 @@
/* Decode header and get dimensions */
setParams(mStride, IVD_DECODE_HEADER);
}
- WORD32 delay;
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
+
+ mTimeStart = systemTime();
+ nsecs_t delay = mTimeStart - mTimeEnd;
(void) ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
- WORD32 decodeTime;
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%6d delay=%6d numBytes=%6d", decodeTime, delay,
+ mTimeEnd = systemTime();
+ nsecs_t decodeTime = mTimeEnd - mTimeStart;
+ ALOGV("decodeTime=%6" PRId64 " delay=%6" PRId64 " numBytes=%6d", decodeTime, delay,
ps_decode_op->u4_num_bytes_consumed);
if (IVD_MEM_ALLOC_FAILED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
ALOGE("allocation failure in decoder");
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.h b/media/codec2/components/hevc/C2SoftHevcDec.h
index b9296e9..6abf69e 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.h
+++ b/media/codec2/components/hevc/C2SoftHevcDec.h
@@ -20,6 +20,7 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <atomic>
+#include <inttypes.h>
#include <SimpleC2Component.h>
#include "ihevc_typedefs.h"
@@ -41,10 +42,6 @@
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
struct C2SoftHevcDec : public SimpleC2Component {
@@ -142,8 +139,8 @@
} mBitstreamColorAspects;
// profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
+ nsecs_t mTimeStart = 0;
+ nsecs_t mTimeEnd = 0;
C2_DO_NOT_COPY(C2SoftHevcDec);
};
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 4f5caec..947e387 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -591,8 +591,7 @@
CREATE_DUMP_FILE(mInFile);
CREATE_DUMP_FILE(mOutFile);
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
C2SoftHevcEnc::~C2SoftHevcEnc() {
@@ -1203,11 +1202,11 @@
}
}
- uint64_t timeDelay = 0;
- uint64_t timeTaken = 0;
+ nsecs_t timeDelay = 0;
+ nsecs_t timeTaken = 0;
memset(&s_encode_op, 0, sizeof(s_encode_op));
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);
+ mTimeStart = systemTime();
+ timeDelay = mTimeStart - mTimeEnd;
if (inputBuffer) {
err = ihevce_encode(mCodecCtx, &s_encode_ip, &s_encode_op);
@@ -1222,12 +1221,12 @@
fillEmptyWork(work);
}
- GETTIME(&mTimeEnd, nullptr);
/* Compute time taken for decode() */
- TIME_DIFF(mTimeStart, mTimeEnd, timeTaken);
+ mTimeEnd = systemTime();
+ timeTaken = mTimeEnd - mTimeStart;
- ALOGV("timeTaken=%6d delay=%6d numBytes=%6d", (int)timeTaken,
- (int)timeDelay, s_encode_op.i4_bytes_generated);
+ ALOGV("timeTaken=%6" PRId64 " delay=%6" PRId64 " numBytes=%6d", timeTaken,
+ timeDelay, s_encode_op.i4_bytes_generated);
if (s_encode_op.i4_bytes_generated) {
finishWork(s_encode_op.u8_pts, work, pool, &s_encode_op);
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.h b/media/codec2/components/hevc/C2SoftHevcEnc.h
index 4217a8b..ce9cec8 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.h
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.h
@@ -19,6 +19,7 @@
#include <SimpleC2Component.h>
#include <algorithm>
+#include <inttypes.h>
#include <map>
#include <media/stagefright/foundation/ColorUtils.h>
#include <utils/Vector.h>
@@ -27,14 +28,6 @@
namespace android {
-/** Get time */
-#define GETTIME(a, b) gettimeofday(a, b)
-
-/** Compute difference between start and end */
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
-
#define CODEC_MAX_CORES 4
#define MAX_B_FRAMES 1
#define MAX_RC_LOOKAHEAD 1
@@ -102,8 +95,8 @@
#endif /* FILE_DUMP_ENABLE */
// profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
+ nsecs_t mTimeStart = 0;
+ nsecs_t mTimeEnd = 0;
c2_status_t initEncParams();
c2_status_t initEncoder();
@@ -127,14 +120,12 @@
#define OUTPUT_DUMP_EXT "h265"
#define GENERATE_FILE_NAMES() \
{ \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
+ nsecs_t now = systemTime(); \
ALOGD("GENERATE_FILE_NAMES"); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, mTimeStart.tv_sec, \
- mTimeStart.tv_usec, INPUT_DUMP_EXT); \
- strcpy(mOutFile, ""); \
- sprintf(mOutFile, "%s_%ld.%ld.%s", OUTPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, OUTPUT_DUMP_EXT); \
+ sprintf(mInFile, "%s_%" PRId64 ".%s", INPUT_DUMP_PATH, \
+ mTimeStart, INPUT_DUMP_EXT); \
+ sprintf(mutFile, "%s_%" PRId64 ".%s", OUTPUT_DUMP_PATH, \
+ mTimeStart, OUTPUT_DUMP_EXT); \
}
#define CREATE_DUMP_FILE(m_filename) \
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 5f9b30b..9a41910 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -731,8 +731,7 @@
void C2SoftMpeg2Dec::resetPlugin() {
mSignalledOutputEos = false;
- gettimeofday(&mTimeStart, nullptr);
- gettimeofday(&mTimeEnd, nullptr);
+ mTimeStart = mTimeEnd = systemTime();
}
status_t C2SoftMpeg2Dec::deleteDecoder() {
@@ -929,14 +928,12 @@
}
// If input dump is enabled, then write to file
DUMP_TO_FILE(mInFile, s_decode_ip.pv_stream_buffer, s_decode_ip.u4_num_Bytes);
- WORD32 delay;
- GETTIME(&mTimeStart, nullptr);
- TIME_DIFF(mTimeEnd, mTimeStart, delay);
+ nsecs_t delay = mTimeStart - mTimeEnd;
(void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
- WORD32 decodeTime;
- GETTIME(&mTimeEnd, nullptr);
- TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- ALOGV("decodeTime=%6d delay=%6d numBytes=%6d ", decodeTime, delay,
+
+ mTimeEnd = systemTime();
+ nsecs_t decodeTime = mTimeEnd - mTimeStart;
+ ALOGV("decodeTime=%" PRId64 " delay=%" PRId64 " numBytes=%6d ", decodeTime, delay,
s_decode_op.u4_num_bytes_consumed);
if (IMPEG2D_UNSUPPORTED_DIMENSIONS == s_decode_op.u4_error_code) {
ALOGV("unsupported resolution : %dx%d", s_decode_op.u4_pic_wd, s_decode_op.u4_pic_ht);
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
index 8a29c14..3965bcc 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.h
@@ -18,6 +18,7 @@
#define ANDROID_C2_SOFT_MPEG2_DEC_H_
#include <atomic>
+#include <inttypes.h>
#include <SimpleC2Component.h>
#include <media/stagefright/foundation/ColorUtils.h>
@@ -42,19 +43,14 @@
#define IVDEXT_CMD_CTL_SET_NUM_CORES \
(IVD_CONTROL_API_COMMAND_TYPE_T)IMPEG2D_CMD_CTL_SET_NUM_CORES
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define GETTIME(a, b) gettimeofday(a, b);
-#define TIME_DIFF(start, end, diff) \
- diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
- ((end).tv_usec - (start).tv_usec);
#ifdef FILE_DUMP_ENABLE
#define INPUT_DUMP_PATH "/sdcard/clips/mpeg2d_input"
#define INPUT_DUMP_EXT "m2v"
#define GENERATE_FILE_NAMES() { \
- GETTIME(&mTimeStart, NULL); \
- strcpy(mInFile, ""); \
- sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH, \
- mTimeStart.tv_sec, mTimeStart.tv_usec, \
+ nsecs_t now = systemTime(); \
+ sprintf(mInFile, "%s_%" PRId64 ".%s", \
+ INPUT_DUMP_PATH, now, \
INPUT_DUMP_EXT); \
}
#define CREATE_DUMP_FILE(m_filename) { \
@@ -183,8 +179,8 @@
} mBitstreamColorAspects;
// profile
- struct timeval mTimeStart;
- struct timeval mTimeEnd;
+ nsecs_t mTimeStart = 0;
+ nsecs_t mTimeEnd = 0;
#ifdef FILE_DUMP_ENABLE
char mInFile[200];
#endif /* FILE_DUMP_ENABLE */
diff --git a/media/codec2/fuzzer/Android.bp b/media/codec2/fuzzer/Android.bp
index 3adc212..147a52e 100644
--- a/media/codec2/fuzzer/Android.bp
+++ b/media/codec2/fuzzer/Android.bp
@@ -38,6 +38,12 @@
"-Wall",
"-Werror",
],
+
+ fuzz_config: {
+ cc: [
+ "wonsik@google.com",
+ ],
+ },
}
cc_fuzz {
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index a73b493..c36ae94 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -67,6 +67,7 @@
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx",
+ "libstagefright_surface_utils",
"libstagefright_xmlparser",
"libui",
"libutils",
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 3302dd3..fffd60a 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -30,6 +30,7 @@
#include <android/hardware/media/c2/1.0/IInputSurface.h>
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <gui/IGraphicBufferProducer.h>
@@ -871,6 +872,11 @@
}
config->mTunneled = true;
}
+
+ int32_t pushBlankBuffersOnStop = 0;
+ if (msg->findInt32(KEY_PUSH_BLANK_BUFFERS_ON_STOP, &pushBlankBuffersOnStop)) {
+ config->mPushBlankBuffersOnStop = pushBlankBuffersOnStop == 1;
+ }
}
}
setSurface(surface);
@@ -1006,7 +1012,9 @@
// Query vendor format for Flexible YUV
std::vector<std::unique_ptr<C2Param>> heapParams;
C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
- if (mClient->query(
+ int vendorSdkVersion = base::GetIntProperty(
+ "ro.vendor.build.version.sdk", android_get_device_api_level());
+ if (vendorSdkVersion >= __ANDROID_API_S__ && mClient->query(
{},
{C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
C2_MAY_BLOCK,
@@ -1526,6 +1534,9 @@
using namespace android::hardware::graphics::bufferqueue::V1_0::utils;
typedef android::hardware::media::omx::V1_0::Status OmxStatus;
android::sp<IOmx> omx = IOmx::getService();
+ if (omx == nullptr) {
+ return nullptr;
+ }
typedef android::hardware::graphics::bufferqueue::V1_0::
IGraphicBufferProducer HGraphicBufferProducer;
typedef android::hardware::media::omx::V1_0::
@@ -1838,7 +1849,13 @@
}
state->set(STOPPING);
}
-
+ {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if (config->mPushBlankBuffersOnStop) {
+ mChannel->pushBlankBufferToOutputSurface();
+ }
+ }
mChannel->reset();
(new AMessage(kWhatStop, this))->post();
}
@@ -1926,6 +1943,13 @@
config->mInputSurfaceDataspace = HAL_DATASPACE_UNKNOWN;
}
}
+ {
+ Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
+ const std::unique_ptr<Config> &config = *configLocked;
+ if (config->mPushBlankBuffersOnStop) {
+ mChannel->pushBlankBufferToOutputSurface();
+ }
+ }
mChannel->reset();
// thiz holds strong ref to this while the thread is running.
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 674714f..a086128 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#include <utils/Errors.h>
#define LOG_TAG "CCodecBufferChannel"
#define ATRACE_TAG ATRACE_TAG_VIDEO
#include <utils/Log.h>
@@ -48,6 +49,7 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaCodecConstants.h>
#include <media/stagefright/SkipCutBuffer.h>
+#include <media/stagefright/SurfaceUtils.h>
#include <media/MediaCodecBuffer.h>
#include <mediadrm/ICrypto.h>
#include <system/window.h>
@@ -2180,4 +2182,13 @@
}
}
+status_t CCodecBufferChannel::pushBlankBufferToOutputSurface() {
+ Mutexed<OutputSurface>::Locked output(mOutputSurface);
+ sp<ANativeWindow> nativeWindow = static_cast<ANativeWindow *>(output->surface.get());
+ if (nativeWindow == nullptr) {
+ return INVALID_OPERATION;
+ }
+ return pushBlankBuffersToNativeWindow(nativeWindow.get());
+}
+
} // namespace android
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 26eef30..b3a5f4b 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -181,6 +181,11 @@
void setMetaMode(MetaMode mode);
+ /**
+ * Push a blank buffer to the configured native output surface.
+ */
+ status_t pushBlankBufferToOutputSurface();
+
private:
class QueueGuard;
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index c15b5ca..836d2a7 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -20,6 +20,8 @@
#include <log/log.h>
#include <utils/NativeHandle.h>
+#include <android-base/properties.h>
+
#include <C2Component.h>
#include <C2Param.h>
#include <util/C2InterfaceHelper.h>
@@ -324,7 +326,8 @@
: mInputFormat(new AMessage),
mOutputFormat(new AMessage),
mUsingSurface(false),
- mTunneled(false) { }
+ mTunneled(false),
+ mPushBlankBuffersOnStop(false) { }
void CCodecConfig::initializeStandardParams() {
typedef Domain D;
@@ -963,8 +966,6 @@
.limitTo(D::ENCODER & D::VIDEO & D::READ));
/* still to do
- constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
-
not yet used by MediaCodec, but defined as MediaFormat
KEY_AUDIO_SESSION_ID // we use "audio-hw-sync"
KEY_OUTPUT_REORDER_DEPTH
@@ -1112,15 +1113,21 @@
const std::shared_ptr<Codec2Client::Configurable> &configurable,
const std::vector<C2Param::Index> &indices,
c2_blocking_t blocking) {
+ static const int32_t kProductFirstApiLevel =
+ base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
+ static const int32_t kBoardApiLevel =
+ base::GetIntProperty<int32_t>("ro.board.first_api_level", 0);
+ static const int32_t kFirstApiLevel =
+ (kBoardApiLevel != 0) ? kBoardApiLevel : kProductFirstApiLevel;
mSubscribedIndices.insert(indices.begin(), indices.end());
- // TODO: enable this when components no longer crash on this config
- if (mSubscribedIndices.size() != mSubscribedIndicesSize && false) {
- std::vector<uint32_t> indices;
+ if (mSubscribedIndices.size() != mSubscribedIndicesSize
+ && kFirstApiLevel >= __ANDROID_API_T__) {
+ std::vector<uint32_t> indicesVector;
for (C2Param::Index ix : mSubscribedIndices) {
- indices.push_back(ix);
+ indicesVector.push_back(ix);
}
std::unique_ptr<C2SubscribedParamIndicesTuning> subscribeTuning =
- C2SubscribedParamIndicesTuning::AllocUnique(indices);
+ C2SubscribedParamIndicesTuning::AllocUnique(indicesVector);
std::vector<std::unique_ptr<C2SettingResult>> results;
c2_status_t c2Err = configurable->config({ subscribeTuning.get() }, blocking, &results);
if (c2Err != C2_OK && c2Err != C2_BAD_INDEX) {
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 88e6239..2e7b866 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -148,6 +148,8 @@
bool mTunneled;
sp<NativeHandle> mSidebandHandle;
+ bool mPushBlankBuffersOnStop;
+
CCodecConfig();
/// initializes the members required to manage the format: descriptors, reflector,
@@ -396,4 +398,3 @@
} // namespace android
#endif // C_CODEC_H_
-
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 7b593ee..a6a733e 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -31,6 +31,7 @@
#include <C2HandleIonInternal.h>
#include <android-base/properties.h>
+#include <media/stagefright/foundation/Mutexed.h>
namespace android {
@@ -180,7 +181,7 @@
c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
(void)fence; // TODO: wait for fence
*addr = nullptr;
- if (!mMappings.empty()) {
+ if (!mMappings.lock()->empty()) {
ALOGV("multiple map");
// TODO: technically we should return DUPLICATE here, but our block views don't
// actually unmap, so we end up remapping an ion buffer multiple times.
@@ -207,47 +208,44 @@
c2_status_t err = mapInternal(mapSize, mapOffset, alignmentBytes, prot, flags, &(map.addr), addr);
if (map.addr) {
- std::lock_guard<std::mutex> guard(mMutexMappings);
- mMappings.push_back(map);
+ mMappings.lock()->push_back(map);
}
return err;
}
c2_status_t unmap(void *addr, size_t size, C2Fence *fence) {
- if (mMappings.empty()) {
+ Mutexed<std::list<Mapping>>::Locked mappings(mMappings);
+ if (mappings->empty()) {
ALOGD("tried to unmap unmapped buffer");
return C2_NOT_FOUND;
}
- { // Scope for the lock_guard of mMutexMappings.
- std::lock_guard<std::mutex> guard(mMutexMappings);
- for (auto it = mMappings.begin(); it != mMappings.end(); ++it) {
- if (addr != (uint8_t *)it->addr + it->alignmentBytes ||
- size + it->alignmentBytes != it->size) {
- continue;
- }
- int err = munmap(it->addr, it->size);
- if (err != 0) {
- ALOGD("munmap failed");
- return c2_map_errno<EINVAL>(errno);
- }
- if (fence) {
- *fence = C2Fence(); // not using fences
- }
- (void)mMappings.erase(it);
- ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size,
- mHandle.bufferFd());
- return C2_OK;
+ for (auto it = mappings->begin(); it != mappings->end(); ++it) {
+ if (addr != (uint8_t *)it->addr + it->alignmentBytes ||
+ size + it->alignmentBytes != it->size) {
+ continue;
}
+ int err = munmap(it->addr, it->size);
+ if (err != 0) {
+ ALOGD("munmap failed");
+ return c2_map_errno<EINVAL>(errno);
+ }
+ if (fence) {
+ *fence = C2Fence(); // not using fences
+ }
+ (void)mappings->erase(it);
+ ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size,
+ mHandle.bufferFd());
+ return C2_OK;
}
ALOGD("unmap failed to find specified map");
return C2_BAD_VALUE;
}
virtual ~Impl() {
- if (!mMappings.empty()) {
+ Mutexed<std::list<Mapping>>::Locked mappings(mMappings);
+ if (!mappings->empty()) {
ALOGD("Dangling mappings!");
- std::lock_guard<std::mutex> guard(mMutexMappings);
- for (const Mapping &map : mMappings) {
+ for (const Mapping &map : *mappings) {
(void)munmap(map.addr, map.size);
}
}
@@ -325,8 +323,7 @@
size_t alignmentBytes;
size_t size;
};
- std::list<Mapping> mMappings;
- std::mutex mMutexMappings;
+ Mutexed<std::list<Mapping>> mMappings;
};
class C2AllocationIon::ImplV2 : public C2AllocationIon::Impl {
diff --git a/media/codec2/vndk/C2DmaBufAllocator.cpp b/media/codec2/vndk/C2DmaBufAllocator.cpp
index 1aa3d69..c470171 100644
--- a/media/codec2/vndk/C2DmaBufAllocator.cpp
+++ b/media/codec2/vndk/C2DmaBufAllocator.cpp
@@ -31,6 +31,7 @@
#include <list>
#include <android-base/properties.h>
+#include <media/stagefright/foundation/Mutexed.h>
namespace android {
@@ -161,7 +162,7 @@
size_t alignmentBytes;
size_t size;
};
- std::list<Mapping> mMappings;
+ Mutexed<std::list<Mapping>> mMappings;
// TODO: we could make this encapsulate shared_ptr and copiable
C2_DO_NOT_COPY(C2DmaBufAllocation);
@@ -171,7 +172,7 @@
void** addr) {
(void)fence; // TODO: wait for fence
*addr = nullptr;
- if (!mMappings.empty()) {
+ if (!mMappings.lock()->empty()) {
ALOGV("multiple map");
// TODO: technically we should return DUPLICATE here, but our block views
// don't actually unmap, so we end up remapping the buffer multiple times.
@@ -199,17 +200,18 @@
c2_status_t err =
mapInternal(mapSize, mapOffset, alignmentBytes, prot, flags, &(map.addr), addr);
if (map.addr) {
- mMappings.push_back(map);
+ mMappings.lock()->push_back(map);
}
return err;
}
c2_status_t C2DmaBufAllocation::unmap(void* addr, size_t size, C2Fence* fence) {
- if (mMappings.empty()) {
+ Mutexed<std::list<Mapping>>::Locked mappings(mMappings);
+ if (mappings->empty()) {
ALOGD("tried to unmap unmapped buffer");
return C2_NOT_FOUND;
}
- for (auto it = mMappings.begin(); it != mMappings.end(); ++it) {
+ for (auto it = mappings->begin(); it != mappings->end(); ++it) {
if (addr != (uint8_t*)it->addr + it->alignmentBytes ||
size + it->alignmentBytes != it->size) {
continue;
@@ -222,7 +224,7 @@
if (fence) {
*fence = C2Fence(); // not using fences
}
- (void)mMappings.erase(it);
+ (void)mappings->erase(it);
ALOGV("successfully unmapped: %d", mHandle.bufferFd());
return C2_OK;
}
@@ -253,9 +255,10 @@
}
C2DmaBufAllocation::~C2DmaBufAllocation() {
- if (!mMappings.empty()) {
+ Mutexed<std::list<Mapping>>::Locked mappings(mMappings);
+ if (!mappings->empty()) {
ALOGD("Dangling mappings!");
- for (const Mapping& map : mMappings) {
+ for (const Mapping& map : *mappings) {
int err = munmap(map.addr, map.size);
if (err) ALOGD("munmap failed");
}
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 2cca3c8..63b0f39 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -576,14 +576,7 @@
}
~Impl() {
- bool noInit = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
- if (!noInit && mProducer) {
- Return<HStatus> transResult =
- mProducer->detachBuffer(static_cast<int32_t>(i));
- noInit = !transResult.isOk() ||
- static_cast<HStatus>(transResult) == HStatus::NO_INIT;
- }
mBuffers[i].clear();
}
}
@@ -692,15 +685,6 @@
{
sp<GraphicBuffer> buffers[NUM_BUFFER_SLOTS];
std::scoped_lock<std::mutex> lock(mMutex);
- bool noInit = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
- if (!noInit && mProducer) {
- Return<HStatus> transResult =
- mProducer->detachBuffer(static_cast<int32_t>(i));
- noInit = !transResult.isOk() ||
- static_cast<HStatus>(transResult) == HStatus::NO_INIT;
- }
- }
int32_t oldGeneration = mGeneration;
if (producer) {
mProducer = producer;
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index e2eec7a..2a12191 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -36,11 +36,11 @@
"libaudiomanager",
"libaudiopolicy",
"libaudioclient_aidl_conversion",
+ "libutils",
],
static_libs: [
"android.media.audio.common.types-V1-cpp",
"liblog",
- "libutils",
"libcutils",
"libaaudio",
"libjsoncpp",
diff --git a/media/libaaudio/scripts/measure_device_power.py b/media/libaaudio/scripts/measure_device_power.py
index fd7f85f..1f90933 100755
--- a/media/libaaudio/scripts/measure_device_power.py
+++ b/media/libaaudio/scripts/measure_device_power.py
@@ -79,28 +79,42 @@
SORTED_ENERGY_LIST = sorted(ENERGY_DICTIONARY, key=ENERGY_DICTIONARY.get)
-# Sometimes "adb unroot" returns 1!
+# Sometimes adb returns 1 for no apparent reason.
# So try several times.
# @return 0 on success
-def adbUnroot():
+def adbTryMultiple(command):
returnCode = 1
count = 0
limit = 5
while count < limit and returnCode != 0:
- print(('Try to adb unroot {} of {}'.format(count, limit)))
+ print(('Try to adb {} {} of {}'.format(command, count, limit)))
subprocess.call(["adb", "wait-for-device"])
time.sleep(PRE_DELAY_SECONDS)
- returnCode = subprocess.call(["adb", "unroot"])
+ returnCode = subprocess.call(["adb", command])
print(('returnCode = {}'.format(returnCode)))
count += 1
return returnCode
+# Sometimes "adb root" returns 1!
+# So try several times.
+# @return 0 on success
+def adbRoot():
+ return adbTryMultiple("root");
+
+# Sometimes "adb unroot" returns 1!
+# So try several times.
+# @return 0 on success
+def adbUnroot():
+ return adbTryMultiple("unroot");
+
# @param commandString String containing shell command
# @return Both the stdout and stderr of the commands run
def runCommand(commandString):
print(commandString)
if commandString == "adb unroot":
result = adbUnroot()
+ elif commandString == "adb root":
+ result = adbRoot()
else:
commandArray = commandString.split(' ')
result = subprocess.run(commandArray, check=True, capture_output=True).stdout
@@ -111,6 +125,8 @@
def adbCommand(commandString):
if commandString == "unroot":
result = adbUnroot()
+ elif commandString == "root":
+ result = adbRoot()
else:
print(("adb " + commandString))
commandArray = ["adb"] + commandString.split(' ')
@@ -230,7 +246,7 @@
print((command + "\n"))
comment = command[1:].strip() # remove leading '#'
elif command.endswith('\\'):
- command = command[:-1].strip() # remove \\
+ command = command[:-1].strip() # remove trailing '\'
runCommand(command)
elif command:
report = averageEnergyForCommand(command, DEFAULT_NUM_ITERATIONS)
diff --git a/media/libaaudio/scripts/synthmark_tests.txt b/media/libaaudio/scripts/synthmark_tests.txt
index 24e719d..8b6d47e 100644
--- a/media/libaaudio/scripts/synthmark_tests.txt
+++ b/media/libaaudio/scripts/synthmark_tests.txt
@@ -1,31 +1,36 @@
# Measure energy consumption with synthmark.
-# ADPF <400 RR
-adb root \
-adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 400 \
-adb shell synthmark -tj -n1 -N50 -B2 -z1
-adb shell synthmark -tj -n1 -N75 -B2 -z1
-adb shell synthmark -tj -n1 -N100 -B2 -z1
-
-# ADPF <500 RR
-adb root \
-adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 500 \
-adb shell synthmark -tj -n1 -N50 -B2 -z1
-adb shell synthmark -tj -n1 -N75 -B2 -z1
-adb shell synthmark -tj -n1 -N100 -B2 -z1
-
-# ADPF <600 RR
-adb root \
-adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 600 \
-adb shell synthmark -tj -n1 -N50 -B2 -z1
-adb shell synthmark -tj -n1 -N75 -B2 -z1
-adb shell synthmark -tj -n1 -N100 -B2 -z1
-
# None
adb shell synthmark -tj -n1 -N50 -B2 -z0
adb shell synthmark -tj -n1 -N75 -B2 -z0
adb shell synthmark -tj -n1 -N100 -B2 -z0
+# ADPF PID
+adb shell synthmark -tj -n1 -N50 -B2 -z1
+adb shell synthmark -tj -n1 -N75 -B2 -z1
+adb shell synthmark -tj -n1 -N100 -B2 -z1
+
+# ADPF <400 RR
+# adb root \
+# adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 400 \
+# adb shell synthmark -tj -n1 -N50 -B2 -z1
+# adb shell synthmark -tj -n1 -N75 -B2 -z1
+# adb shell synthmark -tj -n1 -N100 -B2 -z1
+
+# ADPF <500 RR
+# adb root \
+# adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 500 \
+# adb shell synthmark -tj -n1 -N50 -B2 -z1
+# adb shell synthmark -tj -n1 -N75 -B2 -z1
+# adb shell synthmark -tj -n1 -N100 -B2 -z1
+
+# ADPF <600 RR
+# adb root \
+# adb shell setprop vendor.powerhal.adpf.uclamp_min.high_limit 600 \
+# adb shell synthmark -tj -n1 -N50 -B2 -z1
+# adb shell synthmark -tj -n1 -N75 -B2 -z1
+# adb shell synthmark -tj -n1 -N100 -B2 -z1
+
# uclamp
# adb root \
# adb shell synthmark -tj -n1 -N75 -B2 -u1
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index e262a38..363d219 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -260,7 +260,7 @@
"binding/aidl/aaudio/IAAudioService.aidl",
],
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V1",
"audioclient-types-aidl",
"shared-file-region-aidl",
"framework-permission-aidl",
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 450d390..7c7a969 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -202,10 +202,18 @@
break;
case AAUDIO_STREAM_STATE_STARTED:
{
- // Sleep until the readCounter catches up and we only have
- // the getBufferSize() frames of data sitting in the buffer.
- int64_t nextReadPosition = mAudioEndpoint->getDataWriteCounter() - getBufferSize();
- wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
+ // Calculate when there will be room available to write to the buffer.
+ // If the appBufferSize is smaller than the endpointBufferSize then
+ // we will have room to write data beyond the appBufferSize.
+ // That is a technique used to reduce glitches without adding latency.
+ const int32_t appBufferSize = getBufferSize();
+ // The endpoint buffer size is set to the maximum that can be written.
+ // If we use it then we must carve out some room to write data when we wake up.
+ const int32_t endBufferSize = mAudioEndpoint->getBufferSizeInFrames()
+ - getFramesPerBurst();
+ const int32_t bestBufferSize = std::min(appBufferSize, endBufferSize);
+ int64_t targetReadPosition = mAudioEndpoint->getDataWriteCounter() - bestBufferSize;
+ wakeTime = mClockModel.convertPositionToTime(targetReadPosition);
}
break;
default:
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 4b42203..872faca 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -562,7 +562,9 @@
int32_t AAudioProperty_getMinimumSleepMicros() {
const int32_t minMicros = 1; // arbitrary
// Higher values can increase latency for moderate workloads.
- const int32_t defaultMicros = 1; // arbitrary
+ // Short values can cause the CPU to short cycle if there is a bug in
+ // calculating the wakeup times.
+ const int32_t defaultMicros = 100; // arbitrary
const int32_t maxMicros = 200; // arbitrary
int32_t prop = property_get_int32(AAUDIO_PROP_MINIMUM_SLEEP_USEC, defaultMicros);
if (prop < minMicros) {
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index e890e97..69a9c68 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -345,7 +345,7 @@
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V1",
"framework-permission-aidl",
],
backend: {
@@ -389,7 +389,7 @@
"aidl/android/media/SpatializerHeadTrackingMode.aidl",
],
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V1",
"audioclient-types-aidl",
],
backend: {
@@ -432,7 +432,7 @@
"aidl/android/media/IAudioTrackCallback.aidl",
],
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V1",
"audioclient-types-aidl",
"av-types-aidl",
"effect-aidl",
@@ -469,7 +469,7 @@
"aidl/android/media/IAudioPolicyServiceClient.aidl",
],
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V1",
"audioclient-types-aidl",
"audiopolicy-types-aidl",
"capture_state_listener-aidl",
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index b9d795d..165a8ad 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -44,7 +44,10 @@
"-Wextra",
"-Wall",
],
- shared_libs: ["libutils", "liblog"],
+ shared_libs: [
+ "libutils",
+ "liblog",
+ ],
header_libs: [
"libmedia_helper_headers",
"libaudio_system_headers",
@@ -52,7 +55,7 @@
export_header_lib_headers: [
"libmedia_helper_headers",
],
- clang: true,
+
host_supported: true,
target: {
darwin: {
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index 55b1ed7..b3f7f25 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -216,7 +216,8 @@
sp<AMessage> format = new AMessage;
status_t err = convertMetaDataToMessage(trackMeta, &format);
if (err != OK) {
- format = NULL;
+ ALOGE("getImageInternal: convertMetaDataToMessage() failed, unable to extract image");
+ return NULL;
}
uint32_t bitDepth = 8;
@@ -400,7 +401,8 @@
sp<AMessage> format = new AMessage;
status_t err = convertMetaDataToMessage(trackMeta, &format);
if (err != OK) {
- format = NULL;
+ ALOGE("getFrameInternal: convertMetaDataToMessage() failed, unable to extract frame");
+ return NULL;
}
Vector<AString> matchingCodecs;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index e47e7ff..10baec4 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -253,6 +253,40 @@
],
},
}
+
+cc_library_shared {
+ name: "libstagefright_surface_utils",
+
+ srcs: [
+ "SurfaceUtils.cpp",
+ ],
+
+ shared_libs: [
+ "libgui",
+ "liblog",
+ "libui",
+ "libutils",
+ ],
+
+ export_include_dirs: [
+ "include",
+ ],
+
+ cflags: [
+ "-Wno-multichar",
+ "-Werror",
+ "-Wall",
+ ],
+
+ sanitize: {
+ cfi: true,
+ misc_undefined: [
+ "unsigned-integer-overflow",
+ "signed-integer-overflow",
+ ],
+ },
+}
+
cc_library {
name: "libstagefright",
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 2f3792e..5a27362 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -186,9 +186,12 @@
// XXX suppress until we get our representation right
static bool kEmitHistogram = false;
+static int64_t getId(IResourceManagerClient const * client) {
+ return (int64_t) client;
+}
static int64_t getId(const std::shared_ptr<IResourceManagerClient> &client) {
- return (int64_t) client.get();
+ return getId(client.get());
}
static bool isResourceError(status_t err) {
@@ -205,12 +208,20 @@
////////////////////////////////////////////////////////////////////////////////
struct ResourceManagerClient : public BnResourceManagerClient {
- explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
+ explicit ResourceManagerClient(MediaCodec* codec, int32_t pid) :
+ mMediaCodec(codec), mPid(pid) {}
Status reclaimResource(bool* _aidl_return) override {
sp<MediaCodec> codec = mMediaCodec.promote();
if (codec == NULL) {
- // codec is already gone.
+ // Codec is already gone, so remove the resources as well
+ ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
+ std::shared_ptr<IResourceManagerService> service =
+ IResourceManagerService::fromBinder(binder);
+ if (service == nullptr) {
+ ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService");
+ }
+ service->removeClient(mPid, getId(this));
*_aidl_return = true;
return Status::ok();
}
@@ -247,6 +258,7 @@
private:
wp<MediaCodec> mMediaCodec;
+ int32_t mPid;
DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
};
@@ -820,7 +832,7 @@
mGetCodecBase(getCodecBase),
mGetCodecInfo(getCodecInfo) {
mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
- ::ndk::SharedRefBase::make<ResourceManagerClient>(this));
+ ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid));
if (!mGetCodecBase) {
mGetCodecBase = [](const AString &name, const char *owner) {
return GetCodecBase(name, owner);
@@ -3053,8 +3065,9 @@
CHECK(msg->findInt32("err", &err));
CHECK(msg->findInt32("actionCode", &actionCode));
- ALOGE("Codec reported err %#x, actionCode %d, while in state %d/%s",
- err, actionCode, mState, stateString(mState).c_str());
+ ALOGE("Codec reported err %#x/%s, actionCode %d, while in state %d/%s",
+ err, StrMediaError(err).c_str(), actionCode,
+ mState, stateString(mState).c_str());
if (err == DEAD_OBJECT) {
mFlags |= kFlagSawMediaServerDie;
mFlags &= ~kFlagIsComponentAllocated;
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 1b31392..ca17117 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -120,8 +120,6 @@
},
},
- clang: true,
-
sanitize: {
misc_undefined: [
"unsigned-integer-overflow",
@@ -172,7 +170,7 @@
shared_libs: [
"liblog",
- "libutils", // for sp<>
+ "libutils", // for sp<>
// actually invokes this, but called from folks who already load it
// "libmediandk",
],
@@ -200,8 +198,6 @@
"ColorUtils_fill.cpp",
],
- clang: true,
-
sanitize: {
misc_undefined: [
"unsigned-integer-overflow",
@@ -218,4 +214,3 @@
],
}
-
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index d1df2ca..b91c850 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -163,11 +163,28 @@
|| (ERROR_DRM_VENDOR_MIN <= err && err <= ERROR_DRM_VENDOR_MAX);
}
-static inline std::string StrCryptoError(status_t err) {
#define STATUS_CASE(STATUS) \
case STATUS: \
return #STATUS
+static inline std::string StrMediaError(status_t err) {
+ switch(err) {
+ STATUS_CASE(ERROR_ALREADY_CONNECTED);
+ STATUS_CASE(ERROR_NOT_CONNECTED);
+ STATUS_CASE(ERROR_UNKNOWN_HOST);
+ STATUS_CASE(ERROR_CANNOT_CONNECT);
+ STATUS_CASE(ERROR_IO);
+ STATUS_CASE(ERROR_CONNECTION_LOST);
+ STATUS_CASE(ERROR_MALFORMED);
+ STATUS_CASE(ERROR_OUT_OF_RANGE);
+ STATUS_CASE(ERROR_BUFFER_TOO_SMALL);
+ STATUS_CASE(ERROR_UNSUPPORTED);
+ STATUS_CASE(ERROR_END_OF_STREAM);
+ }
+ return statusToString(err);
+}
+
+static inline std::string StrCryptoError(status_t err) {
switch (err) {
STATUS_CASE(ERROR_DRM_UNKNOWN);
STATUS_CASE(ERROR_DRM_NO_LICENSE);
@@ -209,10 +226,10 @@
STATUS_CASE(ERROR_DRM_STORAGE_READ);
STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
-#undef STATUS_CASE
}
return statusToString(err);
}
+#undef STATUS_CASE
} // namespace android
diff --git a/media/libstagefright/omx/OMXStore.cpp b/media/libstagefright/omx/OMXStore.cpp
index e8fee42..7e33f09 100644
--- a/media/libstagefright/omx/OMXStore.cpp
+++ b/media/libstagefright/omx/OMXStore.cpp
@@ -99,6 +99,15 @@
}
}
+static int getFirstApiLevel() {
+ int boardApiLevel = android::base::GetIntProperty("ro.board.first_api_level", 0);
+ if (boardApiLevel != 0) {
+ return boardApiLevel;
+ }
+
+ return android::base::GetIntProperty("ro.product.first_api_level", __ANDROID_API_T__);
+}
+
void OMXStore::addPlugin(OMXPluginBase *plugin) {
Mutex::Autolock autoLock(mLock);
@@ -110,6 +119,29 @@
name, sizeof(name), index++)) == OMX_ErrorNone) {
String8 name8(name);
+ Vector<String8> roles;
+ OMX_ERRORTYPE err = plugin->getRolesOfComponent(name, &roles);
+ if (err == OMX_ErrorNone) {
+ bool skip = false;
+ for (String8 role : roles) {
+ if (role.find("video_decoder") != -1 || role.find("video_encoder") != -1) {
+ if (getFirstApiLevel() >= __ANDROID_API_S__) {
+ skip = true;
+ break;
+ }
+ }
+ if (role.find("audio_decoder") != -1 || role.find("audio_encoder") != -1) {
+ if (getFirstApiLevel() >= __ANDROID_API_T__) {
+ skip = true;
+ break;
+ }
+ }
+ }
+ if (skip) {
+ continue;
+ }
+ }
+
if (mPluginByComponentName.indexOfKey(name8) >= 0) {
ALOGE("A component of name '%s' already exists, ignoring this one.",
name8.string());
diff --git a/media/libstagefright/renderfright/Android.bp b/media/libstagefright/renderfright/Android.bp
index 9a7bad9..3c00a1c 100644
--- a/media/libstagefright/renderfright/Android.bp
+++ b/media/libstagefright/renderfright/Android.bp
@@ -87,7 +87,7 @@
enabled: true,
},
double_loadable: true,
- clang: true,
+
cflags: [
"-fvisibility=hidden",
"-Werror=format",
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index 055dd80..afc873c 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -41,8 +41,6 @@
"-Wall",
],
- clang: true,
-
sanitize: {
misc_undefined: [
"unsigned-integer-overflow",
diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp
index 6f25cec..38e422d 100644
--- a/media/ndk/NdkMediaCodec.cpp
+++ b/media/ndk/NdkMediaCodec.cpp
@@ -277,8 +277,8 @@
break;
}
msg->findString("detail", &detail);
- ALOGE("Codec reported error(0x%x), actionCode(%d), detail(%s)",
- err, actionCode, detail.c_str());
+ ALOGE("Codec reported error(0x%x/%s), actionCode(%d), detail(%s)",
+ err, StrMediaError(err).c_str(), actionCode, detail.c_str());
Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
if (mCodec->mAsyncCallback.onAsyncError != NULL) {
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 07fc5de..6d3c348 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -388,9 +388,11 @@
mode = CryptoPlugin::kMode_AES_CTR;
}
+ sp<ABuffer> clearbuf;
+ sp<ABuffer> cryptedbuf;
if (sizeof(uint32_t) != sizeof(size_t)) {
- sp<ABuffer> clearbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)cleardata);
- sp<ABuffer> cryptedbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)crypteddata);
+ clearbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)cleardata);
+ cryptedbuf = U32ArrayToSizeBuf(numSubSamples, (uint32_t *)crypteddata);
cleardata = clearbuf == NULL ? NULL : clearbuf->data();
crypteddata = crypteddata == NULL ? NULL : cryptedbuf->data();
if(crypteddata == NULL || cleardata == NULL) {
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index d76602b..a38ef57 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -37,6 +37,7 @@
"ProcessInfo.cpp",
"SchedulingPolicyService.cpp",
"ServiceUtilities.cpp",
+ "ThreadSnapshot.cpp",
"TimeCheck.cpp",
"TimerThread.cpp",
],
diff --git a/media/utils/ThreadSnapshot.cpp b/media/utils/ThreadSnapshot.cpp
new file mode 100644
index 0000000..382738e
--- /dev/null
+++ b/media/utils/ThreadSnapshot.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ThreadSnapshot"
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <mediautils/ThreadSnapshot.h>
+
+#include <mediautils/Process.h>
+
+namespace android::mediautils {
+
+pid_t ThreadSnapshot::getTid() const {
+ std::lock_guard lg(mLock);
+ return mState.mTid;
+}
+
+void ThreadSnapshot::setTid(pid_t tid) {
+ std::lock_guard lg(mLock);
+ if (mState.mTid == tid) return;
+ mState.reset(tid);
+}
+
+void ThreadSnapshot::reset() {
+ std::lock_guard lg(mLock);
+ mState.reset(mState.mTid);
+}
+
+void ThreadSnapshot::onBegin() {
+ std::string sched = getThreadSchedAsString(getTid()); // tid could race here,
+ // accept as benign.
+ std::lock_guard lg(mLock);
+ mState.onBegin(std::move(sched));
+}
+
+void ThreadSnapshot::onEnd() {
+ std::lock_guard lg(mLock);
+ mState.onEnd();
+}
+
+std::string ThreadSnapshot::toString() const {
+ // Make a local copy of the stats data under lock.
+ State state;
+ {
+ std::lock_guard lg(mLock);
+ state = mState;
+ }
+ return state.toString();
+}
+
+void ThreadSnapshot::State::reset(pid_t tid) {
+ mTid = tid;
+ mBeginTimeNs = -2;
+ mEndTimeNs = -1;
+ mCumulativeTimeNs = 0;
+ mBeginSched.clear();
+}
+
+void ThreadSnapshot::State::onBegin(std::string sched) {
+ if (mBeginTimeNs < mEndTimeNs) {
+ mBeginTimeNs = systemTime();
+ mBeginSched = std::move(sched);
+ }
+}
+
+void ThreadSnapshot::State::onEnd() {
+ if (mEndTimeNs < mBeginTimeNs) {
+ mEndTimeNs = systemTime();
+ mCumulativeTimeNs += mEndTimeNs - mBeginTimeNs;
+ }
+}
+
+std::string ThreadSnapshot::State::toString() const {
+ if (mBeginTimeNs < 0) return {}; // never begun.
+
+ // compute time intervals.
+ const int64_t nowNs = systemTime();
+ int64_t cumulativeTimeNs = mCumulativeTimeNs;
+ int64_t diffNs = mEndTimeNs - mBeginTimeNs; // if onEnd() isn't matched, diffNs < 0.
+ if (diffNs < 0) {
+ diffNs = nowNs - mBeginTimeNs;
+ cumulativeTimeNs += diffNs;
+ }
+ // normalization for rate variables
+ const double lastRunPerSec = 1e9 / diffNs;
+ const double totalPerSec = 1e9 / cumulativeTimeNs;
+
+ // HANDLE THE SCHEDULER STATISTICS HERE
+ // current and differential statistics for the scheduler.
+ std::string schedNow = getThreadSchedAsString(mTid);
+ const auto schedMapThen = parseThreadSchedString(mBeginSched);
+ const auto schedMapNow = parseThreadSchedString(schedNow);
+ static const char * schedDiffKeyList[] = {
+ "se.sum_exec_runtime",
+ "se.nr_migrations",
+ "se.statistics.wait_sum",
+ "se.statistics.wait_count",
+ "se.statistics.iowait_sum",
+ "se.statistics.iowait_count",
+ "se.statistics.nr_forced_migrations",
+ "nr_involuntary_switches",
+ };
+
+ // compute differential rate statistics.
+ std::string diffString;
+ for (const auto diffKey : schedDiffKeyList) {
+ if (auto itThen = schedMapThen.find(diffKey);
+ itThen != schedMapThen.end()) {
+
+ if (auto itNow = schedMapNow.find(diffKey);
+ itNow != schedMapNow.end()) {
+ auto diff = itNow->second - itThen->second;
+ diff *= lastRunPerSec;
+ auto total = itNow->second * totalPerSec;
+ diffString.append(diffKey).append(" last-run:")
+ .append(std::to_string(diff))
+ .append(" cumulative:")
+ .append(std::to_string(total))
+ .append("\n");
+ }
+ }
+ }
+
+ if (!diffString.empty()) {
+ schedNow.append("*** per second stats ***\n").append(diffString);
+ }
+
+ // Return snapshot string.
+ return schedNow;
+}
+
+} // android::mediautils
diff --git a/media/utils/include/mediautils/ThreadSnapshot.h b/media/utils/include/mediautils/ThreadSnapshot.h
new file mode 100644
index 0000000..c470822
--- /dev/null
+++ b/media/utils/include/mediautils/ThreadSnapshot.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <string>
+
+#include <android-base/thread_annotations.h>
+
+namespace android::mediautils {
+
+/**
+ * Collect Thread performance statistics.
+ *
+ * An onBegin() and onEnd() signal a continuous "run".
+ * Statistics are returned by toString().
+ */
+class ThreadSnapshot {
+public:
+ explicit ThreadSnapshot(pid_t tid = -1) { mState.reset(tid); };
+
+ // Returns current tid
+ pid_t getTid() const;
+
+ // Sets the tid
+ void setTid(pid_t tid);
+
+ // Reset statistics, keep same tid.
+ void reset();
+
+ // Signal a timing run is beginning
+ void onBegin();
+
+ // Signal a timing run is ending
+ void onEnd();
+
+ // Return the thread snapshot statistics in a string
+ std::string toString() const;
+
+private:
+ mutable std::mutex mLock;
+
+ // State represents our statistics at a given point in time.
+ // It is not thread-safe, so any locking must occur at the caller.
+ struct State {
+ pid_t mTid;
+ int64_t mBeginTimeNs; // when last run began
+ int64_t mEndTimeNs; // when last run ends (if less than begin time, not started)
+ int64_t mCumulativeTimeNs;
+
+ // Sched is the scheduler statistics obtained as a string.
+ // This is parsed only when toString() is called.
+ std::string mBeginSched;
+
+ // Clears existing state.
+ void reset(pid_t tid);
+
+ // onBegin() takes a std::string sched should can be captured outside
+ // of locking.
+ void onBegin(std::string sched);
+ void onEnd();
+ std::string toString() const;
+ };
+
+ // Our current state. We only keep the current running state.
+ State mState GUARDED_BY(mLock);
+};
+
+} // android::mediautils
diff --git a/media/utils/tests/Android.bp b/media/utils/tests/Android.bp
index d9c2b21..a6f408d 100644
--- a/media/utils/tests/Android.bp
+++ b/media/utils/tests/Android.bp
@@ -104,6 +104,26 @@
}
cc_test {
+ name: "media_threadsnapshot_tests",
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libmediautils",
+ "libutils",
+ ],
+
+ srcs: [
+ "media_threadsnapshot_tests.cpp",
+ ],
+}
+
+cc_test {
name: "methodstatistics_tests",
cflags: [
diff --git a/media/utils/tests/media_threadsnapshot_tests.cpp b/media/utils/tests/media_threadsnapshot_tests.cpp
new file mode 100644
index 0000000..c7a45e2
--- /dev/null
+++ b/media/utils/tests/media_threadsnapshot_tests.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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 <mediautils/ThreadSnapshot.h>
+
+#define LOG_TAG "media_threadsnapshot_tests"
+
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+#include <chrono>
+#include <thread>
+
+using namespace android;
+using namespace android::mediautils;
+
+TEST(media_threadsnapshot_tests, basic) {
+ using namespace std::chrono_literals;
+
+ ThreadSnapshot threadSnapshot(gettid());
+
+ threadSnapshot.onBegin();
+
+ std::string snapshot1 = threadSnapshot.toString();
+
+ std::this_thread::sleep_for(100ms);
+
+ threadSnapshot.onEnd();
+
+ std::string snapshot2 = threadSnapshot.toString();
+
+ // Either we can't get a snapshot, or they must be different when taken when thread is running.
+ if (snapshot1.empty()) {
+ ASSERT_TRUE(snapshot2.empty());
+ } else {
+ ASSERT_FALSE(snapshot2.empty());
+ ASSERT_NE(snapshot1, snapshot2);
+ }
+}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 59f22eb..8e4383c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -76,6 +76,7 @@
#include <media/VolumeShaper.h>
#include <mediautils/ServiceUtilities.h>
#include <mediautils/Synchronization.h>
+#include <mediautils/ThreadSnapshot.h>
#include <audio_utils/clock.h>
#include <audio_utils/FdToString.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f8c3ae4..49f6bfc 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -933,7 +933,7 @@
}
}
if (dumpAll || type() == SPATIALIZER) {
- const std::string sched = mediautils::getThreadSchedAsString(getTid());
+ const std::string sched = mThreadSnapshot.toString();
if (!sched.empty()) {
(void)write(fd, sched.c_str(), sched.size());
}
@@ -978,7 +978,8 @@
|| mType == MIXER
|| mType == DUPLICATING
|| mType == DIRECT
- || mType == OFFLOAD) {
+ || mType == OFFLOAD
+ || mType == SPATIALIZER) {
dprintf(fd, " Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
dprintf(fd, " Timestamp corrected: %s\n", isTimestampCorrectionEnabled() ? "yes" : "no");
}
@@ -2113,6 +2114,7 @@
}
}
run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
+ mThreadSnapshot.setTid(getTid());
}
// ThreadBase virtuals
@@ -3006,6 +3008,7 @@
// Calculate size of normal sink buffer relative to the HAL output buffer size
double multiplier = 1.0;
+ // Note: mType == SPATIALIZER does not support FastMixer.
if (mType == MIXER && (kUseFastMixer == FastMixer_Static ||
kUseFastMixer == FastMixer_Dynamic)) {
size_t minNormalFrameCount = (kMinNormalSinkBufferSizeMs * mSampleRate) / 1000;
@@ -3354,6 +3357,7 @@
mInWrite = false;
if (mStandby) {
mThreadMetrics.logBeginInterval();
+ mThreadSnapshot.onBegin();
mStandby = false;
}
return bytesWritten;
@@ -3466,7 +3470,7 @@
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
effect_buffer_t *buffer = nullptr; // only used for non global sessions
- if (mType == SPATIALIZER ) {
+ if (mType == SPATIALIZER) {
if (!audio_is_global_session(session)) {
// player sessions on a spatializer output will use a dedicated input buffer and
// will either output multi channel to mEffectBuffer if the track is spatilaized
@@ -3692,7 +3696,7 @@
cacheParameters_l();
mSleepTimeUs = mIdleSleepTimeUs;
- if (mType == MIXER) {
+ if (mType == MIXER || mType == SPATIALIZER) {
sleepTimeShift = 0;
}
@@ -3839,6 +3843,7 @@
if (!mStandby) {
LOG_AUDIO_STATE();
mThreadMetrics.logEndInterval();
+ mThreadSnapshot.onEnd();
mStandby = true;
}
sendStatistics(false /* force */);
@@ -3869,7 +3874,7 @@
mStandbyTimeNs = systemTime() + mStandbyDelayNs;
mSleepTimeUs = mIdleSleepTimeUs;
- if (mType == MIXER) {
+ if (mType == MIXER || mType == SPATIALIZER) {
sleepTimeShift = 0;
}
@@ -4146,7 +4151,8 @@
// write blocked detection
const int64_t deltaWriteNs = lastIoEndNs - lastIoBeginNs;
- if (mType == MIXER && deltaWriteNs > maxPeriod) {
+ if ((mType == MIXER || mType == SPATIALIZER)
+ && deltaWriteNs > maxPeriod) {
mNumDelayedWrites++;
if ((lastIoEndNs - lastWarning) > kWarningThrottleNs) {
ATRACE_NAME("underrun");
@@ -4167,7 +4173,7 @@
(mMixerStatus == MIXER_DRAIN_ALL)) {
threadLoop_drain();
}
- if (mType == MIXER && !mStandby) {
+ if ((mType == MIXER || mType == SPATIALIZER) && !mStandby) {
if (mThreadThrottle
&& mMixerStatus == MIXER_TRACKS_READY // we are mixing (active tracks)
@@ -4292,13 +4298,6 @@
void AudioFlinger::PlaybackThread::collectTimestamps_l()
{
- // Collect timestamp statistics for the Playback Thread types that support it.
- if (mType != MIXER
- && mType != DUPLICATING
- && mType != DIRECT
- && mType != OFFLOAD) {
- return;
- }
if (mStandby) {
mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
return;
@@ -5974,6 +5973,7 @@
mOutput->standby();
if (!mStandby) {
mThreadMetrics.logEndInterval();
+ mThreadSnapshot.onEnd();
mStandby = true;
}
mBytesWritten = 0;
@@ -6495,6 +6495,7 @@
mOutput->standby();
if (!mStandby) {
mThreadMetrics.logEndInterval();
+ mThreadSnapshot.onEnd();
mStandby = true;
}
mBytesWritten = 0;
@@ -7081,6 +7082,7 @@
}
if (mStandby) {
mThreadMetrics.logBeginInterval();
+ mThreadSnapshot.onBegin();
mStandby = false;
}
return (ssize_t)mSinkBufferSize;
@@ -7606,6 +7608,7 @@
doBroadcast = true;
if (mStandby) {
mThreadMetrics.logBeginInterval();
+ mThreadSnapshot.onBegin();
mStandby = false;
}
activeTrack->mState = TrackBase::ACTIVE;
@@ -8087,6 +8090,7 @@
if (!mStandby) {
inputStandBy();
mThreadMetrics.logEndInterval();
+ mThreadSnapshot.onEnd();
mStandby = true;
}
}
@@ -9472,6 +9476,7 @@
}
if (mStandby) {
mThreadMetrics.logBeginInterval();
+ mThreadSnapshot.onBegin();
mStandby = false;
}
return NO_ERROR;
@@ -9668,6 +9673,7 @@
mHalStream->standby();
if (!mStandby) {
mThreadMetrics.logEndInterval();
+ mThreadSnapshot.onEnd();
mStandby = true;
}
releaseWakeLock();
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1fccdc5..b2962ed8 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -687,6 +687,9 @@
int64_t mLastIoBeginNs = -1;
int64_t mLastIoEndNs = -1;
+ // ThreadSnapshot is thread-safe (internally locked)
+ mediautils::ThreadSnapshot mThreadSnapshot;
+
// This should be read under ThreadBase lock (if not on the threadLoop thread).
audio_utils::Statistics<double> mIoJitterMs{0.995 /* alpha */};
audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index d1655ef..713b0ac 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -125,7 +125,7 @@
void SourceClientCollection::dump(String8 *dst) const
{
- dst->append("\n Audio sources (%zu):\n", size());
+ dst->appendFormat("\n Audio sources (%zu):\n", size());
for (size_t i = 0; i < size(); i++) {
const std::string prefix = base::StringPrintf(" %zu. ", i + 1);
dst->appendFormat("%s", prefix.c_str());
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 334f267..ddc72f6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -287,9 +287,12 @@
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
// close unused outputs after device disconnection or direct outputs that have
// been opened by checkOutputsForDevice() to query dynamic parameters
+ // "outputs" vector never contains duplicated outputs
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)
|| (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
- (desc->mDirectOpenCount == 0))) {
+ (desc->mDirectOpenCount == 0))
+ || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) &&
+ !isOutputOnlyAvailableRouteToSomeDevice(desc))) {
clearAudioSourcesForOutput(output);
closeOutput(output);
}
@@ -5365,6 +5368,29 @@
}
}
+
+bool AudioPolicyManager::isOutputOnlyAvailableRouteToSomeDevice(
+ const sp<SwAudioOutputDescriptor>& outputDesc) {
+ if (outputDesc->isDuplicated()) {
+ return false;
+ }
+ DeviceVector devices = outputDesc->supportedDevices();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if (desc == outputDesc || desc->isDuplicated()) {
+ continue;
+ }
+ DeviceVector sharedDevices = desc->filterSupportedDevices(devices);
+ if (!sharedDevices.isEmpty()
+ && (desc->devicesSupportEncodedFormats(sharedDevices.types())
+ == outputDesc->devicesSupportEncodedFormats(sharedDevices.types()))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
status_t AudioPolicyManager::getSpatializerOutput(const audio_config_base_t *mixerConfig,
const audio_attributes_t *attr,
audio_io_handle_t *output) {
@@ -5380,80 +5406,67 @@
}
if (!canBeSpatializedInt(
attr, configPtr, devicesTypeAddress)) {
- ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
+ ALOGV("%s provided attributes or mixer config cannot be spatialized", __func__);
return BAD_VALUE;
}
sp<IOProfile> profile =
getSpatializerOutputProfile(configPtr, devicesTypeAddress);
if (profile == nullptr) {
- ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__);
+ ALOGV("%s no suitable output profile for provided attributes or mixer config", __func__);
return BAD_VALUE;
}
- if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile
- && configPtr != nullptr
- && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) {
- *output = mSpatializerOutput->mIoHandle;
- ALOGV("%s returns current spatializer output %d", __func__, *output);
- return NO_ERROR;
- }
- mSpatializerOutput.clear();
+ std::vector<sp<SwAudioOutputDescriptor>> spatializerOutputs;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if (!desc->isDuplicated() && desc->mProfile == profile) {
- ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle);
- mSpatializerOutput = desc;
- break;
+ if (!desc->isDuplicated()
+ && (desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
+ spatializerOutputs.push_back(desc);
+ ALOGV("%s adding opened spatializer Output %d", __func__, desc->mIoHandle);
}
}
- if (mSpatializerOutput == nullptr) {
- ALOGW("%s no opened spatializer output for profile %s",
- __func__, profile->getName().c_str());
- return BAD_VALUE;
+ mSpatializerOutput.clear();
+ bool outputsChanged = false;
+ for (const auto& desc : spatializerOutputs) {
+ if (desc->mProfile == profile
+ && (configPtr == nullptr
+ || configPtr->channel_mask == desc->mMixerChannelMask)) {
+ mSpatializerOutput = desc;
+ ALOGV("%s reusing current spatializer output %d", __func__, desc->mIoHandle);
+ } else {
+ ALOGV("%s closing spatializerOutput output %d to match channel mask %#x"
+ " and devices %s", __func__, desc->mIoHandle,
+ configPtr != nullptr ? configPtr->channel_mask : 0,
+ devices.toString().c_str());
+ closeOutput(desc->mIoHandle);
+ outputsChanged = true;
+ }
}
- if (configPtr != nullptr
- && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) {
- audio_config_base_t savedMixerConfig = {
- .sample_rate = mSpatializerOutput->getSamplingRate(),
- .format = mSpatializerOutput->getFormat(),
- .channel_mask = mSpatializerOutput->mMixerChannelMask,
- };
- DeviceVector savedDevices = mSpatializerOutput->devices();
-
- ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)",
- __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask);
-
- closeOutput(mSpatializerOutput->mIoHandle);
- //from now on mSpatializerOutput is null
-
+ if (mSpatializerOutput == nullptr) {
sp<SwAudioOutputDescriptor> desc =
openOutputWithProfileAndDevice(profile, devices, mixerConfig);
- if (desc == nullptr) {
- // re open the spatializer output with previous channel mask
- desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig);
- if (desc == nullptr) {
- ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__);
- } else {
- mSpatializerOutput = desc;
- }
- mPreviousOutputs = mOutputs;
- mpClientInterface->onAudioPortListUpdate();
- *output = AUDIO_IO_HANDLE_NONE;
- ALOGW("%s could not open spatializer output with requested config", __func__);
- return BAD_VALUE;
+ if (desc != nullptr) {
+ mSpatializerOutput = desc;
+ outputsChanged = true;
}
- mSpatializerOutput = desc;
- mPreviousOutputs = mOutputs;
- mpClientInterface->onAudioPortListUpdate();
}
checkVirtualizerClientRoutes();
+ if (outputsChanged) {
+ mPreviousOutputs = mOutputs;
+ mpClientInterface->onAudioPortListUpdate();
+ }
+
+ if (mSpatializerOutput == nullptr) {
+ ALOGV("%s could not open spatializer output with requested config", __func__);
+ return BAD_VALUE;
+ }
*output = mSpatializerOutput->mIoHandle;
- ALOGV("%s returns new spatializer output %d", __func__, *output);
- return NO_ERROR;
+ ALOGV("%s returning new spatializer output %d", __func__, *output);
+ return OK;
}
status_t AudioPolicyManager::releaseSpatializerOutput(audio_io_handle_t output) {
@@ -5464,9 +5477,12 @@
return BAD_VALUE;
}
- mSpatializerOutput.clear();
-
- checkVirtualizerClientRoutes();
+ if (!isOutputOnlyAvailableRouteToSomeDevice(mSpatializerOutput)) {
+ ALOGV("%s closing spatializer output %d", __func__, mSpatializerOutput->mIoHandle);
+ closeOutput(mSpatializerOutput->mIoHandle);
+ //from now on mSpatializerOutput is null
+ checkVirtualizerClientRoutes();
+ }
return NO_ERROR;
}
@@ -5543,6 +5559,7 @@
return status;
}
+ mEngine->updateDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
@@ -5742,6 +5759,21 @@
inputDesc->close();
}
}
+
+ // Check if spatializer outputs can be closed until used.
+ // mOutputs vector never contains duplicated outputs at this point.
+ std::vector<audio_io_handle_t> outputsClosed;
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if ((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0
+ && !isOutputOnlyAvailableRouteToSomeDevice(desc)) {
+ outputsClosed.push_back(desc->mIoHandle);
+ desc->close();
+ }
+ }
+ for (auto output : outputsClosed) {
+ removeOutput(output);
+ }
}
void AudioPolicyManager::addOutput(audio_io_handle_t output,
@@ -6436,6 +6468,18 @@
return false;
}
+bool AudioPolicyManager::isHearingAidUsedForComm() const {
+ DeviceVector devices = mEngine->getOutputDevicesForStream(AUDIO_STREAM_VOICE_CALL,
+ true /*fromCache*/);
+ for (const auto &device : devices) {
+ if (device->type() == AUDIO_DEVICE_OUT_HEARING_AID) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
void AudioPolicyManager::checkA2dpSuspend()
{
audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
@@ -7233,13 +7277,15 @@
bool isBtScoVolSrc = (volumeSource != VOLUME_SOURCE_NONE) && (btScoVolSrc == volumeSource);
bool isScoRequested = isScoRequestedForComm();
+ bool isHAUsed = isHearingAidUsedForComm();
+
// do not change in call volume if bluetooth is connected and vice versa
// if sco and call follow same curves, bypass forceUseForComm
if ((callVolSrc != btScoVolSrc) &&
((isVoiceVolSrc && isScoRequested) ||
- (isBtScoVolSrc && !isScoRequested))) {
+ (isBtScoVolSrc && !(isScoRequested || isHAUsed)))) {
ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
- volumeSource, isScoRequested ? " " : "n ot ");
+ volumeSource, isScoRequested ? " " : " not ");
// Do not return an error here as AudioService will always set both voice call
// and bluetooth SCO volumes due to stream aliasing.
return NO_ERROR;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index b12b71a..0d9b5bf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1097,6 +1097,16 @@
void checkVirtualizerClientRoutes();
/**
+ * @brief Returns true if at least one device can only be reached via the output passed
+ * as argument. Always returns false for duplicated outputs.
+ * This can be used to decide if an output can be closed without forbidding
+ * playback to any given device.
+ * @param outputDesc the output to consider
+ * @return true if at least one device can only be reached via the output.
+ */
+ bool isOutputOnlyAvailableRouteToSomeDevice(const sp<SwAudioOutputDescriptor>& outputDesc);
+
+ /**
* @brief getInputForDevice selects an input handle for a given input device and
* requester context
* @param device to be used by requester, selected by policy mix rules or engine
@@ -1189,6 +1199,8 @@
bool isScoRequestedForComm() const;
+ bool isHearingAidUsedForComm() const;
+
bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output);
/**
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 08ab4b6..e7d945f 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1958,12 +1958,16 @@
while (!exitPending())
{
sp<AudioPolicyService> svc;
+ int numTimesBecameEmpty = 0;
while (!mAudioCommands.isEmpty() && !exitPending()) {
nsecs_t curTime = systemTime();
// commands are sorted by increasing time stamp: execute them from index 0 and up
if (mAudioCommands[0]->mTime <= curTime) {
sp<AudioCommand> command = mAudioCommands[0];
mAudioCommands.removeAt(0);
+ if (mAudioCommands.isEmpty()) {
+ ++numTimesBecameEmpty;
+ }
mLastCommand = command;
switch (command->mCommand) {
@@ -2211,8 +2215,9 @@
}
}
- // release delayed commands wake lock if the queue is empty
- if (mAudioCommands.isEmpty()) {
+ // release delayed commands wake lock as many times as we made the queue is
+ // empty during popping.
+ while (numTimesBecameEmpty--) {
release_wake_lock(mName.string());
}
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 3b466d7..389233e 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -459,9 +459,7 @@
}
std::lock_guard lock(mLock);
mScreenSensor = sensorHandle;
- if (mPoseController != nullptr) {
- mPoseController->setScreenSensor(mScreenSensor);
- }
+ checkSensorsState_l();
return Status::ok();
}
@@ -569,9 +567,6 @@
sp<media::ISpatializerHeadTrackingCallback> callback;
{
std::lock_guard lock(mLock);
- if (mActualHeadTrackingMode == SpatializerHeadTrackingMode::DISABLED) {
- return;
- }
callback = mHeadTrackingCallback;
if (mEngine != nullptr) {
setEffectParameter_l(SPATIALIZER_PARAM_HEAD_TO_STAGE, headToStage);
@@ -595,7 +590,6 @@
ALOGV("%s(%d)", __func__, (int) mode);
sp<media::ISpatializerHeadTrackingCallback> callback;
SpatializerHeadTrackingMode spatializerMode;
- bool modeChanged = false;
{
std::lock_guard lock(mLock);
if (!mSupportsHeadTracking) {
@@ -615,21 +609,19 @@
LOG_ALWAYS_FATAL("Unknown mode: %d", mode);
}
}
- modeChanged = mActualHeadTrackingMode != spatializerMode;
mActualHeadTrackingMode = spatializerMode;
- if (modeChanged && mEngine != nullptr) {
+ if (mEngine != nullptr) {
setEffectParameter_l(SPATIALIZER_PARAM_HEADTRACKING_MODE,
std::vector<SpatializerHeadTrackingMode>{spatializerMode});
}
callback = mHeadTrackingCallback;
}
- if (callback != nullptr && modeChanged) {
+ if (callback != nullptr) {
callback->onHeadTrackingModeChanged(spatializerMode);
}
}
status_t Spatializer::attachOutput(audio_io_handle_t output, size_t numActiveTracks) {
- std::shared_ptr<SpatializerPoseController> poseController;
bool outputChanged = false;
sp<media::INativeSpatializerCallback> callback;
@@ -663,14 +655,9 @@
if (mSupportsHeadTracking) {
checkPoseController_l();
checkSensorsState_l();
- poseController = mPoseController;
}
callback = mSpatializerCallback;
}
- if (poseController != nullptr) {
- poseController->calculateAsync();
- poseController->waitUntilCalculated();
- }
if (outputChanged && callback != nullptr) {
callback->onOutputChanged(output);
@@ -750,7 +737,7 @@
if (isControllerNeeded && mPoseController == nullptr) {
mPoseController = std::make_shared<SpatializerPoseController>(
static_cast<SpatializerPoseController::Listener*>(this),
- 10ms, std::chrono::microseconds::max());
+ 10ms, std::nullopt);
LOG_ALWAYS_FATAL_IF(mPoseController == nullptr,
"%s could not allocate pose controller", __func__);
mPoseController->setDisplayOrientation(mDisplayOrientation);
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 58a57ac..0a9f4d9 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -46,9 +46,8 @@
// high will result in high prediction errors whenever the head accelerates (changes velocity).
constexpr auto kPredictionDuration = 50ms;
-// After losing this many consecutive samples from either sensor, we would treat the measurement as
-// stale;
-constexpr auto kMaxLostSamples = 4;
+// After not getting a pose sample for this long, we would treat the measurement as stale.
+constexpr auto kFreshnessTimeout = 50ms;
// Auto-recenter kicks in after the head has been still for this long.
constexpr auto kAutoRecenterWindowDuration = 6s;
@@ -79,14 +78,14 @@
} // namespace
SpatializerPoseController::SpatializerPoseController(Listener* listener,
- std::chrono::microseconds sensorPeriod,
- std::chrono::microseconds maxUpdatePeriod)
+ std::chrono::microseconds sensorPeriod,
+ std::optional<std::chrono::microseconds> maxUpdatePeriod)
: mListener(listener),
mSensorPeriod(sensorPeriod),
mProcessor(createHeadTrackingProcessor(HeadTrackingProcessor::Options{
.maxTranslationalVelocity = kMaxTranslationalVelocity / kTicksPerSecond,
.maxRotationalVelocity = kMaxRotationalVelocity / kTicksPerSecond,
- .freshnessTimeout = Ticks(sensorPeriod * kMaxLostSamples).count(),
+ .freshnessTimeout = Ticks(kFreshnessTimeout).count(),
.predictionDuration = Ticks(kPredictionDuration).count(),
.autoRecenterWindowDuration = Ticks(kAutoRecenterWindowDuration).count(),
.autoRecenterTranslationalThreshold = kAutoRecenterTranslationThreshold,
@@ -102,8 +101,12 @@
std::optional<HeadTrackingMode> modeIfChanged;
{
std::unique_lock lock(mMutex);
- mCondVar.wait_for(lock, maxUpdatePeriod,
- [this] { return mShouldExit || mShouldCalculate; });
+ if (maxUpdatePeriod.has_value()) {
+ mCondVar.wait_for(lock, maxUpdatePeriod.value(),
+ [this] { return mShouldExit || mShouldCalculate; });
+ } else {
+ mCondVar.wait(lock, [this] { return mShouldExit || mShouldCalculate; });
+ }
if (mShouldExit) {
ALOGV("Exiting thread");
return;
diff --git a/services/audiopolicy/service/SpatializerPoseController.h b/services/audiopolicy/service/SpatializerPoseController.h
index 2b5c189..2c6d79a 100644
--- a/services/audiopolicy/service/SpatializerPoseController.h
+++ b/services/audiopolicy/service/SpatializerPoseController.h
@@ -60,10 +60,10 @@
* Ctor.
* sensorPeriod determines how often to receive updates from the sensors (input rate).
* maxUpdatePeriod determines how often to produce an output when calculateAsync() isn't
- * invoked.
+ * invoked; passing nullopt means an output is never produced.
*/
SpatializerPoseController(Listener* listener, std::chrono::microseconds sensorPeriod,
- std::chrono::microseconds maxUpdatePeriod);
+ std::optional<std::chrono::microseconds> maxUpdatePeriod);
/** Dtor. */
~SpatializerPoseController();
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1e2dccb..47594c3 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -81,6 +81,7 @@
"device3/Camera3OutputUtils.cpp",
"device3/Camera3DeviceInjectionMethods.cpp",
"device3/UHRCropAndMeteringRegionMapper.cpp",
+ "device3/PreviewFrameSpacer.cpp",
"device3/hidl/HidlCamera3Device.cpp",
"device3/hidl/HidlCamera3OfflineSession.cpp",
"device3/hidl/HidlCamera3OutputUtils.cpp",
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1f0e095..5db3fa6 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -721,8 +721,10 @@
}
*status = false;
+ camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+ return mDevice->infoPhysical(id);};
ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
- sessionConfiguration, mOverrideForPerfClass, status);
+ sessionConfiguration, mOverrideForPerfClass, getMetadata, status);
switch (ret) {
case OK:
// Expected, do nothing.
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 6058429..5da77d6 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -441,6 +441,10 @@
newFormat->setInt32(KEY_TILE_HEIGHT, mGridHeight);
newFormat->setInt32(KEY_GRID_ROWS, mGridRows);
newFormat->setInt32(KEY_GRID_COLUMNS, mGridCols);
+ int32_t left, top, right, bottom;
+ if (newFormat->findRect("crop", &left, &top, &right, &bottom)) {
+ newFormat->setRect("crop", 0, 0, mOutputWidth - 1, mOutputHeight - 1);
+ }
}
}
newFormat->setInt32(KEY_IS_DEFAULT, 1 /*isPrimary*/);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 4cc03f0..d545484 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -40,7 +40,6 @@
#include <android-base/logging.h>
#include <cutils/properties.h>
#include <hwbinder/IPCThreadState.h>
-#include <utils/SessionConfigurationUtils.h>
#include <utils/Trace.h>
#include "api2/HeicCompositeStream.h"
@@ -338,14 +337,15 @@
status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
const SessionConfiguration &configuration, bool overrideForPerfClass,
- bool *status /*out*/) const {
+ metadataGetter getMetadata, bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) {
return NAME_NOT_FOUND;
}
- return deviceInfo->isSessionConfigurationSupported(configuration, overrideForPerfClass, status);
+ return deviceInfo->isSessionConfigurationSupported(configuration,
+ overrideForPerfClass, getMetadata, status);
}
status_t CameraProviderManager::getCameraIdIPCTransport(const std::string &id,
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 3d108bd..d934ae8 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -33,6 +33,7 @@
#include <utils/Errors.h>
#include <android/hardware/ICameraService.h>
#include <utils/IPCTransport.h>
+#include <utils/SessionConfigurationUtils.h>
#include <aidl/android/hardware/camera/provider/ICameraProvider.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
@@ -278,7 +279,7 @@
*/
status_t isSessionConfigurationSupported(const std::string& id,
const SessionConfiguration &configuration,
- bool overrideForPerfClass,
+ bool overrideForPerfClass, camera3::metadataGetter getMetadata,
bool *status /*out*/) const;
/**
@@ -587,6 +588,7 @@
virtual status_t isSessionConfigurationSupported(
const SessionConfiguration &/*configuration*/,
bool /*overrideForPerfClass*/,
+ camera3::metadataGetter /*getMetadata*/,
bool * /*status*/) {
return INVALID_OPERATION;
}
@@ -639,6 +641,7 @@
CameraMetadata *characteristics) const override;
virtual status_t isSessionConfigurationSupported(
const SessionConfiguration &configuration, bool /*overrideForPerfClass*/,
+ camera3::metadataGetter /*getMetadata*/,
bool *status /*out*/) = 0;
virtual status_t filterSmallJpegSizes() override;
virtual void notifyDeviceStateChange(
@@ -658,6 +661,8 @@
// A copy of mCameraCharacteristics without performance class
// override
std::unique_ptr<CameraMetadata> mCameraCharNoPCOverride;
+ // Only contains characteristics for hidden physical cameras,
+ // not for public physical cameras.
std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
void queryPhysicalCameraIds();
SystemCameraKind getSystemCameraKind();
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 6f35e56..f58ed00 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -693,15 +693,11 @@
}
status_t AidlProviderInfo::AidlDeviceInfo3::isSessionConfigurationSupported(
- const SessionConfiguration &configuration, bool overrideForPerfClass, bool *status) {
+ const SessionConfiguration &configuration, bool overrideForPerfClass,
+ camera3::metadataGetter getMetadata, bool *status) {
camera::device::StreamConfiguration streamConfiguration;
bool earlyExit = false;
- camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
- CameraMetadata physicalChars;
- getPhysicalCameraCharacteristics(id.c_str(), &physicalChars);
- return physicalChars;
- };
auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
streamConfiguration, overrideForPerfClass, &earlyExit);
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
index aa71e85..97a8fed 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.h
@@ -129,7 +129,7 @@
virtual status_t isSessionConfigurationSupported(
const SessionConfiguration &/*configuration*/,
- bool overrideForPerfClass,
+ bool overrideForPerfClass, camera3::metadataGetter /*getMetadata*/,
bool *status/*status*/);
std::shared_ptr<aidl::android::hardware::camera::device::ICameraDevice>
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 3c5ea75..9cbfbcf 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -878,15 +878,11 @@
}
status_t HidlProviderInfo::HidlDeviceInfo3::isSessionConfigurationSupported(
- const SessionConfiguration &configuration, bool overrideForPerfClass, bool *status) {
+ const SessionConfiguration &configuration, bool overrideForPerfClass,
+ metadataGetter getMetadata, bool *status) {
hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
bool earlyExit = false;
- camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
- CameraMetadata physicalChars;
- getPhysicalCameraCharacteristics(id.c_str(), &physicalChars);
- return physicalChars;
- };
auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
streamConfiguration, overrideForPerfClass, &earlyExit);
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
index 4181fea..e0f1646 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -105,7 +105,7 @@
virtual status_t isSessionConfigurationSupported(
const SessionConfiguration &/*configuration*/,
- bool overrideForPerfClass,
+ bool overrideForPerfClass, camera3::metadataGetter getMetadata,
bool *status/*status*/);
sp<hardware::camera::device::V3_2::ICameraDevice> startDeviceInterface();
};
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 37f9227..c5bdd00 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -376,24 +376,35 @@
dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
}
- nsecs_t captureTime = (mSyncToDisplay ? readoutTimestamp : timestamp) - mTimestampOffset;
- nsecs_t presentTime = mSyncToDisplay ?
- syncTimestampToDisplayLocked(captureTime) : captureTime;
+ if (mPreviewFrameSpacer != nullptr) {
+ res = mPreviewFrameSpacer->queuePreviewBuffer(timestamp - mTimestampOffset, transform,
+ anwBuffer, anwReleaseFence);
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Error queuing buffer to preview buffer spacer: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
+ } else {
+ nsecs_t captureTime = (mSyncToDisplay ? readoutTimestamp : timestamp)
+ - mTimestampOffset;
+ nsecs_t presentTime = mSyncToDisplay ?
+ syncTimestampToDisplayLocked(captureTime) : captureTime;
- setTransform(transform, true/*mayChangeMirror*/);
- res = native_window_set_buffers_timestamp(mConsumer.get(), presentTime);
- if (res != OK) {
- ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
- __FUNCTION__, mId, strerror(-res), res);
- return res;
- }
+ setTransform(transform, true/*mayChangeMirror*/);
+ res = native_window_set_buffers_timestamp(mConsumer.get(), presentTime);
+ if (res != OK) {
+ ALOGE("%s: Stream %d: Error setting timestamp: %s (%d)",
+ __FUNCTION__, mId, strerror(-res), res);
+ return res;
+ }
- queueHDRMetadata(anwBuffer->handle, currentConsumer, dynamic_range_profile);
+ queueHDRMetadata(anwBuffer->handle, currentConsumer, dynamic_range_profile);
- res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
- if (shouldLogError(res, state)) {
- ALOGE("%s: Stream %d: Error queueing buffer to native window:"
- " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
+ res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
+ if (shouldLogError(res, state)) {
+ ALOGE("%s: Stream %d: Error queueing buffer to native window:"
+ " %s (%d)", __FUNCTION__, mId, strerror(-res), res);
+ }
}
}
mLock.lock();
@@ -468,7 +479,7 @@
return res;
}
- if ((res = configureConsumerQueueLocked(true /*allowDisplaySync*/)) != OK) {
+ if ((res = configureConsumerQueueLocked(true /*allowPreviewRespace*/)) != OK) {
return res;
}
@@ -492,7 +503,7 @@
return OK;
}
-status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowDisplaySync) {
+status_t Camera3OutputStream::configureConsumerQueueLocked(bool allowPreviewRespace) {
status_t res;
mTraceFirstBuffer = true;
@@ -582,20 +593,25 @@
int timestampBase = getTimestampBase();
bool isDefaultTimeBase = (timestampBase ==
OutputConfiguration::TIMESTAMP_BASE_DEFAULT);
- if (allowDisplaySync) {
- // We cannot distinguish between a SurfaceView and an ImageReader of
- // preview buffer format. Frames are synchronized to display in both
- // cases.
+ if (allowPreviewRespace) {
bool forceChoreographer = (timestampBase ==
OutputConfiguration::TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED);
- bool defaultToChoreographer = (isDefaultTimeBase && isConsumedByHWComposer() &&
+ bool defaultToChoreographer = (isDefaultTimeBase &&
+ isConsumedByHWComposer() &&
!property_get_bool("camera.disable_preview_scheduler", false));
if (forceChoreographer || defaultToChoreographer) {
mSyncToDisplay = true;
mTotalBufferCount += kDisplaySyncExtraBuffer;
+ } else if (isConsumedByHWTexture() && !isVideoStream()) {
+ mPreviewFrameSpacer = new PreviewFrameSpacer(*this, mConsumer);
+ mTotalBufferCount ++;
+ res = mPreviewFrameSpacer->run(String8::format("PreviewSpacer-%d", mId).string());
+ if (res != OK) {
+ ALOGE("%s: Unable to start preview spacer", __FUNCTION__);
+ return res;
+ }
}
}
-
mHandoutTotalBufferCount = 0;
mFrameCount = 0;
mLastTimestamp = 0;
@@ -1316,6 +1332,11 @@
return expectedPresentT - vsyncEventData.frameInterval/3;
}
+bool Camera3OutputStream::shouldLogError(status_t res) {
+ Mutex::Autolock l(mLock);
+ return shouldLogError(res, mState);
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 6ea7ef7..e68bc67 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -28,6 +28,7 @@
#include "Camera3IOStreamBase.h"
#include "Camera3OutputStreamInterface.h"
#include "Camera3BufferManager.h"
+#include "PreviewFrameSpacer.h"
namespace android {
@@ -250,6 +251,7 @@
static void applyZSLUsageQuirk(int format, uint64_t *consumerUsage /*inout*/);
void setImageDumpMask(int mask) { mImageDumpMask = mask; }
+ bool shouldLogError(status_t res);
protected:
Camera3OutputStream(int id, camera_stream_type_t type,
@@ -282,7 +284,7 @@
status_t getEndpointUsageForSurface(uint64_t *usage,
const sp<Surface>& surface) const;
- status_t configureConsumerQueueLocked(bool allowDisplaySync);
+ status_t configureConsumerQueueLocked(bool allowPreviewRespace);
// Consumer as the output of camera HAL
sp<Surface> mConsumer;
@@ -396,15 +398,14 @@
void returnPrefetchedBuffersLocked();
- // Synchronize camera timestamp to display, and the return value
- // can be used as presentation timestamp
- nsecs_t syncTimestampToDisplayLocked(nsecs_t t);
static const int32_t kDequeueLatencyBinSize = 5; // in ms
CameraLatencyHistogram mDequeueBufferLatency;
int mImageDumpMask = 0;
+ // Re-space frames by overriding timestamp to align with display Vsync.
+ // Default is on for SurfaceView bound streams.
nsecs_t mMinExpectedDuration = 0;
bool mSyncToDisplay = false;
DisplayEventReceiver mDisplayEventReceiver;
@@ -414,6 +415,12 @@
static constexpr size_t kDisplaySyncExtraBuffer = 2;
static constexpr nsecs_t kSpacingResetIntervalNs = 1000000000LL; // 1 second
static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond
+ nsecs_t syncTimestampToDisplayLocked(nsecs_t t);
+
+ // Re-space frames by delaying queueBuffer so that frame delivery has
+ // the same cadence as capture. Default is on for SurfaceTexture bound
+ // streams.
+ sp<PreviewFrameSpacer> mPreviewFrameSpacer;
}; // class Camera3OutputStream
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index d24b527..82958a2 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -251,7 +251,7 @@
return res;
}
- res = configureConsumerQueueLocked(false/*allowDisplaySync*/);
+ res = configureConsumerQueueLocked(false/*allowPreviewRespace*/);
if (res != OK) {
ALOGE("Failed to configureConsumerQueueLocked: %s(%d)", strerror(-res), res);
return res;
diff --git a/services/camera/libcameraservice/device3/PreviewFrameSpacer.cpp b/services/camera/libcameraservice/device3/PreviewFrameSpacer.cpp
new file mode 100644
index 0000000..9112b93
--- /dev/null
+++ b/services/camera/libcameraservice/device3/PreviewFrameSpacer.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera3-PreviewFrameSpacer"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include "PreviewFrameSpacer.h"
+#include "Camera3OutputStream.h"
+
+namespace android {
+
+namespace camera3 {
+
+PreviewFrameSpacer::PreviewFrameSpacer(Camera3OutputStream& parent, sp<Surface> consumer) :
+ mParent(parent),
+ mConsumer(consumer) {
+}
+
+PreviewFrameSpacer::~PreviewFrameSpacer() {
+ Thread::requestExitAndWait();
+}
+
+status_t PreviewFrameSpacer::queuePreviewBuffer(nsecs_t timestamp, int32_t transform,
+ ANativeWindowBuffer* anwBuffer, int releaseFence) {
+ Mutex::Autolock l(mLock);
+ mPendingBuffers.emplace(timestamp, transform, anwBuffer, releaseFence);
+ ALOGV("%s: mPendingBuffers size %zu, timestamp %" PRId64, __FUNCTION__,
+ mPendingBuffers.size(), timestamp);
+
+ mBufferCond.signal();
+ return OK;
+}
+
+bool PreviewFrameSpacer::threadLoop() {
+ Mutex::Autolock l(mLock);
+ if (mPendingBuffers.size() == 0) {
+ mBufferCond.waitRelative(mLock, kWaitDuration);
+ return true;
+ }
+
+ nsecs_t currentTime = systemTime();
+ auto buffer = mPendingBuffers.front();
+ nsecs_t captureInterval = buffer.timestamp - mLastCameraCaptureTime;
+ // If the capture interval exceeds threshold, directly queue
+ // cached buffer.
+ if (captureInterval >= kFrameIntervalThreshold) {
+ mPendingBuffers.pop();
+ queueBufferToClientLocked(buffer, currentTime);
+ return true;
+ }
+
+ // Cache the frame to match capture time interval, for up to 33ms
+ nsecs_t expectedQueueTime = mLastCameraPresentTime + captureInterval;
+ nsecs_t frameWaitTime = std::min(kMaxFrameWaitTime, expectedQueueTime - currentTime);
+ if (frameWaitTime > 0 && mPendingBuffers.size() < 2) {
+ mBufferCond.waitRelative(mLock, frameWaitTime);
+ if (exitPending()) {
+ return true;
+ }
+ currentTime = systemTime();
+ }
+ ALOGV("%s: captureInterval %" PRId64 ", queueInterval %" PRId64 ", waited for %" PRId64
+ ", timestamp %" PRId64, __FUNCTION__, captureInterval,
+ currentTime - mLastCameraPresentTime, frameWaitTime, buffer.timestamp);
+ mPendingBuffers.pop();
+ queueBufferToClientLocked(buffer, currentTime);
+ return true;
+}
+
+void PreviewFrameSpacer::requestExit() {
+ // Call parent to set up shutdown
+ Thread::requestExit();
+ // Exit from other possible wait
+ mBufferCond.signal();
+}
+
+void PreviewFrameSpacer::queueBufferToClientLocked(
+ const BufferHolder& bufferHolder, nsecs_t currentTime) {
+ mParent.setTransform(bufferHolder.transform, true/*mayChangeMirror*/);
+
+ status_t res = native_window_set_buffers_timestamp(mConsumer.get(), bufferHolder.timestamp);
+ if (res != OK) {
+ ALOGE("%s: Preview Stream: Error setting timestamp: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+
+ Camera3Stream::queueHDRMetadata(bufferHolder.anwBuffer.get()->handle, mConsumer,
+ mParent.getDynamicRangeProfile());
+
+ res = mConsumer->queueBuffer(mConsumer.get(), bufferHolder.anwBuffer.get(),
+ bufferHolder.releaseFence);
+ if (res != OK) {
+ close(bufferHolder.releaseFence);
+ if (mParent.shouldLogError(res)) {
+ ALOGE("%s: Failed to queue buffer to client: %s(%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+ }
+
+ mLastCameraPresentTime = currentTime;
+ mLastCameraCaptureTime = bufferHolder.timestamp;
+}
+
+}; // namespace camera3
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/PreviewFrameSpacer.h b/services/camera/libcameraservice/device3/PreviewFrameSpacer.h
new file mode 100644
index 0000000..5062553
--- /dev/null
+++ b/services/camera/libcameraservice/device3/PreviewFrameSpacer.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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_SERVERS_CAMERA_CAMERA3_PREVIEWFRAMESPACER_H
+#define ANDROID_SERVERS_CAMERA_CAMERA3_PREVIEWFRAMESPACER_H
+
+#include <queue>
+
+#include <gui/Surface.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3OutputStream;
+
+/***
+ * Preview stream spacer for better frame spacing
+ *
+ * The ideal viewfinder user experience is that frames are presented to the
+ * user in the same cadence as outputed by the camera sensor. However, the
+ * processing latency between frames could vary, due to factors such
+ * as CPU load, differences in request settings, etc. This frame processing
+ * latency results in variation in presentation of frames to the user.
+ *
+ * The PreviewFrameSpacer improves the viewfinder user experience by:
+ * - Cache the frame buffers if the intervals between queueBuffer is shorter
+ * than the camera capture intervals.
+ * - Queue frame buffers in the same cadence as the camera capture time.
+ * - Maintain at most 1 queue-able buffer. If the 2nd preview buffer becomes
+ * available, queue the oldest cached buffer to the buffer queue.
+ */
+class PreviewFrameSpacer : public Thread {
+ public:
+ explicit PreviewFrameSpacer(Camera3OutputStream& parent, sp<Surface> consumer);
+ virtual ~PreviewFrameSpacer();
+
+ // Queue preview buffer locally
+ status_t queuePreviewBuffer(nsecs_t timestamp, int32_t transform,
+ ANativeWindowBuffer* anwBuffer, int releaseFence);
+
+ bool threadLoop() override;
+ void requestExit() override;
+
+ private:
+ // structure holding cached preview buffer info
+ struct BufferHolder {
+ nsecs_t timestamp;
+ int32_t transform;
+ sp<ANativeWindowBuffer> anwBuffer;
+ int releaseFence;
+
+ BufferHolder(nsecs_t t, int32_t tr, ANativeWindowBuffer* anwb, int rf) :
+ timestamp(t), transform(tr), anwBuffer(anwb), releaseFence(rf) {}
+ };
+
+ void queueBufferToClientLocked(const BufferHolder& bufferHolder, nsecs_t currentTime);
+
+
+ Camera3OutputStream& mParent;
+ sp<ANativeWindow> mConsumer;
+ mutable Mutex mLock;
+ Condition mBufferCond;
+
+ std::queue<BufferHolder> mPendingBuffers;
+ nsecs_t mLastCameraCaptureTime = 0;
+ nsecs_t mLastCameraPresentTime = 0;
+ static constexpr nsecs_t kWaitDuration = 5000000LL; // 50ms
+ static constexpr nsecs_t kFrameIntervalThreshold = 80000000LL; // 80ms
+ static constexpr nsecs_t kMaxFrameWaitTime = 33333333LL; // 33ms
+};
+
+}; //namespace camera3
+}; //namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 8abcc95..038c075 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -48,7 +48,7 @@
namespace android {
namespace camera3 {
-typedef std::function<CameraMetadata (const String8 &, int targetSdkVersion)> metadataGetter;
+typedef std::function<CameraMetadata (const String8 &, bool overrideForPerfClass)> metadataGetter;
class StreamConfiguration {
public:
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index 594809c..6e24a58 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -128,6 +128,9 @@
{"AUDIO_DEVICE_OUT_BLE_HEADSET", 1LL << 31},
{"AUDIO_DEVICE_OUT_BLE_SPEAKER", 1LL << 32},
{"AUDIO_DEVICE_OUT_HDMI_EARC", 1LL << 33},
+ // S values above
+ {"AUDIO_DEVICE_OUT_BLE_BROADCAST", 1LL << 34},
+ // T values above
};
return map;
}
@@ -145,6 +148,8 @@
{"MMAP_PLAYBACK", 5}, // Thread class for MMAP playback stream
{"MMAP_CAPTURE", 6}, // Thread class for MMAP capture stream
// R values above.
+ {"SPATIALIZER", 7}, // Thread class for SpatializerThread
+ // S values above.
};
return map;
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index e0584df..b4610bc 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -732,6 +732,7 @@
return true;
}
+ int failedClientPid = -1;
{
Mutex::Autolock lock(mLock);
bool found = false;
@@ -746,11 +747,14 @@
}
}
if (found) {
+ failedClientPid = mMap.keyAt(i);
break;
}
}
- if (!found) {
- ALOGV("didn't find failed client");
+ if (found) {
+ ALOGW("Failed to reclaim resources from client with pid %d", failedClientPid);
+ } else {
+ ALOGW("Failed to reclaim resources from unlocateable client");
}
}
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index 8f25ee6..e4aaea0 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -227,33 +227,31 @@
mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(kMinThreadPairs, kMaxThreadPairs);
// Make even number of threads
size_t numThreads = numThreadPairs * 2;
- resourceThreadArgs threadArgs;
- vector<MediaResourceParcel> mediaResource;
+ resourceThreadArgs threadArgs[numThreadPairs];
+ vector<MediaResourceParcel> mediaResource[numThreadPairs];
pthread_t pt[numThreads];
- int i;
- for (i = 0; i < numThreads - 1; i += 2) {
- threadArgs.pid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
- threadArgs.uid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ for (int k = 0; k < numThreadPairs; ++k) {
+ threadArgs[k].pid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
+ threadArgs[k].uid = mFuzzedDataProvider->ConsumeIntegral<int32_t>();
int32_t mediaResourceType = mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
kMinResourceType, kMaxResourceType);
int32_t mediaResourceSubType = mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(
kMinResourceType, kMaxResourceType);
uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
- threadArgs.service = mService;
+ threadArgs[k].service = mService;
shared_ptr<IResourceManagerClient> testClient =
- ::ndk::SharedRefBase::make<TestClient>(threadArgs.pid, mService);
- threadArgs.testClient = testClient;
- threadArgs.testClientId = getId(testClient);
- mediaResource.push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
- static_cast<MedResSubType>(mediaResourceSubType),
- mediaResourceValue));
- threadArgs.mediaResource = mediaResource;
- pthread_create(&pt[i], nullptr, addResource, &threadArgs);
- pthread_create(&pt[i + 1], nullptr, removeResource, &threadArgs);
- mediaResource.clear();
+ ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, mService);
+ threadArgs[k].testClient = testClient;
+ threadArgs[k].testClientId = getId(testClient);
+ mediaResource[k].push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
+ static_cast<MedResSubType>(mediaResourceSubType),
+ mediaResourceValue));
+ threadArgs[k].mediaResource = mediaResource[k];
+ pthread_create(&pt[2 * k], nullptr, addResource, &threadArgs[k]);
+ pthread_create(&pt[2 * k + 1], nullptr, removeResource, &threadArgs[k]);
}
- for (i = 0; i < numThreads; ++i) {
+ for (int i = 0; i < numThreads; ++i) {
pthread_join(pt[i], nullptr);
}
@@ -266,14 +264,14 @@
int32_t mediaResourceSubType =
mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
- mediaResource.push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
- static_cast<MedResSubType>(mediaResourceSubType),
- mediaResourceValue));
+ vector<MediaResourceParcel> mediaRes;
+ mediaRes.push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
+ static_cast<MedResSubType>(mediaResourceSubType),
+ mediaResourceValue));
bool result;
- mService->reclaimResource(pidZero, mediaResource, &result);
- mService->removeResource(pidZero, getId(testClient), mediaResource);
+ mService->reclaimResource(pidZero, mediaRes, &result);
+ mService->removeResource(pidZero, getId(testClient), mediaRes);
mService->removeClient(pidZero, getId(testClient));
- mediaResource.clear();
}
void ResourceManagerServiceFuzzer::setServiceLog() {
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index 6d8ae03..fe74a5c 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -390,7 +390,9 @@
static_cast<int32_t>(Result::INVALID_STATE));
}
- HidlResult res = mFilter->releaseAvHandle(hidl_handle(makeFromAidl(in_handle)), in_avDataId);
+ hidl_handle handle;
+ handle.setTo(makeFromAidl(in_handle), true);
+ HidlResult res = mFilter->releaseAvHandle(handle, in_avDataId);
if (res != HidlResult::SUCCESS) {
return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
}