Merge changes from topic "AV1Enc"
* changes:
AV1 Encoder. Fixing idents
Add AV1 Encoder to the registry and XMLs
Implement AV1 Encoder via Codec2 interface
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
index 490bbbf..4e1d3a2 100644
--- a/MainlineFiles.cfg
+++ b/MainlineFiles.cfg
@@ -21,11 +21,19 @@
#
# matching is purely prefix
# so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
-# if you want to exclude a directory, best to use a pattern like "foo/"
+# if you want to specify a directory, best to use a pattern like "foo/"
#
+apex/
media/codec2/components/
-media/codecs/
-media/extractors/
-media/libstagefright/mpeg2ts/
-media/libstagefright/flac/
+media/codec2/core/
+media/codec2/hidl/
+media/codec2/sfplugin/utils/
+media/codec2/vndk/
+media/module/
+services/mediacodec/
+
+# source code used in both framework and mainline libraries
+media/libstagefright/HevcUtils.cpp
+media/libstagefright/MediaSource.cpp
+media/libstagefright/Utils.cpp
diff --git a/OWNERS b/OWNERS
index 87bc809..3c7a3ab 100644
--- a/OWNERS
+++ b/OWNERS
@@ -10,3 +10,7 @@
## Only contact for media changes as a fallback
etalvala@google.com
shuzhenwang@google.com
+
+# mainline related
+per-file MainlineFiles.cfg=essick@google.com
+per-file MainlineFiles.cfg=file:/media/janitors/reliability_mainline_OWNERS
diff --git a/camera/Android.bp b/camera/Android.bp
index e44202b..a933553 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -47,7 +47,7 @@
name: "camera_headers",
export_include_dirs: ["include"],
}
-cc_library_shared {
+cc_library {
name: "libcamera_client",
aidl: {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 124a893..72301db 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1973,7 +1973,6 @@
}
mChannel->reset();
- mChannel->stopUseOutputSurface();
// thiz holds strong ref to this while the thread is running.
sp<CCodec> thiz(this);
std::thread([thiz, sendCallback] { thiz->release(sendCallback); }).detach();
@@ -1994,6 +1993,7 @@
comp = state->comp;
}
comp->release();
+ mChannel->stopUseOutputSurface();
{
Mutexed<State>::Locked state(mState);
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index bebd382..27f987d 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -87,6 +87,7 @@
#define AMEDIAMETRICS_PROP_PREFIX_EFFECTIVE "effective."
#define AMEDIAMETRICS_PROP_PREFIX_HAL "hal."
#define AMEDIAMETRICS_PROP_PREFIX_HAPTIC "haptic."
+#define AMEDIAMETRICS_PROP_PREFIX_LAST "last."
#define AMEDIAMETRICS_PROP_PREFIX_SERVER "server."
// Properties within mediametrics are string constants denoted by
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 6de112a..2370a7b 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -86,11 +86,14 @@
displayHeight = height;
}
- if (allocRotated && (rotationAngle == 90 || rotationAngle == 270)) {
- int32_t tmp;
- tmp = width; width = height; height = tmp;
- tmp = displayWidth; displayWidth = displayHeight; displayHeight = tmp;
- tmp = tileWidth; tileWidth = tileHeight; tileHeight = tmp;
+ if (allocRotated) {
+ if (rotationAngle == 90 || rotationAngle == 270) {
+ // swap width and height for 90 & 270 degrees rotation
+ std::swap(width, height);
+ std::swap(displayWidth, displayHeight);
+ std::swap(tileWidth, tileHeight);
+ }
+ // Rotation is already applied.
rotationAngle = 0;
}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index b4baf03..0536f2a 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -72,6 +72,37 @@
}
}
+status_t NuMediaExtractor::initMediaExtractor(const sp<DataSource>& dataSource) {
+ status_t err = OK;
+
+ mImpl = MediaExtractorFactory::Create(dataSource);
+ if (mImpl == NULL) {
+ ALOGE("%s: failed to create MediaExtractor", __FUNCTION__);
+ return ERROR_UNSUPPORTED;
+ }
+
+ setEntryPointToRemoteMediaExtractor();
+
+ if (!mCasToken.empty()) {
+ err = mImpl->setMediaCas(mCasToken);
+ if (err != OK) {
+ ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+ return err;
+ }
+ }
+
+ // Get the name of the implementation.
+ mName = mImpl->name();
+
+ // Update the duration and bitrate
+ err = updateDurationAndBitrate();
+ if (err == OK) {
+ mDataSource = dataSource;
+ }
+
+ return OK;
+}
+
status_t NuMediaExtractor::setDataSource(
const sp<MediaHTTPService> &httpService,
const char *path,
@@ -89,28 +120,8 @@
return -ENOENT;
}
- mImpl = MediaExtractorFactory::Create(dataSource);
-
- if (mImpl == NULL) {
- return ERROR_UNSUPPORTED;
- }
- setEntryPointToRemoteMediaExtractor();
-
- status_t err = OK;
- if (!mCasToken.empty()) {
- err = mImpl->setMediaCas(mCasToken);
- if (err != OK) {
- ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
- return err;
- }
- }
-
- err = updateDurationAndBitrate();
- if (err == OK) {
- mDataSource = dataSource;
- }
-
- return OK;
+ // Initialize MediaExtractor using the data source
+ return initMediaExtractor(dataSource);
}
status_t NuMediaExtractor::setDataSource(int fd, off64_t offset, off64_t size) {
@@ -131,27 +142,8 @@
return err;
}
- mImpl = MediaExtractorFactory::Create(fileSource);
-
- if (mImpl == NULL) {
- return ERROR_UNSUPPORTED;
- }
- setEntryPointToRemoteMediaExtractor();
-
- if (!mCasToken.empty()) {
- err = mImpl->setMediaCas(mCasToken);
- if (err != OK) {
- ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
- return err;
- }
- }
-
- err = updateDurationAndBitrate();
- if (err == OK) {
- mDataSource = fileSource;
- }
-
- return OK;
+ // Initialize MediaExtractor using the file source
+ return initMediaExtractor(fileSource);
}
status_t NuMediaExtractor::setDataSource(const sp<DataSource> &source) {
@@ -166,32 +158,13 @@
return err;
}
- mImpl = MediaExtractorFactory::Create(source);
-
- if (mImpl == NULL) {
- return ERROR_UNSUPPORTED;
- }
- setEntryPointToRemoteMediaExtractor();
-
- if (!mCasToken.empty()) {
- err = mImpl->setMediaCas(mCasToken);
- if (err != OK) {
- ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
- return err;
- }
- }
-
- err = updateDurationAndBitrate();
- if (err == OK) {
- mDataSource = source;
- }
-
- return err;
+ // Initialize MediaExtractor using the given data source
+ return initMediaExtractor(source);
}
const char* NuMediaExtractor::getName() const {
Mutex::Autolock autoLock(mLock);
- return mImpl == nullptr ? nullptr : mImpl->name().string();
+ return mImpl == nullptr ? nullptr : mName.string();
}
static String8 arrayToString(const std::vector<uint8_t> &array) {
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index d17a480..52ea28b 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -146,6 +146,7 @@
Vector<TrackInfo> mSelectedTracks;
int64_t mTotalBitrate; // in bits/sec
int64_t mDurationUs;
+ String8 mName;
void setEntryPointToRemoteMediaExtractor();
@@ -165,6 +166,7 @@
bool getTotalBitrate(int64_t *bitRate) const;
status_t updateDurationAndBitrate();
status_t appendVorbisNumPageSamples(MediaBufferBase *mbuf, const sp<ABuffer> &buffer);
+ status_t initMediaExtractor(const sp<DataSource>& dataSource);
DISALLOW_EVIL_CONSTRUCTORS(NuMediaExtractor);
};
diff --git a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
index c4dd564..c32d28a 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
@@ -79,8 +79,6 @@
usb_device* device = usb_device_new(deviceName.c_str(), fd);
MtpDevice mtpDevice(device, fdp.ConsumeIntegral<int32_t>(), &descriptor.ep[0],
&descriptor.ep[1], &descriptor.ep[2]);
- MtpObjectInfo objectinfo(fdp.ConsumeIntegral<uint32_t>());
- MtpStorageInfo storageInfo(fdp.ConsumeIntegral<uint32_t>());
while (fdp.remaining_bytes()) {
auto mtpDeviceFunction = fdp.PickValueInArray<const std::function<void()>>(
{[&]() { mtpDevice.getStorageIDs(); },
@@ -190,6 +188,7 @@
},
[&]() { MtpDevice::open(deviceName.c_str(), fd); },
[&]() {
+ MtpObjectInfo objectinfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
MtpDataPacket mtpDataPacket;
MtpDevHandle devHandle;
std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
@@ -198,6 +197,7 @@
objectinfo.print();
},
[&]() {
+ MtpStorageInfo storageInfo(fdp.ConsumeIntegral<uint32_t>() /* id */);
MtpDataPacket mtpDataPacket;
MtpDevHandle devHandle;
std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
diff --git a/services/audioflinger/ThreadMetrics.h b/services/audioflinger/ThreadMetrics.h
index 6526655..5493b3c 100644
--- a/services/audioflinger/ThreadMetrics.h
+++ b/services/audioflinger/ThreadMetrics.h
@@ -148,7 +148,14 @@
item.set(AMEDIAMETRICS_PROP_CUMULATIVETIMENS, mCumulativeTimeNs)
.set(AMEDIAMETRICS_PROP_DEVICETIMENS, mDeviceTimeNs)
.set(AMEDIAMETRICS_PROP_EVENT, eventName)
- .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount);
+ .set(AMEDIAMETRICS_PROP_INTERVALCOUNT, (int32_t)mIntervalCount)
+ // we set "last" device to indicate the device the group was
+ // associated with (because a createPatch which is logged in ThreadMetrics
+ // could have changed the device).
+ .set(mIsOut
+ ? AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_OUTPUTDEVICES
+ : AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_INPUTDEVICES,
+ mDevices.c_str());
if (mDeviceLatencyMs.getN() > 0) {
item.set(AMEDIAMETRICS_PROP_DEVICELATENCYMS, mDeviceLatencyMs.getMean());
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 71c24f3..b021c5e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4103,10 +4103,19 @@
mEffectBufferFormat,
mNormalFrameCount * mHapticChannelCount);
}
-
- memcpy_by_audio_format(mSinkBuffer, mFormat, effectBuffer, mEffectBufferFormat,
- mNormalFrameCount * (mChannelCount + mHapticChannelCount));
-
+ const size_t framesToCopy = mNormalFrameCount * (mChannelCount + mHapticChannelCount);
+ if (mFormat == AUDIO_FORMAT_PCM_FLOAT &&
+ mEffectBufferFormat == AUDIO_FORMAT_PCM_FLOAT) {
+ // Clamp PCM float values more than this distance from 0 to insulate
+ // a HAL which doesn't handle NaN correctly.
+ static constexpr float HAL_FLOAT_SAMPLE_LIMIT = 2.0f;
+ memcpy_to_float_from_float_with_clamping(static_cast<float*>(mSinkBuffer),
+ static_cast<const float*>(effectBuffer),
+ framesToCopy, HAL_FLOAT_SAMPLE_LIMIT /* absMax */);
+ } else {
+ memcpy_by_audio_format(mSinkBuffer, mFormat,
+ effectBuffer, mEffectBufferFormat, framesToCopy);
+ }
// The sample data is partially interleaved when haptic channels exist,
// we need to adjust channels here.
if (mHapticChannelCount > 0) {
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 77ea507..b6089b7 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -21,18 +21,6 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-python_defaults {
- name: "tools_default",
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-}
-
//##################################################################################################
// Tools for audio policy engine criterion type configuration file
//
@@ -42,7 +30,6 @@
srcs: [
"buildPolicyCriterionTypes.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
@@ -77,7 +64,6 @@
srcs: [
"domainGeneratorPolicy.py",
],
- defaults: ["tools_default"],
libs: [
"EddParser.py",
"hostConfig.py",
@@ -126,7 +112,6 @@
srcs: [
"buildStrategiesStructureFile.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
@@ -154,7 +139,6 @@
srcs: [
"buildCommonTypesStructureFile.py",
],
- defaults: ["tools_default"],
}
genrule_defaults {
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 7534984..924b4ad 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -463,7 +463,7 @@
}
if (devices.isEmpty()) {
- ALOGV("%s no device found for strategy %d", __func__, strategy);
+ ALOGI("%s no device found for strategy %d", __func__, strategy);
sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
if (defaultOutputDevice != nullptr) {
devices.add(defaultOutputDevice);
@@ -699,6 +699,18 @@
return preferredAvailableDevVec;
}
+DeviceVector Engine::getDisabledDevicesForProductStrategy(
+ const DeviceVector &availableOutputDevices, product_strategy_t strategy) const {
+ DeviceVector disabledDevices = {};
+ AudioDeviceTypeAddrVector disabledDevicesTypeAddr;
+ const status_t status = getDevicesForRoleAndStrategy(
+ strategy, DEVICE_ROLE_DISABLED, disabledDevicesTypeAddr);
+ if (status == NO_ERROR) {
+ disabledDevices =
+ availableOutputDevices.getDevicesFromDeviceTypeAddrVec(disabledDevicesTypeAddr);
+ }
+ return disabledDevices;
+}
DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
@@ -722,6 +734,11 @@
return preferredAvailableDevVec;
}
+ // Remove all disabled devices from the available device list.
+ DeviceVector disabledDevVec =
+ getDisabledDevicesForProductStrategy(availableOutputDevices, strategy);
+ availableOutputDevices.remove(disabledDevVec);
+
return getDevicesForStrategyInt(legacyStrategy,
availableOutputDevices,
outputs);
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289..1efdf24 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -96,6 +96,8 @@
const DeviceVector& availableOutputDevices, legacy_strategy legacyStrategy) const;
DeviceVector getPreferredAvailableDevicesForProductStrategy(
const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
+ DeviceVector getDisabledDevicesForProductStrategy(
+ const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
DeviceStrategyMap mDevicesForStrategies;
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 9735479..72dba3d 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -43,7 +43,7 @@
constexpr float kMaxTranslationalVelocity = 2;
// This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
-constexpr float kMaxRotationalVelocity = 8;
+constexpr float kMaxRotationalVelocity = 0.8f;
// This is how far into the future we predict the head pose, using linear extrapolation based on
// twist (velocity). It should be set to a value that matches the characteristic durations of moving
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 644f682..3672666 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2680,7 +2680,7 @@
status_t Camera3Device::registerInFlight(uint32_t frameNumber,
int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
bool hasAppCallback, nsecs_t minExpectedDuration, nsecs_t maxExpectedDuration,
- const std::set<std::set<String8>>& physicalCameraIds,
+ bool isFixedFps, const std::set<std::set<String8>>& physicalCameraIds,
bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto,
const std::set<std::string>& cameraIdsWithZoom,
const SurfaceMap& outputSurfaces, nsecs_t requestTimeNs) {
@@ -2689,7 +2689,7 @@
ssize_t res;
res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers, resultExtras, hasInput,
- hasAppCallback, minExpectedDuration, maxExpectedDuration, physicalCameraIds,
+ hasAppCallback, minExpectedDuration, maxExpectedDuration, isFixedFps, physicalCameraIds,
isStillCapture, isZslCapture, rotateAndCropAuto, cameraIdsWithZoom, requestTimeNs,
outputSurfaces));
if (res < 0) return res;
@@ -3249,16 +3249,18 @@
return true;
}
-std::pair<nsecs_t, nsecs_t> Camera3Device::RequestThread::calculateExpectedDurationRange(
- const camera_metadata_t *request) {
- std::pair<nsecs_t, nsecs_t> expectedRange(
+Camera3Device::RequestThread::ExpectedDurationInfo
+ Camera3Device::RequestThread::calculateExpectedDurationRange(
+ const camera_metadata_t *request) {
+ ExpectedDurationInfo expectedDurationInfo = {
InFlightRequest::kDefaultMinExpectedDuration,
- InFlightRequest::kDefaultMaxExpectedDuration);
+ InFlightRequest::kDefaultMaxExpectedDuration,
+ /*isFixedFps*/false};
camera_metadata_ro_entry_t e = camera_metadata_ro_entry_t();
find_camera_metadata_ro_entry(request,
ANDROID_CONTROL_AE_MODE,
&e);
- if (e.count == 0) return expectedRange;
+ if (e.count == 0) return expectedDurationInfo;
switch (e.data.u8[0]) {
case ANDROID_CONTROL_AE_MODE_OFF:
@@ -3266,29 +3268,32 @@
ANDROID_SENSOR_EXPOSURE_TIME,
&e);
if (e.count > 0) {
- expectedRange.first = e.data.i64[0];
- expectedRange.second = expectedRange.first;
+ expectedDurationInfo.minDuration = e.data.i64[0];
+ expectedDurationInfo.maxDuration = expectedDurationInfo.minDuration;
}
find_camera_metadata_ro_entry(request,
ANDROID_SENSOR_FRAME_DURATION,
&e);
if (e.count > 0) {
- expectedRange.first = std::max(e.data.i64[0], expectedRange.first);
- expectedRange.second = expectedRange.first;
+ expectedDurationInfo.minDuration =
+ std::max(e.data.i64[0], expectedDurationInfo.minDuration);
+ expectedDurationInfo.maxDuration = expectedDurationInfo.minDuration;
}
+ expectedDurationInfo.isFixedFps = false;
break;
default:
find_camera_metadata_ro_entry(request,
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
&e);
if (e.count > 1) {
- expectedRange.first = 1e9 / e.data.i32[1];
- expectedRange.second = 1e9 / e.data.i32[0];
+ expectedDurationInfo.minDuration = 1e9 / e.data.i32[1];
+ expectedDurationInfo.maxDuration = 1e9 / e.data.i32[0];
}
+ expectedDurationInfo.isFixedFps = (e.data.i32[1] == e.data.i32[0]);
break;
}
- return expectedRange;
+ return expectedDurationInfo;
}
bool Camera3Device::RequestThread::skipHFRTargetFPSUpdate(int32_t tag,
@@ -3907,13 +3912,14 @@
isZslCapture = true;
}
}
- auto expectedDurationRange = calculateExpectedDurationRange(settings);
+ auto expectedDurationInfo = calculateExpectedDurationRange(settings);
res = parent->registerInFlight(halRequest->frame_number,
totalNumBuffers, captureRequest->mResultExtras,
/*hasInput*/halRequest->input_buffer != NULL,
hasCallback,
- /*min*/expectedDurationRange.first,
- /*max*/expectedDurationRange.second,
+ expectedDurationInfo.minDuration,
+ expectedDurationInfo.maxDuration,
+ expectedDurationInfo.isFixedFps,
requestedPhysicalCameras, isStillCapture, isZslCapture,
captureRequest->mRotateAndCropAuto, mPrevCameraIdsWithZoom,
(mUseHalBufManager) ? uniqueSurfaceIdMap :
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d757eb9..80b1722 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -993,8 +993,13 @@
// send request in mNextRequests to HAL in a batch. Return true = sucssess
bool sendRequestsBatch();
- // Calculate the expected (minimum, maximum) duration range for a request
- std::pair<nsecs_t, nsecs_t> calculateExpectedDurationRange(
+ // Calculate the expected (minimum, maximum, isFixedFps) duration info for a request
+ struct ExpectedDurationInfo {
+ nsecs_t minDuration;
+ nsecs_t maxDuration;
+ bool isFixedFps;
+ };
+ ExpectedDurationInfo calculateExpectedDurationRange(
const camera_metadata_t *request);
// Check and update latest session parameters based on the current request settings.
@@ -1113,7 +1118,7 @@
status_t registerInFlight(uint32_t frameNumber,
int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
bool callback, nsecs_t minExpectedDuration, nsecs_t maxExpectedDuration,
- const std::set<std::set<String8>>& physicalCameraIds,
+ bool isFixedFps, const std::set<std::set<String8>>& physicalCameraIds,
bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto,
const std::set<std::string>& cameraIdsWithZoom, const SurfaceMap& outputSurfaces,
nsecs_t requestTimeNs);
@@ -1365,6 +1370,9 @@
// The current minimum expected frame duration based on AE_TARGET_FPS_RANGE
nsecs_t mMinExpectedDuration = 0;
+ // Whether the camera device runs at fixed frame rate based on AE_MODE and
+ // AE_TARGET_FPS_RANGE
+ bool mIsFixedFps = false;
// Injection camera related methods.
class Camera3DeviceInjectionMethods : public virtual RefBase {
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index 8cecabd..a93d1da 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -100,7 +100,7 @@
virtual status_t setBatchSize(size_t batchSize) override;
- virtual void onMinDurationChanged(nsecs_t /*duration*/) {}
+ virtual void onMinDurationChanged(nsecs_t /*duration*/, bool /*fixedFps*/) {}
protected:
/**
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index a799719..5ee6ca5 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -248,6 +248,9 @@
// The current minimum expected frame duration based on AE_TARGET_FPS_RANGE
nsecs_t mMinExpectedDuration = 0;
+ // Whether the camera device runs at fixed frame rate based on AE_MODE and
+ // AE_TARGET_FPS_RANGE
+ bool mIsFixedFps = false;
// SetErrorInterface
void setErrorState(const char *fmt, ...) override;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 5a1ee9b..e80bfa3 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -1364,9 +1364,10 @@
return OK;
}
-void Camera3OutputStream::onMinDurationChanged(nsecs_t duration) {
+void Camera3OutputStream::onMinDurationChanged(nsecs_t duration, bool fixedFps) {
Mutex::Autolock l(mLock);
mMinExpectedDuration = duration;
+ mFixedFps = fixedFps;
}
void Camera3OutputStream::returnPrefetchedBuffersLocked() {
@@ -1399,17 +1400,21 @@
const VsyncEventData& vsyncEventData = parcelableVsyncEventData.vsync;
nsecs_t currentTime = systemTime();
+ nsecs_t minPresentT = mLastPresentTime + vsyncEventData.frameInterval / 2;
- // Reset capture to present time offset if:
- // - More than 1 second between frames.
- // - The frame duration deviates from multiples of vsync frame intervals.
+ // Find the best presentation time without worrying about previous frame's
+ // presentation time if capture interval is more than kSpacingResetIntervalNs.
+ //
+ // When frame interval is more than 50 ms apart (3 vsyncs for 60hz refresh rate),
+ // there is little risk in starting over and finding the earliest vsync to latch onto.
+ // - Update captureToPresentTime offset to be used for later frames.
+ // - Example use cases:
+ // - when frame rate drops down to below 20 fps, or
+ // - A new streaming session starts (stopPreview followed by
+ // startPreview)
+ //
nsecs_t captureInterval = t - mLastCaptureTime;
- float captureToVsyncIntervalRatio = 1.0f * captureInterval / vsyncEventData.frameInterval;
- float ratioDeviation = std::fabs(
- captureToVsyncIntervalRatio - std::roundf(captureToVsyncIntervalRatio));
- if (captureInterval > kSpacingResetIntervalNs ||
- ratioDeviation >= kMaxIntervalRatioDeviation) {
- nsecs_t minPresentT = mLastPresentTime + vsyncEventData.frameInterval / 2;
+ if (captureInterval > kSpacingResetIntervalNs) {
for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
const auto& timeline = vsyncEventData.frameTimelines[i];
if (timeline.deadlineTimestamp >= currentTime &&
@@ -1431,21 +1436,54 @@
nsecs_t idealPresentT = t + mCaptureToPresentOffset;
nsecs_t expectedPresentT = mLastPresentTime;
nsecs_t minDiff = INT64_MAX;
- // Derive minimum intervals between presentation times based on minimal
+
+ // In fixed FPS case, when frame durations are close to multiples of display refresh
+ // rate, derive minimum intervals between presentation times based on minimal
// expected duration. The minimum number of Vsyncs is:
// - 0 if minFrameDuration in (0, 1.5] * vSyncInterval,
// - 1 if minFrameDuration in (1.5, 2.5] * vSyncInterval,
// - and so on.
+ //
+ // This spaces out the displaying of the frames so that the frame
+ // presentations are roughly in sync with frame captures.
int minVsyncs = (mMinExpectedDuration - vsyncEventData.frameInterval / 2) /
vsyncEventData.frameInterval;
if (minVsyncs < 0) minVsyncs = 0;
nsecs_t minInterval = minVsyncs * vsyncEventData.frameInterval;
+
+ // In fixed FPS case, if the frame duration deviates from multiples of
+ // display refresh rate, find the closest Vsync without requiring a minimum
+ // number of Vsync.
+ //
+ // Example: (24fps camera, 60hz refresh):
+ // capture readout: | t1 | t1 | .. | t1 | .. | t1 | .. | t1 |
+ // display VSYNC: | t2 | t2 | ... | t2 | ... | t2 | ... | t2 |
+ // | : 1 frame
+ // t1 : 41.67ms
+ // t2 : 16.67ms
+ // t1/t2 = 2.5
+ //
+ // 24fps is a commonly used video frame rate. Because the capture
+ // interval is 2.5 times of display refresh interval, the minVsyncs
+ // calculation will directly fall at the boundary condition. In this case,
+ // we should fall back to the basic logic of finding closest vsync
+ // timestamp without worrying about minVsyncs.
+ float captureToVsyncIntervalRatio = 1.0f * mMinExpectedDuration / vsyncEventData.frameInterval;
+ float ratioDeviation = std::fabs(
+ captureToVsyncIntervalRatio - std::roundf(captureToVsyncIntervalRatio));
+ bool captureDeviateFromVsync = ratioDeviation >= kMaxIntervalRatioDeviation;
+ bool cameraDisplayInSync = (mFixedFps && !captureDeviateFromVsync);
+
// Find best timestamp in the vsync timelines:
- // - Only use at most 3 timelines to avoid long latency
- // - closest to the ideal present time,
+ // - Only use at most kMaxTimelines timelines to avoid long latency
+ // - closest to the ideal presentation time,
// - deadline timestamp is greater than the current time, and
- // - the candidate present time is at least minInterval in the future
- // compared to last present time.
+ // - For fixed FPS, if the capture interval doesn't deviate too much from refresh interval,
+ // the candidate presentation time is at least minInterval in the future compared to last
+ // presentation time.
+ // - For variable FPS, or if the capture interval deviates from refresh
+ // interval for more than 5%, find a presentation time closest to the
+ // (lastPresentationTime + captureToPresentOffset) instead.
int maxTimelines = std::min(kMaxTimelines, (int)VsyncEventData::kFrameTimelinesLength);
float biasForShortDelay = 1.0f;
for (int i = 0; i < maxTimelines; i ++) {
@@ -1458,12 +1496,50 @@
}
if (std::abs(vsyncTime.expectedPresentationTime - idealPresentT) < minDiff &&
vsyncTime.deadlineTimestamp >= currentTime &&
- vsyncTime.expectedPresentationTime >
- mLastPresentTime + minInterval + biasForShortDelay * kTimelineThresholdNs) {
+ ((!cameraDisplayInSync && vsyncTime.expectedPresentationTime > minPresentT) ||
+ (cameraDisplayInSync && vsyncTime.expectedPresentationTime >
+ mLastPresentTime + minInterval + biasForShortDelay * kTimelineThresholdNs))) {
expectedPresentT = vsyncTime.expectedPresentationTime;
minDiff = std::abs(vsyncTime.expectedPresentationTime - idealPresentT);
}
}
+
+ if (expectedPresentT == mLastPresentTime && expectedPresentT <=
+ vsyncEventData.frameTimelines[maxTimelines].expectedPresentationTime) {
+ // Couldn't find a reasonable presentation time. Using last frame's
+ // presentation time would cause a frame drop. The best option now
+ // is to use the next VSync as long as the last presentation time
+ // doesn't already has the maximum latency, in which case dropping the
+ // buffer is more desired than increasing latency.
+ //
+ // Example: (60fps camera, 59.9hz refresh):
+ // capture readout: | t1 | t1 | .. | t1 | .. | t1 | .. | t1 |
+ // \ \ \ \ \ \ \ \ \
+ // queue to BQ: | | | | | | | | |
+ // \ \ \ \ \ \ \ \ \
+ // display VSYNC: | t2 | t2 | ... | t2 | ... | t2 | ... | t2 |
+ //
+ // |: 1 frame
+ // t1 : 16.67ms
+ // t2 : 16.69ms
+ //
+ // It takes 833 frames for capture readout count and display VSYNC count to be off
+ // by 1.
+ // - At frames [0, 832], presentationTime is set to timeline[0]
+ // - At frames [833, 833*2-1], presentationTime is set to timeline[1]
+ // - At frames [833*2, 833*3-1] presentationTime is set to timeline[2]
+ // - At frame 833*3, no presentation time is found because we only
+ // search for timeline[0..2].
+ // - Drop one buffer is better than further extend the presentation
+ // time.
+ //
+ // However, if frame 833*2 arrives 16.67ms early (right after frame
+ // 833*2-1), no presentation time can be found because
+ // getLatestVsyncEventData is called early. In that case, it's better to
+ // set presentation time by offseting last presentation time.
+ expectedPresentT += vsyncEventData.frameInterval;
+ }
+
mLastCaptureTime = t;
mLastPresentTime = expectedPresentT;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 3587af4..1b4739c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -247,9 +247,10 @@
virtual status_t setBatchSize(size_t batchSize = 1) override;
/**
- * Notify the stream on change of min frame durations.
+ * Notify the stream on change of min frame durations or variable/fixed
+ * frame rate.
*/
- virtual void onMinDurationChanged(nsecs_t duration) override;
+ virtual void onMinDurationChanged(nsecs_t duration, bool fixedFps) override;
/**
* Apply ZSL related consumer usage quirk.
@@ -419,6 +420,7 @@
// Re-space frames by overriding timestamp to align with display Vsync.
// Default is on for SurfaceView bound streams.
+ bool mFixedFps = false;
nsecs_t mMinExpectedDuration = 0;
bool mSyncToDisplay = false;
DisplayEventReceiver mDisplayEventReceiver;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index a6d4b96..dbc6fe1 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -110,12 +110,13 @@
virtual status_t setBatchSize(size_t batchSize = 1) = 0;
/**
- * Notify the output stream that the minimum frame duration has changed.
+ * Notify the output stream that the minimum frame duration has changed, or
+ * frame rate has switched between variable and fixed.
*
* The minimum frame duration is calculated based on the upper bound of
* AE_TARGET_FPS_RANGE in the capture request.
*/
- virtual void onMinDurationChanged(nsecs_t duration) = 0;
+ virtual void onMinDurationChanged(nsecs_t duration, bool fixedFps) = 0;
};
// Helper class to organize a synchronized mapping of stream IDs to stream instances
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 5d3da45..65c45ff 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -888,12 +888,14 @@
r.resultExtras.hasReadoutTimestamp = true;
r.resultExtras.readoutTimestamp = msg.readout_timestamp;
}
- if (r.minExpectedDuration != states.minFrameDuration) {
+ if (r.minExpectedDuration != states.minFrameDuration ||
+ r.isFixedFps != states.isFixedFps) {
for (size_t i = 0; i < states.outputStreams.size(); i++) {
auto outputStream = states.outputStreams[i];
- outputStream->onMinDurationChanged(r.minExpectedDuration);
+ outputStream->onMinDurationChanged(r.minExpectedDuration, r.isFixedFps);
}
states.minFrameDuration = r.minExpectedDuration;
+ states.isFixedFps = r.isFixedFps;
}
if (r.hasCallback) {
ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index d6107c2..8c71c2b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -106,6 +106,7 @@
BufferRecordsInterface& bufferRecordsIntf;
bool legacyClient;
nsecs_t& minFrameDuration;
+ bool& isFixedFps;
};
void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result);
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
index fa00495..444445b 100644
--- a/services/camera/libcameraservice/device3/InFlightRequest.h
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -152,6 +152,9 @@
// For auto-exposure modes, equal to 1/(lower end of target FPS range)
nsecs_t maxExpectedDuration;
+ // Whether the FPS range is fixed, aka, minFps == maxFps
+ bool isFixedFps;
+
// Whether the result metadata for this request is to be skipped. The
// result metadata should be skipped in the case of
// REQUEST/RESULT error.
@@ -205,6 +208,7 @@
hasCallback(true),
minExpectedDuration(kDefaultMinExpectedDuration),
maxExpectedDuration(kDefaultMaxExpectedDuration),
+ isFixedFps(false),
skipResultMetadata(false),
errorBufStrategy(ERROR_BUF_CACHE),
stillCapture(false),
@@ -215,7 +219,7 @@
}
InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
- bool hasAppCallback, nsecs_t minDuration, nsecs_t maxDuration,
+ bool hasAppCallback, nsecs_t minDuration, nsecs_t maxDuration, bool fixedFps,
const std::set<std::set<String8>>& physicalCameraIdSet, bool isStillCapture,
bool isZslCapture, bool rotateAndCropAuto, const std::set<std::string>& idsWithZoom,
nsecs_t requestNs, const SurfaceMap& outSurfaces = SurfaceMap{}) :
@@ -229,6 +233,7 @@
hasCallback(hasAppCallback),
minExpectedDuration(minDuration),
maxExpectedDuration(maxDuration),
+ isFixedFps(fixedFps),
skipResultMetadata(false),
errorBufStrategy(ERROR_BUF_CACHE),
physicalCameraIds(physicalCameraIdSet),
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index 973bc04..4f4e581 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -51,6 +51,7 @@
#include <aidl/android/hardware/camera/device/ICameraInjectionSession.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_ibinder_platform.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include "utils/CameraTraces.h"
@@ -373,7 +374,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
- *this, *(mInterface), mLegacyClient, mMinExpectedDuration}, mResultMetadataQueue
+ *this, *(mInterface), mLegacyClient, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
for (const auto& result : results) {
@@ -414,7 +416,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
- *this, *(mInterface), mLegacyClient, mMinExpectedDuration}, mResultMetadataQueue
+ *this, *(mInterface), mLegacyClient, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
for (const auto& msg : msgs) {
camera3::notify(states, msg);
@@ -671,6 +674,12 @@
return p->returnStreamBuffers(buffers);
}
+::ndk::SpAIBinder AidlCamera3Device::AidlCameraDeviceCallbacks::createBinder() {
+ auto binder = BnCameraDeviceCallback::createBinder();
+ AIBinder_setInheritRt(binder.get(), /*inheritRt*/ true);
+ return binder;
+}
+
::ndk::ScopedAStatus AidlCamera3Device::returnStreamBuffers(
const std::vector<camera::device::StreamBuffer>& buffers) {
ReturnBufferStates states {
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index ecf42b4..ef5bb74 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -243,6 +243,10 @@
::ndk::ScopedAStatus returnStreamBuffers(
const std::vector<
aidl::android::hardware::camera::device::StreamBuffer>& buffers) override;
+
+ protected:
+ ::ndk::SpAIBinder createBinder() override;
+
private:
wp<AidlCamera3Device> mParent = nullptr;
};
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
index 336719d..8ff0b07 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -30,6 +30,7 @@
#include <utils/Trace.h>
#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <android/binder_ibinder_platform.h>
#include "device3/aidl/AidlCamera3OfflineSession.h"
#include "device3/Camera3OutputStream.h"
@@ -123,7 +124,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
- *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration}, mResultMetadataQueue
+ *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
@@ -168,7 +170,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this,
- *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration}, mResultMetadataQueue
+ *this, mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
for (const auto& msg : msgs) {
camera3::notify(states, msg);
@@ -218,6 +221,12 @@
return p->returnStreamBuffers(buffers);
}
+::ndk::SpAIBinder AidlCamera3OfflineSession::AidlCameraDeviceCallbacks::createBinder() {
+ auto binder = BnCameraDeviceCallback::createBinder();
+ AIBinder_setInheritRt(binder.get(), /*inheritRt*/ true);
+ return binder;
+}
+
::ndk::ScopedAStatus AidlCamera3OfflineSession::returnStreamBuffers(
const std::vector<camera::device::StreamBuffer>& buffers) {
{
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
index 33de2c5..d107af6 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
@@ -97,6 +97,10 @@
::ndk::ScopedAStatus returnStreamBuffers(
const std::vector<
aidl::android::hardware::camera::device::StreamBuffer>& buffers) override;
+ protected:
+
+ ::ndk::SpAIBinder createBinder() override;
+
private:
wp<AidlCamera3OfflineSession> mParent = nullptr;
};
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 4bb426c..9557692 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -363,7 +363,7 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient, mMinExpectedDuration}, mResultMetadataQueue
+ *mInterface, mLegacyClient, mMinExpectedDuration, mIsFixedFps}, mResultMetadataQueue
};
//HidlCaptureOutputStates hidlStates {
@@ -425,7 +425,7 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient, mMinExpectedDuration}, mResultMetadataQueue
+ *mInterface, mLegacyClient, mMinExpectedDuration, mIsFixedFps}, mResultMetadataQueue
};
for (const auto& result : results) {
@@ -472,7 +472,7 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient, mMinExpectedDuration}, mResultMetadataQueue
+ *mInterface, mLegacyClient, mMinExpectedDuration, mIsFixedFps}, mResultMetadataQueue
};
for (const auto& msg : msgs) {
camera3::notify(states, msg);
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
index 5c97f0e..2b4f8a1 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -105,7 +105,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration}, mResultMetadataQueue
+ mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
@@ -145,7 +146,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration}, mResultMetadataQueue
+ mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
@@ -180,7 +182,8 @@
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration}, mResultMetadataQueue
+ mBufferRecords, /*legacyClient*/ false, mMinExpectedDuration, mIsFixedFps},
+ mResultMetadataQueue
};
for (const auto& msg : msgs) {
camera3::notify(states, msg);
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 12593ff..b03e418 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -788,15 +788,9 @@
int32_t frameCount = 0;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_FRAMECOUNT, &frameCount);
- std::string inputDevicePairs;
- mAudioAnalytics.mAnalyticsState->timeMachine().get(
- key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
int32_t intervalCount = 0;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_INTERVALCOUNT, &intervalCount);
- std::string outputDevicePairs;
- mAudioAnalytics.mAnalyticsState->timeMachine().get(
- key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
int32_t sampleRate = 0;
mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_SAMPLERATE, &sampleRate);
@@ -804,53 +798,16 @@
mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_FLAGS, &flags);
- // We may have several devices.
- // Accumulate the bit flags for input and output devices.
- std::stringstream oss;
- long_enum_type_t outputDeviceBits{};
- { // compute outputDevices
- const auto devaddrvec = stringutils::getDeviceAddressPairs(outputDevicePairs);
- for (const auto& [device, addr] : devaddrvec) {
- if (oss.tellp() > 0) oss << "|"; // delimit devices with '|'.
- oss << device;
- outputDeviceBits += types::lookup<types::OUTPUT_DEVICE, long_enum_type_t>(device);
- }
- }
- const std::string outputDevices = oss.str();
-
- std::stringstream iss;
- long_enum_type_t inputDeviceBits{};
- { // compute inputDevices
- const auto devaddrvec = stringutils::getDeviceAddressPairs(inputDevicePairs);
- for (const auto& [device, addr] : devaddrvec) {
- if (iss.tellp() > 0) iss << "|"; // delimit devices with '|'.
- iss << device;
- inputDeviceBits += types::lookup<types::INPUT_DEVICE, long_enum_type_t>(device);
- }
- }
- const std::string inputDevices = iss.str();
-
- // Get connected device name if from bluetooth.
- bool isBluetooth = false;
-
- std::string inputDeviceNames; // not filled currently.
- std::string outputDeviceNames;
- if (outputDevices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos) {
- isBluetooth = true;
- outputDeviceNames = SUPPRESSED;
-#if 0 // TODO(b/161554630) sanitize name
- mAudioAnalytics.mAnalyticsState->timeMachine().get(
- "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &outputDeviceNames);
- // Remove | if present
- stringutils::replace(outputDeviceNames, "|", '?');
- if (outputDeviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
- outputDeviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
- }
-#endif
- }
-
switch (itemType) {
case RECORD: {
+ std::string inputDevicePairs;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_INPUTDEVICES, &inputDevicePairs);
+
+ const auto [ inputDeviceStatsd, inputDevices ] =
+ stringutils::parseInputDevicePairs(inputDevicePairs);
+ const std::string inputDeviceNames; // not filled currently.
+
std::string callerName;
const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
@@ -886,7 +843,7 @@
LOG(LOG_LEVEL) << "key:" << key
<< " id:" << id
- << " inputDevices:" << inputDevices << "(" << inputDeviceBits
+ << " inputDevices:" << inputDevices << "(" << inputDeviceStatsd
<< ") inputDeviceNames:" << inputDeviceNames
<< " deviceTimeNs:" << deviceTimeNs
<< " encoding:" << encoding << "(" << encodingForStats
@@ -904,7 +861,7 @@
&& mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
- , ENUM_EXTRACT(inputDeviceBits)
+ , ENUM_EXTRACT(inputDeviceStatsd)
, inputDeviceNames.c_str()
, deviceTimeNs
, ENUM_EXTRACT(encodingForStats)
@@ -933,18 +890,35 @@
key, AMEDIAMETRICS_PROP_UNDERRUN, &underrun);
const bool isInput = types::isInputThreadType(type);
+
+ // get device information
+ std::string devicePairs;
+ std::string deviceStatsd;
+ std::string devices;
+ std::string deviceNames;
+ if (isInput) {
+ // Note we get the "last" device which is the one associated with group.
+ item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_INPUTDEVICES,
+ &devicePairs);
+ std::tie(deviceStatsd, devices) = stringutils::parseInputDevicePairs(devicePairs);
+ } else {
+ // Note we get the "last" device which is the one associated with group.
+ item->get(AMEDIAMETRICS_PROP_PREFIX_LAST AMEDIAMETRICS_PROP_OUTPUTDEVICES,
+ &devicePairs);
+ std::tie(deviceStatsd, devices) = stringutils::parseOutputDevicePairs(devicePairs);
+ deviceNames = mAudioAnalytics.getDeviceNamesFromOutputDevices(devices);
+ }
+
const auto encodingForStats = types::lookup<types::ENCODING, short_enum_type_t>(encoding);
const auto flagsForStats =
(isInput ? types::lookup<types::INPUT_FLAG, short_enum_type_t>(flags)
: types::lookup<types::OUTPUT_FLAG, short_enum_type_t>(flags));
const auto typeForStats = types::lookup<types::THREAD_TYPE, short_enum_type_t>(type);
- LOG(LOG_LEVEL) << "key:" << key
+ LOG(LOG_LEVEL) << "key:" << key
<< " id:" << id
- << " inputDevices:" << inputDevices << "(" << inputDeviceBits
- << ") outputDevices:" << outputDevices << "(" << outputDeviceBits
- << ") inputDeviceNames:" << inputDeviceNames
- << " outputDeviceNames:" << outputDeviceNames
+ << " devices:" << devices << "(" << deviceStatsd
+ << ") deviceNames:" << deviceNames
<< " deviceTimeNs:" << deviceTimeNs
<< " encoding:" << encoding << "(" << encodingForStats
<< ") frameCount:" << frameCount
@@ -957,8 +931,8 @@
if (mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
- , isInput ? ENUM_EXTRACT(inputDeviceBits) : ENUM_EXTRACT(outputDeviceBits)
- , isInput ? inputDeviceNames.c_str() : outputDeviceNames.c_str()
+ , ENUM_EXTRACT(deviceStatsd)
+ , deviceNames.c_str()
, deviceTimeNs
, ENUM_EXTRACT(encodingForStats)
, frameCount
@@ -974,6 +948,15 @@
}
} break;
case TRACK: {
+ std::string outputDevicePairs;
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ key, AMEDIAMETRICS_PROP_OUTPUTDEVICES, &outputDevicePairs);
+
+ const auto [ outputDeviceStatsd, outputDevices ] =
+ stringutils::parseOutputDevicePairs(outputDevicePairs);
+ const std::string outputDeviceNames =
+ mAudioAnalytics.getDeviceNamesFromOutputDevices(outputDevices);
+
std::string callerName;
const bool clientCalled = mAudioAnalytics.mAnalyticsState->timeMachine().get(
key, AMEDIAMETRICS_PROP_CALLERNAME, &callerName) == OK;
@@ -1041,7 +1024,7 @@
LOG(LOG_LEVEL) << "key:" << key
<< " id:" << id
- << " outputDevices:" << outputDevices << "(" << outputDeviceBits
+ << " outputDevices:" << outputDevices << "(" << outputDeviceStatsd
<< ") outputDeviceNames:" << outputDeviceNames
<< " deviceTimeNs:" << deviceTimeNs
<< " encoding:" << encoding << "(" << encodingForStats
@@ -1068,7 +1051,7 @@
&& mAudioAnalytics.mDeliverStatistics) {
const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
- , ENUM_EXTRACT(outputDeviceBits)
+ , ENUM_EXTRACT(outputDeviceStatsd)
, outputDeviceNames.c_str()
, deviceTimeNs
, ENUM_EXTRACT(encodingForStats)
@@ -1095,11 +1078,6 @@
}
} break;
}
-
- // Report this as needed.
- if (isBluetooth) {
- // report this for Bluetooth
- }
}
// DeviceConnection helper class.
@@ -1732,4 +1710,22 @@
return { s, n };
}
+// This method currently suppresses the name.
+std::string AudioAnalytics::getDeviceNamesFromOutputDevices(std::string_view devices) const {
+ std::string deviceNames;
+ if (stringutils::hasBluetoothOutputDevice(devices)) {
+ deviceNames = SUPPRESSED;
+#if 0 // TODO(b/161554630) sanitize name
+ mAudioAnalytics.mAnalyticsState->timeMachine().get(
+ "audio.device.bt_a2dp", AMEDIAMETRICS_PROP_NAME, &deviceNames);
+ // Remove | if present
+ stringutils::replace(deviceNames, "|", '?');
+ if (deviceNames.size() > STATSD_DEVICE_NAME_MAX_LENGTH) {
+ deviceNames.resize(STATSD_DEVICE_NAME_MAX_LENGTH); // truncate
+ }
+#endif
+ }
+ return deviceNames;
+}
+
} // namespace android::mediametrics
diff --git a/services/mediametrics/StringUtils.cpp b/services/mediametrics/StringUtils.cpp
index 50525bc..d1c7a18 100644
--- a/services/mediametrics/StringUtils.cpp
+++ b/services/mediametrics/StringUtils.cpp
@@ -20,6 +20,8 @@
#include "StringUtils.h"
+#include "AudioTypes.h"
+
namespace android::mediametrics::stringutils {
std::string tokenizer(std::string::const_iterator& it,
@@ -99,4 +101,30 @@
return replaced;
}
+template <types::AudioEnumCategory CATEGORY>
+std::pair<std::string /* external statsd */, std::string /* internal */>
+parseDevicePairs(const std::string& devicePairs) {
+ std::pair<std::string, std::string> result{};
+ const auto devaddrvec = stringutils::getDeviceAddressPairs(devicePairs);
+ for (const auto& [device, addr] : devaddrvec) { // addr ignored for now.
+ if (!result.second.empty()) {
+ result.second.append("|"); // delimit devices with '|'.
+ result.first.append("|");
+ }
+ result.second.append(device);
+ result.first.append(types::lookup<CATEGORY, std::string>(device));
+ }
+ return result;
+}
+
+std::pair<std::string /* external statsd */, std::string /* internal */>
+parseOutputDevicePairs(const std::string& devicePairs) {
+ return parseDevicePairs<types::OUTPUT_DEVICE>(devicePairs);
+}
+
+std::pair<std::string /* external statsd */, std::string /* internal */>
+parseInputDevicePairs(const std::string& devicePairs) {
+ return parseDevicePairs<types::INPUT_DEVICE>(devicePairs);
+}
+
} // namespace android::mediametrics::stringutils
diff --git a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
index 7000ba8..82e928e 100644
--- a/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
+++ b/services/mediametrics/include/mediametricsservice/AudioAnalytics.h
@@ -161,6 +161,13 @@
*/
std::string getThreadFromTrack(const std::string& track) const;
+ /**
+ * return the device name, if present.
+ *
+ * This is currently enabled only for Bluetooth output devices.
+ */
+ std::string getDeviceNamesFromOutputDevices(std::string_view devices) const;
+
const bool mDeliverStatistics;
// Actions is individually locked
diff --git a/services/mediametrics/include/mediametricsservice/StringUtils.h b/services/mediametrics/include/mediametricsservice/StringUtils.h
index a91d37b..78c25ff 100644
--- a/services/mediametrics/include/mediametricsservice/StringUtils.h
+++ b/services/mediametrics/include/mediametricsservice/StringUtils.h
@@ -217,4 +217,14 @@
return { key, "" };
}
+std::pair<std::string /* external statsd */, std::string /* internal */>
+parseOutputDevicePairs(const std::string& outputDevicePairs);
+
+std::pair<std::string /* external statsd */, std::string /* internal */>
+parseInputDevicePairs(const std::string& inputDevicePairs);
+
+inline bool hasBluetoothOutputDevice(std::string_view devices) {
+ return devices.find("AUDIO_DEVICE_OUT_BLUETOOTH") != std::string::npos;
+}
+
} // namespace android::mediametrics::stringutils
diff --git a/tools/OWNERS b/tools/OWNERS
new file mode 100644
index 0000000..7598c6f
--- /dev/null
+++ b/tools/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1344
+essick@google.com
+
+# reliability builds mainline trains, so needs to manage these scripts
+include platform/frameworks/av/:/media/janitors/reliability_mainline_OWNERS
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index bd82315..cd3e579 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index cb5fc44..1cc3b2b 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -17,7 +17,7 @@
# tunables
DEV_BRANCH=master
-MAINLINE_BRANCH=sc-mainline-prod
+MAINLINE_BRANCH=tm-mainline-prod
###
RED=$(tput setaf 1)