Merge "Record MediaCodecReported atom" into sc-dev
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index f7d194e..604dbb8 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -71,9 +71,10 @@
}
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
- int clientUid, int clientPid)
+ int clientUid, int clientPid, int targetSdkVersion)
{
- return CameraBaseT::connect(cameraId, clientPackageName, clientUid, clientPid);
+ return CameraBaseT::connect(cameraId, clientPackageName, clientUid,
+ clientPid, targetSdkVersion);
}
status_t Camera::reconnect()
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 0b0f584..03439fd 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -152,7 +152,7 @@
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
- int clientUid, int clientPid)
+ int clientUid, int clientPid, int targetSdkVersion)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
@@ -163,7 +163,7 @@
if (cs != nullptr) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
- clientPid, /*out*/ &c->mCamera);
+ clientPid, targetSdkVersion, /*out*/ &c->mCamera);
}
if (ret.isOk() && c->mCamera != nullptr) {
IInterface::asBinder(c->mCamera)->linkToDeath(c);
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 6e82968..78a77d4 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -82,7 +82,8 @@
ICamera connect(ICameraClient client,
int cameraId,
String opPackageName,
- int clientUid, int clientPid);
+ int clientUid, int clientPid,
+ int targetSdkVersion);
/**
* Open a camera device through the new camera API
@@ -92,7 +93,8 @@
String cameraId,
String opPackageName,
@nullable String featureId,
- int clientUid, int oomScoreOffset);
+ int clientUid, int oomScoreOffset,
+ int targetSdkVersion);
/**
* Add listener for changes to camera device and flashlight state.
@@ -114,13 +116,15 @@
* corresponding camera ids.
*
* @param sessions the set of camera id and session configuration pairs to be queried.
+ * @param targetSdkVersion the target sdk level of the application calling this function.
* @return true - the set of concurrent camera id and stream combinations is supported.
* false - the set of concurrent camera id and stream combinations is not supported
* OR the method was called with a set of camera ids not returned by
* getConcurrentCameraIds().
*/
boolean isConcurrentSessionConfigurationSupported(
- in CameraIdAndSessionConfiguration[] sessions);
+ in CameraIdAndSessionConfiguration[] sessions,
+ int targetSdkVersion);
/**
* Remove listener for changes to camera device and flashlight state.
@@ -131,7 +135,7 @@
* Read the static camera metadata for a camera device.
* Only supported for device HAL versions >= 3.2
*/
- CameraMetadataNative getCameraCharacteristics(String cameraId);
+ CameraMetadataNative getCameraCharacteristics(String cameraId, int targetSdkVersion);
/**
* Read in the vendor tag descriptors from the camera module HAL.
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 5579183..58ccd69 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -58,7 +58,7 @@
typedef ::android::hardware::ICameraClient TCamCallbacks;
typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
(const sp<::android::hardware::ICameraClient>&,
- int, const String16&, int, int,
+ int, const String16&, int, int, int,
/*out*/
sp<::android::hardware::ICamera>*);
static TCamConnectService fnConnectService;
@@ -81,7 +81,7 @@
static sp<Camera> create(const sp<::android::hardware::ICamera>& camera);
static sp<Camera> connect(int cameraId,
const String16& clientPackageName,
- int clientUid, int clientPid);
+ int clientUid, int clientPid, int targetSdkVersion);
virtual ~Camera();
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index 499b0e6..e156994 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -113,7 +113,7 @@
static sp<TCam> connect(int cameraId,
const String16& clientPackageName,
- int clientUid, int clientPid);
+ int clientUid, int clientPid, int targetSdkVersion);
virtual void disconnect();
void setListener(const sp<TCamListener>& listener);
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index a03c69c..95ef2b2 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -689,7 +689,9 @@
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
CameraMetadata rawMetadata;
- binder::Status serviceRet = cs->getCameraCharacteristics(String16(cameraIdStr), &rawMetadata);
+ int targetSdkVersion = android_get_application_target_sdk_version();
+ binder::Status serviceRet = cs->getCameraCharacteristics(String16(cameraIdStr),
+ targetSdkVersion, &rawMetadata);
if (!serviceRet.isOk()) {
switch(serviceRet.serviceSpecificErrorCode()) {
case hardware::ICameraService::ERROR_DISCONNECTED:
@@ -735,11 +737,13 @@
sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = device->getServiceCallback();
sp<hardware::camera2::ICameraDeviceUser> deviceRemote;
+ int targetSdkVersion = android_get_application_target_sdk_version();
// No way to get package name from native.
// Send a zero length package name and let camera service figure it out from UID
binder::Status serviceRet = cs->connectDevice(
callbacks, String16(cameraId), String16(""), {},
- hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0, /*out*/&deviceRemote);
+ hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0,
+ targetSdkVersion, /*out*/&deviceRemote);
if (!serviceRet.isOk()) {
ALOGE("%s: connect camera device failed: %s", __FUNCTION__, serviceRet.toString8().string());
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 1609c7b..3d93ba5 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3576,9 +3576,9 @@
* <p>Not all output formats may be supported in a configuration with
* an input stream of a particular format. For more details, see
* android.scaler.availableInputOutputFormatsMap.</p>
- * <p>The following table describes the minimum required output stream
- * configurations based on the hardware level
- * (ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL), prior to Android 12:</p>
+ * <p>For applications targeting SDK version older than 31, the following table
+ * describes the minimum required output stream configurations based on the hardware level
+ * (ACAMERA_INFO_SUPPORTED_HARDWARE_LEVEL):</p>
* <p>Format | Size | Hardware Level | Notes
* :-------------:|:--------------------------------------------:|:--------------:|:--------------:
* JPEG | ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE | Any |
@@ -3589,10 +3589,13 @@
* YUV_420_888 | all output sizes available for JPEG | FULL |
* YUV_420_888 | all output sizes available for JPEG, up to the maximum video size | LIMITED |
* IMPLEMENTATION_DEFINED | same as YUV_420_888 | Any |</p>
- * <p>Starting from Android 12, the camera device may not support JPEG sizes smaller than the
- * minimum of 1080p and the camera sensor active array size. The requirements for
- * IMPLEMENTATION_DEFINED and YUV_420_888 stay the same. This new minimum required output
- * stream configurations are illustrated by the table below:</p>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device declares to be
+ * <a href="https://developer.android.com/reference/android/os/Build/VERSION_CDOES/MEDIA_PERFORMANCE_CLASS.html">media performance class</a> S,
+ * the primary camera devices (first rear/front camera in the camera ID list) will not
+ * support JPEG sizes smaller than 1080p. If the application configures a JPEG stream
+ * smaller than 1080p, the camera device will round up the JPEG image size to at least
+ * 1080p. The requirements for IMPLEMENTATION_DEFINED and YUV_420_888 stay the same.
+ * This new minimum required output stream configurations are illustrated by the table below:</p>
* <p>Format | Size | Hardware Level | Notes
* :-------------:|:--------------------------------------------:|:--------------:|:--------------:
* JPEG | ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE | Any |
@@ -3604,6 +3607,10 @@
* YUV_420_888 | 320x240 (240p) | FULL | if 240p <= activeArraySize
* YUV_420_888 | all output sizes available for FULL hardware level, up to the maximum video size | LIMITED |
* IMPLEMENTATION_DEFINED | same as YUV_420_888 | Any |</p>
+ * <p>For applications targeting SDK version 31 or newer, if the mobile device doesn't declare
+ * to be media performance class S, or if the camera device isn't a primary rear/front
+ * camera, the minimum required output stream configurations are the same as for applications
+ * targeting SDK version older than 31.</p>
* <p>Refer to ACAMERA_REQUEST_AVAILABLE_CAPABILITIES for additional
* mandatory stream configurations on a per-capability basis.</p>
* <p>Exception on 176x144 (QCIF) resolution: camera devices usually have a fixed capability for
@@ -9224,10 +9231,10 @@
* respective color channel provided in
* ACAMERA_SENSOR_TEST_PATTERN_DATA.</p>
* <p>For example:</p>
- * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
+ * <pre><code>ACAMERA_SENSOR_TEST_PATTERN_DATA = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All green pixels are 100% green. All red/blue pixels are black.</p>
- * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
+ * <pre><code>ACAMERA_SENSOR_TEST_PATTERN_DATA = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0]
* </code></pre>
* <p>All red pixels are 100% red. Only the odd green pixels
* are 100% green. All blue pixels are 100% black.</p>
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index a0773a2..9f2f430 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -363,7 +363,8 @@
// Check metadata binder call
CameraMetadata metadata;
- res = service->getCameraCharacteristics(cameraId, &metadata);
+ res = service->getCameraCharacteristics(cameraId,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &metadata);
EXPECT_TRUE(res.isOk()) << res;
EXPECT_FALSE(metadata.isEmpty());
@@ -379,7 +380,7 @@
sp<hardware::camera2::ICameraDeviceUser> device;
res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
{}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
- /*out*/&device);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
ASSERT_NE(nullptr, device.get());
device->disconnect();
@@ -422,7 +423,7 @@
SCOPED_TRACE("openNewDevice");
binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
{}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
- /*out*/&device);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*out*/&device);
EXPECT_TRUE(res.isOk()) << res;
}
auto p = std::make_pair(callbacks, device);
diff --git a/camera/tests/CameraCharacteristicsPermission.cpp b/camera/tests/CameraCharacteristicsPermission.cpp
index 135d2a3..76dc38c 100644
--- a/camera/tests/CameraCharacteristicsPermission.cpp
+++ b/camera/tests/CameraCharacteristicsPermission.cpp
@@ -73,7 +73,8 @@
CameraMetadata metadata;
std::vector<int32_t> tagsNeedingPermission;
- rc = mCameraService->getCameraCharacteristics(cameraIdStr, &metadata);
+ rc = mCameraService->getCameraCharacteristics(cameraIdStr,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &metadata);
ASSERT_TRUE(rc.isOk());
EXPECT_FALSE(metadata.isEmpty());
EXPECT_EQ(metadata.removePermissionEntries(CAMERA_METADATA_INVALID_VENDOR_ID,
diff --git a/camera/tests/CameraZSLTests.cpp b/camera/tests/CameraZSLTests.cpp
index 02c6e2a..efd9dae 100644
--- a/camera/tests/CameraZSLTests.cpp
+++ b/camera/tests/CameraZSLTests.cpp
@@ -181,7 +181,8 @@
}
CameraMetadata metadata;
- rc = mCameraService->getCameraCharacteristics(cameraIdStr, &metadata);
+ rc = mCameraService->getCameraCharacteristics(cameraIdStr,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &metadata);
if (!rc.isOk()) {
// The test is relevant only for cameras with Hal 3.x
// support.
@@ -207,7 +208,8 @@
rc = mCameraService->connect(this, cameraId,
String16("ZSLTest"), hardware::ICameraService::USE_CALLING_UID,
- hardware::ICameraService::USE_CALLING_PID, &cameraDevice);
+ hardware::ICameraService::USE_CALLING_PID,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &cameraDevice);
EXPECT_TRUE(rc.isOk());
CameraParameters params(cameraDevice->getParameters());
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 76345ae..2fa4f25 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -65,12 +65,14 @@
C2Config::PROFILE_AV1_1}),
C2F(mProfileLevel, level)
.oneOf({
- C2Config::LEVEL_AV1_2,
- C2Config::LEVEL_AV1_2_1,
- C2Config::LEVEL_AV1_2_2,
- C2Config::LEVEL_AV1_3,
- C2Config::LEVEL_AV1_3_1,
- C2Config::LEVEL_AV1_3_2,
+ C2Config::LEVEL_AV1_2, C2Config::LEVEL_AV1_2_1,
+ C2Config::LEVEL_AV1_2_2, C2Config::LEVEL_AV1_2_3,
+ C2Config::LEVEL_AV1_3, C2Config::LEVEL_AV1_3_1,
+ C2Config::LEVEL_AV1_3_2, C2Config::LEVEL_AV1_3_3,
+ C2Config::LEVEL_AV1_4, C2Config::LEVEL_AV1_4_1,
+ C2Config::LEVEL_AV1_4_2, C2Config::LEVEL_AV1_4_3,
+ C2Config::LEVEL_AV1_5, C2Config::LEVEL_AV1_5_1,
+ C2Config::LEVEL_AV1_5_2, C2Config::LEVEL_AV1_5_3,
})})
.withSetter(ProfileLevelSetter, mSize)
.build());
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 9d9ed70..7caa457 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -262,6 +262,8 @@
kParamIndexTunneledMode, // struct
kParamIndexTunnelHandle, // int32[]
kParamIndexTunnelSystemTime, // int64
+ kParamIndexTunnelHoldRender, // bool
+ kParamIndexTunnelStartRender, // bool
// dmabuf allocator
kParamIndexStoreDmaBufUsage, // store, struct
@@ -2366,6 +2368,31 @@
C2PortTunnelSystemTime;
constexpr char C2_PARAMKEY_OUTPUT_RENDER_TIME[] = "output.render-time";
+
+/**
+ * Tunneled mode video peek signaling flag.
+ *
+ * When a video frame is pushed to the decoder with this parameter set to true,
+ * the decoder must decode the frame, signal partial completion, and hold on the
+ * frame until C2StreamTunnelStartRender is set to true (which resets this
+ * flag). Flush will also result in the frames being returned back to the
+ * client (but not rendered).
+ */
+typedef C2StreamParam<C2Info, C2EasyBoolValue, kParamIndexTunnelHoldRender>
+ C2StreamTunnelHoldRender;
+constexpr char C2_PARAMKEY_TUNNEL_HOLD_RENDER[] = "output.tunnel-hold-render";
+
+/**
+ * Tunneled mode video peek signaling flag.
+ *
+ * Upon receiving this flag, the decoder shall set C2StreamTunnelHoldRender to
+ * false, which shall cause any frames held for rendering to be immediately
+ * displayed, regardless of their timestamps.
+*/
+typedef C2StreamParam<C2Info, C2EasyBoolValue, kParamIndexTunnelStartRender>
+ C2StreamTunnelStartRender;
+constexpr char C2_PARAMKEY_TUNNEL_START_RENDER[] = "output.tunnel-start-render";
+
C2ENUM(C2PlatformConfig::encoding_quality_level_t, uint32_t,
NONE,
S_HANDHELD,
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index ce15a30..16398a4 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -673,6 +673,10 @@
mCodec->mCallback->onOutputBuffersChanged();
}
+ void onFirstTunnelFrameReady() override {
+ mCodec->mCallback->onFirstTunnelFrameReady();
+ }
+
private:
CCodec *mCodec;
};
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3c3b41d..f88408e 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -209,6 +209,7 @@
int32_t flags = 0;
int32_t tmp = 0;
bool eos = false;
+ bool tunnelFirstFrame = false;
if (buffer->meta()->findInt32("eos", &tmp) && tmp) {
eos = true;
mInputMetEos = true;
@@ -217,6 +218,9 @@
if (buffer->meta()->findInt32("csd", &tmp) && tmp) {
flags |= C2FrameData::FLAG_CODEC_CONFIG;
}
+ if (buffer->meta()->findInt32("tunnel-first-frame", &tmp) && tmp) {
+ tunnelFirstFrame = true;
+ }
ALOGV("[%s] queueInputBuffer: buffer->size() = %zu", mName, buffer->size());
std::list<std::unique_ptr<C2Work>> items;
std::unique_ptr<C2Work> work(new C2Work);
@@ -288,6 +292,13 @@
// TODO: fill info's
work->input.configUpdate = std::move(mParamsToBeSet);
+ if (tunnelFirstFrame) {
+ C2StreamTunnelHoldRender::input tunnelHoldRender{
+ 0u /* stream */,
+ C2_TRUE /* value */
+ };
+ work->input.configUpdate.push_back(C2Param::Copy(tunnelHoldRender));
+ }
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
@@ -1724,6 +1735,15 @@
}
break;
}
+ case C2StreamTunnelHoldRender::CORE_INDEX: {
+ C2StreamTunnelHoldRender::output firstTunnelFrameHoldRender;
+ if (!(worklet->output.flags & C2FrameData::FLAG_INCOMPLETE)) break;
+ if (!firstTunnelFrameHoldRender.updateFrom(*param)) break;
+ if (firstTunnelFrameHoldRender.value != C2_TRUE) break;
+ ALOGV("[%s] onWorkDone: first tunnel frame ready", mName);
+ mCCodecCallback->onFirstTunnelFrameReady();
+ break;
+ }
default:
ALOGV("[%s] onWorkDone: unrecognized config update (%08X)",
mName, param->index());
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 45da003..5a2aca2 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -45,6 +45,7 @@
virtual void onError(status_t err, enum ActionCode actionCode) = 0;
virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0;
virtual void onOutputBuffersChanged() = 0;
+ virtual void onFirstTunnelFrameReady() = 0;
};
/**
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 27e87e6..2df0ba2 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -938,6 +938,14 @@
return value == 0 ? C2_FALSE : C2_TRUE;
}));
+ add(ConfigMapper("android._trigger-tunnel-peek", C2_PARAMKEY_TUNNEL_START_RENDER, "value")
+ .limitTo(D::PARAM & D::VIDEO & D::DECODER)
+ .withMapper([](C2Value v) -> C2Value {
+ int32_t value = 0;
+ (void)v.get(&value);
+ return value == 0 ? C2_FALSE : C2_TRUE;
+ }));
+
/* still to do
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 4fd3a56..443e26c 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1700,17 +1700,17 @@
return ERROR_MALFORMED;
}
- size_t header_start = 0;
- size_t header_lenth = 0;
+ long header_start = 0;
+ long header_length = 0;
for (header_start = 0; header_start < frame.len - 4; header_start++) {
if (ntohl(0x000001b3) == *(uint32_t*)((uint8_t*)tmpData.get() + header_start)) {
break;
}
}
bool isComplete_csd = false;
- for (header_lenth = 0; header_lenth < frame.len - 4 - header_start; header_lenth++) {
+ for (header_length = 0; header_length < frame.len - 4 - header_start; header_length++) {
if (ntohl(0x000001b8) == *(uint32_t*)((uint8_t*)tmpData.get()
- + header_start + header_lenth)) {
+ + header_start + header_length)) {
isComplete_csd = true;
break;
}
@@ -1720,7 +1720,7 @@
return ERROR_MALFORMED;
}
addESDSFromCodecPrivate(trackInfo->mMeta, false,
- (uint8_t*)(tmpData.get()) + header_start, header_lenth);
+ (uint8_t*)(tmpData.get()) + header_start, header_length);
return OK;
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 5bbabdf..248a39c 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -504,7 +504,14 @@
}
mCurrentTimeUs = seekTimeUs;
- mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000;
+ int64_t seekTimeUsTimesBitrate;
+ if (__builtin_mul_overflow(seekTimeUs, bitrate, &seekTimeUsTimesBitrate)) {
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
+ if (__builtin_add_overflow(
+ mFirstFramePos, seekTimeUsTimesBitrate / 8000000, &mCurrentPos)) {
+ return AMEDIA_ERROR_UNSUPPORTED;
+ }
seekCBR = true;
} else {
mCurrentTimeUs = actualSeekTimeUs;
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 0d60120..acfac24 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -25,8 +25,7 @@
// TODO These defines should be moved to a central place in audio.
#define SAMPLES_PER_FRAME_MIN 1
-// TODO Remove 8 channel limitation.
-#define SAMPLES_PER_FRAME_MAX FCC_8
+#define SAMPLES_PER_FRAME_MAX FCC_LIMIT
#define SAMPLE_RATE_HZ_MIN 8000
// HDMI supports up to 32 channels at 1536000 Hz.
#define SAMPLE_RATE_HZ_MAX 1600000
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 2135c54..e015592 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -43,8 +43,7 @@
// on the edge of being ridiculous.
// TODO These defines should be moved to a central place in audio.
#define SAMPLES_PER_FRAME_MIN 1
-// TODO Remove 8 channel limitation.
-#define SAMPLES_PER_FRAME_MAX FCC_8
+#define SAMPLES_PER_FRAME_MAX FCC_LIMIT
#define SAMPLE_RATE_HZ_MIN 8000
// HDMI supports up to 32 channels at 1536000 Hz.
#define SAMPLE_RATE_HZ_MAX 1600000
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 4789ad2..88e752b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -71,6 +71,25 @@
Mutex gSoundTriggerCaptureStateListenerLock;
sp<CaptureStateListenerImpl> gSoundTriggerCaptureStateListener = nullptr;
+// Binder for the AudioFlinger service that's passed to this client process from the system server.
+// This allows specific isolated processes to access the audio system. Currently used only for the
+// HotwordDetectionService.
+sp<IBinder> gAudioFlingerBinder = nullptr;
+
+void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
+ if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
+ ALOGE("setAudioFlingerBinder: received a binder of type %s",
+ String8(audioFlinger->getInterfaceDescriptor()).string());
+ return;
+ }
+ Mutex::Autolock _l(gLock);
+ if (gAudioFlinger != nullptr) {
+ ALOGW("setAudioFlingerBinder: ignoring; AudioFlinger connection already established.");
+ return;
+ }
+ gAudioFlingerBinder = audioFlinger;
+}
+
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::get_audio_flinger() {
sp<IAudioFlinger> af;
@@ -79,15 +98,19 @@
{
Mutex::Autolock _l(gLock);
if (gAudioFlinger == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
- do {
- binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
- if (binder != 0)
- break;
- ALOGW("AudioFlinger not published, waiting...");
- usleep(500000); // 0.5 s
- } while (true);
+ if (gAudioFlingerBinder != nullptr) {
+ binder = gAudioFlingerBinder;
+ } else {
+ sp<IServiceManager> sm = defaultServiceManager();
+ do {
+ binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
+ if (binder != 0)
+ break;
+ ALOGW("AudioFlinger not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while (true);
+ }
if (gAudioFlingerClient == NULL) {
gAudioFlingerClient = new AudioFlingerClient();
} else {
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 5e7def1..a9109c8 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -148,6 +148,11 @@
static void setRecordConfigCallback(record_config_callback);
static void setRoutingCallback(routing_callback cb);
+ // Sets the binder to use for accessing the AudioFlinger service. This enables the system server
+ // to grant specific isolated processes access to the audio system. Currently used only for the
+ // HotwordDetectionService.
+ static void setAudioFlingerBinder(const sp<IBinder>& audioFlinger);
+
// helper function to obtain AudioFlinger service handle
static const sp<IAudioFlinger> get_audio_flinger();
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index a54e22f..f30eb54 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "AudioMixer"
//#define LOG_NDEBUG 0
+#include <array>
#include <sstream>
#include <string.h>
@@ -1295,8 +1296,29 @@
// Needs to derive a compile time constant (constexpr). Could be targeted to go
// to a MONOVOL mixtype based on MAX_NUM_VOLUMES, but that's an unnecessary complication.
-#define MIXTYPE_MONOVOL(mixtype) ((mixtype) == MIXTYPE_MULTI ? MIXTYPE_MULTI_MONOVOL : \
- (mixtype) == MIXTYPE_MULTI_SAVEONLY ? MIXTYPE_MULTI_SAVEONLY_MONOVOL : (mixtype))
+
+constexpr int MIXTYPE_MONOVOL(int mixtype, int channels) {
+ if (channels <= FCC_2) {
+ return mixtype;
+ } else if (mixtype == MIXTYPE_MULTI) {
+ return MIXTYPE_MULTI_MONOVOL;
+ } else if (mixtype == MIXTYPE_MULTI_SAVEONLY) {
+ return MIXTYPE_MULTI_SAVEONLY_MONOVOL;
+ } else {
+ return mixtype;
+ }
+}
+
+// Helper to make a functional array from volumeRampMulti.
+template <int MIXTYPE, typename TO, typename TI, typename TV, typename TA, typename TAV,
+ std::size_t ... Is>
+static constexpr auto makeVRMArray(std::index_sequence<Is...>)
+{
+ using F = void(*)(TO*, size_t, const TI*, TA*, TV*, const TV*, TAV*, TAV);
+ return std::array<F, sizeof...(Is)>{
+ { &volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE, Is + 1), Is + 1, TO, TI, TV, TA, TAV> ...}
+ };
+}
/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float
@@ -1308,40 +1330,26 @@
static void volumeRampMulti(uint32_t channels, TO* out, size_t frameCount,
const TI* in, TA* aux, TV *vol, const TV *volinc, TAV *vola, TAV volainc)
{
- switch (channels) {
- case 1:
- volumeRampMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 2:
- volumeRampMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 3:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 4:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 5:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 6:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 7:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
- case 8:
- volumeRampMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out,
- frameCount, in, aux, vol, volinc, vola, volainc);
- break;
+ static constexpr auto volumeRampMultiArray =
+ makeVRMArray<MIXTYPE, TO, TI, TV, TA, TAV>(std::make_index_sequence<FCC_LIMIT>());
+ if (channels > 0 && channels <= volumeRampMultiArray.size()) {
+ volumeRampMultiArray[channels - 1](out, frameCount, in, aux, vol, volinc, vola, volainc);
+ } else {
+ ALOGE("%s: invalid channel count:%d", __func__, channels);
}
}
+// Helper to make a functional array from volumeMulti.
+template <int MIXTYPE, typename TO, typename TI, typename TV, typename TA, typename TAV,
+ std::size_t ... Is>
+static constexpr auto makeVMArray(std::index_sequence<Is...>)
+{
+ using F = void(*)(TO*, size_t, const TI*, TA*, const TV*, TAV);
+ return std::array<F, sizeof...(Is)>{
+ { &volumeMulti<MIXTYPE_MONOVOL(MIXTYPE, Is + 1), Is + 1, TO, TI, TV, TA, TAV> ... }
+ };
+}
+
/* MIXTYPE (see AudioMixerOps.h MIXTYPE_* enumeration)
* TO: int32_t (Q4.27) or float
* TI: int32_t (Q4.27) or int16_t (Q0.15) or float
@@ -1352,31 +1360,12 @@
static void volumeMulti(uint32_t channels, TO* out, size_t frameCount,
const TI* in, TA* aux, const TV *vol, TAV vola)
{
- switch (channels) {
- case 1:
- volumeMulti<MIXTYPE, 1>(out, frameCount, in, aux, vol, vola);
- break;
- case 2:
- volumeMulti<MIXTYPE, 2>(out, frameCount, in, aux, vol, vola);
- break;
- case 3:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 3>(out, frameCount, in, aux, vol, vola);
- break;
- case 4:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 4>(out, frameCount, in, aux, vol, vola);
- break;
- case 5:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 5>(out, frameCount, in, aux, vol, vola);
- break;
- case 6:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 6>(out, frameCount, in, aux, vol, vola);
- break;
- case 7:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 7>(out, frameCount, in, aux, vol, vola);
- break;
- case 8:
- volumeMulti<MIXTYPE_MONOVOL(MIXTYPE), 8>(out, frameCount, in, aux, vol, vola);
- break;
+ static constexpr auto volumeMultiArray =
+ makeVMArray<MIXTYPE, TO, TI, TV, TA, TAV>(std::make_index_sequence<FCC_LIMIT>());
+ if (channels > 0 && channels <= volumeMultiArray.size()) {
+ volumeMultiArray[channels - 1](out, frameCount, in, aux, vol, vola);
+ } else {
+ ALOGE("%s: invalid channel count:%d", __func__, channels);
}
}
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index 8d374c9..cd47dc6 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_AUDIO_MIXER_OPS_H
#define ANDROID_AUDIO_MIXER_OPS_H
+#include <system/audio.h>
+
namespace android {
// Hack to make static_assert work in a constexpr
@@ -231,7 +233,7 @@
typename TO, typename TI, typename TV,
typename F>
void stereoVolumeHelper(TO*& out, const TI*& in, const TV *vol, F f) {
- static_assert(NCHAN > 0 && NCHAN <= 8);
+ static_assert(NCHAN > 0 && NCHAN <= FCC_LIMIT);
static_assert(MIXTYPE == MIXTYPE_MULTI_STEREOVOL
|| MIXTYPE == MIXTYPE_MULTI_SAVEONLY_STEREOVOL
|| MIXTYPE == MIXTYPE_STEREOEXPAND
@@ -291,6 +293,16 @@
// NCHAN == 8
proc(*out++, f(inp(), vol[0])); // side left
proc(*out++, f(inp(), vol[1])); // side right
+ if constexpr (NCHAN > FCC_8) {
+ // Mutes to zero extended surround channels.
+ // 7.1.4 has the correct behavior.
+ // 22.2 has the behavior that FLC and FRC will be mixed instead
+ // of SL and SR and LFE will be center, not left.
+ for (int i = 8; i < NCHAN; ++i) {
+ // TODO: Consider using android::audio_utils::channels::kSideFromChannelIdx
+ proc(*out++, f(inp(), 0.f));
+ }
+ }
}
/*
diff --git a/media/libaudioprocessing/AudioResampler.cpp b/media/libaudioprocessing/AudioResampler.cpp
index c761b38..51673d7 100644
--- a/media/libaudioprocessing/AudioResampler.cpp
+++ b/media/libaudioprocessing/AudioResampler.cpp
@@ -268,7 +268,7 @@
mPhaseFraction(0),
mQuality(quality) {
- const int maxChannels = quality < DYN_LOW_QUALITY ? 2 : 8;
+ const int maxChannels = quality < DYN_LOW_QUALITY ? FCC_2 : FCC_LIMIT;
if (inChannelCount < 1
|| inChannelCount > maxChannels) {
LOG_ALWAYS_FATAL("Unsupported sample format %d quality %d channels",
diff --git a/media/libaudioprocessing/AudioResamplerDyn.cpp b/media/libaudioprocessing/AudioResamplerDyn.cpp
index 1aacfd1..2292b19 100644
--- a/media/libaudioprocessing/AudioResamplerDyn.cpp
+++ b/media/libaudioprocessing/AudioResamplerDyn.cpp
@@ -545,64 +545,76 @@
// Note: A stride of 2 is achieved with non-SIMD processing.
int stride = ((c.mHalfNumCoefs & 7) == 0) ? 16 : 2;
LOG_ALWAYS_FATAL_IF(stride < 16, "Resampler stride must be 16 or more");
- LOG_ALWAYS_FATAL_IF(mChannelCount < 1 || mChannelCount > 8,
- "Resampler channels(%d) must be between 1 to 8", mChannelCount);
+ LOG_ALWAYS_FATAL_IF(mChannelCount < 1 || mChannelCount > FCC_LIMIT,
+ "Resampler channels(%d) must be between 1 to %d", mChannelCount, FCC_LIMIT);
// stride 16 (falls back to stride 2 for machines that do not support NEON)
+
+
+// For now use a #define as a compiler generated function table requires renaming.
+#pragma push_macro("AUDIORESAMPLERDYN_CASE")
+#undef AUDIORESAMPLERDYN_CASE
+#define AUDIORESAMPLERDYN_CASE(CHANNEL, LOCKED) \
+ case CHANNEL: if constexpr (CHANNEL <= FCC_LIMIT) {\
+ mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<CHANNEL, LOCKED, 16>; \
+ } break
+
if (locked) {
switch (mChannelCount) {
- case 1:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, true, 16>;
- break;
- case 2:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, true, 16>;
- break;
- case 3:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, true, 16>;
- break;
- case 4:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, true, 16>;
- break;
- case 5:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, true, 16>;
- break;
- case 6:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, true, 16>;
- break;
- case 7:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, true, 16>;
- break;
- case 8:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, true, 16>;
- break;
+ AUDIORESAMPLERDYN_CASE(1, true);
+ AUDIORESAMPLERDYN_CASE(2, true);
+ AUDIORESAMPLERDYN_CASE(3, true);
+ AUDIORESAMPLERDYN_CASE(4, true);
+ AUDIORESAMPLERDYN_CASE(5, true);
+ AUDIORESAMPLERDYN_CASE(6, true);
+ AUDIORESAMPLERDYN_CASE(7, true);
+ AUDIORESAMPLERDYN_CASE(8, true);
+ AUDIORESAMPLERDYN_CASE(9, true);
+ AUDIORESAMPLERDYN_CASE(10, true);
+ AUDIORESAMPLERDYN_CASE(11, true);
+ AUDIORESAMPLERDYN_CASE(12, true);
+ AUDIORESAMPLERDYN_CASE(13, true);
+ AUDIORESAMPLERDYN_CASE(14, true);
+ AUDIORESAMPLERDYN_CASE(15, true);
+ AUDIORESAMPLERDYN_CASE(16, true);
+ AUDIORESAMPLERDYN_CASE(17, true);
+ AUDIORESAMPLERDYN_CASE(18, true);
+ AUDIORESAMPLERDYN_CASE(19, true);
+ AUDIORESAMPLERDYN_CASE(20, true);
+ AUDIORESAMPLERDYN_CASE(21, true);
+ AUDIORESAMPLERDYN_CASE(22, true);
+ AUDIORESAMPLERDYN_CASE(23, true);
+ AUDIORESAMPLERDYN_CASE(24, true);
}
} else {
switch (mChannelCount) {
- case 1:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<1, false, 16>;
- break;
- case 2:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<2, false, 16>;
- break;
- case 3:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<3, false, 16>;
- break;
- case 4:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<4, false, 16>;
- break;
- case 5:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<5, false, 16>;
- break;
- case 6:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<6, false, 16>;
- break;
- case 7:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<7, false, 16>;
- break;
- case 8:
- mResampleFunc = &AudioResamplerDyn<TC, TI, TO>::resample<8, false, 16>;
- break;
+ AUDIORESAMPLERDYN_CASE(1, false);
+ AUDIORESAMPLERDYN_CASE(2, false);
+ AUDIORESAMPLERDYN_CASE(3, false);
+ AUDIORESAMPLERDYN_CASE(4, false);
+ AUDIORESAMPLERDYN_CASE(5, false);
+ AUDIORESAMPLERDYN_CASE(6, false);
+ AUDIORESAMPLERDYN_CASE(7, false);
+ AUDIORESAMPLERDYN_CASE(8, false);
+ AUDIORESAMPLERDYN_CASE(9, false);
+ AUDIORESAMPLERDYN_CASE(10, false);
+ AUDIORESAMPLERDYN_CASE(11, false);
+ AUDIORESAMPLERDYN_CASE(12, false);
+ AUDIORESAMPLERDYN_CASE(13, false);
+ AUDIORESAMPLERDYN_CASE(14, false);
+ AUDIORESAMPLERDYN_CASE(15, false);
+ AUDIORESAMPLERDYN_CASE(16, false);
+ AUDIORESAMPLERDYN_CASE(17, false);
+ AUDIORESAMPLERDYN_CASE(18, false);
+ AUDIORESAMPLERDYN_CASE(19, false);
+ AUDIORESAMPLERDYN_CASE(20, false);
+ AUDIORESAMPLERDYN_CASE(21, false);
+ AUDIORESAMPLERDYN_CASE(22, false);
+ AUDIORESAMPLERDYN_CASE(23, false);
+ AUDIORESAMPLERDYN_CASE(24, false);
}
}
+#pragma pop_macro("AUDIORESAMPLERDYN_CASE")
+
#ifdef DEBUG_RESAMPLER
printf("channels:%d %s stride:%d %s coef:%d shift:%d\n",
mChannelCount, locked ? "locked" : "interpolated",
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
index cf84b83..3419816 100644
--- a/media/libaudioprocessing/include/media/AudioMixerBase.h
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -45,8 +45,7 @@
{
public:
// Do not change these unless underlying code changes.
- // This mixer has a hard-coded upper limit of 8 channels for output.
- static constexpr uint32_t MAX_NUM_CHANNELS = FCC_8;
+ static constexpr uint32_t MAX_NUM_CHANNELS = FCC_LIMIT;
static constexpr uint32_t MAX_NUM_VOLUMES = FCC_2; // stereo volume only
static const uint16_t UNITY_GAIN_INT = 0x1000;
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index f838892..1551e33 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -157,7 +157,7 @@
if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
const uint32_t channelCount = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
#ifdef SUPPORT_MC
- if (channelCount < 1 || channelCount > FCC_8) return -EINVAL;
+ if (channelCount < 1 || channelCount > FCC_LIMIT) return -EINVAL;
#else
if (channelCount != FCC_2) return -EINVAL;
#endif
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/libmediaformatshaper/CodecSeeding.cpp
index cc241f4..d2ad7ac 100644
--- a/media/libmediaformatshaper/CodecSeeding.cpp
+++ b/media/libmediaformatshaper/CodecSeeding.cpp
@@ -53,6 +53,7 @@
{true, "vq-target-bpp-720p", "2.25"},
{true, "vq-target-bpp-540p", "2.65"},
{true, "vq-target-bpp-480p", "3.00"},
+ {true, "vq-target-bpp-320x240", "0"},
{true, "vq-target-qpmax", "-1"},
{true, "vq-target-qpmax-1080p", "45"},
{true, "vq-target-qpmax-720p", "43"},
@@ -69,6 +70,7 @@
{true, "vq-target-bpp-720p", "1.80"},
{true, "vq-target-bpp-540p", "2.10"},
{true, "vq-target-bpp-480p", "2.30"},
+ {true, "vq-target-bpp-320x240", "0"},
{true, "vq-target-qpmax", "-1"},
{true, "vq-target-qpmax-1080p", "45"},
{true, "vq-target-qpmax-720p", "44"},
diff --git a/media/libmediametrics/MediaMetricsItem.cpp b/media/libmediametrics/MediaMetricsItem.cpp
index a8350ea..d597a4d 100644
--- a/media/libmediametrics/MediaMetricsItem.cpp
+++ b/media/libmediametrics/MediaMetricsItem.cpp
@@ -308,6 +308,17 @@
switch (uid) {
case AID_RADIO: // telephony subsystem, RIL
return false;
+ default:
+ // Some isolated processes can access the audio system; see
+ // AudioSystem::setAudioFlingerBinder (currently only the HotwordDetectionService). Instead
+ // of also allowing access to the MediaMetrics service, it's simpler to just disable it for
+ // now.
+ // TODO(b/190151205): Either allow the HotwordDetectionService to access MediaMetrics or
+ // make this disabling specific to that process.
+ if (uid >= AID_ISOLATED_START && uid <= AID_ISOLATED_END) {
+ return false;
+ }
+ break;
}
int enabled = property_get_int32(Item::EnabledProperty, -1);
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index b1aa7a9..95afa62 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -149,7 +149,8 @@
int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid) {
if (camera == 0) {
- mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid);
+ mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__);
if (mCamera == 0) return -EBUSY;
mCameraFlags &= ~FLAGS_HOT_CAMERA;
} else {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7c90b81..f2bcebb 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -976,6 +976,10 @@
return "BufferDecoded";
case TunnelPeekState::kBufferRendered:
return "BufferRendered";
+ case TunnelPeekState::kDisabledQueued:
+ return "DisabledQueued";
+ case TunnelPeekState::kEnabledQueued:
+ return "EnabledQueued";
default:
return default_string;
}
@@ -986,25 +990,39 @@
if (!msg->findInt32("tunnel-peek", &tunnelPeek)){
return;
}
+
+ TunnelPeekState previousState = mTunnelPeekState;
if(tunnelPeek == 0){
- if (mTunnelPeekState == TunnelPeekState::kEnabledNoBuffer) {
- mTunnelPeekState = TunnelPeekState::kDisabledNoBuffer;
- ALOGV("TunnelPeekState: %s -> %s",
- asString(TunnelPeekState::kEnabledNoBuffer),
- asString(TunnelPeekState::kDisabledNoBuffer));
- return;
+ switch (mTunnelPeekState) {
+ case TunnelPeekState::kEnabledNoBuffer:
+ mTunnelPeekState = TunnelPeekState::kDisabledNoBuffer;
+ break;
+ case TunnelPeekState::kEnabledQueued:
+ mTunnelPeekState = TunnelPeekState::kDisabledQueued;
+ break;
+ default:
+ ALOGV("Ignoring tunnel-peek=%d for %s", tunnelPeek, asString(mTunnelPeekState));
+ return;
}
} else {
- if (mTunnelPeekState == TunnelPeekState::kDisabledNoBuffer) {
- mTunnelPeekState = TunnelPeekState::kEnabledNoBuffer;
- ALOGV("TunnelPeekState: %s -> %s",
- asString(TunnelPeekState::kDisabledNoBuffer),
- asString(TunnelPeekState::kEnabledNoBuffer));
- return;
+ switch (mTunnelPeekState) {
+ case TunnelPeekState::kDisabledNoBuffer:
+ mTunnelPeekState = TunnelPeekState::kEnabledNoBuffer;
+ break;
+ case TunnelPeekState::kDisabledQueued:
+ mTunnelPeekState = TunnelPeekState::kEnabledQueued;
+ break;
+ case TunnelPeekState::kBufferDecoded:
+ msg->setInt32("android._trigger-tunnel-peek", 1);
+ mTunnelPeekState = TunnelPeekState::kBufferRendered;
+ break;
+ default:
+ ALOGV("Ignoring tunnel-peek=%d for %s", tunnelPeek, asString(mTunnelPeekState));
+ return;
}
}
- ALOGV("Ignoring tunnel-peek=%d for %s", tunnelPeek, asString(mTunnelPeekState));
+ ALOGV("TunnelPeekState: %s -> %s", asString(previousState), asString(mTunnelPeekState));
}
void MediaCodec::updatePlaybackDuration(const sp<AMessage> &msg) {
@@ -3294,25 +3312,32 @@
if (mState != STARTED) {
break;
}
+ TunnelPeekState previousState = mTunnelPeekState;
switch(mTunnelPeekState) {
case TunnelPeekState::kDisabledNoBuffer:
+ case TunnelPeekState::kDisabledQueued:
mTunnelPeekState = TunnelPeekState::kBufferDecoded;
+ ALOGV("First tunnel frame ready");
ALOGV("TunnelPeekState: %s -> %s",
- asString(TunnelPeekState::kDisabledNoBuffer),
- asString(TunnelPeekState::kBufferDecoded));
+ asString(previousState),
+ asString(mTunnelPeekState));
break;
case TunnelPeekState::kEnabledNoBuffer:
- mTunnelPeekState = TunnelPeekState::kBufferDecoded;
- ALOGV("TunnelPeekState: %s -> %s",
- asString(TunnelPeekState::kEnabledNoBuffer),
- asString(TunnelPeekState::kBufferDecoded));
+ case TunnelPeekState::kEnabledQueued:
{
sp<AMessage> parameters = new AMessage();
parameters->setInt32("android._trigger-tunnel-peek", 1);
mCodec->signalSetParameters(parameters);
}
+ mTunnelPeekState = TunnelPeekState::kBufferRendered;
+ ALOGV("First tunnel frame ready");
+ ALOGV("TunnelPeekState: %s -> %s",
+ asString(previousState),
+ asString(mTunnelPeekState));
break;
default:
+ ALOGV("Ignoring first tunnel frame ready, TunnelPeekState: %s",
+ asString(mTunnelPeekState));
break;
}
@@ -4777,6 +4802,28 @@
buffer->meta()->setInt32("csd", true);
}
+ if (mTunneled) {
+ TunnelPeekState previousState = mTunnelPeekState;
+ switch(mTunnelPeekState){
+ case TunnelPeekState::kEnabledNoBuffer:
+ buffer->meta()->setInt32("tunnel-first-frame", 1);
+ mTunnelPeekState = TunnelPeekState::kEnabledQueued;
+ ALOGV("TunnelPeekState: %s -> %s",
+ asString(previousState),
+ asString(mTunnelPeekState));
+ break;
+ case TunnelPeekState::kDisabledNoBuffer:
+ buffer->meta()->setInt32("tunnel-first-frame", 1);
+ mTunnelPeekState = TunnelPeekState::kDisabledQueued;
+ ALOGV("TunnelPeekState: %s -> %s",
+ asString(previousState),
+ asString(mTunnelPeekState));
+ break;
+ default:
+ break;
+ }
+ }
+
status_t err = OK;
if (hasCryptoOrDescrambler() && !c2Buffer && !memory) {
AString *errorDetailMsg;
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index a15a988..a32bc26 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -183,7 +183,7 @@
<Feature name="adaptive-playback" />
</MediaCodec>
<MediaCodec name="c2.android.av1.decoder" type="video/av01" variant="!slow-cpu">
- <Limit name="size" min="2x2" max="1920x1080" />
+ <Limit name="size" min="2x2" max="2048x2048" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="block-count" range="1-16384" />
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 0e6f0b3..d372140 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -377,15 +377,23 @@
// This type is used to track the tunnel mode video peek state machine:
//
// DisabledNoBuffer -> EnabledNoBuffer when tunnel-peek = true
+ // DisabledQueued -> EnabledQueued when tunnel-peek = true
+ // DisabledNoBuffer -> DisabledQueued when first frame queued
// EnabledNoBuffer -> DisabledNoBuffer when tunnel-peek = false
+ // EnabledQueued -> DisabledQueued when tunnel-peek = false
+ // EnabledNoBuffer -> EnabledQueued when first frame queued
// DisabledNoBuffer -> BufferDecoded when kWhatFirstTunnelFrameReady
+ // DisabledQueued -> BufferDecoded when kWhatFirstTunnelFrameReady
// EnabledNoBuffer -> BufferDecoded when kWhatFirstTunnelFrameReady
+ // EnabledQueued -> BufferDecoded when kWhatFirstTunnelFrameReady
// BufferDecoded -> BufferRendered when kWhatFrameRendered
// <all states> -> EnabledNoBuffer when flush
// <all states> -> EnabledNoBuffer when stop then configure then start
enum struct TunnelPeekState {
kDisabledNoBuffer,
kEnabledNoBuffer,
+ kDisabledQueued,
+ kEnabledQueued,
kBufferDecoded,
kBufferRendered,
};
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index c8b4a03..4d50d66 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -74,6 +74,7 @@
MtpFfsHandle::MtpFfsHandle(int controlFd) {
mControl.reset(controlFd);
+ mBatchCancel = android::base::GetBoolProperty("sys.usb.mtp.batchcancel", false);
}
MtpFfsHandle::~MtpFfsHandle() {}
@@ -370,7 +371,7 @@
}
int MtpFfsHandle::cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start,
- unsigned end) {
+ unsigned end, bool is_batch_cancel) {
// Some manpages for io_cancel are out of date and incorrect.
// io_cancel will return -EINPROGRESS on success and does
// not place the event in the given memory. We have to use
@@ -386,6 +387,10 @@
} else {
num_events++;
}
+ if (is_batch_cancel && num_events == 1) {
+ num_events = end - start;
+ break;
+ }
}
if (num_events != end - start) {
ret = -1;
@@ -495,7 +500,8 @@
num_events += this_events;
if (event_ret == -1) {
- cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual);
+ cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual,
+ mBatchCancel);
return -1;
}
ret += event_ret;
@@ -512,7 +518,7 @@
}
}
if (short_packet) {
- if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual)) {
+ if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual, false)) {
write_error = true;
}
}
@@ -613,7 +619,7 @@
&num_events) != ret) {
error = true;
cancelEvents(mIobuf[(i-1)%NUM_IO_BUFS].iocb.data(), ioevs, num_events,
- mIobuf[(i-1)%NUM_IO_BUFS].actual);
+ mIobuf[(i-1)%NUM_IO_BUFS].actual, false);
}
has_write = false;
}
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index fe343f7..e552e03 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -17,6 +17,7 @@
#ifndef _MTP_FFS_HANDLE_H
#define _MTP_FFS_HANDLE_H
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <linux/aio_abi.h>
#include <mutex>
@@ -57,6 +58,7 @@
static int getPacketSize(int ffs_fd);
bool mCanceled;
+ bool mBatchCancel;
android::base::unique_fd mControl;
// "in" from the host's perspective => sink for mtp server
@@ -76,7 +78,8 @@
int iobufSubmit(struct io_buffer *buf, int fd, unsigned length, bool read);
// Cancel submitted requests from start to end in the given array. Return 0 or -1.
- int cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start, unsigned end);
+ int cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start, unsigned end,
+ bool is_batch_cancel);
// Wait for at minimum the given number of events. Returns the amount of data in the returned
// events. Increments counter by the number of events returned.
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index bc413d1..9c7b863 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -215,14 +215,17 @@
}
bool captureHotwordAllowed(const AttributionSourceState& attributionSource) {
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
- uid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
// CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
bool ok = recordingAllowed(attributionSource);
if (ok) {
static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
- ok = PermissionCache::checkPermission(sCaptureHotwordAllowed, pid, uid);
+ // Use PermissionChecker, which includes some logic for allowing the isolated
+ // HotwordDetectionService to hold certain permissions.
+ permission::PermissionChecker permissionChecker;
+ ok = (permissionChecker.checkPermissionForPreflight(
+ sCaptureHotwordAllowed, attributionSource, String16(),
+ AppOpsManager::OP_NONE) != permission::PermissionChecker::PERMISSION_HARD_DENIED);
}
if (!ok) ALOGV("android.permission.CAPTURE_AUDIO_HOTWORD");
return ok;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8e0de7e..54a6425 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2896,8 +2896,8 @@
audio_is_linear_pcm(config->format) &&
audio_is_linear_pcm(halconfig.format) &&
(halconfig.sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
- (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_8) &&
- (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_8)) {
+ (audio_channel_count_from_in_mask(halconfig.channel_mask) <= FCC_LIMIT) &&
+ (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT)) {
// FIXME describe the change proposed by HAL (save old values so we can log them here)
ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
inStream.clear();
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index d6d6e25..2963202 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -107,7 +107,7 @@
mSampleRate = Format_sampleRate(mFormat);
#if !LOG_NDEBUG
unsigned channelCount = Format_channelCount(mFormat);
- ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_8);
+ ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_LIMIT);
#endif
}
dumpState->mSampleRate = mSampleRate;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 13e2ced..88d4eaf 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -48,6 +48,15 @@
/*static*/ const FastMixerState FastMixer::sInitial;
+static audio_channel_mask_t getChannelMaskFromCount(size_t count) {
+ const audio_channel_mask_t mask = audio_channel_out_mask_from_count(count);
+ if (mask == AUDIO_CHANNEL_INVALID) {
+ // some counts have no positional masks. TODO: Update this to return index count?
+ return audio_channel_mask_for_index_assignment_from_count(count);
+ }
+ return mask;
+}
+
FastMixer::FastMixer(audio_io_handle_t parentIoHandle)
: FastThread("cycle_ms", "load_us"),
// mFastTrackNames
@@ -79,7 +88,7 @@
mDummyDumpState = &mDummyFastMixerDumpState;
// TODO: Add channel mask to NBAIO_Format.
// We assume that the channel mask must be a valid positional channel mask.
- mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
+ mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
unsigned i;
for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
@@ -238,7 +247,7 @@
LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
if (mSinkChannelMask == AUDIO_CHANNEL_NONE) {
- mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
+ mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
}
mAudioChannelCount = mSinkChannelCount - audio_channel_count_from_out_mask(
mSinkChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 51a41af..0929055 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -222,10 +222,23 @@
sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
+ // presentationComplete checked by frames. (Mixed Tracks).
// framesWritten is cumulative, never reset, and is shared all tracks
// audioHalFrames is derived from output latency
- // FIXME parameters not needed, could get them from the thread
bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
+
+ // presentationComplete checked by time. (Direct Tracks).
+ bool presentationComplete(uint32_t latencyMs);
+
+ void resetPresentationComplete() {
+ mPresentationCompleteFrames = 0;
+ mPresentationCompleteTimeNs = 0;
+ }
+
+ // notifyPresentationComplete is called when presentationComplete() detects
+ // that the track is finished stopping.
+ void notifyPresentationComplete();
+
void signalClientFlag(int32_t flag);
public:
@@ -256,9 +269,6 @@
int32_t *mAuxBuffer;
int mAuxEffectId;
bool mHasVolumeController;
- size_t mPresentationCompleteFrames; // number of frames written to the
- // audio HAL when this track will be fully rendered
- // zero means not monitoring
// access these three variables only when holding thread lock.
LinearMap<int64_t> mFrameMap; // track frame to server frame mapping
@@ -294,6 +304,14 @@
for (auto& tp : mTeePatches) { f(tp.patchTrack); }
};
+ size_t mPresentationCompleteFrames = 0; // (Used for Mixed tracks)
+ // The number of frames written to the
+ // audio HAL when this track is considered fully rendered.
+ // Zero means not monitoring.
+ int64_t mPresentationCompleteTimeNs = 0; // (Used for Direct tracks)
+ // The time when this track is considered fully rendered.
+ // Zero means not monitoring.
+
// The following fields are only for fast tracks, and should be in a subclass
int mFastIndex; // index within FastMixerState::mFastTracks[];
// either mFastIndex == -1 if not isFastTrack()
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8ab72a9..9e099ce 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2631,7 +2631,7 @@
}
track->mResetDone = false;
- track->mPresentationCompleteFrames = 0;
+ track->resetPresentationComplete();
mActiveTracks.add(track);
if (chain != 0) {
ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(),
@@ -6038,16 +6038,8 @@
track->isStopping_2() || track->isPaused()) {
// We have consumed all the buffers of this track.
// Remove it from the list of active tracks.
- size_t audioHALFrames;
- if (audio_has_proportional_frames(mFormat)) {
- audioHALFrames = (latency_l() * mSampleRate) / 1000;
- } else {
- audioHALFrames = 0;
- }
-
- int64_t framesWritten = mBytesWritten / mFrameSize;
if (mStandby || !last ||
- track->presentationComplete(framesWritten, audioHALFrames) ||
+ track->presentationComplete(latency_l()) ||
track->isPaused() || mHwPaused) {
if (track->isStopping_2()) {
track->mState = TrackBase::STOPPED;
@@ -6621,14 +6613,7 @@
// Drain has completed or we are in standby, signal presentation complete
if (!(mDrainSequence & 1) || !last || mStandby) {
track->mState = TrackBase::STOPPED;
- uint32_t latency = 0;
- status_t result = mOutput->stream->getLatency(&latency);
- ALOGE_IF(result != OK,
- "Error when retrieving output stream latency: %d", result);
- size_t audioHALFrames = (latency * mSampleRate) / 1000;
- int64_t framesWritten =
- mBytesWritten / mOutput->getFrameSize();
- track->presentationComplete(framesWritten, audioHALFrames);
+ track->presentationComplete(latency_l());
track->reset();
tracksToRemove->add(track);
// OFFLOADED stop resets frame counts.
@@ -8573,7 +8558,7 @@
if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
audio_channel_mask_t mask = (audio_channel_mask_t) value;
if (!audio_is_input_channel(mask) ||
- audio_channel_count_from_in_mask(mask) > FCC_8) {
+ audio_channel_count_from_in_mask(mask) > FCC_LIMIT) {
status = BAD_VALUE;
} else {
channelMask = mask;
@@ -8610,7 +8595,7 @@
if (mInput->stream->getAudioProperties(&config) == OK &&
audio_is_linear_pcm(config.format) && audio_is_linear_pcm(reqFormat) &&
config.sample_rate <= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate) &&
- audio_channel_count_from_in_mask(config.channel_mask) <= FCC_8) {
+ audio_channel_count_from_in_mask(config.channel_mask) <= FCC_LIMIT) {
status = NO_ERROR;
}
}
@@ -8672,10 +8657,10 @@
mFormat = mHALFormat;
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
if (audio_is_linear_pcm(mFormat)) {
- LOG_ALWAYS_FATAL_IF(mChannelCount > FCC_8, "HAL channel count %d > %d",
- mChannelCount, FCC_8);
+ LOG_ALWAYS_FATAL_IF(mChannelCount > FCC_LIMIT, "HAL channel count %d > %d",
+ mChannelCount, FCC_LIMIT);
} else {
- // Can have more that FCC_8 channels in encoded streams.
+ // Can have more that FCC_LIMIT channels in encoded streams.
ALOGI("HAL format %#x is not linear pcm", mFormat);
}
result = mInput->stream->getFrameSize(&mFrameSize);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 57ff0d7..8d98afe 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -650,7 +650,6 @@
mMainBuffer(thread->sinkBuffer()),
mAuxBuffer(NULL),
mAuxEffectId(0), mHasVolumeController(false),
- mPresentationCompleteFrames(0),
mFrameMap(16 /* sink-frame-to-track-frame map memory */),
mVolumeHandler(new media::VolumeHandler(sampleRate)),
mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(attributionSource, attr, id(),
@@ -1462,6 +1461,7 @@
mAuxBuffer = buffer;
}
+// presentationComplete verified by frames, used by Mixed tracks.
bool AudioFlinger::PlaybackThread::Track::presentationComplete(
int64_t framesWritten, size_t audioHalFrames)
{
@@ -1480,30 +1480,70 @@
(long long)mPresentationCompleteFrames, (long long)framesWritten);
if (mPresentationCompleteFrames == 0) {
mPresentationCompleteFrames = framesWritten + audioHalFrames;
- ALOGV("%s(%d): presentationComplete() reset:"
+ ALOGV("%s(%d): set:"
" mPresentationCompleteFrames %lld audioHalFrames %zu",
__func__, mId,
(long long)mPresentationCompleteFrames, audioHalFrames);
}
bool complete;
- if (isOffloaded()) {
- complete = true;
- } else if (isDirect() || isFastTrack()) { // these do not go through linear map
+ if (isFastTrack()) { // does not go through linear map
complete = framesWritten >= (int64_t) mPresentationCompleteFrames;
+ ALOGV("%s(%d): %s framesWritten:%lld mPresentationCompleteFrames:%lld",
+ __func__, mId, (complete ? "complete" : "waiting"),
+ (long long) framesWritten, (long long) mPresentationCompleteFrames);
} else { // Normal tracks, OutputTracks, and PatchTracks
complete = framesWritten >= (int64_t) mPresentationCompleteFrames
&& mAudioTrackServerProxy->isDrained();
}
if (complete) {
- triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
- mAudioTrackServerProxy->setStreamEndDone();
+ notifyPresentationComplete();
return true;
}
return false;
}
+// presentationComplete checked by time, used by DirectTracks.
+bool AudioFlinger::PlaybackThread::Track::presentationComplete(uint32_t latencyMs)
+{
+ // For Offloaded or Direct tracks.
+
+ // For a direct track, we incorporated time based testing for presentationComplete.
+
+ // For an offloaded track the HAL+h/w delay is variable so a HAL drain() is used
+ // to detect when all frames have been played. In this case latencyMs isn't
+ // useful because it doesn't always reflect whether there is data in the h/w
+ // buffers, particularly if a track has been paused and resumed during draining
+
+ constexpr float MIN_SPEED = 0.125f; // min speed scaling allowed for timely response.
+ if (mPresentationCompleteTimeNs == 0) {
+ mPresentationCompleteTimeNs = systemTime() + latencyMs * 1e6 / fmax(mSpeed, MIN_SPEED);
+ ALOGV("%s(%d): set: latencyMs %u mPresentationCompleteTimeNs:%lld",
+ __func__, mId, latencyMs, (long long) mPresentationCompleteTimeNs);
+ }
+
+ bool complete;
+ if (isOffloaded()) {
+ complete = true;
+ } else { // Direct
+ complete = systemTime() >= mPresentationCompleteTimeNs;
+ ALOGV("%s(%d): %s", __func__, mId, (complete ? "complete" : "waiting"));
+ }
+ if (complete) {
+ notifyPresentationComplete();
+ return true;
+ }
+ return false;
+}
+
+void AudioFlinger::PlaybackThread::Track::notifyPresentationComplete()
+{
+ // This only triggers once. TODO: should we enforce this?
+ triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
+ mAudioTrackServerProxy->setStreamEndDone();
+}
+
void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
{
for (size_t i = 0; i < mSyncEvents.size();) {
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 552919d..577f641 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -42,7 +42,7 @@
// For mixed output and inputs, the policy will use max mixer channel count.
// Do not limit channel count otherwise
-#define MAX_MIXER_CHANNEL_COUNT FCC_8
+#define MAX_MIXER_CHANNEL_COUNT FCC_LIMIT
/**
* Alias to AUDIO_DEVICE_OUT_DEFAULT defined for clarification when this value is used by volume
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 1c86051..81e803f 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -139,11 +139,24 @@
Collection &collection);
};
-using xmlCharUnique = std::unique_ptr<xmlChar, decltype(xmlFree)>;
+template <class T>
+constexpr void (*xmlDeleter)(T* t);
+template <>
+constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
+template <>
+constexpr auto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };
+
+/** @return a unique_ptr with the correct deleter for the libxml2 object. */
+template <class T>
+constexpr auto make_xmlUnique(T *t) {
+ // Wrap deleter in lambda to enable empty base optimization
+ auto deleter = [](T *t) { xmlDeleter<T>(t); };
+ return std::unique_ptr<T, decltype(deleter)>{t, deleter};
+}
std::string getXmlAttribute(const xmlNode *cur, const char *attribute)
{
- xmlCharUnique charPtr(xmlGetProp(cur, reinterpret_cast<const xmlChar *>(attribute)), xmlFree);
+ auto charPtr = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar *>(attribute)));
if (charPtr == NULL) {
return "";
}
@@ -441,7 +454,7 @@
for (const xmlNode *child = referenceName.empty() ?
root->xmlChildrenNode : ref->xmlChildrenNode; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, (const xmlChar *)volumePointTag)) {
- xmlCharUnique pointXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
+ auto pointXml = make_xmlUnique(xmlNodeListGetString(doc, child->xmlChildrenNode, 1));
if (pointXml == NULL) {
return BAD_VALUE;
}
@@ -471,14 +484,14 @@
for (const xmlNode *child = root->xmlChildrenNode; child != NULL; child = child->next) {
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::name)) {
- xmlCharUnique nameXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
+ auto nameXml = make_xmlUnique(xmlNodeListGetString(doc, child->xmlChildrenNode, 1));
if (nameXml == nullptr) {
return BAD_VALUE;
}
name = reinterpret_cast<const char*>(nameXml.get());
}
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::indexMin)) {
- xmlCharUnique indexMinXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
+ auto indexMinXml = make_xmlUnique(xmlNodeListGetString(doc, child->xmlChildrenNode, 1));
if (indexMinXml == nullptr) {
return BAD_VALUE;
}
@@ -488,7 +501,7 @@
}
}
if (not xmlStrcmp(child->name, (const xmlChar *)Attributes::indexMax)) {
- xmlCharUnique indexMaxXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
+ auto indexMaxXml = make_xmlUnique(xmlNodeListGetString(doc, child->xmlChildrenNode, 1));
if (indexMaxXml == nullptr) {
return BAD_VALUE;
}
@@ -548,7 +561,7 @@
for (const xmlNode *child = referenceName.empty() ?
cur->xmlChildrenNode : ref->xmlChildrenNode; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, (const xmlChar *)VolumeTraits::volumePointTag)) {
- xmlCharUnique pointXml(xmlNodeListGetString(doc, child->xmlChildrenNode, 1), xmlFree);
+ auto pointXml = make_xmlUnique(xmlNodeListGetString(doc, child->xmlChildrenNode, 1));
if (pointXml == NULL) {
return BAD_VALUE;
}
@@ -640,8 +653,7 @@
ParsingResult parse(const char* path) {
XmlErrorHandler errorHandler;
- xmlDocPtr doc;
- doc = xmlParseFile(path);
+ auto doc = make_xmlUnique(xmlParseFile(path));
if (doc == NULL) {
// It is OK not to find an engine config file at the default location
// as the caller will default to hardcoded default config
@@ -650,13 +662,12 @@
}
return {nullptr, 0};
}
- xmlNodePtr cur = xmlDocGetRootElement(doc);
+ xmlNodePtr cur = xmlDocGetRootElement(doc.get());
if (cur == NULL) {
ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
- xmlFreeDoc(doc);
return {nullptr, 0};
}
- if (xmlXIncludeProcess(doc) < 0) {
+ if (xmlXIncludeProcess(doc.get()) < 0) {
ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
return {nullptr, 0};
}
@@ -669,37 +680,35 @@
auto config = std::make_unique<Config>();
config->version = std::stof(version);
deserializeCollection<ProductStrategyTraits>(
- doc, cur, config->productStrategies, nbSkippedElements);
+ doc.get(), cur, config->productStrategies, nbSkippedElements);
deserializeCollection<CriterionTraits>(
- doc, cur, config->criteria, nbSkippedElements);
+ doc.get(), cur, config->criteria, nbSkippedElements);
deserializeCollection<CriterionTypeTraits>(
- doc, cur, config->criterionTypes, nbSkippedElements);
+ doc.get(), cur, config->criterionTypes, nbSkippedElements);
deserializeCollection<VolumeGroupTraits>(
- doc, cur, config->volumeGroups, nbSkippedElements);
+ doc.get(), cur, config->volumeGroups, nbSkippedElements);
return {std::move(config), nbSkippedElements};
}
android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups) {
XmlErrorHandler errorHandler;
- xmlDocPtr doc;
- doc = xmlParseFile(path);
+ auto doc = make_xmlUnique(xmlParseFile(path));
if (doc == NULL) {
ALOGE("%s: Could not parse document %s", __FUNCTION__, path);
return BAD_VALUE;
}
- xmlNodePtr cur = xmlDocGetRootElement(doc);
+ xmlNodePtr cur = xmlDocGetRootElement(doc.get());
if (cur == NULL) {
ALOGE("%s: Could not parse: empty document %s", __FUNCTION__, path);
- xmlFreeDoc(doc);
return BAD_VALUE;
}
- if (xmlXIncludeProcess(doc) < 0) {
+ if (xmlXIncludeProcess(doc.get()) < 0) {
ALOGE("%s: libxml failed to resolve XIncludes on document %s", __FUNCTION__, path);
return BAD_VALUE;
}
size_t nbSkippedElements = 0;
- return deserializeLegacyVolumeCollection(doc, cur, volumeGroups, nbSkippedElements);
+ return deserializeLegacyVolumeCollection(doc.get(), cur, volumeGroups, nbSkippedElements);
}
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups) {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index cd50e21..201273e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -786,7 +786,7 @@
allowCapture = true;
}
}
- setAppState_l(current->portId,
+ setAppState_l(current,
allowCapture ? apmStatFromAmState(mUidPolicy->getUidState(currentUid)) :
APP_STATE_IDLE);
}
@@ -796,7 +796,7 @@
for (size_t i = 0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
if (!isVirtualSource(current->attributes.source)) {
- setAppState_l(current->portId, APP_STATE_IDLE);
+ setAppState_l(current, APP_STATE_IDLE);
}
}
}
@@ -830,17 +830,32 @@
return false;
}
-void AudioPolicyService::setAppState_l(audio_port_handle_t portId, app_state_t state)
+void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state)
{
AutoCallerClear acc;
if (mAudioPolicyManager) {
- mAudioPolicyManager->setAppState(portId, state);
+ mAudioPolicyManager->setAppState(client->portId, state);
}
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af) {
bool silenced = state == APP_STATE_IDLE;
- af->setRecordSilenced(portId, silenced);
+ if (client->silenced != silenced) {
+ if (client->active) {
+ if (silenced) {
+ finishRecording(client->attributionSource, client->attributes.source);
+ } else {
+ std::stringstream msg;
+ msg << "Audio recording un-silenced on session " << client->session;
+ if (!startRecording(client->attributionSource, String16(msg.str().c_str()),
+ client->attributes.source)) {
+ silenced = true;
+ }
+ }
+ }
+ af->setRecordSilenced(client->portId, silenced);
+ client->silenced = silenced;
+ }
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 48da40c..ac9c20f 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -324,8 +324,10 @@
// Handles binder shell commands
virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
+ class AudioRecordClient;
+
// Sets whether the given UID records only silence
- virtual void setAppState_l(audio_port_handle_t portId, app_state_t state) REQUIRES(mLock);
+ virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mLock);
// Overrides the UID state as if it is idle
status_t handleSetUidState(Vector<String16>& args, int err);
@@ -826,13 +828,14 @@
AudioClient(attributes, io, attributionSource,
session, portId, deviceId), attributionSource(attributionSource),
startTimeNs(0), canCaptureOutput(canCaptureOutput),
- canCaptureHotword(canCaptureHotword) {}
+ canCaptureHotword(canCaptureHotword), silenced(false) {}
~AudioRecordClient() override = default;
const AttributionSourceState attributionSource; // attribution source of client
nsecs_t startTimeNs;
const bool canCaptureOutput;
const bool canCaptureHotword;
+ bool silenced;
};
// --- AudioPlaybackClient ---
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 83d2bc9..3deea6b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -85,6 +85,7 @@
using base::StringPrintf;
using binder::Status;
+using camera3::SessionConfigurationUtils;
using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
using hardware::ICamera;
using hardware::ICameraClient;
@@ -131,7 +132,7 @@
"android.permission.CAMERA_OPEN_CLOSE_LISTENER");
static const String16
sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
-
+const char *sFileName = "lastOpenSessionDumpFile";
static constexpr int32_t kVendorClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
static constexpr int32_t kVendorClientState = ActivityManager::PROCESS_STATE_PERSISTENT_UI;
@@ -148,6 +149,10 @@
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
mServiceLockWrapper = std::make_shared<WaitableMutexWrapper>(&mServiceLock);
+ mMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+ if (mMemFd == -1) {
+ ALOGE("%s: Error while creating the file: %s", __FUNCTION__, sFileName);
+ }
}
void CameraService::onFirstRef()
@@ -234,7 +239,9 @@
//Derive primary rear/front cameras, and filter their charactierstics.
//This needs to be done after all cameras are enumerated and camera ids are sorted.
- filterSPerfClassCharacteristics();
+ if (SessionConfigurationUtils::IS_PERF_CLASS) {
+ filterSPerfClassCharacteristics();
+ }
return OK;
}
@@ -307,12 +314,6 @@
}
void CameraService::filterSPerfClassCharacteristics() {
- static int32_t kPerformanceClassLevel =
- property_get_int32("ro.odm.build.media_performance_class", 0);
- static bool kIsSPerformanceClass = (kPerformanceClassLevel == 31);
-
- if (!kIsSPerformanceClass) return;
-
// To claim to be S Performance primary cameras, the cameras must be
// backward compatible. So performance class primary camera Ids must be API1
// compatible.
@@ -329,7 +330,14 @@
if ((facing == hardware::CAMERA_FACING_BACK && !firstRearCameraSeen) ||
(facing == hardware::CAMERA_FACING_FRONT && !firstFrontCameraSeen)) {
- mCameraProviderManager->filterSmallJpegSizes(cameraId);
+ status_t res = mCameraProviderManager->filterSmallJpegSizes(cameraId);
+ if (res == OK) {
+ mPerfClassPrimaryCameraIds.insert(cameraId);
+ } else {
+ ALOGE("%s: Failed to filter small JPEG sizes for performance class primary "
+ "camera %s: %s(%d)", __FUNCTION__, cameraId.c_str(), strerror(-res), res);
+ break;
+ }
if (facing == hardware::CAMERA_FACING_BACK) {
firstRearCameraSeen = true;
@@ -698,7 +706,7 @@
}
Status CameraService::getCameraCharacteristics(const String16& cameraId,
- CameraMetadata* cameraInfo) {
+ int targetSdkVersion, CameraMetadata* cameraInfo) {
ATRACE_CALL();
if (!cameraInfo) {
ALOGE("%s: cameraInfo is NULL", __FUNCTION__);
@@ -719,8 +727,13 @@
Status ret{};
+
+ std::string cameraIdStr = String8(cameraId).string();
+ bool overrideForPerfClass =
+ SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds,
+ cameraIdStr, targetSdkVersion);
status_t res = mCameraProviderManager->getCameraCharacteristics(
- String8(cameraId).string(), cameraInfo);
+ cameraIdStr, overrideForPerfClass, cameraInfo);
if (res != OK) {
if (res == NAME_NOT_FOUND) {
return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to retrieve camera "
@@ -862,7 +875,7 @@
const sp<IInterface>& cameraCb, const String16& packageName,
const std::optional<String16>& featureId, const String8& cameraId,
int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
- int servicePid, int deviceVersion, apiLevel effectiveApiLevel,
+ int servicePid, int deviceVersion, apiLevel effectiveApiLevel, bool overrideForPerfClass,
/*out*/sp<BasicClient>* client) {
// Create CameraClient based on device version reported by the HAL.
@@ -886,12 +899,13 @@
*client = new Camera2Client(cameraService, tmp, packageName, featureId,
cameraId, api1CameraId,
facing, sensorOrientation, clientPid, clientUid,
- servicePid);
+ servicePid, overrideForPerfClass);
} else { // Camera2 API route
sp<hardware::camera2::ICameraDeviceCallbacks> tmp =
static_cast<hardware::camera2::ICameraDeviceCallbacks*>(cameraCb.get());
*client = new CameraDeviceClient(cameraService, tmp, packageName, featureId,
- cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid);
+ cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid,
+ overrideForPerfClass);
}
break;
default:
@@ -988,7 +1002,8 @@
if (!(ret = connectHelper<ICameraClient,Client>(
sp<ICameraClient>{nullptr}, id, cameraId,
internalPackageName, {}, uid, USE_CALLING_PID,
- API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0, /*out*/ tmp)
+ API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
+ /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*out*/ tmp)
).isOk()) {
ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string());
}
@@ -1503,6 +1518,7 @@
const String16& clientPackageName,
int clientUid,
int clientPid,
+ int targetSdkVersion,
/*out*/
sp<ICamera>* device) {
@@ -1513,7 +1529,7 @@
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
clientPackageName, {}, clientUid, clientPid, API_1,
- /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, /*out*/client);
+ /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, /*out*/client);
if(!ret.isOk()) {
logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
@@ -1589,7 +1605,7 @@
const String16& cameraId,
const String16& clientPackageName,
const std::optional<String16>& clientFeatureId,
- int clientUid, int oomScoreOffset,
+ int clientUid, int oomScoreOffset, int targetSdkVersion,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device) {
@@ -1629,7 +1645,7 @@
ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
/*api1CameraId*/-1, clientPackageNameAdj, clientFeatureId,
clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
- /*out*/client);
+ targetSdkVersion, /*out*/client);
if(!ret.isOk()) {
logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8());
@@ -1637,6 +1653,22 @@
}
*device = client;
+ Mutex::Autolock lock(mServiceLock);
+
+ // Clear the previous cached logs and reposition the
+ // file offset to beginning of the file to log new data.
+ // If either truncate or lseek fails, close the previous file and create a new one.
+ if ((ftruncate(mMemFd, 0) == -1) || (lseek(mMemFd, 0, SEEK_SET) == -1)) {
+ ALOGE("%s: Error while truncating the file: %s", __FUNCTION__, sFileName);
+ // Close the previous memfd.
+ close(mMemFd);
+ // If failure to wipe the data, then create a new file and
+ // assign the new value to mMemFd.
+ mMemFd = memfd_create(sFileName, MFD_ALLOW_SEALING);
+ if (mMemFd == -1) {
+ ALOGE("%s: Error while creating the file: %s", __FUNCTION__, sFileName);
+ }
+ }
return ret;
}
@@ -1644,7 +1676,7 @@
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, const String16& clientPackageName,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
- apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset,
+ apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
/*out*/sp<CLIENT>& device) {
binder::Status ret = binder::Status::ok();
@@ -1734,10 +1766,12 @@
}
sp<BasicClient> tmp = nullptr;
+ bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+ mPerfClassPrimaryCameraIds, cameraId.string(), targetSdkVersion);
if(!(ret = makeClient(this, cameraCb, clientPackageName, clientFeatureId,
cameraId, api1CameraId, facing, orientation,
clientPid, clientUid, getpid(),
- deviceVersion, effectiveApiLevel,
+ deviceVersion, effectiveApiLevel, overrideForPerfClass,
/*out*/&tmp)).isOk()) {
return ret;
}
@@ -2212,7 +2246,7 @@
Status CameraService::isConcurrentSessionConfigurationSupported(
const std::vector<CameraIdAndSessionConfiguration>& cameraIdsAndSessionConfigurations,
- /*out*/bool* isSupported) {
+ int targetSdkVersion, /*out*/bool* isSupported) {
if (!isSupported) {
ALOGE("%s: isSupported is NULL", __FUNCTION__);
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "isSupported is NULL");
@@ -2236,7 +2270,8 @@
status_t res =
mCameraProviderManager->isConcurrentSessionConfigurationSupported(
- cameraIdsAndSessionConfigurations, isSupported);
+ cameraIdsAndSessionConfigurations, mPerfClassPrimaryCameraIds,
+ targetSdkVersion, isSupported);
if (res != OK) {
logServiceError(String8::format("Unable to query session configuration support"),
ERROR_INVALID_OPERATION);
@@ -3832,6 +3867,28 @@
return locked;
}
+void CameraService::cacheDump() {
+ if (mMemFd != -1) {
+ const Vector<String16> args;
+ ATRACE_CALL();
+ // Acquiring service lock here will avoid the deadlock since
+ // cacheDump will not be called during the second disconnect.
+ Mutex::Autolock lock(mServiceLock);
+
+ Mutex::Autolock l(mCameraStatesLock);
+ // Start collecting the info for open sessions and store it in temp file.
+ for (const auto& state : mCameraStates) {
+ String8 cameraId = state.first;
+ auto clientDescriptor = mActiveClientManager.get(cameraId);
+ if (clientDescriptor != nullptr) {
+ dprintf(mMemFd, "== Camera device %s dynamic info: ==\n", cameraId.string());
+ // Log the current open session info before device is disconnected.
+ dumpOpenSessionClientLogs(mMemFd, args, cameraId);
+ }
+ }
+ }
+}
+
status_t CameraService::dump(int fd, const Vector<String16>& args) {
ATRACE_CALL();
@@ -3898,21 +3955,10 @@
auto clientDescriptor = mActiveClientManager.get(cameraId);
if (clientDescriptor != nullptr) {
- dprintf(fd, " Device %s is open. Client instance dump:\n",
- cameraId.string());
- dprintf(fd, " Client priority score: %d state: %d\n",
- clientDescriptor->getPriority().getScore(),
- clientDescriptor->getPriority().getState());
- dprintf(fd, " Client PID: %d\n", clientDescriptor->getOwnerId());
-
- auto client = clientDescriptor->getValue();
- dprintf(fd, " Client package: %s\n",
- String8(client->getPackageName()).string());
-
- client->dumpClient(fd, args);
+ // log the current open session info
+ dumpOpenSessionClientLogs(fd, args, cameraId);
} else {
- dprintf(fd, " Device %s is closed, no client instance\n",
- cameraId.string());
+ dumpClosedSessionClientLogs(fd, cameraId);
}
}
@@ -3969,9 +4015,55 @@
}
}
}
+
+ bool serviceLocked = tryLock(mServiceLock);
+
+ // Dump info from previous open sessions.
+ // Reposition the offset to beginning of the file before reading
+
+ if ((mMemFd >= 0) && (lseek(mMemFd, 0, SEEK_SET) != -1)) {
+ dprintf(fd, "\n**********Dumpsys from previous open session**********\n");
+ ssize_t size_read;
+ char buf[4096];
+ while ((size_read = read(mMemFd, buf, (sizeof(buf) - 1))) > 0) {
+ // Read data from file to a small buffer and write it to fd.
+ write(fd, buf, size_read);
+ if (size_read == -1) {
+ ALOGE("%s: Error during reading the file: %s", __FUNCTION__, sFileName);
+ break;
+ }
+ }
+ dprintf(fd, "\n**********End of Dumpsys from previous open session**********\n");
+ } else {
+ ALOGE("%s: Error during reading the file: %s", __FUNCTION__, sFileName);
+ }
+
+ if (serviceLocked) mServiceLock.unlock();
return NO_ERROR;
}
+void CameraService::dumpOpenSessionClientLogs(int fd,
+ const Vector<String16>& args, const String8& cameraId) {
+ auto clientDescriptor = mActiveClientManager.get(cameraId);
+ dprintf(fd, " Device %s is open. Client instance dump:\n",
+ cameraId.string());
+ dprintf(fd, " Client priority score: %d state: %d\n",
+ clientDescriptor->getPriority().getScore(),
+ clientDescriptor->getPriority().getState());
+ dprintf(fd, " Client PID: %d\n", clientDescriptor->getOwnerId());
+
+ auto client = clientDescriptor->getValue();
+ dprintf(fd, " Client package: %s\n",
+ String8(client->getPackageName()).string());
+
+ client->dumpClient(fd, args);
+}
+
+void CameraService::dumpClosedSessionClientLogs(int fd, const String8& cameraId) {
+ dprintf(fd, " Device %s is closed, no client instance\n",
+ cameraId.string());
+}
+
void CameraService::dumpEventLog(int fd) {
dprintf(fd, "\n== Camera service events log (most recent at top): ==\n");
@@ -4051,25 +4143,13 @@
ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
return;
}
- bool supportsHAL3 = false;
- // supportsCameraApi also holds mInterfaceMutex, we can't call it in the
- // HIDL onStatusChanged wrapper call (we'll hold mStatusListenerLock and
- // mInterfaceMutex together, which can lead to deadlocks)
- binder::Status sRet =
- supportsCameraApi(String16(cameraId), hardware::ICameraService::API_VERSION_2,
- &supportsHAL3);
- if (!sRet.isOk()) {
- ALOGW("%s: Failed to determine if device supports HAL3 %s, supportsCameraApi call failed",
- __FUNCTION__, cameraId.string());
- return;
- }
// Collect the logical cameras without holding mStatusLock in updateStatus
// as that can lead to a deadlock(b/162192331).
auto logicalCameraIds = getLogicalCameras(cameraId);
// Update the status for this camera state, then send the onStatusChangedCallbacks to each
// of the listeners with both the mStatusLock and mStatusListenerLock held
- state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &supportsHAL3,
+ state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind,
&logicalCameraIds]
(const String8& cameraId, StatusInternal status) {
@@ -4097,8 +4177,8 @@
bool isVendorListener = listener->isVendorListener();
if (shouldSkipStatusUpdates(deviceKind, isVendorListener,
listener->getListenerPid(), listener->getListenerUid()) ||
- (isVendorListener && !supportsHAL3)) {
- ALOGV("Skipping discovery callback for system-only camera/HAL1 device %s",
+ isVendorListener) {
+ ALOGV("Skipping discovery callback for system-only camera device %s",
cameraId.c_str());
continue;
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index d1ed59a..1fb7104 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -121,7 +121,7 @@
virtual binder::Status getCameraInfo(int cameraId,
hardware::CameraInfo* cameraInfo);
virtual binder::Status getCameraCharacteristics(const String16& cameraId,
- CameraMetadata* cameraInfo);
+ int targetSdkVersion, CameraMetadata* cameraInfo);
virtual binder::Status getCameraVendorTagDescriptor(
/*out*/
hardware::camera2::params::VendorTagDescriptor* desc);
@@ -131,14 +131,14 @@
virtual binder::Status connect(const sp<hardware::ICameraClient>& cameraClient,
int32_t cameraId, const String16& clientPackageName,
- int32_t clientUid, int clientPid,
+ int32_t clientUid, int clientPid, int targetSdkVersion,
/*out*/
sp<hardware::ICamera>* device);
virtual binder::Status connectDevice(
const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
- int32_t clientUid, int scoreOffset,
+ int32_t clientUid, int scoreOffset, int targetSdkVersion,
/*out*/
sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -154,7 +154,7 @@
virtual binder::Status isConcurrentSessionConfigurationSupported(
const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>& sessions,
- /*out*/bool* supported);
+ int targetSdkVersion, /*out*/bool* supported);
virtual binder::Status getLegacyParameters(
int32_t cameraId,
@@ -205,6 +205,9 @@
// Monitored UIDs availability notification
void notifyMonitoredUids();
+ // Stores current open session device info in temp file.
+ void cacheDump();
+
// Register an offline client for a given active camera id
status_t addOfflineClient(String8 cameraId, sp<BasicClient> offlineClient);
@@ -773,7 +776,7 @@
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
int api1CameraId, const String16& clientPackageName,
const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
- apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset,
+ apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
/*out*/sp<CLIENT>& device);
// Lock guarding camera service state
@@ -788,6 +791,12 @@
// Container for managing currently active application-layer clients
CameraClientManager mActiveClientManager;
+ // Adds client logs during open session to the file pointed by fd.
+ void dumpOpenSessionClientLogs(int fd, const Vector<String16>& args, const String8& cameraId);
+
+ // Adds client logs during closed session to the file pointed by fd.
+ void dumpClosedSessionClientLogs(int fd, const String8& cameraId);
+
// Mapping from camera ID -> state for each device, map is protected by mCameraStatesLock
std::map<String8, std::shared_ptr<CameraState>> mCameraStates;
@@ -940,6 +949,10 @@
*/
void filterSPerfClassCharacteristics();
+ // File descriptor to temp file used for caching previous open
+ // session dumpsys info.
+ int mMemFd;
+
// Number of camera devices (excluding hidden secure cameras)
int mNumberOfCameras;
// Number of camera devices (excluding hidden secure cameras and
@@ -948,6 +961,7 @@
std::vector<std::string> mNormalDeviceIds;
std::vector<std::string> mNormalDeviceIdsWithoutSystemCamera;
+ std::set<std::string> mPerfClassPrimaryCameraIds;
// sounds
sp<MediaPlayer> newMediaPlayer(const char *file);
@@ -1128,7 +1142,7 @@
const sp<IInterface>& cameraCb, const String16& packageName,
const std::optional<String16>& featureId, const String8& cameraId, int api1CameraId,
int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid,
- int deviceVersion, apiLevel effectiveApiLevel,
+ int deviceVersion, apiLevel effectiveApiLevel, bool overrideForPerfClass,
/*out*/sp<BasicClient>* client);
status_t checkCameraAccess(const String16& opPackageName);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 72b3c40..944b8ab 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -58,10 +58,11 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid):
+ int servicePid,
+ bool overrideForPerfClass):
Camera2ClientBase(cameraService, cameraClient, clientPackageName, clientFeatureId,
cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation,
- clientPid, clientUid, servicePid),
+ clientPid, clientUid, servicePid, overrideForPerfClass),
mParameters(api1CameraId, cameraFacing)
{
ATRACE_CALL();
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index d16b242..64ab8ff 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -104,7 +104,8 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid);
+ int servicePid,
+ bool overrideForPerfClass);
virtual ~Camera2Client();
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 343f4a7..1f3d478 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -52,6 +52,7 @@
namespace android {
using namespace camera2;
using camera3::camera_stream_rotation_t::CAMERA_STREAM_ROTATION_0;
+using camera3::SessionConfigurationUtils;
CameraDeviceClientBase::CameraDeviceClientBase(
const sp<CameraService>& cameraService,
@@ -91,13 +92,15 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid) :
+ int servicePid,
+ bool overrideForPerfClass) :
Camera2ClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
- cameraId, /*API1 camera ID*/ -1,
- cameraFacing, sensorOrientation, clientPid, clientUid, servicePid),
+ cameraId, /*API1 camera ID*/ -1, cameraFacing, sensorOrientation,
+ clientPid, clientUid, servicePid, overrideForPerfClass),
mInputStream(),
mStreamingRequestId(REQUEST_ID_NONE),
- mRequestIdCounter(0) {
+ mRequestIdCounter(0),
+ mOverrideForPerfClass(overrideForPerfClass) {
ATRACE_CALL();
ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
@@ -537,7 +540,7 @@
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- res = camera3::SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
+ res = SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
mCameraIdStr);
if (!res.isOk()) {
return res;
@@ -616,7 +619,7 @@
}
auto operatingMode = sessionConfiguration.getOperatingMode();
- res = camera3::SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
+ res = SessionConfigurationUtils::checkOperatingMode(operatingMode, mDevice->info(),
mCameraIdStr);
if (!res.isOk()) {
return res;
@@ -627,14 +630,16 @@
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
+
hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
bool earlyExit = false;
- metadataGetter getMetadata = [this](const String8 &id) {return mDevice->infoPhysical(id);};
+ camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+ return mDevice->infoPhysical(id);};
std::vector<std::string> physicalCameraIds;
mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
- res = camera3::SessionConfigurationUtils::convertToHALStreamCombination(sessionConfiguration,
+ res = SessionConfigurationUtils::convertToHALStreamCombination(sessionConfiguration,
mCameraIdStr, mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration,
- &earlyExit);
+ mOverrideForPerfClass, &earlyExit);
if (!res.isOk()) {
return res;
}
@@ -790,7 +795,7 @@
bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
bool isMultiResolution = outputConfiguration.isMultiResolution();
- res = camera3::SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
+ res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
outputConfiguration.getSurfaceType());
if (!res.isOk()) {
return res;
@@ -799,7 +804,7 @@
if (!mDevice.get()) {
return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
}
- res = camera3::SessionConfigurationUtils::checkPhysicalCameraId(mPhysicalCameraIds,
+ res = SessionConfigurationUtils::checkPhysicalCameraId(mPhysicalCameraIds,
physicalCameraId, mCameraIdStr);
if (!res.isOk()) {
return res;
@@ -830,7 +835,7 @@
}
sp<Surface> surface;
- res = camera3::SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
+ res = SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
isStreamInfoValid, surface, bufferProducer, mCameraIdStr,
mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed);
@@ -844,6 +849,11 @@
binders.push_back(IInterface::asBinder(bufferProducer));
surfaces.push_back(surface);
}
+
+ // If mOverrideForPerfClass is true, do not fail createStream() for small
+ // JPEG sizes because existing createSurfaceFromGbp() logic will find the
+ // closest possible supported size.
+
int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
std::vector<int> surfaceIds;
bool isDepthCompositeStream =
@@ -951,7 +961,7 @@
std::unordered_set<int32_t> overriddenSensorPixelModesUsed;
const std::vector<int32_t> &sensorPixelModesUsed =
outputConfiguration.getSensorPixelModesUsed();
- if (camera3::SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
+ if (SessionConfigurationUtils::checkAndOverrideSensorPixelModesUsed(
sensorPixelModesUsed, format, width, height, getStaticInfo(cameraIdUsed),
/*allowRounding*/ false, &overriddenSensorPixelModesUsed) != OK) {
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
@@ -1170,7 +1180,7 @@
for (size_t i = 0; i < newOutputsMap.size(); i++) {
OutputStreamInfo outInfo;
sp<Surface> surface;
- res = camera3::SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
+ res = SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
/*isStreamInfoValid*/ false, surface, newOutputsMap.valueAt(i), mCameraIdStr,
mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed);
if (!res.isOk())
@@ -1539,7 +1549,7 @@
}
sp<Surface> surface;
- res = camera3::SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
+ res = SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
true /*isStreamInfoValid*/, surface, bufferProducer, mCameraIdStr,
mDevice->infoPhysical(physicalId), sensorPixelModesUsed);
@@ -2034,7 +2044,7 @@
bool CameraDeviceClient::isUltraHighResolutionSensor(const String8 &cameraId) {
const CameraMetadata &deviceInfo = getStaticInfo(cameraId);
- return camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(deviceInfo);
+ return SessionConfigurationUtils::isUltraHighResolutionSensor(deviceInfo);
}
bool CameraDeviceClient::isSensorPixelModeConsistent(
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 44ffeef..76b3f53 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -35,8 +35,6 @@
namespace android {
-typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
-
struct CameraDeviceClientBase :
public CameraService::BasicClient,
public hardware::camera2::BnCameraDeviceUser
@@ -185,7 +183,8 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid);
+ int servicePid,
+ bool overrideForPerfClass);
virtual ~CameraDeviceClient();
virtual status_t initialize(sp<CameraProviderManager> manager,
@@ -334,6 +333,9 @@
KeyedVector<sp<IBinder>, sp<CompositeStream>> mCompositeStreamMap;
sp<CameraProviderManager> mProviderManager;
+
+ // Override the camera characteristics for performance class primary cameras.
+ bool mOverrideForPerfClass;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index ce479a1..13d044a 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -54,13 +54,14 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid):
+ int servicePid,
+ bool overrideForPerfClass):
TClientBase(cameraService, remoteCallback, clientPackageName, clientFeatureId,
cameraId, api1CameraId, cameraFacing, sensorOrientation, clientPid, clientUid,
servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
- mDevice(new Camera3Device(cameraId)),
+ mDevice(new Camera3Device(cameraId, overrideForPerfClass)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
@@ -195,6 +196,13 @@
ALOGV("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
+ // Before detaching the device, cache the info from current open session.
+ // The disconnected check avoids duplication of info and also prevents
+ // deadlock while acquiring service lock in cacheDump.
+ if (!TClientBase::mDisconnected) {
+ Camera2ClientBase::getCameraService()->cacheDump();
+ }
+
detachDevice();
CameraService::BasicClient::disconnect();
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index b3a38a2..6246f7b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -55,7 +55,8 @@
int sensorOrientation,
int clientPid,
uid_t clientUid,
- int servicePid);
+ int servicePid,
+ bool overrideForPerfClass);
virtual ~Camera2ClientBase();
virtual status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 46e5d6d..1bbc2ba 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -46,6 +46,7 @@
using namespace ::android::hardware::camera;
using namespace ::android::hardware::camera::common::V1_0;
+using camera3::SessionConfigurationUtils;
using std::literals::chrono_literals::operator""s;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
@@ -278,9 +279,9 @@
}
status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
- CameraMetadata* characteristics) const {
+ bool overrideForPerfClass, CameraMetadata* characteristics) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- return getCameraCharacteristicsLocked(id, characteristics);
+ return getCameraCharacteristicsLocked(id, overrideForPerfClass, characteristics);
}
status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
@@ -691,32 +692,32 @@
const int32_t depthExclTag = ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE;
const int32_t scalerSizesTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
const int32_t scalerMinFrameDurationsTag =
ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
const int32_t scalerStallDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, maxResolution);
const int32_t depthSizesTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS, maxResolution);
const int32_t depthStallDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS, maxResolution);
const int32_t depthMinFrameDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS, maxResolution);
const int32_t dynamicDepthSizesTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS, maxResolution);
const int32_t dynamicDepthStallDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS, maxResolution);
const int32_t dynamicDepthMinFrameDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS, maxResolution);
auto& c = mCameraCharacteristics;
@@ -1077,20 +1078,20 @@
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::deriveHeicTags(bool maxResolution) {
int32_t scalerStreamSizesTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, maxResolution);
int32_t scalerMinFrameDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, maxResolution);
int32_t heicStreamSizesTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, maxResolution);
int32_t heicMinFrameDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS, maxResolution);
int32_t heicStallDurationsTag =
- camera3::SessionConfigurationUtils::getAppropriateModeTag(
+ SessionConfigurationUtils::getAppropriateModeTag(
ANDROID_HEIC_AVAILABLE_HEIC_STALL_DURATIONS, maxResolution);
auto& c = mCameraCharacteristics;
@@ -1186,15 +1187,15 @@
return isHiddenPhysicalCameraInternal(cameraId).first;
}
-void CameraProviderManager::filterSmallJpegSizes(const std::string& cameraId) {
+status_t CameraProviderManager::filterSmallJpegSizes(const std::string& cameraId) {
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
if (deviceInfo->mId == cameraId) {
- deviceInfo->filterSmallJpegSizes();
- return;
+ return deviceInfo->filterSmallJpegSizes();
}
}
}
+ return NAME_NOT_FOUND;
}
std::pair<bool, CameraProviderManager::ProviderInfo::DeviceInfo *>
@@ -1212,14 +1213,6 @@
for (auto& provider : mProviders) {
for (auto& deviceInfo : provider->mDevices) {
- CameraMetadata info;
- status_t res = deviceInfo->getCameraCharacteristics(&info);
- if (res != OK) {
- ALOGE("%s: Failed to getCameraCharacteristics for id %s", __FUNCTION__,
- deviceInfo->mId.c_str());
- return falseRet;
- }
-
std::vector<std::string> physicalIds;
if (deviceInfo->mIsLogicalCamera) {
if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
@@ -1705,7 +1698,7 @@
dprintf(fd, " Orientation: %d\n", info.orientation);
}
CameraMetadata info2;
- res = device->getCameraCharacteristics(&info2);
+ res = device->getCameraCharacteristics(true /*overrideForPerfClass*/, &info2);
if (res == INVALID_OPERATION) {
dprintf(fd, " API2 not directly supported\n");
} else if (res != OK) {
@@ -2104,9 +2097,6 @@
*isSupported = false;
return OK;
}
- camera3::SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
- combination.streamConfiguration);
}
ret = interface_2_6->isConcurrentStreamCombinationSupported(
halCameraIdsAndStreamCombinations_2_6, cb);
@@ -2313,7 +2303,7 @@
__FUNCTION__, strerror(-res), res);
}
- if (camera3::SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(mCameraCharacteristics)) {
status_t status = addDynamicDepthTags(/*maxResolution*/true);
if (OK != status) {
ALOGE("%s: Failed appending dynamic depth tags for maximum resolution mode: %s (%d)",
@@ -2497,10 +2487,15 @@
}
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacteristics(
- CameraMetadata *characteristics) const {
+ bool overrideForPerfClass, CameraMetadata *characteristics) const {
if (characteristics == nullptr) return BAD_VALUE;
- *characteristics = mCameraCharacteristics;
+ if (!overrideForPerfClass && mCameraCharNoPCOverride != nullptr) {
+ *characteristics = *mCameraCharNoPCOverride;
+ } else {
+ *characteristics = mCameraCharacteristics;
+ }
+
return OK;
}
@@ -2542,7 +2537,7 @@
ret = interface_3_7->isStreamCombinationSupported_3_7(configuration, halCb);
} else if (interface_3_5 != nullptr) {
hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
- bool success = camera3::SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
configuration_3_4, configuration);
if (!success) {
*status = false;
@@ -2573,68 +2568,94 @@
return res;
}
-void CameraProviderManager::ProviderInfo::DeviceInfo3::filterSmallJpegSizes() {
- static constexpr int FHD_W = 1920;
- static constexpr int FHD_H = 1080;
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::filterSmallJpegSizes() {
+ int32_t thresholdW = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_W;
+ int32_t thresholdH = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_H;
+
+ if (mCameraCharNoPCOverride != nullptr) return OK;
+
+ mCameraCharNoPCOverride = std::make_unique<CameraMetadata>(mCameraCharacteristics);
// Remove small JPEG sizes from available stream configurations
+ size_t largeJpegCount = 0;
std::vector<int32_t> newStreamConfigs;
camera_metadata_entry streamConfigs =
mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
for (size_t i = 0; i < streamConfigs.count; i += 4) {
if ((streamConfigs.data.i32[i] == HAL_PIXEL_FORMAT_BLOB) && (streamConfigs.data.i32[i+3] ==
- ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) &&
- (streamConfigs.data.i32[i+1] < FHD_W || streamConfigs.data.i32[i+2] < FHD_H)) {
- continue;
+ ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT)) {
+ if (streamConfigs.data.i32[i+1] < thresholdW ||
+ streamConfigs.data.i32[i+2] < thresholdH) {
+ continue;
+ } else {
+ largeJpegCount ++;
+ }
}
newStreamConfigs.insert(newStreamConfigs.end(), streamConfigs.data.i32 + i,
streamConfigs.data.i32 + i + 4);
}
- if (newStreamConfigs.size() > 0) {
- mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
- newStreamConfigs.data(), newStreamConfigs.size());
+ if (newStreamConfigs.size() == 0 || largeJpegCount == 0) {
+ return BAD_VALUE;
}
// Remove small JPEG sizes from available min frame durations
+ largeJpegCount = 0;
std::vector<int64_t> newMinDurations;
camera_metadata_entry minDurations =
mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
for (size_t i = 0; i < minDurations.count; i += 4) {
- if ((minDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) &&
- (minDurations.data.i64[i+1] < FHD_W || minDurations.data.i64[i+2] < FHD_H)) {
- continue;
+ if (minDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) {
+ if (minDurations.data.i64[i+1] < thresholdW ||
+ minDurations.data.i64[i+2] < thresholdH) {
+ continue;
+ } else {
+ largeJpegCount++;
+ }
}
newMinDurations.insert(newMinDurations.end(), minDurations.data.i64 + i,
minDurations.data.i64 + i + 4);
}
- if (newMinDurations.size() > 0) {
- mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
- newMinDurations.data(), newMinDurations.size());
+ if (newMinDurations.size() == 0 || largeJpegCount == 0) {
+ return BAD_VALUE;
}
// Remove small JPEG sizes from available stall durations
+ largeJpegCount = 0;
std::vector<int64_t> newStallDurations;
camera_metadata_entry stallDurations =
mCameraCharacteristics.find(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS);
for (size_t i = 0; i < stallDurations.count; i += 4) {
- if ((stallDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) &&
- (stallDurations.data.i64[i+1] < FHD_W || stallDurations.data.i64[i+2] < FHD_H)) {
- continue;
+ if (stallDurations.data.i64[i] == HAL_PIXEL_FORMAT_BLOB) {
+ if (stallDurations.data.i64[i+1] < thresholdW ||
+ stallDurations.data.i64[i+2] < thresholdH) {
+ continue;
+ } else {
+ largeJpegCount++;
+ }
}
newStallDurations.insert(newStallDurations.end(), stallDurations.data.i64 + i,
stallDurations.data.i64 + i + 4);
}
- if (newStallDurations.size() > 0) {
- mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
- newStallDurations.data(), newStallDurations.size());
+ if (newStallDurations.size() == 0 || largeJpegCount == 0) {
+ return BAD_VALUE;
}
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+ newStreamConfigs.data(), newStreamConfigs.size());
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ newMinDurations.data(), newMinDurations.size());
+ mCameraCharacteristics.update(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+ newStallDurations.data(), newStallDurations.size());
+
// Re-generate metadata tags that have dependencies on BLOB sizes
auto res = addDynamicDepthTags();
if (OK != res) {
ALOGE("%s: Failed to append dynamic depth tags: %s (%d)", __FUNCTION__,
strerror(-res), res);
+ return res;
}
+
+ return OK;
}
status_t CameraProviderManager::ProviderInfo::parseProviderName(const std::string& name,
@@ -2983,6 +3004,8 @@
status_t CameraProviderManager::convertToHALStreamCombinationAndCameraIdsLocked(
const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion,
hardware::hidl_vec<CameraIdAndStreamCombination> *halCameraIdsAndStreamCombinations,
bool *earlyExit) {
binder::Status bStatus = binder::Status::ok();
@@ -2990,25 +3013,31 @@
bool shouldExit = false;
status_t res = OK;
for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+ const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
CameraMetadata deviceInfo;
- res = getCameraCharacteristicsLocked(cameraIdAndSessionConfig.mCameraId, &deviceInfo);
+ bool overrideForPerfClass =
+ SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+ perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
+ res = getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
if (res != OK) {
return res;
}
camera3::metadataGetter getMetadata =
- [this](const String8 &id) {
+ [this](const String8 &id, bool overrideForPerfClass) {
CameraMetadata physicalDeviceInfo;
- getCameraCharacteristicsLocked(id.string(), &physicalDeviceInfo);
+ getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+ &physicalDeviceInfo);
return physicalDeviceInfo;
};
std::vector<std::string> physicalCameraIds;
- isLogicalCameraLocked(cameraIdAndSessionConfig.mCameraId, &physicalCameraIds);
+ isLogicalCameraLocked(cameraId, &physicalCameraIds);
bStatus =
- camera3::SessionConfigurationUtils::convertToHALStreamCombination(
+ SessionConfigurationUtils::convertToHALStreamCombination(
cameraIdAndSessionConfig.mSessionConfiguration,
- String8(cameraIdAndSessionConfig.mCameraId.c_str()), deviceInfo, getMetadata,
- physicalCameraIds, streamConfiguration, &shouldExit);
+ String8(cameraId.c_str()), deviceInfo, getMetadata,
+ physicalCameraIds, streamConfiguration,
+ overrideForPerfClass, &shouldExit);
if (!bStatus.isOk()) {
ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
return INVALID_OPERATION;
@@ -3018,7 +3047,7 @@
return OK;
}
CameraIdAndStreamCombination halCameraIdAndStream;
- halCameraIdAndStream.cameraId = cameraIdAndSessionConfig.mCameraId;
+ halCameraIdAndStream.cameraId = cameraId;
halCameraIdAndStream.streamConfiguration = streamConfiguration;
halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
}
@@ -3051,7 +3080,8 @@
status_t CameraProviderManager::isConcurrentSessionConfigurationSupported(
const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
- bool *isSupported) {
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
// Check if all the devices are a subset of devices advertised by the
// same provider through getConcurrentStreamingCameraIds()
@@ -3065,8 +3095,8 @@
hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
bool knowUnsupported = false;
status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
- cameraIdsAndSessionConfigs, &halCameraIdsAndStreamCombinations,
- &knowUnsupported);
+ cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
+ targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
if (res != OK) {
ALOGE("%s unable to convert session configurations provided to HAL stream"
"combinations", __FUNCTION__);
@@ -3088,10 +3118,10 @@
}
status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
- CameraMetadata* characteristics) const {
+ bool overrideForPerfClass, CameraMetadata* characteristics) const {
auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
if (deviceInfo != nullptr) {
- return deviceInfo->getCameraCharacteristics(characteristics);
+ return deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics);
}
// Find hidden physical camera characteristics
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 4fde556..1bdbb44 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -20,6 +20,7 @@
#include <vector>
#include <unordered_map>
#include <unordered_set>
+#include <set>
#include <string>
#include <mutex>
#include <future>
@@ -226,12 +227,13 @@
* not have a v3 or newer HAL version.
*/
status_t getCameraCharacteristics(const std::string &id,
- CameraMetadata* characteristics) const;
+ bool overrideForPerfClass, CameraMetadata* characteristics) const;
status_t isConcurrentSessionConfigurationSupported(
const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
&cameraIdsAndSessionConfigs,
- bool *isSupported);
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported);
std::vector<std::unordered_set<std::string>> getConcurrentCameraIds() const;
/**
@@ -327,7 +329,7 @@
status_t getSystemCameraKind(const std::string& id, SystemCameraKind *kind) const;
bool isHiddenPhysicalCamera(const std::string& cameraId) const;
- void filterSmallJpegSizes(const std::string& cameraId);
+ status_t filterSmallJpegSizes(const std::string& cameraId);
static const float kDepthARTolerance;
private:
@@ -472,7 +474,9 @@
virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
virtual bool isAPI1Compatible() const = 0;
virtual status_t dumpState(int fd) = 0;
- virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
+ virtual status_t getCameraCharacteristics(bool overrideForPerfClass,
+ CameraMetadata *characteristics) const {
+ (void) overrideForPerfClass;
(void) characteristics;
return INVALID_OPERATION;
}
@@ -488,7 +492,7 @@
bool * /*status*/) {
return INVALID_OPERATION;
}
- virtual void filterSmallJpegSizes() = 0;
+ virtual status_t filterSmallJpegSizes() = 0;
template<class InterfaceT>
sp<InterfaceT> startDeviceInterface();
@@ -540,6 +544,7 @@
virtual bool isAPI1Compatible() const override;
virtual status_t dumpState(int fd) override;
virtual status_t getCameraCharacteristics(
+ bool overrideForPerfClass,
CameraMetadata *characteristics) const override;
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
@@ -547,7 +552,7 @@
const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/)
override;
- virtual void filterSmallJpegSizes() override;
+ virtual status_t filterSmallJpegSizes() override;
DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
@@ -557,6 +562,9 @@
virtual ~DeviceInfo3();
private:
CameraMetadata mCameraCharacteristics;
+ // A copy of mCameraCharacteristics without performance class
+ // override
+ std::unique_ptr<CameraMetadata> mCameraCharNoPCOverride;
std::unordered_map<std::string, CameraMetadata> mPhysicalCameraCharacteristics;
void queryPhysicalCameraIds();
SystemCameraKind getSystemCameraKind();
@@ -569,11 +577,12 @@
static void getSupportedSizes(const CameraMetadata& ch, uint32_t tag,
android_pixel_format_t format,
std::vector<std::tuple<size_t, size_t>> *sizes /*out*/);
- void getSupportedDurations( const CameraMetadata& ch, uint32_t tag,
+ static void getSupportedDurations( const CameraMetadata& ch, uint32_t tag,
android_pixel_format_t format,
const std::vector<std::tuple<size_t, size_t>>& sizes,
std::vector<int64_t> *durations/*out*/);
- void getSupportedDynamicDepthDurations(const std::vector<int64_t>& depthDurations,
+ static void getSupportedDynamicDepthDurations(
+ const std::vector<int64_t>& depthDurations,
const std::vector<int64_t>& blobDurations,
std::vector<int64_t> *dynamicDepthDurations /*out*/);
static void getSupportedDynamicDepthSizes(
@@ -690,7 +699,7 @@
static const char* torchStatusToString(
const hardware::camera::common::V1_0::TorchModeStatus&);
- status_t getCameraCharacteristicsLocked(const std::string &id,
+ status_t getCameraCharacteristicsLocked(const std::string &id, bool overrideForPerfClass,
CameraMetadata* characteristics) const;
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
@@ -704,6 +713,8 @@
status_t convertToHALStreamCombinationAndCameraIdsLocked(
const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
&cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion,
hardware::hidl_vec<hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
*halCameraIdsAndStreamCombinations,
bool *earlyExit);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d05a2e1..578a32f 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -75,7 +75,7 @@
namespace android {
-Camera3Device::Camera3Device(const String8 &id):
+Camera3Device::Camera3Device(const String8 &id, bool overrideForPerfClass):
mId(id),
mOperatingMode(NO_MODE),
mIsConstrainedHighSpeedConfiguration(false),
@@ -93,7 +93,8 @@
mListener(NULL),
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID),
mLastTemplateId(-1),
- mNeedFixupMonochromeTags(false)
+ mNeedFixupMonochromeTags(false),
+ mOverrideForPerfClass(overrideForPerfClass)
{
ATRACE_CALL();
ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
@@ -132,7 +133,7 @@
return res;
}
- res = manager->getCameraCharacteristics(mId.string(), &mDeviceInfo);
+ res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo);
if (res != OK) {
SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
session->close();
@@ -144,8 +145,9 @@
bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
if (isLogical) {
for (auto& physicalId : physicalCameraIds) {
+ // Do not override characteristics for physical cameras
res = manager->getCameraCharacteristics(
- physicalId, &mPhysicalDeviceInfoMap[physicalId]);
+ physicalId, /*overrideForPerfClass*/false, &mPhysicalDeviceInfoMap[physicalId]);
if (res != OK) {
SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
physicalId.c_str(), strerror(-res), res);
@@ -353,9 +355,15 @@
camera_metadata_entry_t availableTestPatternModes = mDeviceInfo.find(
ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES);
for (size_t i = 0; i < availableTestPatternModes.count; i++) {
- if (availableTestPatternModes.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
+ if (availableTestPatternModes.data.i32[i] ==
+ ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
mSupportCameraMute = true;
+ mSupportTestPatternSolidColor = true;
break;
+ } else if (availableTestPatternModes.data.i32[i] ==
+ ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+ mSupportCameraMute = true;
+ mSupportTestPatternSolidColor = false;
}
}
@@ -4163,7 +4171,7 @@
mCurrentAfTriggerId(0),
mCurrentPreCaptureTriggerId(0),
mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE),
- mCameraMute(false),
+ mCameraMute(ANDROID_SENSOR_TEST_PATTERN_MODE_OFF),
mCameraMuteChanged(false),
mRepeatingLastFrameNumber(
hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES),
@@ -5265,11 +5273,11 @@
return OK;
}
-status_t Camera3Device::RequestThread::setCameraMute(bool enabled) {
+status_t Camera3Device::RequestThread::setCameraMute(int32_t muteMode) {
ATRACE_CALL();
Mutex::Autolock l(mTriggerMutex);
- if (enabled != mCameraMute) {
- mCameraMute = enabled;
+ if (muteMode != mCameraMute) {
+ mCameraMute = muteMode;
mCameraMuteChanged = true;
}
return OK;
@@ -5844,8 +5852,8 @@
request->mOriginalTestPatternData[3]
};
- if (mCameraMute) {
- testPatternMode = ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR;
+ if (mCameraMute != ANDROID_SENSOR_TEST_PATTERN_MODE_OFF) {
+ testPatternMode = mCameraMute;
testPatternData[0] = 0;
testPatternData[1] = 0;
testPatternData[2] = 0;
@@ -6535,7 +6543,11 @@
if (mRequestThread == nullptr || !mSupportCameraMute) {
return INVALID_OPERATION;
}
- return mRequestThread->setCameraMute(enabled);
+ int32_t muteMode =
+ !enabled ? ANDROID_SENSOR_TEST_PATTERN_MODE_OFF :
+ mSupportTestPatternSolidColor ? ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR :
+ ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK;
+ return mRequestThread->setCameraMute(muteMode);
}
status_t Camera3Device::injectCamera(const String8& injectedCamId,
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index f962c78..aeae042 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -89,7 +89,7 @@
public camera3::FlushBufferInterface {
public:
- explicit Camera3Device(const String8& id);
+ explicit Camera3Device(const String8& id, bool overrideForPerfClass);
virtual ~Camera3Device();
@@ -918,7 +918,7 @@
status_t setRotateAndCropAutoBehavior(
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);
- status_t setCameraMute(bool enabled);
+ status_t setCameraMute(int32_t muteMode);
status_t setHalInterface(sp<HalInterface> newHalInterface);
@@ -1069,7 +1069,7 @@
uint32_t mCurrentAfTriggerId;
uint32_t mCurrentPreCaptureTriggerId;
camera_metadata_enum_android_scaler_rotate_and_crop_t mRotateAndCropOverride;
- bool mCameraMute;
+ int32_t mCameraMute; // 0 = no mute, otherwise the TEST_PATTERN_MODE to use
bool mCameraMuteChanged;
int64_t mRepeatingLastFrameNumber;
@@ -1342,6 +1342,12 @@
// Whether the HAL supports camera muting via test pattern
bool mSupportCameraMute = false;
+ // Whether the HAL supports SOLID_COLOR or BLACK if mSupportCameraMute is true
+ bool mSupportTestPatternSolidColor = false;
+
+ // Whether the camera framework overrides the device characteristics for
+ // performance class.
+ bool mOverrideForPerfClass;
// Injection camera related methods.
class Camera3DeviceInjectionMethods : public virtual RefBase {
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index 88d2f72..7d1b3cf 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -59,7 +59,8 @@
android::CameraMetadata cameraMetadata;
HStatus status = HStatus::NO_ERROR;
binder::Status serviceRet =
- mAidlICameraService->getCameraCharacteristics(String16(cameraId.c_str()), &cameraMetadata);
+ mAidlICameraService->getCameraCharacteristics(String16(cameraId.c_str()),
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &cameraMetadata);
HCameraMetadata hidlMetadata;
if (!serviceRet.isOk()) {
switch(serviceRet.serviceSpecificErrorCode()) {
@@ -104,7 +105,8 @@
sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
binder::Status serviceRet = mAidlICameraService->connectDevice(
callbacks, String16(cameraId.c_str()), String16(""), {},
- hardware::ICameraService::USE_CALLING_UID, 0/*oomScoreOffset*/, /*out*/&deviceRemote);
+ hardware::ICameraService::USE_CALLING_UID, 0/*oomScoreOffset*/,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*out*/&deviceRemote);
HStatus status = HStatus::NO_ERROR;
if (!serviceRet.isOk()) {
ALOGE("%s: Unable to connect to camera device", __FUNCTION__);
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index 8bd4ed7..e46bf74 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -232,7 +232,8 @@
mCameraService->getCameraInfo(cameraId, &cameraInfo);
CameraMetadata metadata;
- mCameraService->getCameraCharacteristics(cameraIdStr, &metadata);
+ mCameraService->getCameraCharacteristics(cameraIdStr,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &metadata);
}
void CameraFuzzer::invokeCameraSound() {
@@ -319,7 +320,7 @@
rc = mCameraService->connect(this, cameraId, String16(),
android::CameraService::USE_CALLING_UID, android::CameraService::USE_CALLING_PID,
- &cameraDevice);
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &cameraDevice);
if (!rc.isOk()) {
// camera not connected
return;
@@ -526,7 +527,8 @@
sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
sp<hardware::camera2::ICameraDeviceUser> device;
mCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
- android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/, &device);
+ android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
+ /*targetSdkVersion*/__ANDROID_API_FUTURE__, &device);
if (device == nullptr) {
continue;
}
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 5afdfb9..ed6ee9b 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -13,6 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <cutils/properties.h>
+
#include "SessionConfigurationUtils.h"
#include "../api2/DepthCompositeStream.h"
#include "../api2/HeicCompositeStream.h"
@@ -29,6 +31,11 @@
namespace android {
namespace camera3 {
+int32_t SessionConfigurationUtils::PERF_CLASS_LEVEL =
+ property_get_int32("ro.odm.build.media_performance_class", 0);
+
+bool SessionConfigurationUtils::IS_PERF_CLASS = (PERF_CLASS_LEVEL == SDK_VERSION_S);
+
void StreamConfiguration::getStreamConfigurations(
const CameraMetadata &staticInfo, int configuration,
std::unordered_map<int, std::vector<StreamConfiguration>> *scm) {
@@ -480,7 +487,8 @@
const SessionConfiguration& sessionConfiguration,
const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
- hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration, bool *earlyExit) {
+ hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
+ bool overrideForPerfClass, bool *earlyExit) {
auto operatingMode = sessionConfiguration.getOperatingMode();
binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
@@ -539,7 +547,8 @@
String8 physicalCameraId = String8(it.getPhysicalCameraId());
std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
- const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId);
+ const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
+ overrideForPerfClass);
const CameraMetadata &metadataChosen =
physicalCameraId.size() > 0 ? physicalDeviceInfo : deviceInfo;
@@ -768,5 +777,13 @@
return true;
}
+bool SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+ const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
+ int targetSdkVersion) {
+ bool isPerfClassPrimaryCamera =
+ perfClassPrimaryCameraIds.find(cameraId) != perfClassPrimaryCameraIds.end();
+ return targetSdkVersion >= SDK_VERSION_S && isPerfClassPrimaryCamera;
+}
+
} // namespace camera3
} // namespace android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 863a0cd..b4814b6 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -27,6 +27,7 @@
#include <device3/Camera3StreamInterface.h>
+#include <set>
#include <stdint.h>
// Convenience methods for constructing binder::Status objects for error returns
@@ -43,7 +44,7 @@
namespace android {
namespace camera3 {
-typedef std::function<CameraMetadata (const String8 &)> metadataGetter;
+typedef std::function<CameraMetadata (const String8 &, int targetSdkVersion)> metadataGetter;
class StreamConfiguration {
public:
@@ -114,7 +115,7 @@
const String8 &cameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
- bool *earlyExit);
+ bool overrideForPerfClass, bool *earlyExit);
// Utility function to convert a V3_7::StreamConfiguration to
// V3_4::StreamConfiguration. Return false if the original V3_7 configuration cannot
@@ -134,10 +135,19 @@
static int32_t getAppropriateModeTag(int32_t defaultTag, bool maxResolution = false);
+ static bool targetPerfClassPrimaryCamera(
+ const std::set<std::string>& perfClassPrimaryCameraIds, const std::string& cameraId,
+ int32_t targetSdkVersion);
+
static const int32_t MAX_SURFACES_PER_STREAM = 4;
static const int32_t ROUNDING_WIDTH_CAP = 1920;
+ static const int32_t SDK_VERSION_S = 31;
+ static int32_t PERF_CLASS_LEVEL;
+ static bool IS_PERF_CLASS;
+ static const int32_t PERF_CLASS_JPEG_THRESH_W = 1920;
+ static const int32_t PERF_CLASS_JPEG_THRESH_H = 1080;
};
} // camera3
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 77e1c40..5b4129a 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -445,90 +445,118 @@
TunerFrontendCapabilities caps;
switch (halInfo.type) {
case FrontendType::ANALOG: {
- TunerFrontendAnalogCapabilities analogCaps{
- .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
- .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
- };
- caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendAnalogCapabilities analogCaps{
+ .typeCap = (int)halInfo.frontendCaps.analogCaps().typeCap,
+ .sifStandardCap = (int)halInfo.frontendCaps.analogCaps().sifStandardCap,
+ };
+ caps.set<TunerFrontendCapabilities::analogCaps>(analogCaps);
+ }
break;
}
case FrontendType::ATSC: {
- TunerFrontendAtscCapabilities atscCaps{
- .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
- };
- caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atscCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendAtscCapabilities atscCaps{
+ .modulationCap = (int)halInfo.frontendCaps.atscCaps().modulationCap,
+ };
+ caps.set<TunerFrontendCapabilities::atscCaps>(atscCaps);
+ }
break;
}
case FrontendType::ATSC3: {
- TunerFrontendAtsc3Capabilities atsc3Caps{
- .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
- .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
- .timeInterleaveModeCap =
- (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
- .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
- .demodOutputFormatCap = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
- .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
- };
- caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::atsc3Caps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendAtsc3Capabilities atsc3Caps{
+ .bandwidthCap = (int)halInfo.frontendCaps.atsc3Caps().bandwidthCap,
+ .modulationCap = (int)halInfo.frontendCaps.atsc3Caps().modulationCap,
+ .timeInterleaveModeCap =
+ (int)halInfo.frontendCaps.atsc3Caps().timeInterleaveModeCap,
+ .codeRateCap = (int)halInfo.frontendCaps.atsc3Caps().codeRateCap,
+ .demodOutputFormatCap
+ = (int)halInfo.frontendCaps.atsc3Caps().demodOutputFormatCap,
+ .fecCap = (int)halInfo.frontendCaps.atsc3Caps().fecCap,
+ };
+ caps.set<TunerFrontendCapabilities::atsc3Caps>(atsc3Caps);
+ }
break;
}
case FrontendType::DVBC: {
- TunerFrontendCableCapabilities cableCaps{
- .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
- .codeRateCap = (int64_t)halInfo.frontendCaps.dvbcCaps().fecCap,
- .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
- };
- caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbcCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendCableCapabilities cableCaps{
+ .modulationCap = (int)halInfo.frontendCaps.dvbcCaps().modulationCap,
+ .codeRateCap = (int64_t)halInfo.frontendCaps.dvbcCaps().fecCap,
+ .annexCap = (int)halInfo.frontendCaps.dvbcCaps().annexCap,
+ };
+ caps.set<TunerFrontendCapabilities::cableCaps>(cableCaps);
+ }
break;
}
case FrontendType::DVBS: {
- TunerFrontendDvbsCapabilities dvbsCaps{
- .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
- .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
- .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
- };
- caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbsCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendDvbsCapabilities dvbsCaps{
+ .modulationCap = (int)halInfo.frontendCaps.dvbsCaps().modulationCap,
+ .codeRateCap = (long)halInfo.frontendCaps.dvbsCaps().innerfecCap,
+ .standard = (int)halInfo.frontendCaps.dvbsCaps().standard,
+ };
+ caps.set<TunerFrontendCapabilities::dvbsCaps>(dvbsCaps);
+ }
break;
}
case FrontendType::DVBT: {
- TunerFrontendDvbtCapabilities dvbtCaps{
- .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
- .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
- .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
- .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
- .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
- .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
- .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
- .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
- };
- caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::dvbtCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendDvbtCapabilities dvbtCaps{
+ .transmissionModeCap = (int)halInfo.frontendCaps.dvbtCaps().transmissionModeCap,
+ .bandwidthCap = (int)halInfo.frontendCaps.dvbtCaps().bandwidthCap,
+ .constellationCap = (int)halInfo.frontendCaps.dvbtCaps().constellationCap,
+ .codeRateCap = (int)halInfo.frontendCaps.dvbtCaps().coderateCap,
+ .hierarchyCap = (int)halInfo.frontendCaps.dvbtCaps().hierarchyCap,
+ .guardIntervalCap = (int)halInfo.frontendCaps.dvbtCaps().guardIntervalCap,
+ .isT2Supported = (bool)halInfo.frontendCaps.dvbtCaps().isT2Supported,
+ .isMisoSupported = (bool)halInfo.frontendCaps.dvbtCaps().isMisoSupported,
+ };
+ caps.set<TunerFrontendCapabilities::dvbtCaps>(dvbtCaps);
+ }
break;
}
case FrontendType::ISDBS: {
- TunerFrontendIsdbsCapabilities isdbsCaps{
- .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
- .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
- };
- caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbsCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendIsdbsCapabilities isdbsCaps{
+ .modulationCap = (int)halInfo.frontendCaps.isdbsCaps().modulationCap,
+ .codeRateCap = (int)halInfo.frontendCaps.isdbsCaps().coderateCap,
+ };
+ caps.set<TunerFrontendCapabilities::isdbsCaps>(isdbsCaps);
+ }
break;
}
case FrontendType::ISDBS3: {
- TunerFrontendIsdbs3Capabilities isdbs3Caps{
- .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
- .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
- };
- caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbs3Caps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendIsdbs3Capabilities isdbs3Caps{
+ .modulationCap = (int)halInfo.frontendCaps.isdbs3Caps().modulationCap,
+ .codeRateCap = (int)halInfo.frontendCaps.isdbs3Caps().coderateCap,
+ };
+ caps.set<TunerFrontendCapabilities::isdbs3Caps>(isdbs3Caps);
+ }
break;
}
case FrontendType::ISDBT: {
- TunerFrontendIsdbtCapabilities isdbtCaps{
- .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
- .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
- .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
- .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
- .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
- };
- caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
+ if (FrontendInfo::FrontendCapabilities::hidl_discriminator::isdbtCaps
+ == halInfo.frontendCaps.getDiscriminator()) {
+ TunerFrontendIsdbtCapabilities isdbtCaps{
+ .modeCap = (int)halInfo.frontendCaps.isdbtCaps().modeCap,
+ .bandwidthCap = (int)halInfo.frontendCaps.isdbtCaps().bandwidthCap,
+ .modulationCap = (int)halInfo.frontendCaps.isdbtCaps().modulationCap,
+ .codeRateCap = (int)halInfo.frontendCaps.isdbtCaps().coderateCap,
+ .guardIntervalCap = (int)halInfo.frontendCaps.isdbtCaps().guardIntervalCap,
+ };
+ caps.set<TunerFrontendCapabilities::isdbtCaps>(isdbtCaps);
+ }
break;
}
default: