[automerger skipped] Merge "AudioMixer: Enable 5.1 based for fallback downmix" am: 580a0d5508 am: 92447b3f4f am: c90c222035 -s ours am: 0af2bb463d -s ours am: 0f9e829f3f -s ours
am skip reason: Merged-In Ie093319c5fefc459165ae3d6c57b7836e8b625e5 with SHA-1 8514b930b1 is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/2556150
Change-Id: I957508024e80544b0f4c61040970226fb065df1e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 8aed623..3e4247b 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -29,6 +29,14 @@
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/MediaDefs.h>
+// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
+#if LIBYUV_VERSION >= 1780
+#include <algorithm>
+#define HAVE_LIBYUV_I410_I210_TO_AB30 1
+#else
+#define HAVE_LIBYUV_I410_I210_TO_AB30 0
+#endif
+
namespace android {
// codecname set and passed in as a compile flag from Android.bp
@@ -790,6 +798,18 @@
getHDRStaticParams(buffer, work);
getHDR10PlusInfoData(buffer, work);
+#if LIBYUV_VERSION < 1779
+ if (buffer->bitdepth == 10 &&
+ !(buffer->image_format == libgav1::kImageFormatYuv420 ||
+ buffer->image_format == libgav1::kImageFormatMonochrome400)) {
+ ALOGE("image_format %d not supported for 10bit", buffer->image_format);
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return false;
+ }
+#endif
+
const bool isMonochrome =
buffer->image_format == libgav1::kImageFormatMonochrome400;
@@ -806,6 +826,7 @@
allowRGBA1010102 = true;
}
format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
+#if !HAVE_LIBYUV_I410_I210_TO_AB30
if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
(buffer->image_format != libgav1::kImageFormatYuv420)) {
ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
@@ -814,6 +835,7 @@
work->workletsProcessed = 1u;
return false;
}
+#endif
}
if (mHalPixelFormat != format) {
@@ -877,15 +899,46 @@
size_t srcVStride = buffer->stride[2] / 2;
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
- convertYUV420Planar16ToY410OrRGBA1010102(
- (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
- srcUStride, srcVStride,
- dstYStride / sizeof(uint32_t), mWidth, mHeight,
- std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
+ bool processed = false;
+#if HAVE_LIBYUV_I410_I210_TO_AB30
+ if (buffer->image_format == libgav1::kImageFormatYuv444) {
+ libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ dstY, dstYStride, &libyuv::kYuvV2020Constants,
+ mWidth, mHeight);
+ processed = true;
+ } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
+ libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+ dstY, dstYStride, &libyuv::kYuvV2020Constants,
+ mWidth, mHeight);
+ processed = true;
+ }
+#endif // HAVE_LIBYUV_I410_I210_TO_AB30
+ if (!processed) {
+ if (isMonochrome) {
+ const size_t tmpSize = mWidth;
+ const bool needFill = tmpSize > mTmpFrameBufferSize;
+ if (!allocTmpFrameBuffer(tmpSize)) {
+ ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+ setError(work, C2_NO_MEMORY);
+ return false;
+ }
+ srcU = srcV = mTmpFrameBuffer.get();
+ srcUStride = srcVStride = 0;
+ if (needFill) {
+ std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
+ }
+ }
+ convertYUV420Planar16ToY410OrRGBA1010102(
+ (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
+ srcUStride, srcVStride,
+ dstYStride / sizeof(uint32_t), mWidth, mHeight,
+ std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
+ }
} else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
dstYStride /= 2;
dstUStride /= 2;
dstVStride /= 2;
+#if LIBYUV_VERSION >= 1779
if (buffer->image_format == libgav1::kImageFormatYuv444 ||
buffer->image_format == libgav1::kImageFormatYuv422) {
// TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010 and
@@ -918,7 +971,13 @@
srcYStride, srcUStride, srcVStride, dstYStride,
dstUStride, mWidth, mHeight, isMonochrome);
}
+#else // LIBYUV_VERSION < 1779
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, dstYStride,
+ dstUStride, mWidth, mHeight, isMonochrome);
+#endif // LIBYUV_VERSION >= 1779
} else {
+#if LIBYUV_VERSION >= 1779
if (buffer->image_format == libgav1::kImageFormatYuv444) {
// TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420 when
// it's available.
@@ -942,10 +1001,15 @@
dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
mWidth, mHeight);
} else {
- convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
- srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
+ srcUStride, srcVStride, dstYStride, dstUStride,
mWidth, mHeight, isMonochrome);
}
+#else // LIBYUV_VERSION < 1779
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
+ srcUStride, srcVStride, dstYStride, dstUStride,
+ mWidth, mHeight, isMonochrome);
+#endif // LIBYUV_VERSION >= 1779
}
} else {
const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index f272499..0803dc3 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -23,6 +23,7 @@
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
#include <android/hardware/graphics/common/1.2/types.h>
#include <cutils/native_handle.h>
+#include <drm/drm_fourcc.h>
#include <gralloctypes/Gralloc4.h>
#include <hardware/gralloc.h>
#include <ui/GraphicBufferAllocator.h>
@@ -478,7 +479,25 @@
// 'NATIVE' on Android means LITTLE_ENDIAN
constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
- switch (mFormat) {
+ // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
+ // possible.
+ uint32_t format = mFormat;
+ uint32_t fourCc;
+ if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+ !GraphicBufferMapper::get().getPixelFormatFourCC(mBuffer, &fourCc)) {
+ switch (fourCc) {
+ case DRM_FORMAT_XBGR8888:
+ format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
+ break;
+ case DRM_FORMAT_ABGR8888:
+ format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (format) {
case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
// TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
// Surface. In all other cases it is RGBA. We don't know which case it is here, so
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index b731702..a093279 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -132,12 +132,10 @@
binder = gAudioFlingerBinder;
} else {
sp<IServiceManager> sm = defaultServiceManager();
- do {
- binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
- if (binder != nullptr) break;
- ALOGW("AudioFlinger not published, waiting...");
- usleep(500000); // 0.5 s
- } while (true);
+ binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
+ if (binder == nullptr) {
+ return nullptr;
+ }
}
binder->linkToDeath(gAudioFlingerClient);
const auto afs = interface_cast<media::IAudioFlingerService>(binder);
@@ -870,14 +868,10 @@
Mutex::Autolock _l(gLockAPS);
if (gAudioPolicyService == 0) {
sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("media.audio_policy"));
- if (binder != 0)
- break;
- ALOGW("AudioPolicyService not published, waiting...");
- usleep(500000); // 0.5 s
- } while (true);
+ sp<IBinder> binder = sm->waitForService(String16("media.audio_policy"));
+ if (binder == nullptr) {
+ return nullptr;
+ }
if (gAudioPolicyServiceClient == NULL) {
gAudioPolicyServiceClient = new AudioPolicyServiceClient();
}
@@ -2093,8 +2087,7 @@
return BAD_VALUE;
}
- const sp<IAudioPolicyService>
- & aps = AudioSystem::get_audio_policy_service();
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
std::vector<AudioFormatDescription> formatsAidl;
diff --git a/media/libmediaplayerservice/ActivityManager.cpp b/media/libmediaplayerservice/ActivityManager.cpp
deleted file mode 100644
index 438d422..0000000
--- a/media/libmediaplayerservice/ActivityManager.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <binder/IActivityManager.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
-
-#include "ActivityManager.h"
-
-namespace android {
-
-// Perform ContentProvider.openFile() on the given URI, returning
-// the resulting native file descriptor. Returns < 0 on error.
-int openContentProviderFile(const String16& uri)
-{
- int fd = -1;
-
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("activity"));
- sp<IActivityManager> am = interface_cast<IActivityManager>(binder);
- if (am != NULL) {
- fd = am->openContentUri(uri);
- }
-
- return fd;
-}
-
-} /* namespace android */
diff --git a/media/libmediaplayerservice/ActivityManager.h b/media/libmediaplayerservice/ActivityManager.h
deleted file mode 100644
index 451a004..0000000
--- a/media/libmediaplayerservice/ActivityManager.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ActivityManager_H
-#define ActivityManager_H
-
-#include <utils/String16.h>
-
-namespace android {
-
-// Perform a ContentProvider.openFile() call for the given URI.
-//
-// Returns the native file descriptor for the opened stream, < 0 on error.
-extern int openContentProviderFile(const String16& uri);
-
-}
-
-#endif
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 266cb17..6ddaf25 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -20,7 +20,6 @@
cc_library {
srcs: [
- "ActivityManager.cpp",
"DeathNotifier.cpp",
"MediaPlayerFactory.cpp",
"MediaPlayerService.cpp",
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9e9e9d8..65381c4 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -75,7 +75,6 @@
#include <private/android_filesystem_config.h>
-#include "ActivityManager.h"
#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
#include "MetadataRetrieverClient.h"
@@ -1002,31 +1001,13 @@
}
}
- if (strncmp(url, "content://", 10) == 0) {
- // get a filedescriptor for the content Uri and
- // pass it to the setDataSource(fd) method
-
- String16 url16(url);
- int fd = android::openContentProviderFile(url16);
- if (fd < 0)
- {
- ALOGE("Couldn't open fd for %s", url);
- return UNKNOWN_ERROR;
- }
- status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
- close(fd);
- return mStatus = status;
- } else {
- player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
- sp<MediaPlayerBase> p = setDataSource_pre(playerType);
- if (p == NULL) {
- return NO_INIT;
- }
-
- return mStatus =
- setDataSource_post(
- p, p->setDataSource(httpService, url, headers));
+ player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
+ sp<MediaPlayerBase> p = setDataSource_pre(playerType);
+ if (p == NULL) {
+ return NO_INIT;
}
+
+ return mStatus = setDataSource_post(p, p->setDataSource(httpService, url, headers));
}
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 09c5d64..080c3d0 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -118,15 +118,6 @@
static const char *kCodecCaptureRate = "android.media.mediacodec.capture-rate";
static const char *kCodecOperatingRate = "android.media.mediacodec.operating-rate";
static const char *kCodecPriority = "android.media.mediacodec.priority";
-static const char *kCodecConfigColorStandard = "android.media.mediacodec.config-color-standard";
-static const char *kCodecConfigColorRange = "android.media.mediacodec.config-color-range";
-static const char *kCodecConfigColorTransfer = "android.media.mediacodec.config-color-transfer";
-static const char *kCodecParsedColorStandard = "android.media.mediacodec.parsed-color-standard";
-static const char *kCodecParsedColorRange = "android.media.mediacodec.parsed-color-range";
-static const char *kCodecParsedColorTransfer = "android.media.mediacodec.parsed-color-transfer";
-static const char *kCodecHDRStaticInfo = "android.media.mediacodec.hdr-static-info";
-static const char *kCodecHDR10PlusInfo = "android.media.mediacodec.hdr10-plus-info";
-static const char *kCodecHDRFormat = "android.media.mediacodec.hdr-format";
// Min/Max QP before shaping
static const char *kCodecOriginalVideoQPIMin = "android.media.mediacodec.original-video-qp-i-min";
@@ -175,6 +166,29 @@
static const char *kCodecVideoInputBytes = "android.media.mediacodec.video.input.bytes";
static const char *kCodecVideoInputFrames = "android.media.mediacodec.video.input.frames";
static const char *kCodecVideoEncodedDurationUs = "android.media.mediacodec.vencode.durationUs";
+// HDR metrics
+static const char *kCodecConfigColorStandard = "android.media.mediacodec.config-color-standard";
+static const char *kCodecConfigColorRange = "android.media.mediacodec.config-color-range";
+static const char *kCodecConfigColorTransfer = "android.media.mediacodec.config-color-transfer";
+static const char *kCodecParsedColorStandard = "android.media.mediacodec.parsed-color-standard";
+static const char *kCodecParsedColorRange = "android.media.mediacodec.parsed-color-range";
+static const char *kCodecParsedColorTransfer = "android.media.mediacodec.parsed-color-transfer";
+static const char *kCodecHDRStaticInfo = "android.media.mediacodec.hdr-static-info";
+static const char *kCodecHDR10PlusInfo = "android.media.mediacodec.hdr10-plus-info";
+static const char *kCodecHDRFormat = "android.media.mediacodec.hdr-format";
+// array/sync/async/block modes
+static const char *kCodecArrayMode = "android.media.mediacodec.array-mode";
+static const char *kCodecOperationMode = "android.media.mediacodec.operation-mode";
+static const char *kCodecOutputSurface = "android.media.mediacodec.output-surface";
+// max size configured by the app
+static const char *kCodecAppMaxInputSize = "android.media.mediacodec.app-max-input-size";
+// max size actually used
+static const char *kCodecUsedMaxInputSize = "android.media.mediacodec.used-max-input-size";
+// max size suggested by the codec
+static const char *kCodecCodecMaxInputSize = "android.media.mediacodec.codec-max-input-size";
+static const char *kCodecFlushCount = "android.media.mediacodec.flush-count";
+static const char *kCodecSetSurfaceCount = "android.media.mediacodec.set-surface-count";
+static const char *kCodecResolutionChangeCount = "android.media.mediacodec.resolution-change-count";
// the kCodecRecent* fields appear only in getMetrics() results
static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max"; /* in us */
@@ -935,7 +949,6 @@
mWidth(0),
mHeight(0),
mRotationDegrees(0),
- mHdrInfoFlags(0),
mDequeueInputTimeoutGeneration(0),
mDequeueInputReplyID(0),
mDequeueOutputTimeoutGeneration(0),
@@ -1043,6 +1056,14 @@
}
mLifetimeStartNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ resetMetricsFields();
+}
+
+void MediaCodec::resetMetricsFields() {
+ mHdrInfoFlags = 0;
+
+ mApiUsageMetrics = ApiUsageMetrics();
+ mReliabilityContextMetrics = ReliabilityContextMetrics();
}
void MediaCodec::updateMediametrics() {
@@ -1053,6 +1074,28 @@
Mutex::Autolock _lock(mMetricsLock);
+ mediametrics_setInt32(mMetricsHandle, kCodecArrayMode, mApiUsageMetrics.isArrayMode ? 1 : 0);
+ mApiUsageMetrics.operationMode = (mFlags & kFlagIsAsync) ?
+ ((mFlags & kFlagUseBlockModel) ? ApiUsageMetrics::kBlockMode
+ : ApiUsageMetrics::kAsynchronousMode)
+ : ApiUsageMetrics::kSynchronousMode;
+ mediametrics_setInt32(mMetricsHandle, kCodecOperationMode, mApiUsageMetrics.operationMode);
+ mediametrics_setInt32(mMetricsHandle, kCodecOutputSurface,
+ mApiUsageMetrics.isUsingOutputSurface ? 1 : 0);
+
+ mediametrics_setInt32(mMetricsHandle, kCodecAppMaxInputSize,
+ mApiUsageMetrics.inputBufferSize.appMax);
+ mediametrics_setInt32(mMetricsHandle, kCodecUsedMaxInputSize,
+ mApiUsageMetrics.inputBufferSize.usedMax);
+ mediametrics_setInt32(mMetricsHandle, kCodecCodecMaxInputSize,
+ mApiUsageMetrics.inputBufferSize.codecMax);
+
+ mediametrics_setInt32(mMetricsHandle, kCodecFlushCount, mReliabilityContextMetrics.flushCount);
+ mediametrics_setInt32(mMetricsHandle, kCodecSetSurfaceCount,
+ mReliabilityContextMetrics.setOutputSurfaceCount);
+ mediametrics_setInt32(mMetricsHandle, kCodecResolutionChangeCount,
+ mReliabilityContextMetrics.resolutionChangeCount);
+
if (mLatencyHist.getCount() != 0 ) {
mediametrics_setInt64(mMetricsHandle, kCodecLatencyMax, mLatencyHist.getMax());
mediametrics_setInt64(mMetricsHandle, kCodecLatencyMin, mLatencyHist.getMin());
@@ -1295,7 +1338,7 @@
// update does its own mutex locking
updateMediametrics();
- mHdrInfoFlags = 0;
+ resetMetricsFields();
// ensure mutex while we do our own work
Mutex::Autolock _lock(mMetricsLock);
@@ -1967,6 +2010,10 @@
if (format->findInt32("color-format", &colorFormat)) {
mediametrics_setInt32(nextMetricsHandle, kCodecColorFormat, colorFormat);
}
+ int32_t appMaxInputSize = -1;
+ if (format->findInt32(KEY_MAX_INPUT_SIZE, &appMaxInputSize)) {
+ mApiUsageMetrics.inputBufferSize.appMax = appMaxInputSize;
+ }
if (mDomain == DOMAIN_VIDEO) {
float frameRate = -1.0;
if (format->findFloat("frame-rate", &frameRate)) {
@@ -3768,6 +3815,10 @@
mediametrics_setInt32(mMetricsHandle, kCodecLevel, level);
}
updateHdrMetrics(true /* isConfig */);
+ int32_t codecMaxInputSize = -1;
+ if (mInputFormat->findInt32(KEY_MAX_INPUT_SIZE, &codecMaxInputSize)) {
+ mApiUsageMetrics.inputBufferSize.codecMax = codecMaxInputSize;
+ }
// bitrate and bitrate mode, encoder only
if (mFlags & kFlagIsEncoder) {
// encoder specific values
@@ -4168,6 +4219,7 @@
setState(STARTED);
mCodec->signalResume();
}
+ mReliabilityContextMetrics.flushCount++;
postPendingRepliesAndDeferredMessages("kWhatFlushCompleted");
break;
@@ -4328,6 +4380,8 @@
handleSetSurface(NULL);
}
+ mApiUsageMetrics.isUsingOutputSurface = true;
+
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL ||
@@ -4468,6 +4522,7 @@
(void)disconnectFromSurface();
mSurface = surface;
}
+ mReliabilityContextMetrics.setOutputSurfaceCount++;
}
}
break;
@@ -5005,6 +5060,8 @@
}
}
+ mApiUsageMetrics.isArrayMode = true;
+
(new AMessage)->postReply(replyID);
break;
}
@@ -5273,6 +5330,7 @@
ClientConfigParcel clientConfig;
initClientConfigParcel(clientConfig);
mResourceManagerProxy->notifyClientConfigChanged(clientConfig);
+ mReliabilityContextMetrics.resolutionChangeCount++;
}
updateHdrMetrics(false /* isConfig */);
@@ -5708,6 +5766,10 @@
if (err != OK) {
return -EINVAL;
}
+
+ int32_t usedMaxInputSize = mApiUsageMetrics.inputBufferSize.usedMax;
+ mApiUsageMetrics.inputBufferSize.usedMax = size > usedMaxInputSize ? size : usedMaxInputSize;
+
if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
AString *errorDetailMsg;
CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 1cc281b..3d4b6f8 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -453,6 +453,7 @@
void initMediametrics();
void updateMediametrics();
void flushMediametrics();
+ void resetMetricsFields();
void updateEphemeralMediametrics(mediametrics_handle_t item);
void updateLowLatency(const sp<AMessage> &msg);
void onGetMetrics(const sp<AMessage>& msg);
@@ -492,6 +493,28 @@
const int32_t colorTransfer);
bool profileSupport10Bits(const AString &mime, const int32_t profile);
+ struct ApiUsageMetrics {
+ bool isArrayMode;
+ enum OperationMode {
+ kUnknownMode = 0,
+ kSynchronousMode = 1,
+ kAsynchronousMode = 2,
+ kBlockMode = 3,
+ };
+ OperationMode operationMode;
+ bool isUsingOutputSurface;
+ struct InputBufferSize {
+ int32_t appMax; // max size configured by the app
+ int32_t usedMax; // max size actually used
+ int32_t codecMax; // max size suggested by the codec
+ } inputBufferSize;
+ } mApiUsageMetrics;
+ struct ReliabilityContextMetrics {
+ int32_t flushCount;
+ int32_t setOutputSurfaceCount;
+ int32_t resolutionChangeCount;
+ } mReliabilityContextMetrics;
+
// initial create parameters
AString mInitName;
diff --git a/media/ndk/fuzzer/Android.bp b/media/ndk/fuzzer/Android.bp
index a3d6a96..6d7dda9 100644
--- a/media/ndk/fuzzer/Android.bp
+++ b/media/ndk/fuzzer/Android.bp
@@ -56,6 +56,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmediandk library",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
@@ -116,3 +124,16 @@
header_libs: ["libnativewindow_headers",],
defaults: ["libmediandk_fuzzer_defaults",],
}
+
+cc_fuzz {
+ name: "ndk_async_codec_fuzzer",
+ srcs: [
+ "ndk_async_codec_fuzzer.cpp",
+ "NdkMediaCodecFuzzerBase.cpp",
+ ],
+ header_libs: [
+ "libnativewindow_headers",
+ "libutils_headers",
+ ],
+ defaults: ["libmediandk_fuzzer_defaults",],
+}
diff --git a/media/ndk/fuzzer/README.md b/media/ndk/fuzzer/README.md
index 0fd08b0..7f6bdd7 100644
--- a/media/ndk/fuzzer/README.md
+++ b/media/ndk/fuzzer/README.md
@@ -8,6 +8,7 @@
+ [ndk_drm_fuzzer](#NdkDrm)
+ [ndk_mediamuxer_fuzzer](#NdkMediaMuxer)
+ [ndk_sync_codec_fuzzer](#NdkSyncCodec)
++ [ndk_async_codec_fuzzer](#NdkAsyncCodec)
# <a name="NdkCrypto"></a> Fuzzer for NdkCrypto
@@ -156,3 +157,16 @@
$ adb sync data
$ adb shell /data/fuzz/arm64/ndk_sync_codec_fuzzer/ndk_sync_codec_fuzzer
```
+
+# <a name="NdkAsyncCodec"></a>Fuzzer for NdkAsyncCodec
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) ndk_async_codec_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/ndk_async_codec_fuzzer/ndk_sync_codec_fuzzer
+```
diff --git a/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp b/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp
new file mode 100644
index 0000000..60d271f
--- /dev/null
+++ b/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp
@@ -0,0 +1,379 @@
+/*
+ * 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 <NdkMediaCodecFuzzerBase.h>
+#include <media/NdkMediaFormatPriv.h>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+using namespace android;
+using namespace std;
+
+constexpr int32_t kMaxCryptoInfoAPIs = 3;
+constexpr int32_t kMaxNdkCodecAPIs = 5;
+
+template <typename T>
+class CallBackQueue {
+ public:
+ void push(T elem) {
+ bool needsNotify = false;
+ {
+ unique_lock<mutex> lock(mMutex);
+ needsNotify = mQueue.empty();
+ mQueue.push(std::move(elem));
+ }
+ if (needsNotify) {
+ mQueueNotEmptyCondition.notify_one();
+ }
+ }
+
+ T pop() {
+ unique_lock<mutex> lock(mMutex);
+ if (mQueue.empty()) {
+ mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
+ }
+ auto result = mQueue.front();
+ mQueue.pop();
+ return result;
+ }
+
+ private:
+ mutex mMutex;
+ std::queue<T> mQueue;
+ std::condition_variable mQueueNotEmptyCondition;
+};
+
+class CallBackHandle {
+ public:
+ CallBackHandle() : mSawError(false), mIsDone(false) {}
+
+ virtual ~CallBackHandle() {
+ if (mIOThread.joinable()) {
+ mIOThread.join();
+ }
+ }
+
+ void ioThread();
+
+ // Implementation in child class (Decoder/Encoder)
+ virtual void invokeInputBufferAPI(AMediaCodec* codec, int32_t index) {
+ (void)codec;
+ (void)index;
+ }
+ virtual void onFormatChanged(AMediaCodec* codec, AMediaFormat* format) {
+ (void)codec;
+ (void)format;
+ }
+ virtual void receiveError(void) {}
+ virtual void invokeOutputBufferAPI(AMediaCodec* codec, int32_t index,
+ AMediaCodecBufferInfo* bufferInfo) {
+ (void)codec;
+ (void)index;
+ (void)bufferInfo;
+ }
+
+ // Keep a queue of all function callbacks.
+ typedef function<void()> IOTask;
+ CallBackQueue<IOTask> mIOQueue;
+ thread mIOThread;
+ bool mSawError;
+ bool mIsDone;
+};
+
+void CallBackHandle::ioThread() {
+ while (!mIsDone && !mSawError) {
+ auto task = mIOQueue.pop();
+ task();
+ }
+}
+
+static void onAsyncInputAvailable(AMediaCodec* codec, void* userdata, int32_t index) {
+ CallBackHandle* self = (CallBackHandle*)userdata;
+ self->mIOQueue.push([self, codec, index]() { self->invokeInputBufferAPI(codec, index); });
+}
+
+static void onAsyncOutputAvailable(AMediaCodec* codec, void* userdata, int32_t index,
+ AMediaCodecBufferInfo* bufferInfo) {
+ CallBackHandle* self = (CallBackHandle*)userdata;
+ AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
+ self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
+ AMediaCodecBufferInfo bc = bufferInfoCopy;
+ self->invokeOutputBufferAPI(codec, index, &bc);
+ });
+}
+
+static void onAsyncFormatChanged(AMediaCodec* codec, void* userdata, AMediaFormat* format) {
+ (void)codec;
+ (void)userdata;
+ (void)format;
+};
+
+static void onAsyncError(AMediaCodec* codec, void* userdata, media_status_t err, int32_t actionCode,
+ const char* detail) {
+ CallBackHandle* self = (CallBackHandle*)userdata;
+ self->mSawError = true;
+ self->receiveError();
+ (void)codec;
+ (void)err;
+ (void)actionCode;
+ (void)detail;
+};
+
+class NdkAsyncCodecFuzzer : public NdkMediaCodecFuzzerBase, public CallBackHandle {
+ public:
+ NdkAsyncCodecFuzzer(const uint8_t* data, size_t size)
+ : NdkMediaCodecFuzzerBase(), mFdp(data, size) {
+ setFdp(&mFdp);
+ mStopCodec = false;
+ mSawInputEOS = false;
+ mSignalledError = false;
+ mIsEncoder = false;
+ mNumOfFrames = 0;
+ mNumInputFrames = 0;
+ };
+ void process();
+
+ static void codecOnFrameRendered(AMediaCodec* codec, void* userdata, int64_t mediaTimeUs,
+ int64_t systemNano) {
+ (void)codec;
+ (void)userdata;
+ (void)mediaTimeUs;
+ (void)systemNano;
+ };
+
+ private:
+ FuzzedDataProvider mFdp;
+ AMediaCodec* mCodec = nullptr;
+ void invokeCodecCryptoInfoAPI();
+ void invokekAsyncCodecAPIs(bool isEncoder);
+ void invokeAsyncCodeConfigAPI();
+ void invokeInputBufferAPI(AMediaCodec* codec, int32_t bufferIndex);
+ void invokeOutputBufferAPI(AMediaCodec* codec, int32_t bufferIndex,
+ AMediaCodecBufferInfo* bufferInfo);
+ void invokeFormatAPI(AMediaCodec* codec);
+ void receiveError();
+ bool mStopCodec;
+ bool mSawInputEOS;
+ bool mSignalledError;
+ int32_t mNumOfFrames;
+ int32_t mNumInputFrames;
+ mutable Mutex mMutex;
+ bool mIsEncoder;
+};
+
+void NdkAsyncCodecFuzzer::receiveError(void) {
+ mSignalledError = true;
+}
+
+void NdkAsyncCodecFuzzer::invokeInputBufferAPI(AMediaCodec* codec, int32_t bufferIndex) {
+ size_t bufferSize = 0;
+ Mutex::Autolock autoLock(mMutex);
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ return;
+ }
+ if (mStopCodec || bufferIndex < 0 || mSawInputEOS) {
+ return;
+ }
+
+ uint8_t* buffer = AMediaCodec_getInputBuffer(codec, bufferIndex, &bufferSize);
+ if (buffer) {
+ std::vector<uint8_t> bytesRead = mFdp.ConsumeBytes<uint8_t>(
+ std::min(mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes), bufferSize));
+ memcpy(buffer, bytesRead.data(), bytesRead.size());
+ bufferSize = bytesRead.size();
+ } else {
+ mSignalledError = true;
+ return;
+ }
+
+ uint32_t flag = 0;
+ if (!bufferSize || mNumInputFrames == mNumOfFrames) {
+ flag |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
+ mSawInputEOS = true;
+ }
+ AMediaCodec_queueInputBuffer(codec, bufferIndex, 0 /* offset */, bufferSize, 0 /* time */,
+ flag);
+ mNumInputFrames++;
+}
+
+void NdkAsyncCodecFuzzer::invokeOutputBufferAPI(AMediaCodec* codec, int32_t bufferIndex,
+ AMediaCodecBufferInfo* bufferInfo) {
+ size_t bufferSize = 0;
+ Mutex::Autolock autoLock(mMutex);
+
+ if (mSignalledError) {
+ CallBackHandle::mSawError = true;
+ return;
+ }
+
+ if (mStopCodec || bufferIndex < 0 || mIsDone) {
+ return;
+ }
+
+ if (!mIsEncoder) {
+ (void)AMediaCodec_getOutputBuffer(codec, bufferIndex, &bufferSize);
+ }
+ AMediaCodec_releaseOutputBuffer(codec, bufferIndex, mFdp.ConsumeBool());
+ mIsDone = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+}
+
+void NdkAsyncCodecFuzzer::invokeFormatAPI(AMediaCodec* codec) {
+ AMediaFormat* codecFormat = nullptr;
+ if (mFdp.ConsumeBool()) {
+ codecFormat = AMediaCodec_getInputFormat(codec);
+ } else {
+ codecFormat = AMediaCodec_getOutputFormat(codec);
+ }
+ if (codecFormat) {
+ AMediaFormat_delete(codecFormat);
+ }
+}
+
+void NdkAsyncCodecFuzzer::invokekAsyncCodecAPIs(bool isEncoder) {
+ ANativeWindow* nativeWindow = nullptr;
+
+ if (mFdp.ConsumeBool()) {
+ AMediaCodec_createInputSurface(mCodec, &nativeWindow);
+ }
+
+ if (AMEDIA_OK == AMediaCodec_configure(mCodec, getCodecFormat(), nativeWindow,
+ nullptr /* crypto */,
+ (isEncoder ? AMEDIACODEC_CONFIGURE_FLAG_ENCODE : 0))) {
+ mNumOfFrames = mFdp.ConsumeIntegralInRange<size_t>(kMinIterations, kMaxIterations);
+ // Configure codecs to run in async mode.
+ AMediaCodecOnAsyncNotifyCallback callBack = {onAsyncInputAvailable, onAsyncOutputAvailable,
+ onAsyncFormatChanged, onAsyncError};
+ AMediaCodec_setAsyncNotifyCallback(mCodec, callBack, this);
+ mIOThread = thread(&CallBackHandle::ioThread, this);
+
+ AMediaCodec_start(mCodec);
+ sleep(5);
+ int32_t count = 0;
+ while (++count <= mNumOfFrames) {
+ int32_t ndkcodecAPI =
+ mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxNdkCodecAPIs);
+ switch (ndkcodecAPI) {
+ case 0: { // get input and output Format
+ invokeFormatAPI(mCodec);
+ break;
+ }
+ case 1: {
+ AMediaCodec_signalEndOfInputStream(mCodec);
+ mSawInputEOS = true;
+ break;
+ }
+ case 2: { // set parameters
+ // Create a new parameter and set
+ AMediaFormat* params = AMediaFormat_new();
+ AMediaFormat_setInt32(
+ params, "video-bitrate",
+ mFdp.ConsumeIntegralInRange<size_t>(kMinIntKeyValue, kMaxIntKeyValue));
+ AMediaCodec_setParameters(mCodec, params);
+ AMediaFormat_delete(params);
+ break;
+ }
+ case 3: { // flush codec
+ AMediaCodec_flush(mCodec);
+ if (mFdp.ConsumeBool()) {
+ AMediaCodec_start(mCodec);
+ }
+ break;
+ }
+ case 4: {
+ char* name = nullptr;
+ AMediaCodec_getName(mCodec, &name);
+ AMediaCodec_releaseName(mCodec, name);
+ break;
+ }
+ case 5:
+ default: {
+ std::vector<uint8_t> userData = mFdp.ConsumeBytes<uint8_t>(
+ mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+ AMediaCodecOnFrameRendered callback = codecOnFrameRendered;
+ AMediaCodec_setOnFrameRenderedCallback(mCodec, callback, userData.data());
+ break;
+ }
+ }
+ }
+ {
+ Mutex::Autolock autoLock(mMutex);
+ mStopCodec = 1;
+ AMediaCodec_stop(mCodec);
+ }
+ }
+
+ if (nativeWindow) {
+ ANativeWindow_release(nativeWindow);
+ }
+}
+
+void NdkAsyncCodecFuzzer::invokeAsyncCodeConfigAPI() {
+ while (mFdp.remaining_bytes() > 0) {
+ mIsEncoder = mFdp.ConsumeBool();
+ mCodec = createCodec(mIsEncoder, mFdp.ConsumeBool() /* isCodecForClient */);
+ if (mCodec) {
+ invokekAsyncCodecAPIs(mIsEncoder);
+ AMediaCodec_delete(mCodec);
+ }
+ }
+}
+
+void NdkAsyncCodecFuzzer::invokeCodecCryptoInfoAPI() {
+ while (mFdp.remaining_bytes() > 0) {
+ AMediaCodecCryptoInfo* cryptoInfo = getAMediaCodecCryptoInfo();
+ int32_t ndkCryptoInfoAPI =
+ mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxCryptoInfoAPIs);
+ switch (ndkCryptoInfoAPI) {
+ case 0: {
+ size_t sizes[kMaxCryptoKey];
+ AMediaCodecCryptoInfo_getEncryptedBytes(cryptoInfo, sizes);
+ break;
+ }
+ case 1: {
+ size_t sizes[kMaxCryptoKey];
+ AMediaCodecCryptoInfo_getClearBytes(cryptoInfo, sizes);
+ break;
+ }
+ case 2: {
+ uint8_t bytes[kMaxCryptoKey];
+ AMediaCodecCryptoInfo_getIV(cryptoInfo, bytes);
+ break;
+ }
+ case 3:
+ default: {
+ uint8_t bytes[kMaxCryptoKey];
+ AMediaCodecCryptoInfo_getKey(cryptoInfo, bytes);
+ break;
+ }
+ }
+ AMediaCodecCryptoInfo_delete(cryptoInfo);
+ }
+}
+
+void NdkAsyncCodecFuzzer::process() {
+ if (mFdp.ConsumeBool()) {
+ invokeCodecCryptoInfoAPI();
+ } else {
+ invokeAsyncCodeConfigAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ NdkAsyncCodecFuzzer ndkAsyncCodecFuzzer(data, size);
+ ndkAsyncCodecFuzzer.process();
+ return 0;
+}
diff --git a/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp b/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
index c19ea13..23e2eaf 100644
--- a/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
+++ b/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/NdkMediaFormat.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <sys/mman.h>
#include <unistd.h>
#include <utils/Log.h>
@@ -176,11 +177,13 @@
constexpr size_t kMaxBytes = 1000;
constexpr size_t kMinChoice = 0;
constexpr size_t kMaxChoice = 9;
+const size_t kMaxIteration = android::AMessage::maxAllowedEntries();
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
AMediaFormat* mediaFormat = AMediaFormat_new();
- while (fdp.remaining_bytes()) {
+ std::vector<std::string> nameCollection;
+ while (fdp.remaining_bytes() && nameCollection.size() < kMaxIteration) {
const char* name = nullptr;
std::string nameString;
if (fdp.ConsumeBool()) {
@@ -190,6 +193,11 @@
: fdp.ConsumeRandomLengthString(
fdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
name = nameString.c_str();
+ std::vector<std::string>::iterator it =
+ find(nameCollection.begin(), nameCollection.end(), name);
+ if (it == nameCollection.end()) {
+ nameCollection.push_back(name);
+ }
}
switch (fdp.ConsumeIntegralInRange<int32_t>(kMinChoice, kMaxChoice)) {
case 0: {
diff --git a/media/utils/tests/Android.bp b/media/utils/tests/Android.bp
index 0689083..3fdc6eb 100644
--- a/media/utils/tests/Android.bp
+++ b/media/utils/tests/Android.bp
@@ -200,7 +200,10 @@
name: "timerthread_tests",
defaults: ["libmediautils_tests_defaults"],
-
+ // TODO(b/270180838)
+ test_options: {
+ unit_test: false,
+ },
srcs: [
"TimerThread-test.cpp",
],
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 3c0f8f3..b6035b8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3950,7 +3950,7 @@
patchTrack->setPeerProxy(patchRecord, true /* holdReference */);
patchRecord->setPeerProxy(patchTrack, false /* holdReference */);
}
- track->setTeePatches(std::move(teePatches));
+ track->setTeePatchesToUpdate(std::move(teePatches));
}
sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ad191b0..0e1a3c9 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -186,7 +186,9 @@
}
sp<os::ExternalVibration> getExternalVibration() const { return mExternalVibration; }
- void setTeePatches(TeePatches teePatches);
+ // This function should be called with holding thread lock.
+ void updateTeePatches();
+ void setTeePatchesToUpdate(TeePatches teePatchesToUpdate);
void tallyUnderrunFrames(size_t frames) override {
if (isOut()) { // we expect this from output tracks only
@@ -369,6 +371,7 @@
bool mPauseHwPending = false; // direct/offload track request for thread pause
audio_output_flags_t mFlags;
TeePatches mTeePatches;
+ std::optional<TeePatches> mTeePatchesToUpdate;
const float mSpeed;
const bool mIsSpatialized;
const bool mIsBitPerfect;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2d33d3c..c907818 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4104,6 +4104,10 @@
setHalLatencyMode_l();
+ for (const auto &track : mActiveTracks ) {
+ track->updateTeePatches();
+ }
+
// signal actual start of output stream when the render position reported by the kernel
// starts moving.
if (!mStandby && !mHalStarted && mKernelPositionOnStandby !=
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6b5ddce..7d2c4db 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1491,15 +1491,24 @@
*backInserter++ = metadata;
}
-void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
- mTeePatches = std::move(teePatches);
- if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
- mState == TrackBase::STOPPING_1) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+ if (mTeePatchesToUpdate.has_value()) {
+ forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
+ mTeePatches = mTeePatchesToUpdate.value();
+ if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
+ mState == TrackBase::STOPPING_1) {
+ forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+ }
+ mTeePatchesToUpdate.reset();
}
}
+void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+ ALOGW_IF(mTeePatchesToUpdate.has_value(),
+ "%s, existing tee patches to update will be ignored", __func__);
+ mTeePatchesToUpdate = std::move(teePatchesToUpdate);
+}
+
// must be called with player thread lock held
void AudioFlinger::PlaybackThread::Track::processMuteEvent_l(const sp<
IAudioManager>& audioManager, mute_state_t muteState)
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a2aafdf..32f3ad6 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -701,17 +701,100 @@
broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
}
-static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+static bool isAutomotiveDevice() {
+ // Checks the property ro.hardware.type and returns true if it is
+ // automotive.
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("ro.hardware.type", value, "");
+ return strncmp(value, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
+static bool isAutomotivePrivilegedClient(int32_t uid) {
+ // Returns false if this is not an automotive device type.
+ if (!isAutomotiveDevice())
+ return false;
+
+ // Returns true if the uid is AID_AUTOMOTIVE_EVS which is a
+ // privileged client uid used for safety critical use cases such as
+ // rear view and surround view.
+ return uid == AID_AUTOMOTIVE_EVS;
+}
+
+bool CameraService::isAutomotiveExteriorSystemCamera(const String8& cam_id) const{
+ // Returns false if this is not an automotive device type.
+ if (!isAutomotiveDevice())
+ return false;
+
+ // Returns false if no camera id is provided.
+ if (cam_id.isEmpty())
+ return false;
+
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ if (getSystemCameraKind(cam_id, &systemCameraKind) != OK) {
+ // This isn't a known camera ID, so it's not a system camera.
+ ALOGE("%s: Unknown camera id %s, ", __FUNCTION__, cam_id.c_str());
+ return false;
+ }
+
+ if (systemCameraKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ ALOGE("%s: camera id %s is not a system camera", __FUNCTION__, cam_id.c_str());
+ return false;
+ }
+
+ CameraMetadata cameraInfo;
+ status_t res = mCameraProviderManager->getCameraCharacteristics(
+ cam_id.string(), false, &cameraInfo, false);
+ if (res != OK){
+ ALOGE("%s: Not able to get camera characteristics for camera id %s",__FUNCTION__,
+ cam_id.c_str());
+ return false;
+ }
+
+ camera_metadata_entry auto_location = cameraInfo.find(ANDROID_AUTOMOTIVE_LOCATION);
+ if (auto_location.count != 1)
+ return false;
+
+ uint8_t location = auto_location.data.u8[0];
+ if ((location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_FRONT) &&
+ (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_REAR) &&
+ (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_LEFT) &&
+ (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_RIGHT)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool CameraService::checkPermission(const String8& cam_id, const String16& permission,
+ const AttributionSourceState& attributionSource,const String16& message,
+ int32_t attributedOpCode) const{
+ if (isAutomotivePrivilegedClient(attributionSource.uid)) {
+ // If cam_id is empty, then it means that this check is not used for the
+ // purpose of accessing a specific camera, hence grant permission just
+ // based on uid to the automotive privileged client.
+ if (cam_id.isEmpty())
+ return true;
+ // If this call is used for accessing a specific camera then cam_id must be provided.
+ // In that case, only pre-grants the permission for accessing the exterior system only
+ // camera.
+ return isAutomotiveExteriorSystemCamera(cam_id);
+
+ }
+
permission::PermissionChecker permissionChecker;
+ return permissionChecker.checkPermissionForPreflight(permission, attributionSource,
+ message, attributedOpCode) != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+}
+
+bool CameraService::hasPermissionsForSystemCamera(const String8& cam_id, int callingPid,
+ int callingUid) const{
AttributionSourceState attributionSource{};
attributionSource.pid = callingPid;
attributionSource.uid = callingUid;
- bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
- sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
- bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
- sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForSystemCamera = checkPermission(cam_id,
+ sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE);
+ bool checkPermissionForCamera = checkPermission(cam_id,
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE);
return checkPermissionForSystemCamera && checkPermissionForCamera;
}
@@ -719,7 +802,7 @@
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
bool hasSystemCameraPermissions =
- hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+ hasPermissionsForSystemCamera(String8(), CameraThreadState::getCallingPid(),
CameraThreadState::getCallingUid());
switch (type) {
case CAMERA_TYPE_BACKWARD_COMPATIBLE:
@@ -760,9 +843,8 @@
return STATUS_ERROR(ERROR_DISCONNECTED,
"Camera subsystem is not available");
}
- bool hasSystemCameraPermissions =
- hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
- CameraThreadState::getCallingUid());
+ bool hasSystemCameraPermissions = hasPermissionsForSystemCamera(String8::format("%d", cameraId),
+ CameraThreadState::getCallingPid(), CameraThreadState::getCallingUid());
int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
if (hasSystemCameraPermissions) {
cameraIdBound = mNumberOfCameras;
@@ -791,13 +873,11 @@
const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
auto callingPid = CameraThreadState::getCallingPid();
auto callingUid = CameraThreadState::getCallingUid();
- permission::PermissionChecker permissionChecker;
AttributionSourceState attributionSource{};
attributionSource.pid = callingPid;
attributionSource.uid = callingUid;
- bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
- sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForSystemCamera = checkPermission(String8::format("%d", cameraIdInt),
+ sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE);
if (checkPermissionForSystemCamera || getpid() == callingPid) {
deviceIds = &mNormalDeviceIds;
}
@@ -869,13 +949,11 @@
// If it's not calling from cameraserver, check the permission only if
// android.permission.CAMERA is required. If android.permission.SYSTEM_CAMERA was needed,
// it would've already been checked in shouldRejectSystemCameraConnection.
- permission::PermissionChecker permissionChecker;
AttributionSourceState attributionSource{};
attributionSource.pid = callingPid;
attributionSource.uid = callingUid;
- bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
- sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForCamera = checkPermission(String8(cameraId), sCameraPermission,
+ attributionSource, String16(), AppOpsManager::OP_NONE);
if ((callingPid != getpid()) &&
(deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
!checkPermissionForCamera) {
@@ -1314,7 +1392,6 @@
Status CameraService::validateClientPermissionsLocked(const String8& cameraId,
const String8& clientName8, int& clientUid, int& clientPid,
/*out*/int& originalClientPid) const {
- permission::PermissionChecker permissionChecker;
AttributionSourceState attributionSource{};
int callingPid = CameraThreadState::getCallingPid();
@@ -1366,9 +1443,8 @@
attributionSource.pid = clientPid;
attributionSource.uid = clientUid;
attributionSource.packageName = clientName8;
- bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
- sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForCamera = checkPermission(cameraId, sCameraPermission, attributionSource,
+ String16(), AppOpsManager::OP_NONE);
if (callingPid != getpid() &&
(deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) && !checkPermissionForCamera) {
ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", clientPid, clientUid);
@@ -1389,8 +1465,13 @@
callingUid, procState);
}
- // If sensor privacy is enabled then prevent access to the camera
- if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+
+ // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
+ // such as rear view and surround view cannot be disabled and are exempt from sensor privacy
+ // policy. In all other cases,if sensor privacy is enabled then prevent access to the camera.
+ if ((!isAutomotivePrivilegedClient(callingUid) ||
+ !isAutomotiveExteriorSystemCamera(cameraId)) &&
+ mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
return STATUS_ERROR_FMT(ERROR_DISABLED,
"Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
@@ -1729,7 +1810,7 @@
// have android.permission.SYSTEM_CAMERA permissions.
if (!isVendorListener && (systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA ||
(systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
- !hasPermissionsForSystemCamera(clientPid, clientUid)))) {
+ !hasPermissionsForSystemCamera(String8(), clientPid, clientUid)))) {
return true;
}
return false;
@@ -1769,7 +1850,7 @@
// characteristics) even if clients don't have android.permission.CAMERA. We do not want the
// same behavior for system camera devices.
if (!systemClient && systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
- !hasPermissionsForSystemCamera(cPid, cUid)) {
+ !hasPermissionsForSystemCamera(cameraId, cPid, cUid)) {
ALOGW("Rejecting access to system only camera %s, inadequete permissions",
cameraId.c_str());
return true;
@@ -1817,7 +1898,10 @@
clientUserId = multiuser_get_user_id(callingUid);
}
- if (mCameraServiceProxyWrapper->isCameraDisabled(clientUserId)) {
+ // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
+ // such as rear view and surround view cannot be disabled.
+ if ((!isAutomotivePrivilegedClient(callingUid) || !isAutomotiveExteriorSystemCamera(id)) &&
+ mCameraServiceProxyWrapper->isCameraDisabled(clientUserId)) {
String8 msg =
String8::format("Camera disabled by device policy");
ALOGE("%s: %s", __FUNCTION__, msg.string());
@@ -1826,7 +1910,7 @@
// enforce system camera permissions
if (oomScoreOffset > 0 &&
- !hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid()) &&
+ !hasPermissionsForSystemCamera(id, callingPid, CameraThreadState::getCallingUid()) &&
!isTrustedCallingUid(CameraThreadState::getCallingUid())) {
String8 msg =
String8::format("Cannot change the priority of a client %s pid %d for "
@@ -1915,6 +1999,8 @@
bool isNonSystemNdk = false;
String16 clientPackageName;
+ int packageUid = (clientUid == USE_CALLING_UID) ?
+ CameraThreadState::getCallingUid() : clientUid;
if (clientPackageNameMaybe.size() <= 0) {
// NDK calls don't come with package names, but we need one for various cases.
// Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
@@ -1922,8 +2008,6 @@
// same permissions, so picking any associated package name is sufficient. For some
// other cases, this may give inaccurate names for clients in logs.
isNonSystemNdk = true;
- int packageUid = (clientUid == USE_CALLING_UID) ?
- CameraThreadState::getCallingUid() : clientUid;
clientPackageName = getPackageNameFromUid(packageUid);
} else {
clientPackageName = clientPackageNameMaybe;
@@ -2119,32 +2203,38 @@
clientPackageName));
}
- // Set camera muting behavior
- bool isCameraPrivacyEnabled =
- mSensorPrivacyPolicy->isCameraPrivacyEnabled();
- if (client->supportsCameraMute()) {
- client->setCameraMute(
- mOverrideCameraMuteMode || isCameraPrivacyEnabled);
- } else if (isCameraPrivacyEnabled) {
- // no camera mute supported, but privacy is on! => disconnect
- ALOGI("Camera mute not supported for package: %s, camera id: %s",
- String8(client->getPackageName()).string(), cameraId.string());
- // Do not hold mServiceLock while disconnecting clients, but
- // retain the condition blocking other clients from connecting
- // in mServiceLockWrapper if held.
- mServiceLock.unlock();
- // Clear caller identity temporarily so client disconnect PID
- // checks work correctly
- int64_t token = CameraThreadState::clearCallingIdentity();
- // Note AppOp to trigger the "Unblock" dialog
- client->noteAppOp();
- client->disconnect();
- CameraThreadState::restoreCallingIdentity(token);
- // Reacquire mServiceLock
- mServiceLock.lock();
+ // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use
+ // cases such as rear view and surround view cannot be disabled and are exempt from camera
+ // privacy policy.
+ if ((!isAutomotivePrivilegedClient(packageUid) ||
+ !isAutomotiveExteriorSystemCamera(cameraId))) {
+ // Set camera muting behavior.
+ bool isCameraPrivacyEnabled =
+ mSensorPrivacyPolicy->isCameraPrivacyEnabled();
+ if (client->supportsCameraMute()) {
+ client->setCameraMute(
+ mOverrideCameraMuteMode || isCameraPrivacyEnabled);
+ } else if (isCameraPrivacyEnabled) {
+ // no camera mute supported, but privacy is on! => disconnect
+ ALOGI("Camera mute not supported for package: %s, camera id: %s",
+ String8(client->getPackageName()).string(), cameraId.string());
+ // Do not hold mServiceLock while disconnecting clients, but
+ // retain the condition blocking other clients from connecting
+ // in mServiceLockWrapper if held.
+ mServiceLock.unlock();
+ // Clear caller identity temporarily so client disconnect PID
+ // checks work correctly
+ int64_t token = CameraThreadState::clearCallingIdentity();
+ // Note AppOp to trigger the "Unblock" dialog
+ client->noteAppOp();
+ client->disconnect();
+ CameraThreadState::restoreCallingIdentity(token);
+ // Reacquire mServiceLock
+ mServiceLock.lock();
- return STATUS_ERROR_FMT(ERROR_DISABLED,
- "Camera \"%s\" disabled due to camera mute", cameraId.string());
+ return STATUS_ERROR_FMT(ERROR_DISABLED,
+ "Camera \"%s\" disabled due to camera mute", cameraId.string());
+ }
}
if (shimUpdateOnly) {
@@ -2734,13 +2824,11 @@
// Check for camera permissions
int callingPid = CameraThreadState::getCallingPid();
int callingUid = CameraThreadState::getCallingUid();
- permission::PermissionChecker permissionChecker;
AttributionSourceState attributionSource{};
attributionSource.pid = callingPid;
attributionSource.uid = callingUid;
- bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
- sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
- != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ bool checkPermissionForCamera = checkPermission(String8(),
+ sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE);
if ((callingPid != getpid()) && !checkPermissionForCamera) {
ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
return STATUS_ERROR(ERROR_PERMISSION_DENIED,
@@ -2788,13 +2876,13 @@
auto clientUid = CameraThreadState::getCallingUid();
auto clientPid = CameraThreadState::getCallingPid();
- permission::PermissionChecker permissionChecker;
AttributionSourceState attributionSource{};
attributionSource.uid = clientUid;
attributionSource.pid = clientPid;
- bool openCloseCallbackAllowed = permissionChecker.checkPermissionForPreflight(
+
+ bool openCloseCallbackAllowed = checkPermission(String8(),
sCameraOpenCloseListenerPermission, attributionSource, String16(),
- AppOpsManager::OP_NONE) != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+ AppOpsManager::OP_NONE);
Mutex::Autolock lock(mServiceLock);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ecec15f..b77b037 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+#include <android/content/AttributionSourceState.h>
#include <android/hardware/BnCameraService.h>
#include <android/hardware/BnSensorPrivacyListener.h>
#include <android/hardware/ICameraServiceListener.h>
@@ -603,6 +604,13 @@
int32_t updateAudioRestrictionLocked();
private:
+ /**
+ * Returns true if the device is an automotive device and cameraId is system
+ * only camera which has characteristic AUTOMOTIVE_LOCATION value as either
+ * AUTOMOTIVE_LOCATION_EXTERIOR_LEFT,AUTOMOTIVE_LOCATION_EXTERIOR_RIGHT,
+ * AUTOMOTIVE_LOCATION_EXTERIOR_FRONT or AUTOMOTIVE_LOCATION_EXTERIOR_REAR.
+ */
+ bool isAutomotiveExteriorSystemCamera(const String8& cameraId) const;
// TODO: b/263304156 update this to make use of a death callback for more
// robust/fault tolerant logging
@@ -619,6 +627,22 @@
}
/**
+ * Pre-grants the permission if the attribution source uid is for an automotive
+ * privileged client. Otherwise uses system service permission checker to check
+ * for the appropriate permission. If this function is called for accessing a specific
+ * camera,then the cameraID must not be empty. CameraId is used only in case of automotive
+ * privileged client so that permission is pre-granted only to access system camera device
+ * which is located outside of the vehicle body frame because camera located inside the vehicle
+ * cabin would need user permission.
+ */
+ bool checkPermission(const String8& cameraId, const String16& permission,
+ const content::AttributionSourceState& attributionSource,const String16& message,
+ int32_t attributedOpCode) const;
+
+ bool hasPermissionsForSystemCamera(const String8& cameraId, int callingPid, int callingUid)
+ const;
+
+ /**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
*/
@@ -878,7 +902,7 @@
// Should a device status update be skipped for a particular camera device ? (this can happen
// under various conditions. For example if a camera device is advertised as
// system only or hidden secure camera, amongst possible others.
- static bool shouldSkipStatusUpdates(SystemCameraKind systemCameraKind, bool isVendorListener,
+ bool shouldSkipStatusUpdates(SystemCameraKind systemCameraKind, bool isVendorListener,
int clientPid, int clientUid);
// Gets the kind of camera device (i.e public, hidden secure or system only)
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.cpp b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
index e80064a..e802ea3 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.cpp
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "CameraServiceWatchdog"
#include "CameraServiceWatchdog.h"
+#include "android/set_abort_message.h"
#include "utils/CameraServiceProxyWrapper.h"
namespace android {
@@ -36,12 +37,15 @@
{
AutoMutex _l(mWatchdogLock);
- for (auto it = tidToCycleCounterMap.begin(); it != tidToCycleCounterMap.end(); it++) {
+ for (auto it = mTidMap.begin(); it != mTidMap.end(); it++) {
uint32_t currentThreadId = it->first;
- tidToCycleCounterMap[currentThreadId]++;
+ mTidMap[currentThreadId].cycles++;
- if (tidToCycleCounterMap[currentThreadId] >= mMaxCycles) {
+ if (mTidMap[currentThreadId].cycles >= mMaxCycles) {
+ std::string abortMessage = getAbortMessage(getpid(), currentThreadId,
+ mTidMap[currentThreadId].functionName);
+ android_set_abort_message(abortMessage.c_str());
ALOGW("CameraServiceWatchdog triggering abort for pid: %d tid: %d", getpid(),
currentThreadId);
mCameraServiceProxyWrapper->logClose(mCameraId, 0 /*latencyMs*/,
@@ -56,13 +60,20 @@
return true;
}
+std::string CameraServiceWatchdog::getAbortMessage(int pid, int tid, const char* functionName) {
+ std::string res = "CameraServiceWatchdog triggering abort during "
+ + std::string(functionName) + " | pid: " + std::to_string(pid)
+ + " tid: " + std::to_string(tid);
+ return res;
+}
+
void CameraServiceWatchdog::requestExit()
{
Thread::requestExit();
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap.clear();
+ mTidMap.clear();
if (mPause) {
mPause = false;
@@ -85,18 +96,21 @@
{
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap.erase(tid);
+ mTidMap.erase(tid);
- if (tidToCycleCounterMap.empty()) {
+ if (mTidMap.empty()) {
mPause = true;
}
}
-void CameraServiceWatchdog::start(uint32_t tid)
+void CameraServiceWatchdog::start(uint32_t tid, const char* functionName)
{
AutoMutex _l(mWatchdogLock);
- tidToCycleCounterMap[tid] = 0;
+ MonitoredFunction monitoredFunction = {};
+ monitoredFunction.cycles = 0;
+ monitoredFunction.functionName = functionName;
+ mTidMap[tid] = monitoredFunction;
if (mPause) {
mPause = false;
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index 6617873..a374817 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -40,9 +40,9 @@
#include "utils/CameraServiceProxyWrapper.h"
// Used to wrap the call of interest in start and stop calls
-#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid())
+#define WATCH(toMonitor) watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__)
#define WATCH_CUSTOM_TIMER(toMonitor, cycles, cycleLength) \
- watchThread([&]() { return toMonitor;}, gettid(), cycles, cycleLength);
+ watchThread([&]() { return toMonitor;}, gettid(), __FUNCTION__, cycles, cycleLength);
// Default cycles and cycle length values used to calculate permitted elapsed time
const static size_t kMaxCycles = 100;
@@ -52,6 +52,11 @@
class CameraServiceWatchdog : public Thread {
+struct MonitoredFunction {
+ uint32_t cycles;
+ const char* functionName;
+};
+
public:
explicit CameraServiceWatchdog(const String8 &cameraId,
std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
@@ -75,7 +80,8 @@
/** Used to wrap monitored calls in start and stop functions using custom timer values */
template<typename T>
- auto watchThread(T func, uint32_t tid, uint32_t cycles, uint32_t cycleLength) {
+ auto watchThread(T func, uint32_t tid, const char* functionName, uint32_t cycles,
+ uint32_t cycleLength) {
decltype(func()) res;
if (cycles != mMaxCycles || cycleLength != mCycleLengthMs) {
@@ -91,17 +97,17 @@
status_t status = tempWatchdog->run("CameraServiceWatchdog");
if (status != OK) {
ALOGE("Unable to watch thread: %s (%d)", strerror(-status), status);
- res = watchThread(func, tid);
+ res = watchThread(func, tid, functionName);
return res;
}
- res = tempWatchdog->watchThread(func, tid);
+ res = tempWatchdog->watchThread(func, tid, functionName);
tempWatchdog->requestExit();
tempWatchdog.clear();
} else {
// If custom timer values are equivalent to set class timer values, use
// current thread
- res = watchThread(func, tid);
+ res = watchThread(func, tid, functionName);
}
return res;
@@ -109,12 +115,12 @@
/** Used to wrap monitored calls in start and stop functions using class timer values */
template<typename T>
- auto watchThread(T func, uint32_t tid) {
+ auto watchThread(T func, uint32_t tid, const char* functionName) {
decltype(func()) res;
AutoMutex _l(mEnabledLock);
if (mEnabled) {
- start(tid);
+ start(tid, functionName);
res = func();
stop(tid);
} else {
@@ -130,7 +136,7 @@
* Start adds a cycle counter for the calling thread. When threadloop is blocked/paused,
* start() unblocks and starts the watchdog
*/
- void start(uint32_t tid);
+ void start(uint32_t tid, const char* functionName);
/**
* If there are no calls left to be monitored, stop blocks/pauses threadloop
@@ -138,6 +144,8 @@
*/
void stop(uint32_t tid);
+ std::string getAbortMessage(int pid, int tid, const char* functionName);
+
virtual bool threadLoop();
Mutex mWatchdogLock; // Lock for condition variable
@@ -151,7 +159,9 @@
std::shared_ptr<CameraServiceProxyWrapper> mCameraServiceProxyWrapper;
- std::unordered_map<uint32_t, uint32_t> tidToCycleCounterMap; // Thread Id to cycle counter map
+ std::unordered_map<uint32_t, MonitoredFunction> mTidMap; // Thread Id to MonitoredFunction type
+ // which retrieves the num of cycles
+ // and name of the function
};
} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index f742a6d..a2a9d04 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -260,7 +260,7 @@
auto mapper = states.rotateAndCropMappers.find(states.cameraId.c_str());
if (mapper != states.rotateAndCropMappers.end()) {
- const auto& remappedKeys = iter->second.getRemappedKeys();
+ const auto& remappedKeys = mapper->second.getRemappedKeys();
keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
}
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index cb5e783..158914a 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -438,7 +438,7 @@
}
AStatsEvent_writeInt32(event, hdr10PlusInfo);
- int32_t hdrFormat= -1;
+ int32_t hdrFormat = -1;
if (item->getInt32("android.media.mediacodec.hdr-format", &hdrFormat)) {
metrics_proto.set_hdr_format(hdrFormat);
}
@@ -450,6 +450,61 @@
}
AStatsEvent_writeInt64(event, codecId);
+ int32_t arrayMode = -1;
+ if (item->getInt32("android.media.mediacodec.array-mode", &arrayMode)) {
+ metrics_proto.set_array_mode(arrayMode);
+ }
+ AStatsEvent_writeInt32(event, arrayMode);
+
+ int32_t operationMode = -1;
+ if (item->getInt32("android.media.mediacodec.operation-mode", &operationMode)) {
+ metrics_proto.set_operation_mode(operationMode);
+ }
+ AStatsEvent_writeInt32(event, operationMode);
+
+ int32_t outputSurface = -1;
+ if (item->getInt32("android.media.mediacodec.output-surface", &outputSurface)) {
+ metrics_proto.set_output_surface(outputSurface);
+ }
+ AStatsEvent_writeInt32(event, outputSurface);
+
+ int32_t appMaxInputSize = -1;
+ if (item->getInt32("android.media.mediacodec.app-max-input-size", &appMaxInputSize)) {
+ metrics_proto.set_app_max_input_size(appMaxInputSize);
+ }
+ AStatsEvent_writeInt32(event, appMaxInputSize);
+
+ int32_t usedMaxInputSize = -1;
+ if (item->getInt32("android.media.mediacodec.used-max-input-size", &usedMaxInputSize)) {
+ metrics_proto.set_used_max_input_size(usedMaxInputSize);
+ }
+ AStatsEvent_writeInt32(event, usedMaxInputSize);
+
+ int32_t codecMaxInputSize = -1;
+ if (item->getInt32("android.media.mediacodec.codec-max-input-size", &codecMaxInputSize)) {
+ metrics_proto.set_codec_max_input_size(codecMaxInputSize);
+ }
+ AStatsEvent_writeInt32(event, codecMaxInputSize);
+
+ int32_t flushCount = -1;
+ if (item->getInt32("android.media.mediacodec.flush-count", &flushCount)) {
+ metrics_proto.set_flush_count(flushCount);
+ }
+ AStatsEvent_writeInt32(event, flushCount);
+
+ int32_t setSurfaceCount = -1;
+ if (item->getInt32("android.media.mediacodec.set-surface-count", &setSurfaceCount)) {
+ metrics_proto.set_set_surface_count(setSurfaceCount);
+ }
+ AStatsEvent_writeInt32(event, setSurfaceCount);
+
+ int32_t resolutionChangeCount = -1;
+ if (item->getInt32("android.media.mediacodec.resolution-change-count",
+ &resolutionChangeCount)) {
+ metrics_proto.set_resolution_change_count(resolutionChangeCount);
+ }
+ AStatsEvent_writeInt32(event, resolutionChangeCount);
+
int err = AStatsEvent_write(event);
if (err < 0) {
ALOGE("Failed to write codec metrics to statsd (%d)", err);
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index d98974f..d5fdbe5 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -27,21 +27,18 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_fuzz {
- name: "mediaresourcemanager_fuzzer",
- srcs: [
- "mediaresourcemanager_fuzzer.cpp",
+cc_defaults {
+ name: "mediaresourcemanager_fuzzer_defaults",
+ defaults: [
+ "service_fuzzer_defaults",
],
static_libs: [
"liblog",
"libresourcemanagerservice",
],
shared_libs: [
- "libbinder",
- "libbinder_ndk",
"libmedia",
"libmediautils",
- "libutils",
"libstats_media_metrics",
"libstatspull",
"libstatssocket",
@@ -54,3 +51,23 @@
componentid: 155276,
},
}
+
+cc_fuzz {
+ name: "mediaresourcemanager_fuzzer",
+ defaults: [
+ "mediaresourcemanager_fuzzer_defaults",
+ ],
+ srcs: [
+ "mediaresourcemanager_fuzzer.cpp",
+ ],
+}
+
+cc_fuzz {
+ name: "resourcemanager_service_fuzzer",
+ defaults: [
+ "mediaresourcemanager_fuzzer_defaults",
+ ],
+ srcs: [
+ "resourcemanager_service_fuzzer.cpp",
+ ],
+}
\ No newline at end of file
diff --git a/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
new file mode 100644
index 0000000..ca10d20
--- /dev/null
+++ b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_interface_utils.h>
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "ResourceManagerService.h"
+
+using android::fuzzService;
+using android::ResourceManagerService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = SharedRefBase::make<ResourceManagerService>();
+ fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+ return 0;
+}