Merge "AudioTrack: Clean up ctor initialization" into main
diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp
index 057ec99..450bdd8 100644
--- a/camera/CameraSessionStats.cpp
+++ b/camera/CameraSessionStats.cpp
@@ -439,6 +439,16 @@
return err;
}
+ auto mostRequestedFpsRange = std::make_pair(0,0);
+ if ((err = parcel->readInt32(&mostRequestedFpsRange.first)) != OK) {
+ ALOGE("%s: Failed to read frame rate range min info!", __FUNCTION__);
+ return err;
+ }
+ if ((err = parcel->readInt32(&mostRequestedFpsRange.second)) != OK) {
+ ALOGE("%s: Failed to read frame rate range max info!", __FUNCTION__);
+ return err;
+ }
+
mCameraId = toStdString(id);
mFacing = facing;
mNewCameraState = newCameraState;
@@ -460,6 +470,7 @@
mUsedZoomOverride = usedZoomOverride;
mSessionIndex = sessionIdx;
mCameraExtensionSessionStats = extStats;
+ mMostRequestedFpsRange = mostRequestedFpsRange;
return OK;
}
@@ -577,6 +588,16 @@
return err;
}
+ if ((err = parcel->writeInt32(mMostRequestedFpsRange.first)) != OK) {
+ ALOGE("%s: Failed to write frame rate range min info!", __FUNCTION__);
+ return err;
+ }
+
+ if ((err = parcel->writeInt32(mMostRequestedFpsRange.second)) != OK) {
+ ALOGE("%s: Failed to write frame rate range max info!", __FUNCTION__);
+ return err;
+ }
+
return OK;
}
diff --git a/camera/camera_platform.aconfig b/camera/camera_platform.aconfig
index 18543d6..4fcceae 100644
--- a/camera/camera_platform.aconfig
+++ b/camera/camera_platform.aconfig
@@ -210,3 +210,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ namespace: "camera_platform"
+ name: "analytics_24q3"
+ description: "Miscellaneous camera platform metrics for 24Q3"
+ bug: "332557570"
+}
diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h
index 06c154d..34ee882 100644
--- a/camera/include/camera/CameraSessionStats.h
+++ b/camera/include/camera/CameraSessionStats.h
@@ -167,6 +167,8 @@
CameraExtensionSessionStats mCameraExtensionSessionStats;
+ std::pair<int32_t, int32_t> mMostRequestedFpsRange;
+
// Constructors
CameraSessionStats();
CameraSessionStats(const std::string& cameraId, int facing, int newCameraState,
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 2137964..fd9488b 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -469,11 +469,12 @@
mInitialized = false;
}
+ bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
+
if (!mInitialized) {
uint8_t *vol_data[1]{};
int32_t vol_size = 0;
- bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
if (codecConfig || volHeader) {
vol_data[0] = bitstream;
vol_size = inSize;
@@ -512,10 +513,11 @@
return;
}
}
- if (codecConfig) {
- fillEmptyWork(work);
- return;
- }
+ }
+
+ if (codecConfig) {
+ fillEmptyWork(work);
+ return;
}
size_t inPos = 0;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index cdc3be0..40bb26e 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -29,7 +29,6 @@
#include <opus_multistream.h>
}
-#define DEFAULT_FRAME_DURATION_MS 20
namespace android {
namespace {
@@ -38,7 +37,6 @@
} // namespace
-static const int kMaxNumChannelsSupported = 2;
class C2SoftOpusEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
public:
@@ -248,10 +246,11 @@
mAnchorTimeStamp = 0;
mProcessedSamples = 0;
mFilledLen = 0;
- mFrameDurationMs = DEFAULT_FRAME_DURATION_MS;
+ mFrameDurationMs = kDefaultFrameDurationMs;
if (!mInputBufferPcm16) {
+ size_t frameSize = (mFrameDurationMs * kMaxSampleRateSupported) / 1000;
mInputBufferPcm16 =
- (int16_t*)malloc(kFrameSize * kMaxNumChannels * sizeof(int16_t));
+ (int16_t*)malloc(frameSize * kMaxNumChannelsSupported * sizeof(int16_t));
}
if (!mInputBufferPcm16) return C2_NO_MEMORY;
@@ -368,7 +367,9 @@
}
C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
- err = pool->fetchLinearBlock(kMaxPayload, usage, &mOutputBlock);
+ int outCapacity =
+ kMaxPayload * ((inSize + mNumPcmBytesPerInputFrame) / mNumPcmBytesPerInputFrame);
+ err = pool->fetchLinearBlock(outCapacity, usage, &mOutputBlock);
if (err != C2_OK) {
ALOGE("fetchLinearBlock for Output failed with status %d", err);
work->result = C2_NO_MEMORY;
@@ -497,11 +498,11 @@
uint8_t* outPtr = wView.data() + mBytesEncoded;
int encodedBytes =
opus_multistream_encode(mEncoder, mInputBufferPcm16,
- mNumSamplesPerFrame, outPtr, kMaxPayload - mBytesEncoded);
+ mNumSamplesPerFrame, outPtr, outCapacity - mBytesEncoded);
ALOGV("encoded %i Opus bytes from %zu PCM bytes", encodedBytes,
processSize);
- if (encodedBytes < 0 || encodedBytes > (kMaxPayload - mBytesEncoded)) {
+ if (encodedBytes < 0 || encodedBytes > (outCapacity - mBytesEncoded)) {
ALOGE("opus_encode failed, encodedBytes : %d", encodedBytes);
mSignalledError = true;
work->result = C2_CORRUPTED;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.h b/media/codec2/components/opus/C2SoftOpusEnc.h
index 733a6bc..2c9f5e5 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.h
+++ b/media/codec2/components/opus/C2SoftOpusEnc.h
@@ -45,12 +45,13 @@
uint32_t drainMode,
const std::shared_ptr<C2BlockPool> &pool) override;
private:
- /* OPUS_FRAMESIZE_20_MS */
- const int kFrameSize = 960;
- const int kMaxSampleRate = 48000;
- const int kMinSampleRate = 8000;
- const int kMaxPayload = (4000 * kMaxSampleRate) / kMinSampleRate;
- const int kMaxNumChannels = 8;
+ static const int kMaxNumChannelsSupported = 2;
+ static const int kMaxSampleRateSupported = 48000;
+ static const int kDefaultFrameDurationMs = 20;
+ // For a frame duration of 20ms, payload recommended size is 1276 as per
+ // https://www.opus-codec.org/docs/html_api/group__opusencoder.html.
+ // For 40ms, 60ms, .. payload size will change proportionately, 1276 x 2, 1276 x 3, ..
+ static const int kMaxPayload = 1500; // from tests/test_opus_encode.c
std::shared_ptr<IntfImpl> mIntf;
std::shared_ptr<C2LinearBlock> mOutputBlock;
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index 01b0678..1c2a0fb 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -563,6 +563,8 @@
auto mapRet = mDequeued.emplace(bid, *pBuffer);
CHECK(mapRet.second);
} else {
+ ALOGD("allocate error(%d): Dequeued(%zu), Dequeuable(%d)",
+ (int)res, mDequeued.size(), mDequeueable + 1);
if (adjustDequeueConfLocked(updateDequeue)) {
return;
}
@@ -629,7 +631,11 @@
::android::status_t status = igbp->dequeueBuffer(
&slotId, &fence, width, height, format, usage, &outBufferAge, &outTimestamps);
if (status < ::android::OK) {
- ALOGE("dequeueBuffer() error %d", (int)status);
+ if (status == ::android::TIMED_OUT || status == ::android::WOULD_BLOCK) {
+ ALOGW("BQ might not be ready for dequeueBuffer()");
+ return C2_BLOCKING;
+ }
+ ALOGE("BQ in inconsistent status. dequeueBuffer() error %d", (int)status);
return C2_CORRUPTED;
}
cache->waitOnSlot(slotId);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 1a25ff9..3e1245b 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1425,144 +1425,13 @@
if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
return BAD_VALUE;
}
- if (args.size() >= 3 && args[0] == String16("set-uid-state")) {
- return handleSetUidState(args, err);
- } else if (args.size() >= 2 && args[0] == String16("reset-uid-state")) {
- return handleResetUidState(args, err);
- } else if (args.size() >= 2 && args[0] == String16("get-uid-state")) {
- return handleGetUidState(args, out, err);
- } else if (args.size() >= 1 && args[0] == String16("purge_permission-cache")) {
+ if (args.size() >= 1 && args[0] == String16("purge_permission-cache")) {
purgePermissionCache();
return NO_ERROR;
- } else if (args.size() == 1 && args[0] == String16("help")) {
- printHelp(out);
- return NO_ERROR;
}
- printHelp(err);
return BAD_VALUE;
}
-static status_t getUidForPackage(String16 packageName, int userId, /*inout*/uid_t& uid, int err) {
- if (userId < 0) {
- ALOGE("Invalid user: %d", userId);
- dprintf(err, "Invalid user: %d\n", userId);
- return BAD_VALUE;
- }
-
- PermissionController pc;
- uid = pc.getPackageUid(packageName, 0);
- if (uid <= 0) {
- ALOGE("Unknown package: '%s'", String8(packageName).c_str());
- dprintf(err, "Unknown package: '%s'\n", String8(packageName).c_str());
- return BAD_VALUE;
- }
-
- uid = multiuser_get_uid(userId, uid);
- return NO_ERROR;
-}
-
-status_t AudioPolicyService::handleSetUidState(Vector<String16>& args, int err) {
- // Valid arg.size() is 3 or 5, args.size() is 5 with --user option.
- if (!(args.size() == 3 || args.size() == 5)) {
- printHelp(err);
- return BAD_VALUE;
- }
-
- bool active = false;
- if (args[2] == String16("active")) {
- active = true;
- } else if ((args[2] != String16("idle"))) {
- ALOGE("Expected active or idle but got: '%s'", String8(args[2]).c_str());
- return BAD_VALUE;
- }
-
- int userId = 0;
- if (args.size() >= 5 && args[3] == String16("--user")) {
- userId = atoi(String8(args[4]));
- }
-
- uid_t uid;
- if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
- return BAD_VALUE;
- }
-
- sp<UidPolicy> uidPolicy;
- {
- audio_utils::lock_guard _l(mMutex);
- uidPolicy = mUidPolicy;
- }
- if (uidPolicy) {
- uidPolicy->addOverrideUid(uid, active);
- return NO_ERROR;
- }
- return NO_INIT;
-}
-
-status_t AudioPolicyService::handleResetUidState(Vector<String16>& args, int err) {
- // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
- if (!(args.size() == 2 || args.size() == 4)) {
- printHelp(err);
- return BAD_VALUE;
- }
-
- int userId = 0;
- if (args.size() >= 4 && args[2] == String16("--user")) {
- userId = atoi(String8(args[3]));
- }
-
- uid_t uid;
- if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
- return BAD_VALUE;
- }
-
- sp<UidPolicy> uidPolicy;
- {
- audio_utils::lock_guard _l(mMutex);
- uidPolicy = mUidPolicy;
- }
- if (uidPolicy) {
- uidPolicy->removeOverrideUid(uid);
- return NO_ERROR;
- }
- return NO_INIT;
-}
-
-status_t AudioPolicyService::handleGetUidState(Vector<String16>& args, int out, int err) {
- // Valid arg.size() is 2 or 4, args.size() is 4 with --user option.
- if (!(args.size() == 2 || args.size() == 4)) {
- printHelp(err);
- return BAD_VALUE;
- }
-
- int userId = 0;
- if (args.size() >= 4 && args[2] == String16("--user")) {
- userId = atoi(String8(args[3]));
- }
-
- uid_t uid;
- if (getUidForPackage(args[1], userId, uid, err) == BAD_VALUE) {
- return BAD_VALUE;
- }
-
- sp<UidPolicy> uidPolicy;
- {
- audio_utils::lock_guard _l(mMutex);
- uidPolicy = mUidPolicy;
- }
- if (uidPolicy) {
- return dprintf(out, uidPolicy->isUidActive(uid) ? "active\n" : "idle\n");
- }
- return NO_INIT;
-}
-
-status_t AudioPolicyService::printHelp(int out) {
- return dprintf(out, "Audio policy service commands:\n"
- " get-uid-state <PACKAGE> [--user USER_ID] gets the uid state\n"
- " set-uid-state <PACKAGE> <active|idle> [--user USER_ID] overrides the uid state\n"
- " reset-uid-state <PACKAGE> [--user USER_ID] clears the uid state override\n"
- " help print this message\n");
-}
-
status_t AudioPolicyService::registerOutput(audio_io_handle_t output,
const audio_config_base_t& config,
const audio_output_flags_t flags) {
@@ -1623,10 +1492,6 @@
checkRegistered();
{
audio_utils::lock_guard _l(mMutex);
- auto overrideIter = mOverrideUids.find(uid);
- if (overrideIter != mOverrideUids.end()) {
- return overrideIter->second.first;
- }
// In an absense of the ActivityManager, assume everything to be active.
if (!mObserverRegistered) return true;
auto cacheIter = mCachedUids.find(uid);
@@ -1652,20 +1517,6 @@
checkRegistered();
{
audio_utils::lock_guard _l(mMutex);
- auto overrideIter = mOverrideUids.find(uid);
- if (overrideIter != mOverrideUids.end()) {
- if (overrideIter->second.first) {
- if (overrideIter->second.second != ActivityManager::PROCESS_STATE_UNKNOWN) {
- return overrideIter->second.second;
- } else {
- auto cacheIter = mCachedUids.find(uid);
- if (cacheIter != mCachedUids.end()) {
- return cacheIter->second.second;
- }
- }
- }
- return ActivityManager::PROCESS_STATE_UNKNOWN;
- }
// In an absense of the ActivityManager, assume everything to be active.
if (!mObserverRegistered) {
return ActivityManager::PROCESS_STATE_TOP;
@@ -1718,10 +1569,6 @@
void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {
}
-void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
- updateUid(&mOverrideUids, uid, active, ActivityManager::PROCESS_STATE_UNKNOWN, insert);
-}
-
void AudioPolicyService::UidPolicy::notifyService() {
sp<AudioPolicyService> service = mService.promote();
if (service != nullptr) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 7aa80cf..5297e47 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -500,8 +500,6 @@
int32_t capability) override;
void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
- void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
- void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
void updateUid(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
uid_t uid, bool active, int state, bool insert);
@@ -510,7 +508,6 @@
private:
void notifyService();
- void updateOverrideUid(uid_t uid, bool active, bool insert);
void updateUidLocked(std::unordered_map<uid_t, std::pair<bool, int>> *uids,
uid_t uid, bool active, int state, bool insert);
void checkRegistered();
@@ -519,7 +516,6 @@
audio_utils::mutex mMutex{audio_utils::MutexOrder::kUidPolicy_Mutex};
ActivityManager mAm;
bool mObserverRegistered = false;
- std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids GUARDED_BY(mMutex);
std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids GUARDED_BY(mMutex);
std::vector<uid_t> mAssistantUids;
std::vector<uid_t> mActiveAssistantUids;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index ee30e46..daaeae6 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -194,7 +194,6 @@
"utils/SchedulingPolicyUtils.cpp",
"utils/SessionConfigurationUtils.cpp",
"utils/SessionConfigurationUtilsHidl.cpp",
- "utils/SessionStatsBuilder.cpp",
"utils/TagMonitor.cpp",
"utils/LatencyHistogram.cpp",
"utils/Utils.cpp",
@@ -246,6 +245,7 @@
"device3/ZoomRatioMapper.cpp",
"utils/ExifUtils.cpp",
"utils/SessionConfigurationUtilsHost.cpp",
+ "utils/SessionStatsBuilder.cpp",
],
header_libs: [
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 9513eeb..105d04f 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -537,27 +537,28 @@
// Save certain CaptureRequest settings
if (!request.mUserTag.empty()) {
- mUserTag = request.mUserTag;
+ mRunningSessionStats.mUserTag = request.mUserTag;
}
camera_metadata_entry entry =
physicalSettingsList.begin()->metadata.find(
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE);
if (entry.count == 1) {
- mVideoStabilizationMode = entry.data.u8[0];
+ mRunningSessionStats.mVideoStabilizationMode = entry.data.u8[0];
}
- if (flags::log_ultrawide_usage()) {
+
+ if (!mRunningSessionStats.mUsedUltraWide && flags::log_ultrawide_usage()) {
entry = physicalSettingsList.begin()->metadata.find(
ANDROID_CONTROL_ZOOM_RATIO);
if (entry.count == 1 && entry.data.f[0] < 1.0f ) {
- mUsedUltraWide = true;
+ mRunningSessionStats.mUsedUltraWide = true;
}
}
- if (!mUsedSettingsOverrideZoom && flags::log_zoom_override_usage()) {
+ if (!mRunningSessionStats.mUsedSettingsOverrideZoom && flags::log_zoom_override_usage()) {
entry = physicalSettingsList.begin()->metadata.find(
ANDROID_CONTROL_SETTINGS_OVERRIDE);
if (entry.count == 1 && entry.data.i32[0] ==
ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM) {
- mUsedSettingsOverrideZoom = true;
+ mRunningSessionStats.mUsedSettingsOverrideZoom = true;
}
}
}
@@ -2064,6 +2065,7 @@
void CameraDeviceClient::notifyIdle(
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats) {
// Thread safe. Don't bother locking.
sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
@@ -2084,8 +2086,12 @@
}
}
Camera2ClientBase::notifyIdleWithUserTag(requestCount, resultErrorCount, deviceError,
- fullStreamStats, mUserTag, mVideoStabilizationMode, mUsedUltraWide,
- mUsedSettingsOverrideZoom);
+ mostRequestedFpsRange,
+ fullStreamStats,
+ mRunningSessionStats.mUserTag,
+ mRunningSessionStats.mVideoStabilizationMode,
+ mRunningSessionStats.mUsedUltraWide,
+ mRunningSessionStats.mUsedSettingsOverrideZoom);
}
void CameraDeviceClient::notifyShutter(const CaptureResultExtras& resultExtras,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index d93eaff..505c086 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -229,6 +229,7 @@
*/
virtual void notifyIdle(int64_t requestCount, int64_t resultErrorCount, bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats);
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras& resultExtras);
@@ -364,14 +365,17 @@
// Override the camera characteristics for performance class primary cameras.
bool mOverrideForPerfClass;
- // The string representation of object passed into CaptureRequest.setTag.
- std::string mUserTag;
- // The last set video stabilization mode
- int mVideoStabilizationMode = -1;
- // Whether a zoom_ratio < 1.0 has been used during this session
- bool mUsedUltraWide = false;
- // Whether a zoom settings override has been used during this session
- bool mUsedSettingsOverrideZoom = false;
+ // Various fields used to collect session statistics
+ struct RunningSessionStats {
+ // The string representation of object passed into CaptureRequest.setTag.
+ std::string mUserTag;
+ // The last set video stabilization mode
+ int mVideoStabilizationMode = -1;
+ // Whether a zoom_ratio < 1.0 has been used during this session
+ bool mUsedUltraWide = false;
+ // Whether a zoom settings override has been used during this session
+ bool mUsedSettingsOverrideZoom = false;
+ } mRunningSessionStats;
// This only exists in case of camera ID Remapping.
const std::string mOriginalCameraId;
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 93564ac..9a1fdd6 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -325,6 +325,7 @@
void CameraOfflineSessionClient::notifyIdle(
int64_t /*requestCount*/, int64_t /*resultErrorCount*/, bool /*deviceError*/,
+ std::pair<int32_t, int32_t> /*mostRequestedFpsRange*/,
const std::vector<hardware::CameraStreamStats>& /*streamStats*/) {
if (mRemoteCallback.get() != nullptr) {
mRemoteCallback->onDeviceIdle();
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index c6f3e06..82c3d6d 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -112,6 +112,7 @@
void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
status_t notifyActive(float maxPreviewFps) override;
void notifyIdle(int64_t requestCount, int64_t resultErrorCount, bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats) override;
void notifyAutoFocus(uint8_t newState, int triggerId) override;
void notifyAutoExposure(uint8_t newState, int triggerId) override;
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
index 988446b..a1b9383 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
@@ -856,8 +856,9 @@
bool deviceError;
std::map<int, StreamStats> stats;
+ std::pair<int32_t, int32_t> mostRequestedFps;
mSessionStatsBuilder.buildAndReset(&streamStats->mRequestCount, &streamStats->mErrorCount,
- &deviceError, &stats);
+ &deviceError, &mostRequestedFps, &stats);
if (stats.find(mP010StreamId) != stats.end()) {
streamStats->mWidth = mBlobWidth;
streamStats->mHeight = mBlobHeight;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 92309c3..2239c9f 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -380,6 +380,7 @@
template <typename TClientBase>
void Camera2ClientBase<TClientBase>::notifyIdleWithUserTag(
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats,
const std::string& userTag, int videoStabilizationMode, bool usedUltraWide,
bool usedZoomOverride) {
@@ -391,7 +392,7 @@
}
mCameraServiceProxyWrapper->logIdle(TClientBase::mCameraIdStr,
requestCount, resultErrorCount, deviceError, userTag, videoStabilizationMode,
- usedUltraWide, usedZoomOverride, streamStats);
+ usedUltraWide, usedZoomOverride, mostRequestedFpsRange, streamStats);
}
mDeviceActive = false;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index b8a6d8b..c24f92b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -86,6 +86,7 @@
virtual status_t notifyActive(float maxPreviewFps);
virtual void notifyIdle(int64_t /*requestCount*/, int64_t /*resultErrorCount*/,
bool /*deviceError*/,
+ std::pair<int32_t, int32_t> /*mostRequestedFpsRange*/,
const std::vector<hardware::CameraStreamStats>&) {}
virtual void notifyShutter(const CaptureResultExtras& resultExtras,
nsecs_t timestamp);
@@ -99,6 +100,7 @@
void notifyIdleWithUserTag(int64_t requestCount, int64_t resultErrorCount,
bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats,
const std::string& userTag, int videoStabilizationMode,
bool usedUltraWide, bool usedZoomOverride);
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
index 976c47c..b1ba761 100644
--- a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
@@ -46,6 +46,7 @@
// May return an error since it checks appops
virtual status_t notifyActive(float maxPreviewFps) = 0;
virtual void notifyIdle(int64_t requestCount, int64_t resultError, bool deviceError,
+ std::pair<int32_t, int32_t> mostRequestedFpsRange,
const std::vector<hardware::CameraStreamStats>& streamStats) = 0;
// Required only for API2
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 1bf0e66..f4d8f7f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1965,9 +1965,10 @@
// Get session stats from the builder, and notify the listener.
int64_t requestCount, resultErrorCount;
bool deviceError;
+ std::pair<int32_t, int32_t> mostRequestedFpsRange;
std::map<int, StreamStats> streamStatsMap;
mSessionStatsBuilder.buildAndReset(&requestCount, &resultErrorCount,
- &deviceError, &streamStatsMap);
+ &deviceError, &mostRequestedFpsRange, &streamStatsMap);
for (size_t i = 0; i < streamIds.size(); i++) {
int streamId = streamIds[i];
auto stats = streamStatsMap.find(streamId);
@@ -1985,7 +1986,8 @@
stats->second.mCaptureLatencyHistogram.end());
}
}
- listener->notifyIdle(requestCount, resultErrorCount, deviceError, streamStats);
+ listener->notifyIdle(requestCount, resultErrorCount, deviceError,
+ mostRequestedFpsRange, streamStats);
} else {
res = listener->notifyActive(sessionMaxPreviewFps);
}
@@ -2969,6 +2971,16 @@
physicalMetadata, outputBuffers, numOutputBuffers, inputStreamId);
}
+void Camera3Device::collectRequestStats(int64_t frameNumber, const CameraMetadata &request) {
+ if (flags::analytics_24q3()) {
+ auto entry = request.find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
+ if (entry.count >= 2) {
+ mSessionStatsBuilder.incFpsRequestedCount(
+ entry.data.i32[0], entry.data.i32[1], frameNumber);
+ }
+ }
+}
+
void Camera3Device::cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd) {
if (handles == nullptr) {
@@ -3509,7 +3521,8 @@
void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
// Update the latest request sent to HAL
camera_capture_request_t& halRequest = nextRequest.halRequest;
- if (halRequest.settings != NULL) { // Don't update if they were unchanged
+ sp<Camera3Device> parent = mParent.promote();
+ if (halRequest.settings != nullptr) { // Don't update if they were unchanged
Mutex::Autolock al(mLatestRequestMutex);
camera_metadata_t* cloned = clone_camera_metadata(halRequest.settings);
@@ -3522,8 +3535,7 @@
CameraMetadata(cloned));
}
- sp<Camera3Device> parent = mParent.promote();
- if (parent != NULL) {
+ if (parent != nullptr) {
int32_t inputStreamId = -1;
if (halRequest.input_buffer != nullptr) {
inputStreamId = Camera3Stream::cast(halRequest.input_buffer->stream)->getId();
@@ -3535,8 +3547,11 @@
halRequest.num_output_buffers, inputStreamId);
}
}
+ if (parent != nullptr) {
+ parent->collectRequestStats(halRequest.frame_number, mLatestRequest);
+ }
- if (halRequest.settings != NULL) {
+ if (halRequest.settings != nullptr) {
nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
halRequest.settings);
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 42fa8f1..d646886 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1404,6 +1404,10 @@
const camera_stream_buffer_t *outputBuffers, uint32_t numOutputBuffers,
int32_t inputStreamId);
+ // Collect any statistics that are based on the stream of capture requests sent
+ // to the HAL
+ void collectRequestStats(int64_t frameNumber, const CameraMetadata& request);
+
metadata_vendor_id_t mVendorTagId;
// Cached last requested template id
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index 5072edd..55e2c9d 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -18,6 +18,49 @@
],
}
+cc_defaults {
+ name: "cameraservice_test_hostsupported",
+
+ // All test sources that can run on both host and device
+ // should be listed here
+ srcs: [
+ "ClientManagerTest.cpp",
+ "DepthProcessorTest.cpp",
+ "DistortionMapperTest.cpp",
+ "ExifUtilsTest.cpp",
+ "NV12Compressor.cpp",
+ "RotateAndCropMapperTest.cpp",
+ "SessionStatsBuilderTest.cpp",
+ "ZoomRatioTest.cpp",
+ ],
+
+ // All shared libs available on both host and device
+ // should be listed here
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcamera_metadata",
+ "libexif",
+ "libjpeg",
+ "liblog",
+ "libutils",
+ "camera_platform_flags_c_lib",
+ ],
+
+ static_libs: [
+ "libgmock",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
+ test_suites: ["device-tests"],
+
+}
+
cc_test {
name: "cameraservice_test",
@@ -33,20 +76,15 @@
defaults: [
"libcameraservice_deps",
+ "cameraservice_test_hostsupported"
],
+ // Only include libs that can't be run host-side here
shared_libs: [
- "libbase",
- "libbinder",
"libcutils",
"libhidlbase",
- "liblog",
"libcamera_client",
- "libcamera_metadata",
"libui",
- "libutils",
- "libjpeg",
- "libexif",
"android.companion.virtualdevice.flags-aconfig-cc",
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
@@ -57,6 +95,7 @@
"camera_platform_flags_c_lib",
],
+ // Only include libs that can't be run host-side here
static_libs: [
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
@@ -64,76 +103,40 @@
"android.hardware.camera.provider@2.7",
"android.hardware.camera.provider-V3-ndk",
"libcameraservice",
- "libgmock",
"libflagtest",
],
+ // Only include sources that can't be run host-side here
srcs: [
"CameraPermissionsTest.cpp",
"CameraProviderManagerTest.cpp",
- "ClientManagerTest.cpp",
- "DepthProcessorTest.cpp",
- "DistortionMapperTest.cpp",
- "ExifUtilsTest.cpp",
- "NV12Compressor.cpp",
- "RotateAndCropMapperTest.cpp",
- "ZoomRatioTest.cpp",
],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- ],
-
- test_suites: ["device-tests"],
-
}
cc_test_host {
name: "cameraservice_test_host",
+ defaults: [
+ "cameraservice_test_hostsupported"
+ ],
+
include_dirs: [
"frameworks/av/camera/include",
"frameworks/av/camera/include/camera",
"frameworks/native/libs/binder/include_activitymanager"
],
+ // Only include libs that can't be run device-side here
shared_libs: [
"libactivity_manager_procstate_aidl-cpp",
- "libbase",
- "libbinder",
- "libcamera_metadata",
"libdynamic_depth",
- "libexif",
- "libjpeg",
- "liblog",
- "libutils",
- "camera_platform_flags_c_lib",
],
+ // Only include libs that can't be run device-side here
static_libs: [
"libcamera_client_host",
"libcameraservice_device_independent",
- "libgmock",
],
- srcs: [
- "ClientManagerTest.cpp",
- "DepthProcessorTest.cpp",
- "DistortionMapperTest.cpp",
- "ExifUtilsTest.cpp",
- "NV12Compressor.cpp",
- "RotateAndCropMapperTest.cpp",
- "ZoomRatioTest.cpp",
- ],
-
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- ],
-
- test_suites: ["device-tests"],
-
}
diff --git a/services/camera/libcameraservice/tests/SessionStatsBuilderTest.cpp b/services/camera/libcameraservice/tests/SessionStatsBuilderTest.cpp
new file mode 100644
index 0000000..3644358
--- /dev/null
+++ b/services/camera/libcameraservice/tests/SessionStatsBuilderTest.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SessionStatsBuilderTest"
+
+#include <gtest/gtest.h>
+#include <utils/Errors.h>
+
+#include "../utils/SessionStatsBuilder.h"
+
+using namespace std;
+using namespace android;
+
+TEST(SessionStatsBuilderTest, FpsHistogramTest) {
+ SessionStatsBuilder b{};
+
+ int64_t requestCount, resultErrorCount;
+ bool deviceError;
+ pair<int32_t, int32_t> mostRequestedFpsRange;
+ map<int, StreamStats> streamStatsMap;
+
+ // Verify we get the most common FPS
+ int64_t fc = 0;
+ for (size_t i = 0; i < 10; i++, fc++) b.incFpsRequestedCount(30, 30, fc);
+ for (size_t i = 0; i < 15; i++, fc++) b.incFpsRequestedCount(15, 30, fc);
+ for (size_t i = 0; i < 20; i++, fc++) b.incFpsRequestedCount(15, 15, fc);
+ for (size_t i = 0; i < 10; i++, fc++) b.incFpsRequestedCount(60, 60, fc);
+
+ b.buildAndReset(&requestCount, &resultErrorCount,
+ &deviceError, &mostRequestedFpsRange, &streamStatsMap);
+ ASSERT_EQ(mostRequestedFpsRange, make_pair(15, 15)) << "Incorrect most common FPS selected";
+
+ // Verify empty stats behavior
+ b.buildAndReset(&requestCount, &resultErrorCount,
+ &deviceError, &mostRequestedFpsRange, &streamStatsMap);
+ ASSERT_EQ(mostRequestedFpsRange, make_pair(0, 0)) << "Incorrect empty stats FPS reported";
+
+ // Verify one frame behavior
+ b.incFpsRequestedCount(30, 30, 1);
+ b.buildAndReset(&requestCount, &resultErrorCount,
+ &deviceError, &mostRequestedFpsRange, &streamStatsMap);
+ ASSERT_EQ(mostRequestedFpsRange, make_pair(30, 30)) << "Incorrect single-frame FPS reported";
+
+ // Verify overflow stats behavior
+ fc = 0;
+ for (size_t range = 1; range < SessionStatsBuilder::FPS_HISTOGRAM_MAX_SIZE + 2; range++) {
+ int count = SessionStatsBuilder::FPS_HISTOGRAM_MAX_SIZE * 3;
+ for (size_t i = 0; i < count - range; i++, fc++) b.incFpsRequestedCount(range, range, fc);
+ }
+ // Should have the oldest bucket dropped, so second oldest should be most common
+ b.buildAndReset(&requestCount, &resultErrorCount,
+ &deviceError, &mostRequestedFpsRange, &streamStatsMap);
+ ASSERT_EQ(mostRequestedFpsRange, make_pair(2, 2)) << "Incorrect stats overflow behavior";
+
+}
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index 65e93a9..4afae9b 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -95,7 +95,8 @@
sp<hardware::ICameraServiceProxy>& proxyBinder,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
- bool usedZoomOverride, const std::vector<hardware::CameraStreamStats>& streamStats) {
+ bool usedZoomOverride, std::pair<int32_t, int32_t> mostRequestedFpsRange,
+ const std::vector<hardware::CameraStreamStats>& streamStats) {
Mutex::Autolock l(mLock);
mSessionStats.mNewCameraState = CameraSessionStats::CAMERA_STATE_IDLE;
@@ -106,6 +107,7 @@
mSessionStats.mVideoStabilizationMode = videoStabilizationMode;
mSessionStats.mUsedUltraWide = usedUltraWide;
mSessionStats.mUsedZoomOverride = usedZoomOverride;
+ mSessionStats.mMostRequestedFpsRange = mostRequestedFpsRange;
mSessionStats.mStreamStats = streamStats;
updateProxyDeviceState(proxyBinder);
@@ -281,7 +283,8 @@
void CameraServiceProxyWrapper::logIdle(const std::string& id,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
- bool usedZoomOverride, const std::vector<hardware::CameraStreamStats>& streamStats) {
+ bool usedZoomOverride, std::pair<int32_t, int32_t> mostRequestedFpsRange,
+ const std::vector<hardware::CameraStreamStats>& streamStats) {
std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
{
Mutex::Autolock l(mLock);
@@ -294,8 +297,9 @@
}
ALOGV("%s: id %s, requestCount %" PRId64 ", resultErrorCount %" PRId64 ", deviceError %d"
- ", userTag %s, videoStabilizationMode %d", __FUNCTION__, id.c_str(), requestCount,
- resultErrorCount, deviceError, userTag.c_str(), videoStabilizationMode);
+ ", userTag %s, videoStabilizationMode %d, most common FPS [%d,%d]",
+ __FUNCTION__, id.c_str(), requestCount, resultErrorCount, deviceError, userTag.c_str(),
+ videoStabilizationMode, mostRequestedFpsRange.first, mostRequestedFpsRange.second);
for (size_t i = 0; i < streamStats.size(); i++) {
ALOGV("%s: streamStats[%zu]: w %d h %d, requestedCount %" PRId64 ", dropCount %"
PRId64 ", startTimeMs %d" ,
@@ -306,7 +310,8 @@
sp<hardware::ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
sessionStats->onIdle(proxyBinder, requestCount, resultErrorCount, deviceError, userTag,
- videoStabilizationMode, usedUltraWide, usedZoomOverride, streamStats);
+ videoStabilizationMode, usedUltraWide, usedZoomOverride,
+ mostRequestedFpsRange, streamStats);
}
void CameraServiceProxyWrapper::logOpen(const std::string& id, int facing,
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index 49b7a8c..b6a967f 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -62,7 +62,8 @@
void onIdle(sp<hardware::ICameraServiceProxy>& proxyBinder,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
- bool usedZoomOverride, const std::vector<hardware::CameraStreamStats>& streamStats);
+ bool usedZoomOverride, std::pair<int32_t, int32_t> mostRequestedFpsRange,
+ const std::vector<hardware::CameraStreamStats>& streamStats);
std::string updateExtensionSessionStats(
const hardware::CameraExtensionSessionStats& extStats);
@@ -111,7 +112,8 @@
void logIdle(const std::string& id,
int64_t requestCount, int64_t resultErrorCount, bool deviceError,
const std::string& userTag, int32_t videoStabilizationMode, bool usedUltraWide,
- bool usedZoomOverride, const std::vector<hardware::CameraStreamStats>& streamStats);
+ bool usedZoomOverride, std::pair<int32_t, int32_t> mostRequestedFpsRange,
+ const std::vector<hardware::CameraStreamStats>& streamStats);
// Ping camera service proxy for user update
void pingCameraServiceProxy();
diff --git a/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp b/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
index c3aac72..2bca4cb 100644
--- a/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
+++ b/services/camera/libcameraservice/utils/SessionStatsBuilder.cpp
@@ -48,19 +48,35 @@
void SessionStatsBuilder::buildAndReset(int64_t* requestCount,
int64_t* errorResultCount, bool* deviceError,
- std::map<int, StreamStats> *statsMap) {
+ std::pair<int32_t, int32_t>* mostRequestedFpsRange,
+ std::map<int, StreamStats>* statsMap) {
std::lock_guard<std::mutex> l(mLock);
*requestCount = mRequestCount;
*errorResultCount = mErrorResultCount;
*deviceError = mDeviceError;
*statsMap = mStatsMap;
+ int32_t minFps = 0, maxFps = 0;
+ if (mRequestedFpsRangeHistogram.size() > 0) {
+ auto mostCommonIt = mRequestedFpsRangeHistogram.begin();
+ for (auto it = mostCommonIt; it != mRequestedFpsRangeHistogram.end(); it++) {
+ if (it->second.first > mostCommonIt->second.first) {
+ mostCommonIt = it;
+ }
+ }
+ minFps = mostCommonIt->first >> 32;
+ maxFps = mostCommonIt->first & 0xFFFF'FFFFU;
+ }
+ *mostRequestedFpsRange = std::make_pair(minFps, maxFps);
+
// Reset internal states
mRequestCount = 0;
mErrorResultCount = 0;
mCounterStopped = false;
mDeviceError = false;
mUserTag.clear();
+ mRequestedFpsRangeHistogram.clear();
+
for (auto& streamStats : mStatsMap) {
StreamStats& streamStat = streamStats.second;
streamStat.mRequestedFrameCount = 0;
@@ -125,6 +141,31 @@
mDeviceError = true;
}
+void SessionStatsBuilder::incFpsRequestedCount(int32_t minFps, int32_t maxFps,
+ int64_t frameNumber) {
+ std::lock_guard<std::mutex> l(mLock);
+
+ // Stuff range into a 64-bit value to make hashing simple
+ uint64_t currentFpsTarget = minFps;
+ currentFpsTarget = currentFpsTarget << 32 | maxFps;
+
+ auto &stats = mRequestedFpsRangeHistogram[currentFpsTarget];
+ stats.first++;
+ stats.second = frameNumber;
+
+ // Ensure weird app input of target FPS ranges doesn't cause unbounded memory growth
+ if (mRequestedFpsRangeHistogram.size() > FPS_HISTOGRAM_MAX_SIZE) {
+ // Find oldest used fps to drop by last seen frame number
+ auto deleteIt = mRequestedFpsRangeHistogram.begin();
+ for (auto it = deleteIt; it != mRequestedFpsRangeHistogram.end(); it++) {
+ if (it->second.second < deleteIt->second.second) {
+ deleteIt = it;
+ }
+ }
+ mRequestedFpsRangeHistogram.erase(deleteIt);
+ }
+}
+
void StreamStats::updateLatencyHistogram(int32_t latencyMs) {
size_t i;
for (i = 0; i < mCaptureLatencyBins.size(); i++) {
diff --git a/services/camera/libcameraservice/utils/SessionStatsBuilder.h b/services/camera/libcameraservice/utils/SessionStatsBuilder.h
index 2936531..914c09e 100644
--- a/services/camera/libcameraservice/utils/SessionStatsBuilder.h
+++ b/services/camera/libcameraservice/utils/SessionStatsBuilder.h
@@ -22,6 +22,8 @@
#include <array>
#include <map>
#include <mutex>
+#include <unordered_map>
+#include <utility>
namespace android {
@@ -64,7 +66,8 @@
void buildAndReset(/*out*/int64_t* requestCount,
/*out*/int64_t* errorResultCount,
/*out*/bool* deviceError,
- /*out*/std::map<int, StreamStats> *statsMap);
+ /*out*/std::pair<int32_t, int32_t>* mostRequestedFpsRange,
+ /*out*/std::map<int, StreamStats>* statsMap);
// Stream specific counter
void startCounter(int streamId);
@@ -76,6 +79,13 @@
void incResultCounter(bool dropped);
void onDeviceError();
+ // Session specific statistics
+
+ // Limit on size of FPS range histogram
+ static const size_t FPS_HISTOGRAM_MAX_SIZE = 10;
+
+ void incFpsRequestedCount(int32_t minFps, int32_t maxFps, int64_t frameNumber);
+
SessionStatsBuilder() : mRequestCount(0), mErrorResultCount(0),
mCounterStopped(false), mDeviceError(false) {}
private:
@@ -85,6 +95,11 @@
bool mCounterStopped;
bool mDeviceError;
std::string mUserTag;
+
+ // Histogram of frame counts of requested target FPS ranges
+ // (min_fps << 32 | max_fps) -> (# of frames with this fps, last seen framenumber)
+ std::unordered_map<uint64_t, std::pair<int64_t, int64_t>> mRequestedFpsRangeHistogram;
+
// Map from stream id to stream statistics
std::map<int, StreamStats> mStatsMap;
};
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.cc b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
index 50b5709..ca62cce 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.cc
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.cc
@@ -109,7 +109,14 @@
.setControlAeLock(ANDROID_CONTROL_AE_LOCK_OFF)
.setControlAeMode(ANDROID_CONTROL_AE_MODE_ON)
.setControlAePrecaptureTrigger(
- ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
+ // Limited devices are expected to have precapture ae enabled and
+ // respond to cancellation request. Since we don't actuall support
+ // AE at all, let's just respect the cancellation expectation in
+ // case it's requested
+ requestSettings.aePrecaptureTrigger ==
+ ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
+ ? ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL
+ : ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE)
.setControlAeState(ANDROID_CONTROL_AE_STATE_INACTIVE)
.setControlAfMode(ANDROID_CONTROL_AF_MODE_OFF)
.setControlAfTrigger(ANDROID_CONTROL_AF_TRIGGER_IDLE)
diff --git a/services/camera/virtualcamera/VirtualCameraRenderThread.h b/services/camera/virtualcamera/VirtualCameraRenderThread.h
index 90757a0..e222d5b 100644
--- a/services/camera/virtualcamera/VirtualCameraRenderThread.h
+++ b/services/camera/virtualcamera/VirtualCameraRenderThread.h
@@ -64,6 +64,8 @@
camera_metadata_enum_android_control_capture_intent_t captureIntent =
VirtualCameraDevice::kDefaultCaptureIntent;
std::optional<GpsCoordinates> gpsCoordinates;
+ std::optional<camera_metadata_enum_android_control_ae_precapture_trigger>
+ aePrecaptureTrigger;
};
// Represents single capture request to fill set of buffers.
diff --git a/services/camera/virtualcamera/VirtualCameraSession.cc b/services/camera/virtualcamera/VirtualCameraSession.cc
index 7c17d7c..28fa495 100644
--- a/services/camera/virtualcamera/VirtualCameraSession.cc
+++ b/services/camera/virtualcamera/VirtualCameraSession.cc
@@ -265,7 +265,8 @@
.fpsRange = getFpsRange(metadata),
.captureIntent = getCaptureIntent(metadata).value_or(
ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW),
- .gpsCoordinates = getGpsCoordinates(metadata)};
+ .gpsCoordinates = getGpsCoordinates(metadata),
+ .aePrecaptureTrigger = getPrecaptureTrigger(metadata)};
}
} // namespace
diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc
index fd43d38..d8f6125 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.cc
+++ b/services/camera/virtualcamera/util/MetadataUtil.cc
@@ -931,6 +931,22 @@
return static_cast<camera_metadata_enum_android_lens_facing>(entry.data.u8[0]);
}
+std::optional<camera_metadata_enum_android_control_ae_precapture_trigger>
+getPrecaptureTrigger(
+ const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata) {
+ auto metadata =
+ reinterpret_cast<const camera_metadata_t*>(cameraMetadata.metadata.data());
+
+ camera_metadata_ro_entry_t entry;
+ if (find_camera_metadata_ro_entry(
+ metadata, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &entry) != OK) {
+ return std::nullopt;
+ }
+
+ return static_cast<camera_metadata_enum_android_control_ae_precapture_trigger>(
+ entry.data.u8[0]);
+}
+
} // namespace virtualcamera
} // namespace companion
} // namespace android
diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h
index b6c672c..d0af0c1 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.h
+++ b/services/camera/virtualcamera/util/MetadataUtil.h
@@ -480,6 +480,10 @@
std::optional<camera_metadata_enum_android_lens_facing> getLensFacing(
const aidl::android::hardware::camera::device::CameraMetadata& metadata);
+std::optional<camera_metadata_enum_android_control_ae_precapture_trigger>
+getPrecaptureTrigger(
+ const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata);
+
} // namespace virtualcamera
} // namespace companion
} // namespace android