Merge "Camera: Filter out video sizes lower than encoder supported min size"
diff --git a/OWNERS b/OWNERS
index 0be1196..40c65e7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 1344
elaurent@google.com
etalvala@google.com
-hkuang@google.com
lajos@google.com
# go/android-fwk-media-solutions for info on areas of ownership.
diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp
index 28e037f..bc83ec1 100644
--- a/camera/CameraSessionStats.cpp
+++ b/camera/CameraSessionStats.cpp
@@ -112,6 +112,12 @@
return err;
}
+ int dynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
+ if ((err = parcel->readInt32(&dynamicRangeProfile)) != OK) {
+ ALOGE("%s: Failed to read dynamic range profile type from parcel", __FUNCTION__);
+ return err;
+ }
+
mWidth = width;
mHeight = height;
mFormat = format;
@@ -125,6 +131,7 @@
mHistogramType = histogramType;
mHistogramBins = std::move(histogramBins);
mHistogramCounts = std::move(histogramCounts);
+ mDynamicRangeProfile = dynamicRangeProfile;
return OK;
}
@@ -202,6 +209,11 @@
return err;
}
+ if ((err = parcel->writeInt32(mDynamicRangeProfile)) != OK) {
+ ALOGE("%s: Failed to write dynamic range profile type", __FUNCTION__);
+ return err;
+ }
+
return OK;
}
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 3687b15..1e748c7 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -187,6 +187,8 @@
*/
const int EVENT_NONE = 0;
const int EVENT_USER_SWITCHED = 1; // The argument is the set of new foreground user IDs.
+ const int EVENT_USB_DEVICE_ATTACHED = 2; // The argument is the deviceId and vendorId
+ const int EVENT_USB_DEVICE_DETACHED = 3; // The argument is the deviceId and vendorId
oneway void notifySystemEvent(int eventId, in int[] args);
/**
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 2bccd87..15c9dc9 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -23,6 +23,7 @@
#include <camera/camera2/OutputConfiguration.h>
#include <binder/Parcel.h>
#include <gui/view/Surface.h>
+#include <system/camera_metadata.h>
#include <utils/String8.h>
namespace android {
@@ -76,6 +77,10 @@
return mSensorPixelModesUsed;
}
+int OutputConfiguration::getDynamicRangeProfile() const {
+ return mDynamicRangeProfile;
+}
+
OutputConfiguration::OutputConfiguration() :
mRotation(INVALID_ROTATION),
mSurfaceSetID(INVALID_SET_ID),
@@ -84,7 +89,8 @@
mHeight(0),
mIsDeferred(false),
mIsShared(false),
- mIsMultiResolution(false) {
+ mIsMultiResolution(false),
+ mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
}
OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -165,6 +171,12 @@
ALOGE("%s: Failed to read sensor pixel mode(s) from parcel", __FUNCTION__);
return err;
}
+ int dynamicProfile;
+ if ((err = parcel->readInt32(&dynamicProfile)) != OK) {
+ ALOGE("%s: Failed to read surface dynamic range profile flag from parcel", __FUNCTION__);
+ return err;
+ }
+
mRotation = rotation;
mSurfaceSetID = setID;
mSurfaceType = surfaceType;
@@ -181,6 +193,7 @@
}
mSensorPixelModesUsed = std::move(sensorPixelModesUsed);
+ mDynamicRangeProfile = dynamicProfile;
ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
" physicalCameraId = %s, isMultiResolution = %d", __FUNCTION__, mRotation,
@@ -199,6 +212,7 @@
mIsShared = isShared;
mPhysicalCameraId = physicalId;
mIsMultiResolution = false;
+ mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
}
OutputConfiguration::OutputConfiguration(
@@ -207,7 +221,8 @@
int width, int height, bool isShared)
: mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
- mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false) { }
+ mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false),
+ mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) { }
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
@@ -254,6 +269,9 @@
err = parcel->writeParcelableVector(mSensorPixelModesUsed);
if (err != OK) return err;
+ err = parcel->writeInt32(mDynamicRangeProfile ? 1 : 0);
+ if (err != OK) return err;
+
return OK;
}
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 8ca8920..6d884cb 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -46,6 +46,7 @@
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.8",
],
compile_multilib: "first",
cflags: [
diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h
index c398aca..1209a20 100644
--- a/camera/include/camera/CameraSessionStats.h
+++ b/camera/include/camera/CameraSessionStats.h
@@ -19,6 +19,8 @@
#include <binder/Parcelable.h>
+#include <camera/CameraMetadata.h>
+
namespace android {
namespace hardware {
@@ -60,16 +62,21 @@
// size(mHistogramBins) + 1 = size(mHistogramCounts)
std::vector<int64_t> mHistogramCounts;
+ // Dynamic range profile
+ int mDynamicRangeProfile;
+
CameraStreamStats() :
mWidth(0), mHeight(0), mFormat(0), mDataSpace(0), mUsage(0),
mRequestCount(0), mErrorCount(0), mStartLatencyMs(0),
- mMaxHalBuffers(0), mMaxAppBuffers(0), mHistogramType(HISTOGRAM_TYPE_UNKNOWN) {}
+ mMaxHalBuffers(0), mMaxAppBuffers(0), mHistogramType(HISTOGRAM_TYPE_UNKNOWN),
+ mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {}
CameraStreamStats(int width, int height, int format, int dataSpace, int64_t usage,
- int maxHalBuffers, int maxAppBuffers)
+ int maxHalBuffers, int maxAppBuffers, int dynamicRangeProfile)
: mWidth(width), mHeight(height), mFormat(format), mDataSpace(dataSpace),
mUsage(usage), mRequestCount(0), mErrorCount(0), mStartLatencyMs(0),
mMaxHalBuffers(maxHalBuffers), mMaxAppBuffers(maxAppBuffers),
- mHistogramType(HISTOGRAM_TYPE_UNKNOWN) {}
+ mHistogramType(HISTOGRAM_TYPE_UNKNOWN),
+ mDynamicRangeProfile(dynamicRangeProfile) {}
virtual status_t readFromParcel(const android::Parcel* parcel) override;
virtual status_t writeToParcel(android::Parcel* parcel) const override;
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index f80ed3a..1631903 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -44,6 +44,7 @@
int getSurfaceType() const;
int getWidth() const;
int getHeight() const;
+ int getDynamicRangeProfile() const;
bool isDeferred() const;
bool isShared() const;
String16 getPhysicalCameraId() const;
@@ -89,7 +90,8 @@
gbpsEqual(other) &&
mPhysicalCameraId == other.mPhysicalCameraId &&
mIsMultiResolution == other.mIsMultiResolution &&
- sensorPixelModesUsedEqual(other));
+ sensorPixelModesUsedEqual(other) &&
+ mDynamicRangeProfile == other.mDynamicRangeProfile);
}
bool operator != (const OutputConfiguration& other) const {
return !(*this == other);
@@ -126,6 +128,9 @@
if (!sensorPixelModesUsedEqual(other)) {
return sensorPixelModesUsedLessThan(other);
}
+ if (mDynamicRangeProfile != other.mDynamicRangeProfile) {
+ return mDynamicRangeProfile < other.mDynamicRangeProfile;
+ }
return gbpsLessThan(other);
}
@@ -150,6 +155,7 @@
String16 mPhysicalCameraId;
bool mIsMultiResolution;
std::vector<int32_t> mSensorPixelModesUsed;
+ int mDynamicRangeProfile;
};
} // namespace params
} // namespace camera2
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 4015417..bd281c8 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3463,6 +3463,25 @@
*/
ACAMERA_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS = // int32[n]
ACAMERA_REQUEST_START + 17,
+ /**
+ * <p>A map of all available 10-bit dynamic range profiles along with their
+ * capture request constraints.</p>
+ *
+ * <p>Type: int32[n*2] (acamera_metadata_enum_android_request_available_dynamic_range_profiles_map_t)</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>Devices supporting the 10-bit output capability
+ * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT">CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT</a>
+ * must list their supported dynamic range profiles. In case the camera is not able to
+ * support every possible profile combination within a single capture request, then the
+ * constraints must be listed here as well.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP = // int32[n*2] (acamera_metadata_enum_android_request_available_dynamic_range_profiles_map_t)
+ ACAMERA_REQUEST_START + 19,
ACAMERA_REQUEST_END,
/**
@@ -9125,6 +9144,97 @@
} acamera_metadata_enum_android_request_available_capabilities_t;
+// ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP
+typedef enum acamera_metadata_enum_acamera_request_available_dynamic_range_profiles_map {
+ /**
+ * <p>8-bit SDR profile which is the default for all non 10-bit output capable devices.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD = 0x1,
+
+ /**
+ * <p>10-bit pixel samples encoded using the Hybrid log-gamma transfer function.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10 = 0x2,
+
+ /**
+ * <p>10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
+ * This profile utilizes internal static metadata to increase the quality
+ * of the capture.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10 = 0x4,
+
+ /**
+ * <p>10-bit pixel samples encoded using the SMPTE ST 2084 transfer function.
+ * In contrast to HDR10, this profile uses internal per-frame metadata
+ * to further enhance the quality of the capture.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS = 0x8,
+
+ /**
+ * <p>This is a camera mode for Dolby Vision capture optimized for a more scene
+ * accurate capture. This would typically differ from what a specific device
+ * might want to tune for a consumer optimized Dolby Vision general capture.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF
+ = 0x10,
+
+ /**
+ * <p>This is the power optimized mode for 10-bit Dolby Vision HDR Reference Mode.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO
+ = 0x20,
+
+ /**
+ * <p>This is the camera mode for the default Dolby Vision capture mode for the
+ * specific device. This would be tuned by each specific device for consumer
+ * pleasing results that resonate with their particular audience. We expect
+ * that each specific device would have a different look for their default
+ * Dolby Vision capture.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM
+ = 0x40,
+
+ /**
+ * <p>This is the power optimized mode for 10-bit Dolby Vision HDR device specific
+ * capture Mode.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO
+ = 0x80,
+
+ /**
+ * <p>This is the 8-bit version of the Dolby Vision reference capture mode optimized
+ * for scene accuracy.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF
+ = 0x100,
+
+ /**
+ * <p>This is the power optimized mode for 8-bit Dolby Vision HDR Reference Mode.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO
+ = 0x200,
+
+ /**
+ * <p>This is the 8-bit version of device specific tuned and optimized Dolby Vision
+ * capture mode.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM
+ = 0x400,
+
+ /**
+ * <p>This is the power optimized mode for 8-bit Dolby Vision HDR device specific
+ * capture Mode.</p>
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
+ = 0x800,
+
+ /**
+ *
+ */
+ ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX = 0x1000,
+
+} acamera_metadata_enum_android_request_available_dynamic_range_profiles_map_t;
+
// ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
typedef enum acamera_metadata_enum_acamera_scaler_available_stream_configurations {
@@ -9216,6 +9326,20 @@
= 0x7,
/**
+ * <p>If supported, the recommended 10-bit output stream configurations must include
+ * a subset of the advertised <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YCBCR_P010">ImageFormat#YCBCR_P010</a> and
+ * <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> outputs that are optimized for power
+ * and performance when registered along with a supported 10-bit dynamic range profile.
+ * see android.hardware.camera2.params.OutputConfiguration#setDynamicRangeProfile for
+ * details.</p>
+ */
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_10BIT_OUTPUT
+ = 0x8,
+
+ ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8
+ = 0x9,
+
+ /**
* <p>Vendor defined use cases. These depend on the vendor implementation.</p>
*/
ACAMERA_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START
diff --git a/cmds/stagefright/Android.bp b/cmds/stagefright/Android.bp
index c4783d3..e1fe07e 100644
--- a/cmds/stagefright/Android.bp
+++ b/cmds/stagefright/Android.bp
@@ -227,8 +227,6 @@
"rs-headers",
],
- include_dirs: ["frameworks/av/media/libstagefright"],
-
shared_libs: [
"libstagefright",
"liblog",
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index bd6db55..a1e1702 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -55,6 +55,7 @@
// for audio_track_cblk_t::mState, to match TrackBase.h
static inline constexpr int CBLK_STATE_IDLE = 0;
+static inline constexpr int CBLK_STATE_ACTIVE = 6;
static inline constexpr int CBLK_STATE_PAUSING = 7;
/**
diff --git a/media/OWNERS b/media/OWNERS
index 099729f..4a25b68 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 1344
elaurent@google.com
essick@google.com
-hkuang@google.com
hunga@google.com
jiabin@google.com
jmtrivi@google.com
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 5bc7262..41fe080 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -3,18 +3,18 @@
"presubmit-large": [
// runs whenever we change something in this tree
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.EncodeDecodeTest"
+ "include-filter": "android.media.codec.cts.EncodeDecodeTest"
}
]
},
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.DecodeEditEncodeTest"
+ "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
}
]
}
@@ -46,18 +46,18 @@
// runs regularly, independent of changes in this tree.
// signals if changes elsewhere break media functionality
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.EncodeDecodeTest"
+ "include-filter": "android.media.codec.cts.EncodeDecodeTest"
}
]
},
{
- "name": "CtsMediaTestCases",
+ "name": "CtsMediaCodecTestCases",
"options": [
{
- "include-filter": "android.media.cts.DecodeEditEncodeTest"
+ "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
}
]
}
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 2b96055..f477f1c 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -37,6 +37,17 @@
]
},
{
+ "name": "CtsMediaDecoderTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaEncoderTestCases",
"options": [
{
@@ -48,6 +59,17 @@
]
},
{
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaPlayerTestCases",
"options": [
{
diff --git a/media/codec2/components/aom/C2SoftAomDec.cpp b/media/codec2/components/aom/C2SoftAomDec.cpp
index c08cd59..c7985ca 100644
--- a/media/codec2/components/aom/C2SoftAomDec.cpp
+++ b/media/codec2/components/aom/C2SoftAomDec.cpp
@@ -505,124 +505,6 @@
}
}
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width, size_t height) {
-
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *) dst;
- uint32_t *dstBot = (uint32_t *) (dst + dstStride);
- uint16_t *ySrcTop = (uint16_t*) srcY;
- uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
- uint16_t *uSrc = (uint16_t*) srcU;
- uint16_t *vSrc = (uint16_t*) srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
-
- u01 = *((uint32_t*)uSrc); uSrc += 2;
- v01 = *((uint32_t*)vSrc); vSrc += 2;
-
- y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
- y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t*)ySrcTop);
- y45 = *((uint32_t*)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-
- return;
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
- return;
-}
bool C2SoftAomDec::outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work)
@@ -711,21 +593,16 @@
dstYStride / sizeof(uint32_t),
mWidth, mHeight);
} else {
- convertYUV420Planar16ToYUV420Planar(dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride / 2, srcUStride / 2, srcVStride / 2,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ mWidth, mHeight);
}
} else {
const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
- copyOutputBufferToYuvPlanarFrame(
- dstY, dstU, dstV, srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
}
finishWork(*(int64_t*)img->user_priv, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 6c4b7d9..99ff450 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -29,7 +29,179 @@
#include <SimpleC2Component.h>
namespace android {
+constexpr uint8_t kNeutralUVBitDepth8 = 128;
+constexpr uint16_t kNeutralUVBitDepth10 = 512;
+void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
+ const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, uint32_t width, uint32_t height,
+ bool isMonochrome) {
+ for (size_t i = 0; i < height; ++i) {
+ memcpy(dstY, srcY, width);
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t i = 0; i < height / 2; ++i) {
+ memset(dstV, kNeutralUVBitDepth8, width / 2);
+ memset(dstU, kNeutralUVBitDepth8, width / 2);
+ dstV += dstUVStride;
+ dstU += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dstV, srcV, width / 2);
+ srcV += srcVStride;
+ dstV += dstUVStride;
+ }
+
+ for (size_t i = 0; i < height / 2; ++i) {
+ memcpy(dstU, srcU, width / 2);
+ srcU += srcUStride;
+ dstU += dstUVStride;
+ }
+}
+
+void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
+ const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width, size_t height) {
+ // Converting two lines at a time, slightly faster
+ for (size_t y = 0; y < height; y += 2) {
+ uint32_t *dstTop = (uint32_t *)dst;
+ uint32_t *dstBot = (uint32_t *)(dst + dstStride);
+ uint16_t *ySrcTop = (uint16_t *)srcY;
+ uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
+ uint16_t *uSrc = (uint16_t *)srcU;
+ uint16_t *vSrc = (uint16_t *)srcV;
+
+ uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
+ size_t x = 0;
+ for (; x < width - 3; x += 4) {
+ u01 = *((uint32_t *)uSrc);
+ uSrc += 2;
+ v01 = *((uint32_t *)vSrc);
+ vSrc += 2;
+
+ y01 = *((uint32_t *)ySrcTop);
+ ySrcTop += 2;
+ y23 = *((uint32_t *)ySrcTop);
+ ySrcTop += 2;
+ y45 = *((uint32_t *)ySrcBot);
+ ySrcBot += 2;
+ y67 = *((uint32_t *)ySrcBot);
+ ySrcBot += 2;
+
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
+
+ *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
+ *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
+ *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
+
+ *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
+ *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
+ *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
+ }
+
+ // There should be at most 2 more pixels to process. Note that we don't
+ // need to consider odd case as the buffer is always aligned to even.
+ if (x < width) {
+ u01 = *uSrc;
+ v01 = *vSrc;
+ y01 = *((uint32_t *)ySrcTop);
+ y45 = *((uint32_t *)ySrcBot);
+ uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
+ *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
+ *dstTop++ = ((y01 >> 16) << 10) | uv0;
+ *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
+ *dstBot++ = ((y45 >> 16) << 10) | uv0;
+ }
+
+ srcY += srcYStride * 2;
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dst += dstStride * 2;
+ }
+}
+
+void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome) {
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = (uint8_t)(srcY[x] >> 2);
+ }
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
+ memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
+ dstV += dstUVStride;
+ dstU += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstU[x] = (uint8_t)(srcU[x] >> 2);
+ dstV[x] = (uint8_t)(srcV[x] >> 2);
+ }
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstU += dstUVStride;
+ dstV += dstUVStride;
+ }
+}
+
+void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome) {
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; ++x) {
+ dstY[x] = srcY[x] << 6;
+ }
+ srcY += srcYStride;
+ dstY += dstYStride;
+ }
+
+ if (isMonochrome) {
+ // Fill with neutral U/V values.
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstUV[2 * x] = kNeutralUVBitDepth10 << 6;
+ dstUV[2 * x + 1] = kNeutralUVBitDepth10 << 6;
+ }
+ dstUV += dstUVStride;
+ }
+ return;
+ }
+
+ for (size_t y = 0; y < (height + 1) / 2; ++y) {
+ for (size_t x = 0; x < (width + 1) / 2; ++x) {
+ dstUV[2 * x] = srcU[x] << 6;
+ dstUV[2 * x + 1] = srcV[x] << 6;
+ }
+ srcU += srcUStride;
+ srcV += srcVStride;
+ dstUV += dstUVStride;
+ }
+}
std::unique_ptr<C2Work> SimpleC2Component::WorkQueue::pop_front() {
std::unique_ptr<C2Work> work = std::move(mQueue.front().work);
mQueue.pop_front();
diff --git a/media/codec2/components/base/include/SimpleC2Component.h b/media/codec2/components/base/include/SimpleC2Component.h
index e5e16d8..3b4e212 100644
--- a/media/codec2/components/base/include/SimpleC2Component.h
+++ b/media/codec2/components/base/include/SimpleC2Component.h
@@ -28,6 +28,24 @@
namespace android {
+void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
+ const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, uint32_t width, uint32_t height,
+ bool isMonochrome = false);
+void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY, const uint16_t *srcU,
+ const uint16_t *srcV, size_t srcYStride, size_t srcUStride,
+ size_t srcVStride, size_t dstStride, size_t width, size_t height);
+void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome = false);
+void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
+ const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
+ size_t srcUStride, size_t srcVStride, size_t dstYStride,
+ size_t dstUVStride, size_t width, size_t height,
+ bool isMonochrome = false);
class SimpleC2Component
: public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
public:
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 475d863..ff6080d 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -28,11 +28,6 @@
#include <media/stagefright/foundation/MediaDefs.h>
namespace android {
-namespace {
-
-constexpr uint8_t NEUTRAL_UV_VALUE = 128;
-
-} // namespace
// codecname set and passed in as a compile flag from Android.bp
constexpr char COMPONENT_NAME[] = CODECNAME;
@@ -545,150 +540,6 @@
}
}
-static void copyOutputBufferToYV12Frame(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height,
- bool isMonochrome) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- if (isMonochrome) {
- // Fill with neutral U/V values.
- for (size_t i = 0; i < height / 2; ++i) {
- memset(dstV, NEUTRAL_UV_VALUE, width / 2);
- memset(dstU, NEUTRAL_UV_VALUE, width / 2);
- dstV += dstUVStride;
- dstU += dstUVStride;
- }
- return;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst, const uint16_t *srcY,
- const uint16_t *srcU,
- const uint16_t *srcV, size_t srcYStride,
- size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width,
- size_t height) {
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *)dst;
- uint32_t *dstBot = (uint32_t *)(dst + dstStride);
- uint16_t *ySrcTop = (uint16_t *)srcY;
- uint16_t *ySrcBot = (uint16_t *)(srcY + srcYStride);
- uint16_t *uSrc = (uint16_t *)srcU;
- uint16_t *vSrc = (uint16_t *)srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
- u01 = *((uint32_t *)uSrc);
- uSrc += 2;
- v01 = *((uint32_t *)vSrc);
- vSrc += 2;
-
- y01 = *((uint32_t *)ySrcTop);
- ySrcTop += 2;
- y23 = *((uint32_t *)ySrcTop);
- ySrcTop += 2;
- y45 = *((uint32_t *)ySrcBot);
- ySrcBot += 2;
- y67 = *((uint32_t *)ySrcBot);
- ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t *)ySrcTop);
- y45 = *((uint32_t *)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height, bool isMonochrome) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- if (isMonochrome) {
- // Fill with neutral U/V values.
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- memset(dstV, NEUTRAL_UV_VALUE, (width + 1) / 2);
- memset(dstU, NEUTRAL_UV_VALUE, (width + 1) / 2);
- dstV += dstUVStride;
- dstU += dstUVStride;
- }
- return;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
-}
-
void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
VuiColorAspects vuiColorAspects;
vuiColorAspects.primaries = buffer->color_primary;
@@ -841,22 +692,24 @@
const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
- convertYUV420Planar16ToY410(
- (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
- srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight);
+ convertYUV420Planar16ToY410((uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride / sizeof(uint32_t),
+ mWidth, mHeight);
+ } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
+ dstUVStride / 2, mWidth, mHeight, isMonochrome);
} else {
- convertYUV420Planar16ToYUV420Planar(
- dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
- srcVStride / 2, dstYStride, dstUVStride, mWidth, mHeight,
- isMonochrome);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
+ mHeight, isMonochrome);
}
} else {
const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
- copyOutputBufferToYV12Frame(
- dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
}
finishWork(buffer->user_private_data, work, std::move(block));
block = nullptr;
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 81f4679..54a1d0e 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -419,40 +419,6 @@
return resChanged;
}
-/* TODO: can remove temporary copy after library supports writing to display
- * buffer Y, U and V plane pointers using stride info. */
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, uint8_t *src,
- size_t dstYStride, size_t dstUVStride,
- size_t srcYStride, uint32_t width,
- uint32_t height) {
- size_t srcUVStride = srcYStride / 2;
- uint8_t *srcStart = src;
-
- size_t vStride = align(height, 16);
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, src, width);
- src += srcYStride;
- dstY += dstYStride;
- }
-
- /* U buffer */
- src = srcStart + vStride * srcYStride;
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, src, width / 2);
- src += srcUVStride;
- dstU += dstUVStride;
- }
-
- /* V buffer */
- src = srcStart + vStride * srcYStride * 5 / 4;
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, src, width / 2);
- src += srcUVStride;
- dstV += dstUVStride;
- }
-}
-
void C2SoftMpeg4Dec::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
@@ -636,11 +602,17 @@
C2PlanarLayout layout = wView.layout();
size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
- (void)copyOutputBufferToYuvPlanarFrame(
- outputBufferY, outputBufferU, outputBufferV,
- mOutputBuffer[mNumSamplesOutput & 1],
- dstYStride, dstUVStride,
- align(mWidth, 16), mWidth, mHeight);
+ size_t srcYStride = align(mWidth, 16);
+ size_t srcUStride = srcYStride / 2;
+ size_t srcVStride = srcYStride / 2;
+ size_t vStride = align(mHeight, 16);
+ const uint8_t *srcY = (const uint8_t *)mOutputBuffer[mNumSamplesOutput & 1];
+ const uint8_t *srcU = (const uint8_t *)srcY + vStride * srcYStride;
+ const uint8_t *srcV = (const uint8_t *)srcY + vStride * srcYStride * 5 / 4;
+
+ convertYUV420Planar8ToYV12(outputBufferY, outputBufferU, outputBufferV, srcY, srcU, srcV,
+ srcYStride, srcUStride, srcVStride, dstYStride, dstUVStride,
+ mWidth, mHeight);
inPos += inSize - (size_t)tmpInSize;
finishWork(workIndex, work);
diff --git a/media/codec2/components/vpx/C2SoftVpxDec.cpp b/media/codec2/components/vpx/C2SoftVpxDec.cpp
index 2da9d5b..0a27821 100644
--- a/media/codec2/components/vpx/C2SoftVpxDec.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxDec.cpp
@@ -640,125 +640,6 @@
}
}
-static void copyOutputBufferToYuvPlanarFrame(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- uint32_t width, uint32_t height) {
-
- for (size_t i = 0; i < height; ++i) {
- memcpy(dstY, srcY, width);
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstV, srcV, width / 2);
- srcV += srcVStride;
- dstV += dstUVStride;
- }
-
- for (size_t i = 0; i < height / 2; ++i) {
- memcpy(dstU, srcU, width / 2);
- srcU += srcUStride;
- dstU += dstUVStride;
- }
-
-}
-
-static void convertYUV420Planar16ToY410(uint32_t *dst,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstStride, size_t width, size_t height) {
-
- // Converting two lines at a time, slightly faster
- for (size_t y = 0; y < height; y += 2) {
- uint32_t *dstTop = (uint32_t *) dst;
- uint32_t *dstBot = (uint32_t *) (dst + dstStride);
- uint16_t *ySrcTop = (uint16_t*) srcY;
- uint16_t *ySrcBot = (uint16_t*) (srcY + srcYStride);
- uint16_t *uSrc = (uint16_t*) srcU;
- uint16_t *vSrc = (uint16_t*) srcV;
-
- uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1;
- size_t x = 0;
- for (; x < width - 3; x += 4) {
-
- u01 = *((uint32_t*)uSrc); uSrc += 2;
- v01 = *((uint32_t*)vSrc); vSrc += 2;
-
- y01 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y23 = *((uint32_t*)ySrcTop); ySrcTop += 2;
- y45 = *((uint32_t*)ySrcBot); ySrcBot += 2;
- y67 = *((uint32_t*)ySrcBot); ySrcBot += 2;
-
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- uv1 = (u01 >> 16) | ((v01 >> 16) << 20);
-
- *dstTop++ = 3 << 30 | ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y01 >> 16) << 10) | uv0;
- *dstTop++ = 3 << 30 | ((y23 & 0x3FF) << 10) | uv1;
- *dstTop++ = 3 << 30 | ((y23 >> 16) << 10) | uv1;
-
- *dstBot++ = 3 << 30 | ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y45 >> 16) << 10) | uv0;
- *dstBot++ = 3 << 30 | ((y67 & 0x3FF) << 10) | uv1;
- *dstBot++ = 3 << 30 | ((y67 >> 16) << 10) | uv1;
- }
-
- // There should be at most 2 more pixels to process. Note that we don't
- // need to consider odd case as the buffer is always aligned to even.
- if (x < width) {
- u01 = *uSrc;
- v01 = *vSrc;
- y01 = *((uint32_t*)ySrcTop);
- y45 = *((uint32_t*)ySrcBot);
- uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20);
- *dstTop++ = ((y01 & 0x3FF) << 10) | uv0;
- *dstTop++ = ((y01 >> 16) << 10) | uv0;
- *dstBot++ = ((y45 & 0x3FF) << 10) | uv0;
- *dstBot++ = ((y45 >> 16) << 10) | uv0;
- }
-
- srcY += srcYStride * 2;
- srcU += srcUStride;
- srcV += srcVStride;
- dst += dstStride * 2;
- }
-
- return;
-}
-
-static void convertYUV420Planar16ToYUV420Planar(
- uint8_t *dstY, uint8_t *dstU, uint8_t *dstV,
- const uint16_t *srcY, const uint16_t *srcU, const uint16_t *srcV,
- size_t srcYStride, size_t srcUStride, size_t srcVStride,
- size_t dstYStride, size_t dstUVStride,
- size_t width, size_t height) {
-
- for (size_t y = 0; y < height; ++y) {
- for (size_t x = 0; x < width; ++x) {
- dstY[x] = (uint8_t)(srcY[x] >> 2);
- }
-
- srcY += srcYStride;
- dstY += dstYStride;
- }
-
- for (size_t y = 0; y < (height + 1) / 2; ++y) {
- for (size_t x = 0; x < (width + 1) / 2; ++x) {
- dstU[x] = (uint8_t)(srcU[x] >> 2);
- dstV[x] = (uint8_t)(srcV[x] >> 2);
- }
-
- srcU += srcUStride;
- srcV += srcVStride;
- dstU += dstUVStride;
- dstV += dstUVStride;
- }
- return;
-}
status_t C2SoftVpxDec::outputBuffer(
const std::shared_ptr<C2BlockPool> &pool,
const std::unique_ptr<C2Work> &work)
@@ -876,24 +757,22 @@
queue->cond.signal();
queue.waitForCondition(queue->cond);
}
+ } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+ convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
+ srcYStride / 2, srcUStride / 2, srcVStride / 2,
+ dstYStride / 2, dstUVStride / 2, mWidth, mHeight);
} else {
- convertYUV420Planar16ToYUV420Planar(dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride / 2, srcUStride / 2, srcVStride / 2,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
+ srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride,
+ mWidth, mHeight);
}
} else {
const uint8_t *srcY = (const uint8_t *)img->planes[VPX_PLANE_Y];
const uint8_t *srcU = (const uint8_t *)img->planes[VPX_PLANE_U];
const uint8_t *srcV = (const uint8_t *)img->planes[VPX_PLANE_V];
- copyOutputBufferToYuvPlanarFrame(
- dstY, dstU, dstV,
- srcY, srcU, srcV,
- srcYStride, srcUStride, srcVStride,
- dstYStride, dstUVStride,
- mWidth, mHeight);
+ convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+ srcVStride, dstYStride, dstUVStride, mWidth, mHeight);
}
finishWork(((c2_cntr64_t *)img->user_priv)->peekull(), work, std::move(block));
return OK;
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index feaa98c..4b96956 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -270,6 +270,9 @@
// encoding quality requirements
kParamIndexEncodingQualityLevel, // encoders, enum
+
+ // encoding statistics, average block qp of a frame
+ kParamIndexAverageBlockQuantization, // int32
};
}
@@ -2411,6 +2414,17 @@
S_HANDHELD = 1 // corresponds to VMAF=70
);
+/**
+ * Video Encoding Statistics Export
+ */
+
+/**
+ * Average block QP exported from video encoder.
+ */
+typedef C2StreamParam<C2Info, C2SimpleValueStruct<int32_t>, kParamIndexAverageBlockQuantization>
+ C2AndroidStreamAverageBlockQuantizationInfo;
+constexpr char C2_PARAMKEY_AVERAGE_QP[] = "coded.average-qp";
+
/// @}
#endif // C2CONFIG_H_
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 5389339..1f8b33d 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1443,6 +1443,27 @@
config->mOutputFormat->setInt32("android._tunneled", 1);
}
+ // Convert an encoding statistics level to corresponding encoding statistics
+ // kinds
+ int32_t encodingStatisticsLevel = VIDEO_ENCODING_STATISTICS_LEVEL_NONE;
+ if ((config->mDomain & Config::IS_ENCODER)
+ && (config->mDomain & Config::IS_VIDEO)
+ && msg->findInt32(KEY_VIDEO_ENCODING_STATISTICS_LEVEL, &encodingStatisticsLevel)) {
+ // Higher level include all the enc stats belong to lower level.
+ switch (encodingStatisticsLevel) {
+ // case VIDEO_ENCODING_STATISTICS_LEVEL_2: // reserved for the future level 2
+ // with more enc stat kinds
+ // Future extended encoding statistics for the level 2 should be added here
+ case VIDEO_ENCODING_STATISTICS_LEVEL_1:
+ config->subscribeToConfigUpdate(comp,
+ {kParamIndexAverageBlockQuantization, kParamIndexPictureType});
+ break;
+ case VIDEO_ENCODING_STATISTICS_LEVEL_NONE:
+ break;
+ }
+ }
+ ALOGD("encoding statistics level = %d", encodingStatisticsLevel);
+
ALOGD("setup formats input: %s",
config->mInputFormat->debugString().c_str());
ALOGD("setup formats output: %s",
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 03418d9..0899e99 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -953,6 +953,12 @@
return value == 0 ? C2_FALSE : C2_TRUE;
}));
+ add(ConfigMapper(KEY_VIDEO_QP_AVERAGE, C2_PARAMKEY_AVERAGE_QP, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
+ add(ConfigMapper(KEY_PICTURE_TYPE, C2_PARAMKEY_PICTURE_TYPE, "value")
+ .limitTo(D::ENCODER & D::VIDEO & D::READ));
+
/* still to do
constexpr char KEY_PUSH_BLANK_BUFFERS_ON_STOP[] = "push-blank-buffers-on-shutdown";
diff --git a/media/codec2/sfplugin/CCodecConfig.h b/media/codec2/sfplugin/CCodecConfig.h
index 417b773..88e6239 100644
--- a/media/codec2/sfplugin/CCodecConfig.h
+++ b/media/codec2/sfplugin/CCodecConfig.h
@@ -363,11 +363,6 @@
const std::vector<std::string> &names,
c2_blocking_t blocking = C2_DONT_BLOCK);
-private:
-
- /// initializes the standard MediaCodec to Codec 2.0 params mapping
- void initializeStandardParams();
-
/// Adds indices to the subscribed indices, and updated subscription to component
/// \param blocking blocking mode to use with the component
status_t subscribeToConfigUpdate(
@@ -375,6 +370,11 @@
const std::vector<C2Param::Index> &indices,
c2_blocking_t blocking = C2_DONT_BLOCK);
+private:
+
+ /// initializes the standard MediaCodec to Codec 2.0 params mapping
+ void initializeStandardParams();
+
/// Gets SDK format from codec 2.0 reflected configuration
/// \param domain input/output bitmask
sp<AMessage> getFormatForDomain(
diff --git a/media/codec2/vndk/C2AllocatorIon.cpp b/media/codec2/vndk/C2AllocatorIon.cpp
index 77b265a..7b593ee 100644
--- a/media/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/codec2/vndk/C2AllocatorIon.cpp
@@ -207,6 +207,7 @@
c2_status_t err = mapInternal(mapSize, mapOffset, alignmentBytes, prot, flags, &(map.addr), addr);
if (map.addr) {
+ std::lock_guard<std::mutex> guard(mMutexMappings);
mMappings.push_back(map);
}
return err;
@@ -217,22 +218,26 @@
ALOGD("tried to unmap unmapped buffer");
return C2_NOT_FOUND;
}
- for (auto it = mMappings.begin(); it != mMappings.end(); ++it) {
- if (addr != (uint8_t *)it->addr + it->alignmentBytes ||
- size + it->alignmentBytes != it->size) {
- continue;
+ { // Scope for the lock_guard of mMutexMappings.
+ std::lock_guard<std::mutex> guard(mMutexMappings);
+ for (auto it = mMappings.begin(); it != mMappings.end(); ++it) {
+ if (addr != (uint8_t *)it->addr + it->alignmentBytes ||
+ size + it->alignmentBytes != it->size) {
+ continue;
+ }
+ int err = munmap(it->addr, it->size);
+ if (err != 0) {
+ ALOGD("munmap failed");
+ return c2_map_errno<EINVAL>(errno);
+ }
+ if (fence) {
+ *fence = C2Fence(); // not using fences
+ }
+ (void)mMappings.erase(it);
+ ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size,
+ mHandle.bufferFd());
+ return C2_OK;
}
- int err = munmap(it->addr, it->size);
- if (err != 0) {
- ALOGD("munmap failed");
- return c2_map_errno<EINVAL>(errno);
- }
- if (fence) {
- *fence = C2Fence(); // not using fences
- }
- (void)mMappings.erase(it);
- ALOGV("successfully unmapped: addr=%p size=%zu fd=%d", addr, size, mHandle.bufferFd());
- return C2_OK;
}
ALOGD("unmap failed to find specified map");
return C2_BAD_VALUE;
@@ -241,6 +246,7 @@
virtual ~Impl() {
if (!mMappings.empty()) {
ALOGD("Dangling mappings!");
+ std::lock_guard<std::mutex> guard(mMutexMappings);
for (const Mapping &map : mMappings) {
(void)munmap(map.addr, map.size);
}
@@ -320,6 +326,7 @@
size_t size;
};
std::list<Mapping> mMappings;
+ std::mutex mMutexMappings;
};
class C2AllocationIon::ImplV2 : public C2AllocationIon::Impl {
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 1660c38..dfdd84d 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -301,13 +301,21 @@
std::lock_guard<std::mutex> lock(_mComponentStoreReadLock);
_mComponentStore = store;
}
- std::shared_ptr<C2AllocatorIon> allocator;
+ std::shared_ptr<C2AllocatorIon> ionAllocator;
{
std::lock_guard<std::mutex> lock(gIonAllocatorMutex);
- allocator = gIonAllocator.lock();
+ ionAllocator = gIonAllocator.lock();
}
- if (allocator) {
- UseComponentStoreForIonAllocator(allocator, store);
+ if (ionAllocator) {
+ UseComponentStoreForIonAllocator(ionAllocator, store);
+ }
+ std::shared_ptr<C2DmaBufAllocator> dmaAllocator;
+ {
+ std::lock_guard<std::mutex> lock(gDmaBufAllocatorMutex);
+ dmaAllocator = gDmaBufAllocator.lock();
+ }
+ if (dmaAllocator) {
+ UseComponentStoreForDmaBufAllocator(dmaAllocator, store);
}
}
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index fd51622..834f4ad 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -19,7 +19,7 @@
cc_library {
name: "libflacextractor",
- defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
+ defaults: ["extractor-defaults"],
srcs: ["FLACExtractor.cpp"],
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index d431b05..afd28ef 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -20,9 +20,6 @@
#include "MPEG2PSExtractor.h"
-#include <AnotherPacketSource.h>
-#include <ESQueue.h>
-
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -33,6 +30,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <mpeg2ts/AnotherPacketSource.h>
+#include <mpeg2ts/ESQueue.h>
#include <utils/String8.h>
#include <inttypes.h>
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 2e68809..9a3cd92 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -35,10 +35,9 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <mpeg2ts/AnotherPacketSource.h>
#include <utils/String8.h>
-#include <AnotherPacketSource.h>
-
#include <hidl/HybridInterface.h>
#include <android/hardware/cas/1.0/ICas.h>
diff --git a/media/extractors/mpeg2/include/MPEG2TSExtractor.h b/media/extractors/mpeg2/include/MPEG2TSExtractor.h
index fd77b08..0e3e484 100644
--- a/media/extractors/mpeg2/include/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/include/MPEG2TSExtractor.h
@@ -23,12 +23,11 @@
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
#include <media/stagefright/MetaDataBase.h>
+#include <mpeg2ts/ATSParser.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
-#include <ATSParser.h>
-
namespace android {
struct AMessage;
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index b7e2af3..cdf587c 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -18,7 +18,7 @@
cc_library {
name: "libwavextractor",
- defaults: ["extractor-defaults", "libbinder_ndk_host_user"],
+ defaults: ["extractor-defaults"],
srcs: ["WAVExtractor.cpp"],
diff --git a/media/janitors/reliability_mainline_OWNERS b/media/janitors/reliability_mainline_OWNERS
index e4c4fc2..cced19c 100644
--- a/media/janitors/reliability_mainline_OWNERS
+++ b/media/janitors/reliability_mainline_OWNERS
@@ -1,5 +1,5 @@
# Bug component: 1051309
-# go/android-media-relaibility
+# go/android-media-reliability
essick@google.com
nchalko@google.com
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
index 7daac20..956b3cd 100644
--- a/media/libaaudio/examples/utils/AAudioSimplePlayer.h
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -40,6 +40,31 @@
int64_t nanoseconds;
} Timestamp;
+static constexpr int32_t kWorkloadScaler = 500;
+
+// Linear congruential random number generator.
+static uint32_t s_random16() {
+ static uint32_t seed = 1234;
+ seed = ((seed * 31421) + 6927) & 0x0FFFF;
+ return seed;
+}
+
+/**
+ * The random number generator is good for burning CPU because the compiler cannot
+ * easily optimize away the computation.
+ * @param workload number of times to execute the loop
+ * @return a white noise value between -1.0 and +1.0
+ */
+static float s_burnCPU(int32_t workload) {
+ uint32_t random = 0;
+ for (int32_t i = 0; i < workload; i++) {
+ for (int32_t j = 0; j < 10; j++) {
+ random = random ^ s_random16();
+ }
+ }
+ return (random - 32768) * (1.0 / 32768);
+}
+
/**
* Simple wrapper for AAudio that opens an output stream either in callback or blocking write mode.
*/
@@ -268,11 +293,13 @@
int32_t timestampCount = 0; // in timestamps
int32_t sampleRate = 48000;
int32_t prefixToneFrames = 0;
+ double workload = 0.0;
bool sweepSetup = false;
int scheduler = 0;
bool schedulerChecked = false;
int32_t hangTimeMSec = 0;
+ int cpuAffinity = -1;
AAudioSimplePlayer simplePlayer;
int32_t callbackCount = 0;
@@ -304,6 +331,14 @@
} SineThreadedData_t;
+int setCpuAffinity(int cpuIndex) {
+cpu_set_t cpu_set;
+ CPU_ZERO(&cpu_set);
+ CPU_SET(cpuIndex, &cpu_set);
+ int err = sched_setaffinity((pid_t) 0, sizeof(cpu_set_t), &cpu_set);
+ return err == 0 ? 0 : -errno;
+}
+
// Callback function that fills the audio output buffer.
aaudio_data_callback_result_t SimplePlayerDataCallbackProc(
AAudioStream *stream,
@@ -319,6 +354,10 @@
}
SineThreadedData_t *sineData = (SineThreadedData_t *) userData;
+ if (sineData->cpuAffinity >= 0) {
+ setCpuAffinity(sineData->cpuAffinity);
+ sineData->cpuAffinity = -1;
+ }
// Play an initial high tone so we can tell whether the beginning was truncated.
if (!sineData->sweepSetup && sineData->framesTotal >= sineData->prefixToneFrames) {
sineData->setupSineSweeps();
@@ -398,6 +437,8 @@
return AAUDIO_CALLBACK_RESULT_STOP;
}
+ s_burnCPU((int32_t)(sineData->workload * kWorkloadScaler * numFrames));
+
sineData->callbackCount++;
sineData->framesTotal += numFrames;
return AAUDIO_CALLBACK_RESULT_CONTINUE;
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index cdc987b..400fc7c 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -31,10 +31,10 @@
#include "AAudioSimplePlayer.h"
#include "AAudioArgsParser.h"
-#define APP_VERSION "0.1.8"
+#define APP_VERSION "0.2.1"
-constexpr int32_t kDefaultHangTimeMSec = 10;
-
+static constexpr int32_t kDefaultHangTimeMSec = 10;
+static constexpr int32_t kWorkPeriodSeconds = 6;
/**
* Open stream, play some sine waves, then close the stream.
*
@@ -44,7 +44,11 @@
static aaudio_result_t testOpenPlayClose(AAudioArgsParser &argParser,
int32_t loopCount,
int32_t prefixToneMsec,
- int32_t hangTimeMSec)
+ int32_t hangTimeMSec,
+ int cpuAffinity,
+ double lowWorkLoad,
+ double highWorkLoad,
+ int32_t workPeriodSeconds)
{
SineThreadedData_t myData;
AAudioSimplePlayer &player = myData.simplePlayer;
@@ -57,6 +61,7 @@
myData.schedulerChecked = false;
myData.callbackCount = 0;
myData.hangTimeMSec = hangTimeMSec; // test AAudioStream_getXRunCount()
+ myData.cpuAffinity = cpuAffinity;
result = player.open(argParser,
SimplePlayerDataCallbackProc,
@@ -111,8 +116,8 @@
}
// Play a sine wave in the background.
- printf("Sleep for %d seconds while audio plays in a callback thread. %d of %d\n",
- argParser.getDurationSeconds(), (loopIndex + 1), loopCount);
+ printf("Monitor for %d seconds while audio plays in a callback thread. %d of %d, %d\n",
+ argParser.getDurationSeconds(), (loopIndex + 1), loopCount, workPeriodSeconds);
startedAtNanos = getNanoseconds(CLOCK_MONOTONIC);
for (int second = 0; second < durationSeconds; second++) {
// Sleep a while. Wake up early if there is an error, for example a DISCONNECT.
@@ -123,13 +128,17 @@
const int32_t framesWritten = (int32_t) AAudioStream_getFramesWritten(player.getStream());
const int32_t framesRead = (int32_t) AAudioStream_getFramesRead(player.getStream());
const int32_t xruns = AAudioStream_getXRunCount(player.getStream());
+ myData.workload = ((second % (2 * workPeriodSeconds)) < workPeriodSeconds)
+ ? lowWorkLoad : highWorkLoad;
printf(" waker result = %d, at %6d millis"
- ", second = %3d, frames written %8d - read %8d = %8d, underruns = %d\n",
+ ", second = %3d, frames written %8d - read %8d = %8d"
+ ", work = %5.1f, underruns = %d\n",
result, (int) millis,
second,
framesWritten,
framesRead,
framesWritten - framesRead,
+ myData.workload,
xruns);
if (result != AAUDIO_OK) {
disconnected = (result == AAUDIO_ERROR_DISCONNECTED);
@@ -220,6 +229,11 @@
AAudioArgsParser::usage();
printf(" -l{count} loopCount start/stop, every other one is silent\n");
printf(" -t{msec} play a high pitched tone at the beginning\n");
+ printf(" -w{workload} set base workload, default 0.0\n");
+ printf(" -W{workload} alternate between this higher workload and base workload\n");
+ printf(" -Z{duration} number of seconds to spend at each workload, default = %d\n",
+ kWorkPeriodSeconds);
+ printf(" -a{cpu} set CPU affinity, default none\n");
printf(" -h{msec} force periodic underruns by hanging in callback\n");
printf(" If no value specified then %d used.\n",
kDefaultHangTimeMSec);
@@ -232,6 +246,10 @@
int32_t loopCount = 1;
int32_t prefixToneMsec = 0;
int32_t hangTimeMSec = 0;
+ int cpuAffinity = -1;
+ double lowWorkLoad = 0.0;
+ double highWorkLoad = -1.0;
+ int32_t workPeriodSeconds = kWorkPeriodSeconds;
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
@@ -247,6 +265,9 @@
if (arg[0] == '-') {
char option = arg[1];
switch (option) {
+ case 'a':
+ cpuAffinity = atoi(&arg[2]);
+ break;
case 'l':
loopCount = atoi(&arg[2]);
break;
@@ -258,6 +279,15 @@
? atoi(&arg[2])
: kDefaultHangTimeMSec;
break;
+ case 'w':
+ lowWorkLoad = atof(&arg[2]);
+ break;
+ case 'W':
+ highWorkLoad = atof(&arg[2]);
+ break;
+ case 'Z':
+ workPeriodSeconds = atoi(&arg[2]);
+ break;
default:
usage();
exit(EXIT_FAILURE);
@@ -271,9 +301,21 @@
}
}
+ if (highWorkLoad > 0) {
+ if (highWorkLoad < lowWorkLoad) {
+ printf("ERROR - -W%f workload lower than -w%f workload", highWorkLoad, lowWorkLoad);
+ return EXIT_FAILURE;
+ }
+ } else {
+ highWorkLoad = lowWorkLoad; // high not specified so use low
+ }
+
// Keep looping until we can complete the test without disconnecting.
while((result = testOpenPlayClose(argParser, loopCount,
- prefixToneMsec, hangTimeMSec))
+ prefixToneMsec, hangTimeMSec,
+ cpuAffinity,
+ lowWorkLoad, highWorkLoad,
+ workPeriodSeconds))
== AAUDIO_ERROR_DISCONNECTED);
return (result) ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/media/libaaudio/include/aaudio/AAudioTesting.h b/media/libaaudio/include/aaudio/AAudioTesting.h
index 02ec411..0f2d7a2 100644
--- a/media/libaaudio/include/aaudio/AAudioTesting.h
+++ b/media/libaaudio/include/aaudio/AAudioTesting.h
@@ -49,6 +49,12 @@
};
typedef int32_t aaudio_policy_t;
+// Internal error codes. Only used by the framework.
+enum {
+ AAUDIO_INTERNAL_ERROR_BASE = -1000,
+ AAUDIO_ERROR_STANDBY,
+};
+
/**
* Control whether AAudioStreamBuilder_openStream() will use the new MMAP data path
* or the older "Legacy" data path.
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
index 6e3a1c8..42d81ca 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.cpp
@@ -124,4 +124,16 @@
return result;
}
+aaudio_result_t AAudioBinderAdapter::exitStandby(aaudio_handle_t streamHandle,
+ AudioEndpointParcelable &endpointOut) {
+ aaudio_result_t result;
+ Endpoint endpoint;
+ Status status = mDelegate->exitStandby(streamHandle, &endpoint, &result);
+ if (!status.isOk()) {
+ result = AAudioConvert_androidToAAudioResult(statusTFromBinderStatus(status));
+ }
+ endpointOut = std::move(endpoint);
+ return result;
+}
+
} // namespace aaudio
diff --git a/media/libaaudio/src/binding/AAudioBinderAdapter.h b/media/libaaudio/src/binding/AAudioBinderAdapter.h
index 5e9ab57..d170783 100644
--- a/media/libaaudio/src/binding/AAudioBinderAdapter.h
+++ b/media/libaaudio/src/binding/AAudioBinderAdapter.h
@@ -57,6 +57,9 @@
aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) override;
+ aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+ AudioEndpointParcelable &parcelable) override;
+
private:
IAAudioService* const mDelegate;
};
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index 135bac3..8e5facc 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -201,3 +201,11 @@
return service->unregisterAudioThread(streamHandle, clientThreadId);
}
+
+aaudio_result_t AAudioBinderClient::exitStandby(aaudio_handle_t streamHandle,
+ AudioEndpointParcelable &endpointOut) {
+ std::shared_ptr<AAudioServiceInterface> service = getAAudioService();
+ if (service.get() == nullptr) return AAUDIO_ERROR_NO_SERVICE;
+
+ return service->exitStandby(streamHandle, endpointOut);
+}
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index 557ced5..0968f4c 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -108,6 +108,9 @@
return AAUDIO_ERROR_UNAVAILABLE;
}
+ aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+ AudioEndpointParcelable &endpointOut) override;
+
void onStreamChange(aaudio_handle_t /*handle*/, int32_t /*opcode*/, int32_t /*value*/) {
// TODO This is just a stub so we can have a client Binder to pass to the service.
// TODO Implemented in a later CL.
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index bf94774..e901767 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -95,6 +95,16 @@
virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
audio_port_handle_t clientHandle) = 0;
+
+ /**
+ * Exit the standby mode.
+ *
+ * @param streamHandle the stream handle
+ * @param parcelable contains new data queue information
+ * @return the result of the execution
+ */
+ virtual aaudio_result_t exitStandby(aaudio_handle_t streamHandle,
+ AudioEndpointParcelable &parcelable) = 0;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.cpp b/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
index dea3e4a..b1262df 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.cpp
@@ -79,6 +79,22 @@
return index;
}
+void AudioEndpointParcelable::closeDataFileDescriptor() {
+ const int32_t curDataMemoryIndex = mDownDataQueueParcelable.getSharedMemoryIndex();
+ mSharedMemories[curDataMemoryIndex].closeAndReleaseFd();
+}
+
+void AudioEndpointParcelable::updateDataFileDescriptor(
+ AudioEndpointParcelable* endpointParcelable) {
+ const int32_t curDataMemoryIndex = mDownDataQueueParcelable.getSharedMemoryIndex();
+ const int32_t newDataMemoryIndex =
+ endpointParcelable->mDownDataQueueParcelable.getSharedMemoryIndex();
+ mSharedMemories[curDataMemoryIndex].close();
+ mSharedMemories[curDataMemoryIndex].setup(
+ endpointParcelable->mSharedMemories[newDataMemoryIndex]);
+ mDownDataQueueParcelable.updateMemory(endpointParcelable->mDownDataQueueParcelable);
+}
+
aaudio_result_t AudioEndpointParcelable::resolve(EndpointDescriptor *descriptor) {
aaudio_result_t result = mUpMessageQueueParcelable.resolve(mSharedMemories,
&descriptor->upMessageQueueDescriptor);
@@ -92,6 +108,10 @@
return result;
}
+aaudio_result_t AudioEndpointParcelable::resolveDataQueue(RingBufferDescriptor *descriptor) {
+ return mDownDataQueueParcelable.resolve(mSharedMemories, descriptor);
+}
+
aaudio_result_t AudioEndpointParcelable::close() {
int err = 0;
for (int i = 0; i < mNumSharedMemories; i++) {
diff --git a/media/libaaudio/src/binding/AudioEndpointParcelable.h b/media/libaaudio/src/binding/AudioEndpointParcelable.h
index 544aa92..5d2c38f 100644
--- a/media/libaaudio/src/binding/AudioEndpointParcelable.h
+++ b/media/libaaudio/src/binding/AudioEndpointParcelable.h
@@ -52,7 +52,20 @@
*/
int32_t addFileDescriptor(const android::base::unique_fd& fd, int32_t sizeInBytes);
+ /**
+ * Close current data file descriptor. The duplicated file descriptor will be close.
+ */
+ void closeDataFileDescriptor();
+
+ /**
+ * Update current data file descriptor with given endpoint parcelable.
+ * @param endpointParcelable an endpoint parcelable that contains new data file
+ * descriptor information
+ */
+ void updateDataFileDescriptor(AudioEndpointParcelable* endpointParcelable);
+
aaudio_result_t resolve(EndpointDescriptor *descriptor);
+ aaudio_result_t resolveDataQueue(RingBufferDescriptor *descriptor);
aaudio_result_t close();
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.cpp b/media/libaaudio/src/binding/RingBufferParcelable.cpp
index fa7ca72..3bc51d0 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.cpp
+++ b/media/libaaudio/src/binding/RingBufferParcelable.cpp
@@ -33,6 +33,7 @@
: mReadCounterParcelable(parcelable.readCounterParcelable),
mWriteCounterParcelable(parcelable.writeCounterParcelable),
mDataParcelable(parcelable.dataParcelable),
+ mSharedMemoryIndex(parcelable.sharedMemoryIndex),
mBytesPerFrame(parcelable.bytesPerFrame),
mFramesPerBurst(parcelable.framesPerBurst),
mCapacityInFrames(parcelable.capacityInFrames),
@@ -45,6 +46,7 @@
result.readCounterParcelable = mReadCounterParcelable.parcelable();
result.writeCounterParcelable = mWriteCounterParcelable.parcelable();
result.dataParcelable = mDataParcelable.parcelable();
+ result.sharedMemoryIndex = mSharedMemoryIndex;
result.bytesPerFrame = mBytesPerFrame;
result.framesPerBurst = mFramesPerBurst;
result.capacityInFrames = mCapacityInFrames;
@@ -60,6 +62,7 @@
int32_t readCounterOffset,
int32_t writeCounterOffset,
int32_t counterSizeBytes) {
+ mSharedMemoryIndex = sharedMemoryIndex;
mReadCounterParcelable.setup(sharedMemoryIndex, readCounterOffset, counterSizeBytes);
mWriteCounterParcelable.setup(sharedMemoryIndex, writeCounterOffset, counterSizeBytes);
mDataParcelable.setup(sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes);
@@ -68,12 +71,13 @@
void RingBufferParcelable::setupMemory(int32_t sharedMemoryIndex,
int32_t dataMemoryOffset,
int32_t dataSizeInBytes) {
+ mSharedMemoryIndex = sharedMemoryIndex;
mReadCounterParcelable.setup(sharedMemoryIndex, 0, 0);
mWriteCounterParcelable.setup(sharedMemoryIndex, 0, 0);
mDataParcelable.setup(sharedMemoryIndex, dataMemoryOffset, dataSizeInBytes);
}
-int32_t RingBufferParcelable::getBytesPerFrame() {
+int32_t RingBufferParcelable::getBytesPerFrame() const {
return mBytesPerFrame;
}
@@ -81,7 +85,7 @@
mBytesPerFrame = bytesPerFrame;
}
-int32_t RingBufferParcelable::getFramesPerBurst() {
+int32_t RingBufferParcelable::getFramesPerBurst() const {
return mFramesPerBurst;
}
@@ -89,7 +93,7 @@
mFramesPerBurst = framesPerBurst;
}
-int32_t RingBufferParcelable::getCapacityInFrames() {
+int32_t RingBufferParcelable::getCapacityInFrames() const {
return mCapacityInFrames;
}
@@ -124,6 +128,14 @@
return AAUDIO_OK;
}
+void RingBufferParcelable::updateMemory(const RingBufferParcelable& parcelable) {
+ setupMemory(mSharedMemoryIndex, 0,
+ parcelable.getCapacityInFrames() * parcelable.getBytesPerFrame());
+ setBytesPerFrame(parcelable.getBytesPerFrame());
+ setFramesPerBurst(parcelable.getFramesPerBurst());
+ setCapacityInFrames(parcelable.getCapacityInFrames());
+}
+
aaudio_result_t RingBufferParcelable::validate() const {
if (mCapacityInFrames < 0 || mCapacityInFrames >= 32 * 1024) {
ALOGE("invalid mCapacityInFrames = %d", mCapacityInFrames);
diff --git a/media/libaaudio/src/binding/RingBufferParcelable.h b/media/libaaudio/src/binding/RingBufferParcelable.h
index 2508cea..29d0d86 100644
--- a/media/libaaudio/src/binding/RingBufferParcelable.h
+++ b/media/libaaudio/src/binding/RingBufferParcelable.h
@@ -46,15 +46,15 @@
int32_t dataMemoryOffset,
int32_t dataSizeInBytes);
- int32_t getBytesPerFrame();
+ int32_t getBytesPerFrame() const;
void setBytesPerFrame(int32_t bytesPerFrame);
- int32_t getFramesPerBurst();
+ int32_t getFramesPerBurst() const;
void setFramesPerBurst(int32_t framesPerBurst);
- int32_t getCapacityInFrames();
+ int32_t getCapacityInFrames() const;
void setCapacityInFrames(int32_t capacityInFrames);
@@ -62,6 +62,12 @@
aaudio_result_t resolve(SharedMemoryParcelable *memoryParcels, RingBufferDescriptor *descriptor);
+ void updateMemory(const RingBufferParcelable& parcelable);
+
+ int32_t getSharedMemoryIndex() const {
+ return mSharedMemoryIndex;
+ }
+
void dump();
// Extract a parcelable representation of this object.
@@ -71,6 +77,7 @@
SharedRegionParcelable mReadCounterParcelable;
SharedRegionParcelable mWriteCounterParcelable;
SharedRegionParcelable mDataParcelable;
+ int32_t mSharedMemoryIndex = -1;
int32_t mBytesPerFrame = 0; // index is in frames
int32_t mFramesPerBurst = 0; // for ISOCHRONOUS queues
int32_t mCapacityInFrames = 0; // zero if unused
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 3a49655..741aefc 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -64,6 +64,10 @@
mSizeInBytes = sizeInBytes;
}
+void SharedMemoryParcelable::setup(const SharedMemoryParcelable &sharedMemoryParcelable) {
+ setup(sharedMemoryParcelable.mFd, sharedMemoryParcelable.mSizeInBytes);
+}
+
aaudio_result_t SharedMemoryParcelable::close() {
if (mResolvedAddress != MMAP_UNRESOLVED_ADDRESS) {
int err = munmap(mResolvedAddress, mSizeInBytes);
@@ -76,6 +80,14 @@
return AAUDIO_OK;
}
+aaudio_result_t SharedMemoryParcelable::closeAndReleaseFd() {
+ aaudio_result_t result = close();
+ if (result == AAUDIO_OK) {
+ mFd.reset();
+ }
+ return result;
+}
+
aaudio_result_t SharedMemoryParcelable::resolveSharedMemory(const unique_fd& fd) {
mResolvedAddress = (uint8_t *) mmap(nullptr, mSizeInBytes, PROT_READ | PROT_WRITE,
MAP_SHARED, fd.get(), 0);
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.h b/media/libaaudio/src/binding/SharedMemoryParcelable.h
index 1f2c335..7762fef 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.h
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.h
@@ -52,12 +52,16 @@
*/
void setup(const android::base::unique_fd& fd, int32_t sizeInBytes);
+ void setup(const SharedMemoryParcelable& sharedMemoryParcelable);
+
// mmap() shared memory
aaudio_result_t resolve(int32_t offsetInBytes, int32_t sizeInBytes, void **regionAddressPtr);
// munmap() any mapped memory
aaudio_result_t close();
+ aaudio_result_t closeAndReleaseFd();
+
int32_t getSizeInBytes();
void dump();
diff --git a/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl b/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
index 44d2211..485c2e2 100644
--- a/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
+++ b/media/libaaudio/src/binding/aidl/aaudio/IAAudioService.aidl
@@ -78,4 +78,6 @@
int unregisterAudioThread(int streamHandle,
int clientThreadId);
+
+ int exitStandby(int streamHandle, out Endpoint endpoint);
}
diff --git a/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl b/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
index a58b33a..dd64493 100644
--- a/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
+++ b/media/libaaudio/src/binding/aidl/aaudio/RingBuffer.aidl
@@ -26,4 +26,5 @@
int framesPerBurst; // for ISOCHRONOUS queues
int capacityInFrames; // zero if unused
int /* RingbufferFlags */ flags; // = RingbufferFlags::NONE;
+ int sharedMemoryIndex;
}
\ No newline at end of file
diff --git a/media/libaaudio/src/client/AudioEndpoint.cpp b/media/libaaudio/src/client/AudioEndpoint.cpp
index 24888de..e780f4f 100644
--- a/media/libaaudio/src/client/AudioEndpoint.cpp
+++ b/media/libaaudio/src/client/AudioEndpoint.cpp
@@ -139,38 +139,49 @@
);
// ============================ data queue =============================
- descriptor = &pEndpointDescriptor->dataQueueDescriptor;
- ALOGV("configure() data framesPerBurst = %d", descriptor->framesPerBurst);
+ result = configureDataQueue(pEndpointDescriptor->dataQueueDescriptor, direction);
+
+ return result;
+}
+
+aaudio_result_t AudioEndpoint::configureDataQueue(const RingBufferDescriptor& descriptor,
+ aaudio_direction_t direction) {
+ aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("data", &descriptor);
+ if (result != AAUDIO_OK) {
+ return result;
+ }
+
+ ALOGV("configure() data framesPerBurst = %d", descriptor.framesPerBurst);
ALOGV("configure() data readCounterAddress = %p",
- descriptor->readCounterAddress);
+ descriptor.readCounterAddress);
// An example of free running is when the other side is read or written by hardware DMA
// or a DSP. It does not update its counter so we have to update it.
int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT)
- ? descriptor->readCounterAddress // read by other side
- : descriptor->writeCounterAddress; // written by other side
+ ? descriptor.readCounterAddress // read by other side
+ : descriptor.writeCounterAddress; // written by other side
mFreeRunning = (remoteCounter == nullptr);
ALOGV("configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
- int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
+ int64_t *readCounterAddress = (descriptor.readCounterAddress == nullptr)
? &mDataReadCounter
- : descriptor->readCounterAddress;
- int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
+ : descriptor.readCounterAddress;
+ int64_t *writeCounterAddress = (descriptor.writeCounterAddress == nullptr)
? &mDataWriteCounter
- : descriptor->writeCounterAddress;
+ : descriptor.writeCounterAddress;
// Clear buffer to avoid an initial glitch on some devices.
- size_t bufferSizeBytes = descriptor->capacityInFrames * descriptor->bytesPerFrame;
- memset(descriptor->dataAddress, 0, bufferSizeBytes);
+ size_t bufferSizeBytes = descriptor.capacityInFrames * descriptor.bytesPerFrame;
+ memset(descriptor.dataAddress, 0, bufferSizeBytes);
mDataQueue = std::make_unique<FifoBufferIndirect>(
- descriptor->bytesPerFrame,
- descriptor->capacityInFrames,
+ descriptor.bytesPerFrame,
+ descriptor.capacityInFrames,
readCounterAddress,
writeCounterAddress,
- descriptor->dataAddress
+ descriptor.dataAddress
);
- uint32_t threshold = descriptor->capacityInFrames / 2;
+ uint32_t threshold = descriptor.capacityInFrames / 2;
mDataQueue->setThreshold(threshold);
return result;
}
@@ -181,47 +192,66 @@
}
int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
- return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
+ return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
}
int32_t AudioEndpoint::getEmptyFramesAvailable() {
- return mDataQueue->getEmptyFramesAvailable();
+ return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyFramesAvailable();
}
int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) {
- return mDataQueue->getFullDataAvailable(wrappingBuffer);
+ return mDataQueue == nullptr ? 0 : mDataQueue->getFullDataAvailable(wrappingBuffer);
}
int32_t AudioEndpoint::getFullFramesAvailable() {
- return mDataQueue->getFullFramesAvailable();
+ return mDataQueue == nullptr ? 0 : mDataQueue->getFullFramesAvailable();
+}
+
+android::fifo_frames_t AudioEndpoint::read(void *buffer, android::fifo_frames_t numFrames) {
+ return mDataQueue == nullptr ? 0 : mDataQueue->read(buffer, numFrames);
+}
+
+android::fifo_frames_t AudioEndpoint::write(void *buffer, android::fifo_frames_t numFrames) {
+ return mDataQueue == nullptr ? 0 : mDataQueue->write(buffer, numFrames);
}
void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
- mDataQueue->advanceWriteIndex(deltaFrames);
+ if (mDataQueue != nullptr) {
+ mDataQueue->advanceWriteIndex(deltaFrames);
+ }
}
void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
- mDataQueue->advanceReadIndex(deltaFrames);
+ if (mDataQueue != nullptr) {
+ mDataQueue->advanceReadIndex(deltaFrames);
+ }
}
void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) {
- mDataQueue->setReadCounter(framesRead);
+ if (mDataQueue != nullptr) {
+ mDataQueue->setReadCounter(framesRead);
+ }
}
fifo_counter_t AudioEndpoint::getDataReadCounter() const {
- return mDataQueue->getReadCounter();
+ return mDataQueue == nullptr ? 0 : mDataQueue->getReadCounter();
}
void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) {
- mDataQueue->setWriteCounter(framesRead);
+ if (mDataQueue != nullptr) {
+ mDataQueue->setWriteCounter(framesRead);
+ }
}
fifo_counter_t AudioEndpoint::getDataWriteCounter() const {
- return mDataQueue->getWriteCounter();
+ return mDataQueue == nullptr ? 0 : mDataQueue->getWriteCounter();
}
int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
int32_t *actualFrames) {
+ if (mDataQueue == nullptr) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
}
@@ -231,11 +261,11 @@
}
int32_t AudioEndpoint::getBufferSizeInFrames() const {
- return mDataQueue->getThreshold();
+ return mDataQueue == nullptr ? 0 : mDataQueue->getThreshold();
}
int32_t AudioEndpoint::getBufferCapacityInFrames() const {
- return (int32_t)mDataQueue->getBufferCapacityInFrames();
+ return mDataQueue == nullptr ? 0 : (int32_t)mDataQueue->getBufferCapacityInFrames();
}
void AudioEndpoint::dump() const {
@@ -244,5 +274,7 @@
}
void AudioEndpoint::eraseDataMemory() {
- mDataQueue->eraseMemory();
+ if (mDataQueue != nullptr) {
+ mDataQueue->eraseMemory();
+ }
}
diff --git a/media/libaaudio/src/client/AudioEndpoint.h b/media/libaaudio/src/client/AudioEndpoint.h
index b3dbc20..01dd05a 100644
--- a/media/libaaudio/src/client/AudioEndpoint.h
+++ b/media/libaaudio/src/client/AudioEndpoint.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_AAUDIO_AUDIO_ENDPOINT_H
#define ANDROID_AAUDIO_AUDIO_ENDPOINT_H
+#include <mutex>
+
#include <aaudio/AAudio.h>
#include "binding/AAudioServiceMessage.h"
@@ -42,6 +44,9 @@
aaudio_result_t configure(const EndpointDescriptor *pEndpointDescriptor,
aaudio_direction_t direction);
+ aaudio_result_t configureDataQueue(const RingBufferDescriptor &descriptor,
+ aaudio_direction_t direction);
+
/**
* Read from a command passed up from the Server.
* @return 1 if command received, 0 for no command, or negative error.
@@ -56,6 +61,10 @@
int32_t getFullFramesAvailable();
+ android::fifo_frames_t read(void* buffer, android::fifo_frames_t numFrames);
+
+ android::fifo_frames_t write(void* buffer, android::fifo_frames_t numFrames);
+
void advanceReadIndex(int32_t deltaFrames);
void advanceWriteIndex(int32_t deltaFrames);
@@ -85,11 +94,21 @@
int32_t getBufferCapacityInFrames() const;
+ void setThreshold(int32_t frames) {
+ mDataQueue->setThreshold(frames);
+ }
+
+ int32_t getThreshold() {
+ return mDataQueue->getThreshold();
+ }
+
/**
* Write zeros to the data queue memory.
*/
void eraseDataMemory();
+ void freeDataQueue();
+
void dump() const;
private:
@@ -98,6 +117,8 @@
bool mFreeRunning{false};
android::fifo_counter_t mDataReadCounter{0}; // only used if free-running
android::fifo_counter_t mDataWriteCounter{0}; // only used if free-running
+
+ std::mutex mDataQueueLock;
};
} // namespace aaudio
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index afdc2ac..9f0564f 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -81,8 +81,6 @@
aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
aaudio_result_t result = AAUDIO_OK;
- int32_t framesPerBurst;
- int32_t framesPerHardwareBurst;
AAudioStreamRequest request;
AAudioStreamConfiguration configurationOutput;
@@ -97,9 +95,6 @@
return result;
}
- const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
- int32_t burstMicros = 0;
-
const audio_format_t requestedFormat = getFormat();
// We have to do volume scaling. So we prefer FLOAT format.
if (requestedFormat == AUDIO_FORMAT_DEFAULT) {
@@ -215,12 +210,28 @@
goto error;
}
- framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+ if ((result = configureDataInformation(builder.getFramesPerDataCallback())) != AAUDIO_OK) {
+ goto error;
+ }
+
+ setState(AAUDIO_STREAM_STATE_OPEN);
+
+ return result;
+
+error:
+ safeReleaseClose();
+ return result;
+}
+
+aaudio_result_t AudioStreamInternal::configureDataInformation(int32_t callbackFrames) {
+ int32_t framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
// Scale up the burst size to meet the minimum equivalent in microseconds.
// This is to avoid waking the CPU too often when the HW burst is very small
// or at high sample rates.
- framesPerBurst = framesPerHardwareBurst;
+ int32_t framesPerBurst = framesPerHardwareBurst;
+ int32_t burstMicros = 0;
+ const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
do {
if (burstMicros > 0) { // skip first loop
framesPerBurst *= 2;
@@ -233,8 +244,7 @@
// Validate final burst size.
if (framesPerBurst < MIN_FRAMES_PER_BURST || framesPerBurst > MAX_FRAMES_PER_BURST) {
ALOGE("%s - framesPerBurst out of range = %d", __func__, framesPerBurst);
- result = AAUDIO_ERROR_OUT_OF_RANGE;
- goto error;
+ return AAUDIO_ERROR_OUT_OF_RANGE;
}
setFramesPerBurst(framesPerBurst); // only save good value
@@ -242,26 +252,21 @@
if (mBufferCapacityInFrames < getFramesPerBurst()
|| mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) {
ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames);
- result = AAUDIO_ERROR_OUT_OF_RANGE;
- goto error;
+ return AAUDIO_ERROR_OUT_OF_RANGE;
}
mClockModel.setSampleRate(getSampleRate());
mClockModel.setFramesPerBurst(framesPerHardwareBurst);
if (isDataCallbackSet()) {
- mCallbackFrames = builder.getFramesPerDataCallback();
+ mCallbackFrames = callbackFrames;
if (mCallbackFrames > getBufferCapacity() / 2) {
ALOGW("%s - framesPerCallback too big = %d, capacity = %d",
__func__, mCallbackFrames, getBufferCapacity());
- result = AAUDIO_ERROR_OUT_OF_RANGE;
- goto error;
-
+ return AAUDIO_ERROR_OUT_OF_RANGE;
} else if (mCallbackFrames < 0) {
ALOGW("%s - framesPerCallback negative", __func__);
- result = AAUDIO_ERROR_OUT_OF_RANGE;
- goto error;
-
+ return AAUDIO_ERROR_OUT_OF_RANGE;
}
if (mCallbackFrames == AAUDIO_UNSPECIFIED) {
mCallbackFrames = getFramesPerBurst();
@@ -302,14 +307,7 @@
}
setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q
-
- setState(AAUDIO_STREAM_STATE_OPEN);
-
- return result;
-
-error:
- safeReleaseClose();
- return result;
+ return AAUDIO_OK;
}
// This must be called under mStreamLock.
@@ -357,6 +355,60 @@
}
}
+aaudio_result_t AudioStreamInternal::exitStandby_l() {
+ AudioEndpointParcelable endpointParcelable;
+ // The stream is in standby mode, copy all available data and then close the duplicated
+ // shared file descriptor so that it won't cause issue when the HAL try to reallocate new
+ // shared file descriptor when exiting from standby.
+ // Cache current read counter, which will be reset to new read and write counter
+ // when the new data queue and endpoint are reconfigured.
+ const android::fifo_counter_t readCounter = mAudioEndpoint->getDataReadCounter();
+ // Cache the buffer size which may be from client.
+ const int32_t previousBufferSize = mBufferSizeInFrames;
+ // Copy all available data from current data queue.
+ uint8_t buffer[getBufferCapacity() * getBytesPerFrame()];
+ android::fifo_frames_t fullFramesAvailable =
+ mAudioEndpoint->read(buffer, getBufferCapacity());
+ mEndPointParcelable.closeDataFileDescriptor();
+ aaudio_result_t result = mServiceInterface.exitStandby(
+ mServiceStreamHandle, endpointParcelable);
+ if (result != AAUDIO_OK) {
+ ALOGE("Failed to exit standby, error=%d", result);
+ goto exit;
+ }
+ // Reconstruct data queue descriptor using new shared file descriptor.
+ mEndPointParcelable.updateDataFileDescriptor(&endpointParcelable);
+ result = mEndPointParcelable.resolveDataQueue(&mEndpointDescriptor.dataQueueDescriptor);
+ if (result != AAUDIO_OK) {
+ ALOGE("Failed to resolve data queue after exiting standby, error=%d", result);
+ goto exit;
+ }
+ // Reconfigure audio endpoint with new data queue descriptor.
+ mAudioEndpoint->configureDataQueue(
+ mEndpointDescriptor.dataQueueDescriptor, getDirection());
+ // Set read and write counters with previous read counter, the later write action
+ // will make the counter at the correct place.
+ mAudioEndpoint->setDataReadCounter(readCounter);
+ mAudioEndpoint->setDataWriteCounter(readCounter);
+ result = configureDataInformation(mCallbackFrames);
+ if (result != AAUDIO_OK) {
+ ALOGE("Failed to configure data information after exiting standby, error=%d", result);
+ goto exit;
+ }
+ // Write data from previous data buffer to new endpoint.
+ if (android::fifo_frames_t framesWritten =
+ mAudioEndpoint->write(buffer, fullFramesAvailable);
+ framesWritten != fullFramesAvailable) {
+ ALOGW("Some data lost after exiting standby, frames written: %d, "
+ "frames to write: %d", framesWritten, fullFramesAvailable);
+ }
+ // Reset previous buffer size as it may be requested by the client.
+ setBufferSize(previousBufferSize);
+
+exit:
+ return result;
+}
+
/*
* It normally takes about 20-30 msec to start a stream on the server.
* But the first time can take as much as 200-300 msec. The HW
@@ -393,8 +445,15 @@
prepareBuffersForStart(); // tell subclasses to get ready
aaudio_result_t result = mServiceInterface.startStream(mServiceStreamHandle);
- if (result == AAUDIO_ERROR_INVALID_HANDLE) {
- ALOGD("%s() INVALID_HANDLE, stream was probably stolen", __func__);
+ if (result == AAUDIO_ERROR_STANDBY) {
+ // The stream is at standby mode. Need to exit standby before starting the stream.
+ result = exitStandby_l();
+ if (result == AAUDIO_OK) {
+ result = mServiceInterface.startStream(mServiceStreamHandle);
+ }
+ }
+ if (result != AAUDIO_OK) {
+ ALOGD("%s() error = %d, stream was probably stolen", __func__, result);
// Stealing was added in R. Coerce result to improve backward compatibility.
result = AAUDIO_ERROR_DISCONNECTED;
setState(AAUDIO_STREAM_STATE_DISCONNECTED);
@@ -414,6 +473,7 @@
result = createThread_l(periodNanos, aaudio_callback_thread_proc, this);
}
if (result != AAUDIO_OK) {
+ // TODO(b/214607638): Do we want to roll back to original state or keep as disconnected?
setState(originalState);
}
return result;
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index eab1382..2367572 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -184,9 +184,14 @@
aaudio_result_t writeNowWithConversion(const void *buffer,
int32_t numFrames);
+ // Exit the stream from standby, will reconstruct data path.
+ aaudio_result_t exitStandby_l() REQUIRES(mStreamLock);
+
// Adjust timing model based on timestamp from service.
void processTimestamp(uint64_t position, int64_t time);
+ aaudio_result_t configureDataInformation(int32_t callbackFrames);
+
// Thread on other side of FIFO will have wakeup jitter.
// By delaying slightly we can avoid waking up before other side is ready.
const int32_t mWakeupDelayNanos; // delay past typical wakeup jitter
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 73432af..06f05b0 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -602,6 +602,7 @@
void AudioStream::setDuckAndMuteVolume(float duckAndMuteVolume) {
ALOGD("%s() to %f", __func__, duckAndMuteVolume);
+ std::lock_guard<std::mutex> lock(mStreamLock);
mDuckAndMuteVolume = duckAndMuteVolume;
doSetVolume(); // apply this change
}
diff --git a/media/libaaudio/tests/test_steal_exclusive.cpp b/media/libaaudio/tests/test_steal_exclusive.cpp
index 5cb005c..ca4f3d6 100644
--- a/media/libaaudio/tests/test_steal_exclusive.cpp
+++ b/media/libaaudio/tests/test_steal_exclusive.cpp
@@ -114,7 +114,7 @@
mCloseEnabled = enabled;
}
- void restartStream() {
+ aaudio_result_t restartStream() {
int retriesLeft = mMaxRetries;
aaudio_result_t result;
do {
@@ -130,6 +130,7 @@
mName.c_str(),
AAudio_convertResultToText(result));
} while (retriesLeft-- > 0 && result != AAUDIO_OK);
+ return result;
}
aaudio_data_callback_result_t onAudioReady(
@@ -238,6 +239,12 @@
return AAudioStream_requestStart(mStream);
}
+ aaudio_result_t pause() {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStream == nullptr) return 0;
+ return AAudioStream_requestPause(mStream);
+ }
+
aaudio_result_t stop() {
std::lock_guard<std::mutex> lock(mLock);
if (mStream == nullptr) return 0;
@@ -326,9 +333,10 @@
}
static void s_usage() {
- printf("test_steal_exclusive [-i] [-r{maxRetries}] [-d{delay}] -s -c{flag}\n");
+ printf("test_steal_exclusive [-i] [-r{maxRetries}] [-d{delay}] [-p{pausedTime}]-s -c{flag}\n");
printf(" -i direction INPUT, otherwise OUTPUT\n");
printf(" -d Delay open by milliseconds, default = 0\n");
+ printf(" -p Pause first stream then sleep for msec before opening second streams, default = 0\n");
printf(" -r max Retries in the error callback, default = 1\n");
printf(" -s try to open in SHARED mode\n");
printf(" -c enable or disabling Closing of the stream with 0/1, default = 1\n");
@@ -344,6 +352,7 @@
int openDelayMillis = 0;
bool closeEnabled = true;
aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+ int pausedMillis = 0;
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
@@ -366,6 +375,9 @@
case 'i':
direction = AAUDIO_DIRECTION_INPUT;
break;
+ case 'p':
+ pausedMillis = atoi(&arg[2]);
+ break;
case 'r':
maxRetries = atoi(&arg[2]);
break;
@@ -428,6 +440,12 @@
}
}
+ if (pausedMillis > 0) {
+ printf("Pausing the VICTIM for %d millis before starting THIEF -----\n", pausedMillis);
+ victim.pause();
+ usleep(pausedMillis * 1000);
+ }
+
printf("Trying to start the THIEF stream, which may steal the VICTIM MMAP resource -----\n");
result = thief.openAudioStream(direction, requestedSharingMode);
if (result != AAUDIO_OK) {
@@ -443,6 +461,25 @@
errorCount++;
}
+ if (pausedMillis > 0) {
+ result = victim.start();
+ printf("Restarting VICTIM, AAudioStream_requestStart(VICTIM) returned %d "
+ ">>>>>>>>>>>>>>>>>>>>>>\n", result);
+ if (result == AAUDIO_ERROR_DISCONNECTED) {
+ // The stream is disconnected due to thief steal the resource
+ printf("VICTIM was disconnected while hanging as the THIEF "
+ "stole the resource >>>>>>>>>>>>>>>>>>>>>>\n");
+ result = victim.restartStream();
+ printf("Restarting VICTIM, AAudioStream_requestStart(VICTIM) returned %d "
+ ">>>>>>>>>>>>>>>>>>>>>>\n", result);
+ if (result != AAUDIO_OK) {
+ errorCount++;
+ }
+ } else {
+ errorCount++;
+ }
+ }
+
// Give stream time to advance.
usleep(SLEEP_DURATION_MSEC * 1000);
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 323e002..b7be3ff 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1434,6 +1434,8 @@
return AUDIO_INPUT_FLAG_HW_AV_SYNC;
case AudioInputFlags::DIRECT:
return AUDIO_INPUT_FLAG_DIRECT;
+ case AudioInputFlags::ULTRASOUND:
+ return AUDIO_INPUT_FLAG_ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
@@ -1459,6 +1461,8 @@
return AudioInputFlags::HW_AV_SYNC;
case AUDIO_INPUT_FLAG_DIRECT:
return AudioInputFlags::DIRECT;
+ case AUDIO_INPUT_FLAG_ULTRASOUND:
+ return AudioInputFlags::ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
@@ -1498,6 +1502,8 @@
return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
case AudioOutputFlags::GAPLESS_OFFLOAD:
return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+ case AudioOutputFlags::ULTRASOUND:
+ return AUDIO_OUTPUT_FLAG_ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
@@ -1539,6 +1545,8 @@
return AudioOutputFlags::INCALL_MUSIC;
case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
return AudioOutputFlags::GAPLESS_OFFLOAD;
+ case AUDIO_OUTPUT_FLAG_ULTRASOUND:
+ return AudioOutputFlags::ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
@@ -1744,6 +1752,8 @@
return AUDIO_SOURCE_UNPROCESSED;
case AudioSource::VOICE_PERFORMANCE:
return AUDIO_SOURCE_VOICE_PERFORMANCE;
+ case AudioSource::ULTRASOUND:
+ return AUDIO_SOURCE_ULTRASOUND;
case AudioSource::ECHO_REFERENCE:
return AUDIO_SOURCE_ECHO_REFERENCE;
case AudioSource::FM_TUNER:
@@ -1781,6 +1791,8 @@
return AudioSource::UNPROCESSED;
case AUDIO_SOURCE_VOICE_PERFORMANCE:
return AudioSource::VOICE_PERFORMANCE;
+ case AUDIO_SOURCE_ULTRASOUND:
+ return AudioSource::ULTRASOUND;
case AUDIO_SOURCE_ECHO_REFERENCE:
return AudioSource::ECHO_REFERENCE;
case AUDIO_SOURCE_FM_TUNER:
@@ -2141,6 +2153,8 @@
return AUDIO_CONTENT_TYPE_MOVIE;
case AudioContentType::SONIFICATION:
return AUDIO_CONTENT_TYPE_SONIFICATION;
+ case AudioContentType::ULTRASOUND:
+ return AUDIO_CONTENT_TYPE_ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
@@ -2158,6 +2172,8 @@
return AudioContentType::MOVIE;
case AUDIO_CONTENT_TYPE_SONIFICATION:
return AudioContentType::SONIFICATION;
+ case AUDIO_CONTENT_TYPE_ULTRASOUND:
+ return AudioContentType::ULTRASOUND;
}
return unexpected(BAD_VALUE);
}
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 9733cb3..be39527 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -41,7 +41,7 @@
},
}
-cc_library_shared {
+cc_library {
name: "libaudiopolicy",
srcs: [
"AudioAttributes.cpp",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f191c49..ebd488a 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -20,6 +20,7 @@
#include <inttypes.h>
#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
#include <sys/resource.h>
#include <audio_utils/format.h>
@@ -40,6 +41,7 @@
namespace android {
+using ::android::base::StringPrintf;
using android::content::AttributionSourceState;
using aidl_utils::statusTFromBinderStatus;
@@ -304,7 +306,6 @@
int32_t maxSharedAudioHistoryMs)
{
status_t status = NO_ERROR;
- uint32_t channelCount;
const sp<IAudioRecordCallback> callbackHandle = callback.promote();
// Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
ALOGV("%s(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
@@ -336,38 +337,8 @@
mSelectedMicFieldDimension = microphoneFieldDimension;
mMaxSharedAudioHistoryMs = maxSharedAudioHistoryMs;
- switch (transferType) {
- case TRANSFER_DEFAULT:
- if (callbackHandle == nullptr || threadCanCallJava) {
- transferType = TRANSFER_SYNC;
- } else {
- transferType = TRANSFER_CALLBACK;
- }
- break;
- case TRANSFER_CALLBACK:
- if (callbackHandle == nullptr) {
- ALOGE("%s(): Transfer type TRANSFER_CALLBACK but callback == nullptr", __func__);
- status = BAD_VALUE;
- goto exit;
- }
- break;
- case TRANSFER_OBTAIN:
- case TRANSFER_SYNC:
- break;
- default:
- ALOGE("%s(): Invalid transfer type %d", __func__, transferType);
- status = BAD_VALUE;
- goto exit;
- }
- mTransfer = transferType;
-
- // invariant that mAudioRecord != 0 is true only after set() returns successfully
- if (mAudioRecord != 0) {
- ALOGE("%s(): Track already in use", __func__);
- status = INVALID_OPERATION;
- goto exit;
- }
-
+ std::string errorMessage;
+ // Copy the state variables early so they are available for error reporting.
if (pAttributes == nullptr) {
mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
mAttributes.source = inputSource;
@@ -379,37 +350,69 @@
} else {
// stream type shouldn't be looked at, this track has audio attributes
memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
- ALOGV("%s(): Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
+ ALOGV("%s: Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
__func__, mAttributes.source, mAttributes.flags, mAttributes.tags);
}
-
mSampleRate = sampleRate;
-
- // these below should probably come from the audioFlinger too...
if (format == AUDIO_FORMAT_DEFAULT) {
format = AUDIO_FORMAT_PCM_16_BIT;
}
-
- // validate parameters
- // AudioFlinger capture only supports linear PCM
- if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
- ALOGE("%s(): Format %#x is not linear pcm", __func__, format);
- status = BAD_VALUE;
- goto exit;
- }
mFormat = format;
-
- if (!audio_is_input_channel(channelMask)) {
- ALOGE("%s(): Invalid channel mask %#x", __func__, channelMask);
- status = BAD_VALUE;
- goto exit;
- }
mChannelMask = channelMask;
- channelCount = audio_channel_count_from_in_mask(channelMask);
- mChannelCount = channelCount;
+ mSessionId = sessionId;
+ ALOGV("%s: mSessionId %d", __func__, mSessionId);
+ mOrigFlags = mFlags = flags;
- if (audio_is_linear_pcm(format)) {
- mFrameSize = channelCount * audio_bytes_per_sample(format);
+ mTransfer = transferType;
+ switch (mTransfer) {
+ case TRANSFER_DEFAULT:
+ if (callbackHandle == nullptr || threadCanCallJava) {
+ mTransfer = TRANSFER_SYNC;
+ } else {
+ mTransfer = TRANSFER_CALLBACK;
+ }
+ break;
+ case TRANSFER_CALLBACK:
+ if (callbackHandle == nullptr) {
+ errorMessage = StringPrintf(
+ "%s: Transfer type TRANSFER_CALLBACK but callback == nullptr", __func__);
+ status = BAD_VALUE;
+ goto error;
+ }
+ break;
+ case TRANSFER_OBTAIN:
+ case TRANSFER_SYNC:
+ break;
+ default:
+ errorMessage = StringPrintf("%s: Invalid transfer type %d", __func__, mTransfer);
+ status = BAD_VALUE;
+ goto error;
+ }
+
+ // invariant that mAudioRecord != 0 is true only after set() returns successfully
+ if (mAudioRecord != 0) {
+ errorMessage = StringPrintf("%s: Track already in use", __func__);
+ status = INVALID_OPERATION;
+ goto error;
+ }
+
+ // AudioFlinger capture only supports linear PCM
+ if (!audio_is_valid_format(mFormat) || !audio_is_linear_pcm(mFormat)) {
+ errorMessage = StringPrintf("%s: Format %#x is not linear pcm", __func__, mFormat);
+ status = BAD_VALUE;
+ goto error;
+ }
+
+ if (!audio_is_input_channel(mChannelMask)) {
+ errorMessage = StringPrintf("%s: Invalid channel mask %#x", __func__, mChannelMask);
+ status = BAD_VALUE;
+ goto error;
+ }
+
+ mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
+
+ if (audio_is_linear_pcm(mFormat)) {
+ mFrameSize = mChannelCount * audio_bytes_per_sample(mFormat);
} else {
mFrameSize = sizeof(uint8_t);
}
@@ -420,12 +423,7 @@
mNotificationFramesReq = notificationFrames;
// mNotificationFramesAct is initialized in createRecord_l
- mSessionId = sessionId;
- ALOGV("%s(): mSessionId %d", __func__, mSessionId);
-
- mOrigFlags = mFlags = flags;
mCallback = callbackHandle;
-
if (mCallback != nullptr) {
mAudioRecordThread = new AudioRecordThread(*this);
mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
@@ -446,6 +444,7 @@
mAudioRecordThread->requestExitAndWait();
mAudioRecordThread.clear();
}
+ // bypass error message to avoid logging twice (createRecord_l logs the error).
goto exit;
}
@@ -462,11 +461,14 @@
mFramesRead = 0;
mFramesReadServerOffset = 0;
-exit:
- mStatus = status;
+error:
if (status != NO_ERROR) {
mMediaMetrics.markError(status, __FUNCTION__);
+ ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+ reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
}
+exit:
+ mStatus = status;
return status;
}
@@ -857,9 +859,10 @@
status_t status;
static const int32_t kMaxCreateAttempts = 3;
int32_t remainingAttempts = kMaxCreateAttempts;
+ std::string errorMessage;
if (audioFlinger == 0) {
- ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
+ errorMessage = StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId);
status = NO_INIT;
goto exit;
}
@@ -925,8 +928,9 @@
break;
}
if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
- ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
- __func__, mPortId, status);
+ errorMessage = StringPrintf(
+ "%s(%d): AudioFlinger could not create record track, status: %d",
+ __func__, mPortId, status);
goto exit;
}
// FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
@@ -959,7 +963,7 @@
mServerSampleSize = audio_bytes_per_sample(mServerConfig.format);
if (output.cblk == 0) {
- ALOGE("%s(%d): Could not get control block", __func__, mPortId);
+ errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
status = NO_INIT;
goto exit;
}
@@ -969,7 +973,8 @@
// issue (e.g. by copying).
iMemPointer = output.cblk ->unsecurePointer();
if (iMemPointer == NULL) {
- ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
+ errorMessage = StringPrintf(
+ "%s(%d): Could not get control block pointer", __func__, mPortId);
status = NO_INIT;
goto exit;
}
@@ -988,7 +993,8 @@
// issue (e.g. by copying).
buffers = output.buffers->unsecurePointer();
if (buffers == NULL) {
- ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
+ errorMessage = StringPrintf(
+ "%s(%d): Could not get buffer pointer", __func__, mPortId);
status = NO_INIT;
goto exit;
}
@@ -1083,11 +1089,38 @@
.record();
exit:
+ if (status != NO_ERROR) {
+ ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+ reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
+ }
+
mStatus = status;
// sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
return status;
}
+// Report error associated with the event and some configuration details.
+void AudioRecord::reportError(status_t status, const char *event, const char *message) const
+{
+ if (status == NO_ERROR) return;
+ // We report error on the native side because some callers do not come
+ // from Java.
+ // Ensure these variables are initialized in set().
+ mediametrics::LogItem(AMEDIAMETRICS_KEY_AUDIO_RECORD_ERROR)
+ .set(AMEDIAMETRICS_PROP_EVENT, event)
+ .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
+ .set(AMEDIAMETRICS_PROP_STATUSMESSAGE, message)
+ .set(AMEDIAMETRICS_PROP_ORIGINALFLAGS, toString(mOrigFlags).c_str())
+ .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)mSessionId)
+ .set(AMEDIAMETRICS_PROP_SOURCE, toString(mAttributes.source).c_str())
+ .set(AMEDIAMETRICS_PROP_SELECTEDDEVICEID, (int32_t)mSelectedDeviceId)
+ .set(AMEDIAMETRICS_PROP_ENCODING, toString(mFormat).c_str())
+ .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
+ .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
+ .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
+ .record();
+}
+
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
{
if (audioBuffer == NULL) {
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index bdf3147..de14e1c 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1120,8 +1120,16 @@
{
using namespace std::chrono_literals;
+ // We use atomic access here for state variables - these are used as hints
+ // to ensure we have ramped down audio.
+ const int priorState = mProxy->getState();
+ const uint32_t priorPosition = mProxy->getPosition().unsignedValue();
+
pause();
+ // Only if we were previously active, do we wait to ramp down the audio.
+ if (priorState != CBLK_STATE_ACTIVE) return true;
+
AutoMutex lock(mLock);
// offload and direct tracks do not wait because pause volume ramp is handled by hardware.
if (isOffloadedOrDirect_l()) return true;
@@ -1129,16 +1137,25 @@
// Wait for the track state to be anything besides pausing.
// This ensures that the volume has ramped down.
constexpr auto SLEEP_INTERVAL_MS = 10ms;
+ constexpr auto POSITION_TIMEOUT_MS = 40ms; // don't wait longer than this for position change.
auto begin = std::chrono::steady_clock::now();
while (true) {
- // wait for state to change
+ // Wait for state and position to change.
+ // After pause() the server state should be PAUSING, but that may immediately
+ // convert to PAUSED by prepareTracks before data is read into the mixer.
+ // Hence we check that the state is not PAUSING and that the server position
+ // has advanced to be a more reliable estimate that the volume ramp has completed.
const int state = mProxy->getState();
+ const uint32_t position = mProxy->getPosition().unsignedValue();
mLock.unlock(); // only local variables accessed until lock.
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - begin);
- if (state != CBLK_STATE_PAUSING) {
- ALOGV("%s: success state:%d after %lld ms", __func__, state, elapsed.count());
+ if (state != CBLK_STATE_PAUSING &&
+ (elapsed >= POSITION_TIMEOUT_MS || position != priorPosition)) {
+ ALOGV("%s: success state:%d, position:%u after %lld ms"
+ " (prior state:%d prior position:%u)",
+ __func__, state, position, elapsed.count(), priorState, priorPosition);
return true;
}
std::chrono::milliseconds remaining = timeout - elapsed;
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index f6faaae..3cfcbf3 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -890,6 +890,8 @@
MediaMetrics mMediaMetrics;
std::string mMetricsId; // GUARDED_BY(mLock), could change in createRecord_l().
std::string mCallerName; // for example "aaudio"
+
+ void reportError(status_t status, const char *event, const char *message) const;
};
}; // namespace android
diff --git a/media/libheadtracking/HeadTrackingProcessor.cpp b/media/libheadtracking/HeadTrackingProcessor.cpp
index 257ee42..f2f15df 100644
--- a/media/libheadtracking/HeadTrackingProcessor.cpp
+++ b/media/libheadtracking/HeadTrackingProcessor.cpp
@@ -42,11 +42,13 @@
.rotationalDriftTimeConstant = options.rotationalDriftTimeConstant,
}),
mHeadStillnessDetector(StillnessDetector::Options{
+ .defaultValue = false,
.windowDuration = options.autoRecenterWindowDuration,
.translationalThreshold = options.autoRecenterTranslationalThreshold,
.rotationalThreshold = options.autoRecenterRotationalThreshold,
}),
mScreenStillnessDetector(StillnessDetector::Options{
+ .defaultValue = true,
.windowDuration = options.screenStillnessWindowDuration,
.translationalThreshold = options.screenStillnessTranslationalThreshold,
.rotationalThreshold = options.screenStillnessRotationalThreshold,
@@ -64,6 +66,7 @@
Pose3f predictedWorldToHead =
worldToHead * integrate(headTwist, mOptions.predictionDuration);
mHeadPoseDriftCompensator.setInput(timestamp, predictedWorldToHead);
+ mHeadStillnessDetector.setInput(timestamp, predictedWorldToHead);
mWorldToHeadTimestamp = timestamp;
}
@@ -74,8 +77,9 @@
mPhysicalToLogicalAngle = mPendingPhysicalToLogicalAngle;
}
- mScreenPoseDriftCompensator.setInput(
- timestamp, worldToScreen * Pose3f(rotateY(-mPhysicalToLogicalAngle)));
+ Pose3f worldToLogicalScreen = worldToScreen * Pose3f(rotateY(-mPhysicalToLogicalAngle));
+ mScreenPoseDriftCompensator.setInput(timestamp, worldToLogicalScreen);
+ mScreenStillnessDetector.setInput(timestamp, worldToLogicalScreen);
mWorldToScreenTimestamp = timestamp;
}
@@ -91,8 +95,6 @@
// Handle the screen first, since it might trigger a recentering of the head.
if (mWorldToScreenTimestamp.has_value()) {
const Pose3f worldToLogicalScreen = mScreenPoseDriftCompensator.getOutput();
- mScreenStillnessDetector.setInput(mWorldToScreenTimestamp.value(),
- worldToLogicalScreen);
bool screenStable = mScreenStillnessDetector.calculate(timestamp);
mModeSelector.setScreenStable(mWorldToScreenTimestamp.value(), screenStable);
// Whenever the screen is unstable, recenter the head pose.
@@ -106,7 +108,6 @@
// Handle head.
if (mWorldToHeadTimestamp.has_value()) {
Pose3f worldToHead = mHeadPoseDriftCompensator.getOutput();
- mHeadStillnessDetector.setInput(mWorldToHeadTimestamp.value(), worldToHead);
// Auto-recenter.
if (mHeadStillnessDetector.calculate(timestamp)) {
recenter(true, false);
diff --git a/media/libheadtracking/Pose.cpp b/media/libheadtracking/Pose.cpp
index 47241ce..ae39512 100644
--- a/media/libheadtracking/Pose.cpp
+++ b/media/libheadtracking/Pose.cpp
@@ -43,7 +43,7 @@
return {to, false};
}
// Always rate limit if t is 0 (required to avoid division by 0).
- if (t == 0) {
+ if (t == 0 || maxTranslationalVelocity == 0 || maxRotationalVelocity == 0) {
return {from, true};
}
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index ec5e1ec..0e96b03 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -133,14 +133,14 @@
{
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.emplace(sensor, format);
+ mEnabledSensorsExtra.emplace(sensor, SensorExtra{ .format = format });
}
// Enable the sensor.
if (mQueue->enableSensor(sensor, samplingPeriod.count(), 0, 0)) {
ALOGE("Failed to enable sensor");
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.erase(sensor);
+ mEnabledSensorsExtra.erase(sensor);
return false;
}
@@ -151,7 +151,7 @@
void stopSensor(int handle) override {
mEnabledSensors.erase(handle);
std::lock_guard lock(mMutex);
- mEnabledSensorFormats.erase(handle);
+ mEnabledSensorsExtra.erase(handle);
}
private:
@@ -159,6 +159,7 @@
kUnknown,
kQuaternion,
kRotationVectorsAndFlags,
+ kRotationVectorsAndDiscontinuityCount,
};
struct PoseEvent {
@@ -167,13 +168,18 @@
bool isNewReference;
};
+ struct SensorExtra {
+ DataFormat format;
+ std::optional<int32_t> discontinuityCount;
+ };
+
sp<Looper> mLooper;
Listener* const mListener;
SensorManager* const mSensorManager;
std::thread mThread;
std::mutex mMutex;
std::map<int32_t, SensorEnableGuard> mEnabledSensors;
- std::map<int32_t, DataFormat> mEnabledSensorFormats GUARDED_BY(mMutex);
+ std::map<int32_t, SensorExtra> mEnabledSensorsExtra GUARDED_BY(mMutex);
sp<SensorEventQueue> mQueue;
// We must do some of the initialization operations on the worker thread, because the API relies
@@ -248,17 +254,16 @@
}
void handleEvent(const ASensorEvent& event) {
- DataFormat format;
+ PoseEvent value;
{
std::lock_guard lock(mMutex);
- auto iter = mEnabledSensorFormats.find(event.sensor);
- if (iter == mEnabledSensorFormats.end()) {
+ auto iter = mEnabledSensorsExtra.find(event.sensor);
+ if (iter == mEnabledSensorsExtra.end()) {
// This can happen if we have any pending events shortly after stopping.
return;
}
- format = iter->second;
+ value = parseEvent(event, iter->second.format, &iter->second.discontinuityCount);
}
- auto value = parseEvent(event, format);
mListener->onPose(event.timestamp, event.sensor, value.pose, value.twist,
value.isNewReference);
}
@@ -274,6 +279,10 @@
return DataFormat::kQuaternion;
}
+ if (sensor->getType() == ASENSOR_TYPE_HEAD_TRACKER) {
+ return DataFormat::kRotationVectorsAndDiscontinuityCount;
+ }
+
if (sensor->getStringType() == "com.google.hardware.sensor.hid_dynamic.headtracker") {
return DataFormat::kRotationVectorsAndFlags;
}
@@ -313,8 +322,8 @@
return std::nullopt;
}
- static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format) {
- // TODO(ytai): Add more types.
+ static PoseEvent parseEvent(const ASensorEvent& event, DataFormat format,
+ std::optional<int32_t>* discontinutyCount) {
switch (format) {
case DataFormat::kQuaternion: {
Eigen::Quaternionf quat(event.data[3], event.data[0], event.data[1], event.data[2]);
@@ -338,6 +347,21 @@
(flags & (1 << 0)) != 0};
}
+ case DataFormat::kRotationVectorsAndDiscontinuityCount: {
+ Eigen::Vector3f rotation = {event.head_tracker.rx, event.head_tracker.ry,
+ event.head_tracker.rz};
+ Eigen::Vector3f twist = {event.head_tracker.vx, event.head_tracker.vy,
+ event.head_tracker.rz};
+ Eigen::Quaternionf quat = rotationVectorToQuaternion(rotation);
+ bool isNewReference =
+ !discontinutyCount->has_value() ||
+ discontinutyCount->value() != event.head_tracker.discontinuity_count;
+ *discontinutyCount = event.head_tracker.discontinuity_count;
+
+ return PoseEvent{Pose3f(quat), Twist3f(Eigen::Vector3f::Zero(), twist),
+ isNewReference};
+ }
+
default:
LOG_ALWAYS_FATAL("Unexpected sensor type: %d", static_cast<int>(format));
}
diff --git a/media/libheadtracking/StillnessDetector-test.cpp b/media/libheadtracking/StillnessDetector-test.cpp
index 29b036e..b6cd479 100644
--- a/media/libheadtracking/StillnessDetector-test.cpp
+++ b/media/libheadtracking/StillnessDetector-test.cpp
@@ -28,101 +28,140 @@
using Eigen::Vector3f;
using Options = StillnessDetector::Options;
-TEST(StillnessDetectorTest, Still) {
- StillnessDetector detector(Options{
- .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+class StillnessDetectorTest : public testing::TestWithParam<bool> {
+ public:
+ void SetUp() override { mDefaultValue = GetParam(); }
+
+ protected:
+ bool mDefaultValue;
+};
+
+TEST_P(StillnessDetectorTest, Still) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+ .windowDuration = 1000,
+ .translationalThreshold = 1,
+ .rotationalThreshold = 0.05});
const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(0, baseline);
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(300, withinThreshold);
- EXPECT_FALSE(detector.calculate(300));
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
- EXPECT_FALSE(detector.calculate(600));
+ EXPECT_EQ(mDefaultValue, detector.calculate(600));
detector.setInput(999, withinThreshold);
- EXPECT_FALSE(detector.calculate(999));
+ EXPECT_EQ(mDefaultValue, detector.calculate(999));
detector.setInput(1000, baseline);
EXPECT_TRUE(detector.calculate(1000));
}
-TEST(StillnessDetectorTest, ZeroDuration) {
- StillnessDetector detector(Options{.windowDuration = 0});
+TEST_P(StillnessDetectorTest, ZeroDuration) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue, .windowDuration = 0});
EXPECT_TRUE(detector.calculate(0));
EXPECT_TRUE(detector.calculate(1000));
}
-TEST(StillnessDetectorTest, NotStillTranslation) {
- StillnessDetector detector(Options{
- .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, NotStillTranslation) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+ .windowDuration = 1000,
+ .translationalThreshold = 1,
+ .rotationalThreshold = 0.05});
const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
const Pose3f outsideThreshold = baseline * Pose3f(Vector3f(1, 1, 0));
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(0, baseline);
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(300, outsideThreshold);
- EXPECT_FALSE(detector.calculate(300));
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
- EXPECT_FALSE(detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_FALSE(detector.calculate(900));
- detector.setInput(1299, baseline);
+ EXPECT_EQ(mDefaultValue, detector.calculate(600));
+ detector.setInput(1299, withinThreshold);
EXPECT_FALSE(detector.calculate(1299));
+ detector.setInput(1300, baseline);
EXPECT_TRUE(detector.calculate(1300));
}
-TEST(StillnessDetectorTest, NotStillRotation) {
- StillnessDetector detector(Options{
- .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, NotStillRotation) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+ .windowDuration = 1000,
+ .translationalThreshold = 1,
+ .rotationalThreshold = 0.05});
const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.03) * rotateY(-0.03));
const Pose3f outsideThreshold = baseline * Pose3f(rotateZ(0.06));
- EXPECT_FALSE(detector.calculate(0));
+
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(0, baseline);
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
detector.setInput(300, outsideThreshold);
- EXPECT_FALSE(detector.calculate(300));
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
- EXPECT_FALSE(detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_FALSE(detector.calculate(900));
- detector.setInput(1299, baseline);
+ EXPECT_EQ(mDefaultValue, detector.calculate(600));
+ detector.setInput(1299, withinThreshold);
EXPECT_FALSE(detector.calculate(1299));
+ detector.setInput(1300, baseline);
EXPECT_TRUE(detector.calculate(1300));
}
-TEST(StillnessDetectorTest, Reset) {
- StillnessDetector detector(Options{
- .windowDuration = 1000, .translationalThreshold = 1, .rotationalThreshold = 0.05});
+TEST_P(StillnessDetectorTest, Suppression) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+ .windowDuration = 1000,
+ .translationalThreshold = 1,
+ .rotationalThreshold = 0.05});
+
+ const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
+ const Pose3f outsideThreshold = baseline * Pose3f(Vector3f(1.1, 0, 0));
+ const Pose3f middlePoint = baseline * Pose3f(Vector3f(0.55, 0, 0));
+
+ detector.setInput(0, baseline);
+ detector.setInput(1000, baseline);
+ EXPECT_TRUE(detector.calculate(1000));
+ detector.setInput(1100, outsideThreshold);
+ EXPECT_FALSE(detector.calculate(1100));
+ detector.setInput(1500, middlePoint);
+ EXPECT_FALSE(detector.calculate(1500));
+ EXPECT_FALSE(detector.calculate(1999));
+ EXPECT_TRUE(detector.calculate(2000));
+}
+
+TEST_P(StillnessDetectorTest, Reset) {
+ StillnessDetector detector(Options{.defaultValue = mDefaultValue,
+ .windowDuration = 1000,
+ .translationalThreshold = 1,
+ .rotationalThreshold = 0.05});
const Pose3f baseline(Vector3f{1, 2, 3}, Quaternionf::UnitRandom());
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
- EXPECT_FALSE(detector.calculate(0));
- detector.setInput(0, baseline);
- EXPECT_FALSE(detector.calculate(0));
+ EXPECT_EQ(mDefaultValue, detector.calculate(0));
+ detector.setInput(300, baseline);
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.reset();
detector.setInput(600, baseline);
- EXPECT_FALSE(detector.calculate(600));
+ EXPECT_EQ(mDefaultValue, detector.calculate(600));
detector.setInput(900, withinThreshold);
- EXPECT_FALSE(detector.calculate(900));
+ EXPECT_EQ(mDefaultValue, detector.calculate(900));
detector.setInput(1200, baseline);
- EXPECT_FALSE(detector.calculate(1200));
+ EXPECT_EQ(mDefaultValue, detector.calculate(1200));
detector.setInput(1599, withinThreshold);
- EXPECT_FALSE(detector.calculate(1599));
+ EXPECT_EQ(mDefaultValue, detector.calculate(1599));
detector.setInput(1600, baseline);
EXPECT_TRUE(detector.calculate(1600));
}
+INSTANTIATE_TEST_SUITE_P(StillnessDetectorTestParametrized, StillnessDetectorTest,
+ testing::Values(false, true));
+
} // namespace
} // namespace media
} // namespace android
diff --git a/media/libheadtracking/StillnessDetector.cpp b/media/libheadtracking/StillnessDetector.cpp
index 5fa4e3a..be7c893 100644
--- a/media/libheadtracking/StillnessDetector.cpp
+++ b/media/libheadtracking/StillnessDetector.cpp
@@ -25,6 +25,7 @@
void StillnessDetector::reset() {
mFifo.clear();
mWindowFull = false;
+ mSuppressionDeadline.reset();
}
void StillnessDetector::setInput(int64_t timestamp, const Pose3f& input) {
@@ -35,27 +36,39 @@
bool StillnessDetector::calculate(int64_t timestamp) {
discardOld(timestamp);
- // If the window has not been full, we don't consider ourselves still.
- if (!mWindowFull) {
- return false;
- }
+ // Check whether all the poses in the queue are in the proximity of the new one. We want to do
+ // this before checking the overriding conditions below, in order to update the suppression
+ // deadline correctly. We always go from end to start, to find the most recent pose that
+ // violated stillness and update the suppression deadline if it has not been set or if the new
+ // one ends after the current one.
+ bool moved = false;
- // An empty FIFO and window full is considered still (this will happen in the unlikely case when
- // the window duration is shorter than the gap between samples).
- if (mFifo.empty()) {
- return true;
- }
-
- // Otherwise, check whether all the poses remaining in the queue are in the proximity of the new
- // one.
- for (auto iter = mFifo.begin(); iter != mFifo.end() - 1; ++iter) {
- const auto& event = *iter;
- if (!areNear(event.pose, mFifo.back().pose)) {
- return false;
+ if (!mFifo.empty()) {
+ for (auto iter = mFifo.rbegin() + 1; iter != mFifo.rend(); ++iter) {
+ const auto& event = *iter;
+ if (!areNear(event.pose, mFifo.back().pose)) {
+ // Enable suppression for the duration of the window.
+ int64_t deadline = event.timestamp + mOptions.windowDuration;
+ if (!mSuppressionDeadline.has_value() || mSuppressionDeadline.value() < deadline) {
+ mSuppressionDeadline = deadline;
+ }
+ moved = true;
+ break;
+ }
}
}
- return true;
+ // If the window has not been full, return the default value.
+ if (!mWindowFull) {
+ return mOptions.defaultValue;
+ }
+
+ // Force "in motion" while the suppression deadline is active.
+ if (mSuppressionDeadline.has_value()) {
+ return false;
+ }
+
+ return !moved;
}
void StillnessDetector::discardOld(int64_t timestamp) {
@@ -72,6 +85,11 @@
mWindowFull = true;
mFifo.pop_front();
}
+
+ // Expire the suppression deadline.
+ if (mSuppressionDeadline.has_value() && mSuppressionDeadline <= timestamp) {
+ mSuppressionDeadline.reset();
+ }
}
bool StillnessDetector::areNear(const Pose3f& pose1, const Pose3f& pose2) const {
diff --git a/media/libheadtracking/StillnessDetector.h b/media/libheadtracking/StillnessDetector.h
index cae9d9d..ee4b2d8 100644
--- a/media/libheadtracking/StillnessDetector.h
+++ b/media/libheadtracking/StillnessDetector.h
@@ -36,10 +36,11 @@
* bool still = detector.calculate(timestamp);
* }
*
- * The stream is considered not still until a sufficient number of samples has been provided for an
- * initial fill-up of the window. In the special case of the window size being 0, this is not
- * required and the state is considered always "still". The reset() method can be used to empty the
- * window again and get back to this initial state.
+ * The detection is not considered reliable until a sufficient number of samples has been provided
+ * for an initial fill-up of the window. During that time, the detector will return whatever default
+ * value has been configured.
+ * The reset() method can be used to empty the window again and get back to this initial state.
+ * In the special case of the window size being 0, the state will always be considered "still".
*/
class StillnessDetector {
public:
@@ -48,6 +49,10 @@
*/
struct Options {
/**
+ * During the initial fill of the window, should we consider the state still?
+ */
+ bool defaultValue;
+ /**
* How long is the window, in ticks. The special value of 0 indicates that the stream is
* always considered still.
*/
@@ -87,6 +92,11 @@
const float mCosHalfRotationalThreshold;
std::deque<TimestampedPose> mFifo;
bool mWindowFull = false;
+ // As soon as motion is detected, this will be set for the time of detection + window duration,
+ // and during this time we will always consider outselves in motion without checking. This is
+ // used for hyteresis purposes, since because of the approximate method we use for determining
+ // stillness, we may toggle back and forth at a rate faster than the window side.
+ std::optional<int64_t> mSuppressionDeadline;
bool areNear(const Pose3f& pose1, const Pose3f& pose2) const;
void discardOld(int64_t timestamp);
diff --git a/media/libheif/Android.bp b/media/libheif/Android.bp
index 6a3427e..55ba61a 100644
--- a/media/libheif/Android.bp
+++ b/media/libheif/Android.bp
@@ -26,7 +26,5 @@
"-Wall",
],
- include_dirs: [],
-
export_include_dirs: ["include"],
}
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index 2bf72a7..7f0a045 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -63,6 +63,7 @@
// Error keys
#define AMEDIAMETRICS_KEY_AUDIO_TRACK_ERROR AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK "error"
+#define AMEDIAMETRICS_KEY_AUDIO_RECORD_ERROR AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD "error"
/*
* MediaMetrics Properties are unified space for consistency and readability.
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index f521b62..a23d1d9 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -79,6 +79,9 @@
"libstagefright_nuplayer",
"libstagefright_rtsp",
"libstagefright_timedtext",
+ // this needs it, but it can get it transitively through libstagefright.
+ // i'm going to leave it here.
+ "libstagefright_webm",
"framework-permission-aidl-cpp",
],
@@ -91,12 +94,12 @@
"libmediautils_headers",
],
- include_dirs: [
- "frameworks/av/media/libstagefright/webm",
- ],
-
local_include_dirs: ["include"],
+ export_include_dirs: [
+ ".",
+ ],
+
cflags: [
"-Werror",
"-Wno-error=deprecated-declarations",
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 31fa8e2..ea1fdf4 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -24,7 +24,8 @@
#include <android-base/logging.h>
#include <utils/Log.h>
-#include "WebmWriter.h"
+#include <webm/WebmWriter.h>
+
#include "StagefrightRecorder.h"
#include <algorithm>
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index d83d3c9..a36f1d6 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -28,9 +28,6 @@
cc_defaults {
name: "libmediaplayerserviceFuzzer_defaults",
- include_dirs: [
- "frameworks/av/media/libmediaplayerservice",
- ],
static_libs: [
"libmediaplayerservice",
"liblog",
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index ac97e73..89ba584 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -42,16 +42,11 @@
"libmediametrics_headers",
"media_plugin_headers",
"libstagefright_headers",
+ "libstagefright_httplive_headers",
+ "libstagefright_mpeg2support_headers",
"libstagefright_rtsp_headers",
],
- include_dirs: [
- "frameworks/av/media/libstagefright/httplive",
- "frameworks/av/media/libstagefright/mpeg2ts",
- "frameworks/av/media/libstagefright/timedtext",
- "frameworks/native/include/android",
- ],
-
cflags: [
"-Werror",
"-Wall",
@@ -77,6 +72,7 @@
static_libs: [
"libplayerservice_datasource",
+ "libstagefright_timedtext",
],
name: "libstagefright_nuplayer",
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 439dbe8..36e4d4a 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -20,7 +20,6 @@
#include "GenericSource.h"
#include "NuPlayerDrm.h"
-#include "AnotherPacketSource.h"
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <datasource/PlayerServiceDataSourceFactory.h>
@@ -44,6 +43,7 @@
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <mpeg2ts/AnotherPacketSource.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 7a2ab8f..80e06f1 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -21,11 +21,10 @@
#include "NuPlayer.h"
#include "NuPlayerSource.h"
-#include "ATSParser.h"
-
#include <android-base/unique_fd.h>
#include <media/mediaplayer.h>
#include <media/stagefright/MediaBuffer.h>
+#include <mpeg2ts/ATSParser.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 77e7885..4e71e89 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -19,8 +19,6 @@
#include <utils/Log.h>
#include "HTTPLiveSource.h"
-
-#include "AnotherPacketSource.h"
#include "LiveDataSource.h"
#include <media/IMediaHTTPService.h>
@@ -31,6 +29,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/Utils.h>
+#include <mpeg2ts/AnotherPacketSource.h>
// default buffer prepare/ready/underflow marks
static const int kReadyMarkMs = 5000; // 5 seconds
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 9ae7ddb..c6b22a6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -35,9 +35,7 @@
#include "RTSPSource.h"
#include "StreamingSource.h"
#include "GenericSource.h"
-#include "TextDescriptions.h"
-
-#include "ATSParser.h"
+#include <timedtext/TextDescriptions.h>
#include <cutils/properties.h>
@@ -56,6 +54,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
+#include <mpeg2ts/ATSParser.h>
+
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2c1f158..52b2041 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -40,10 +40,9 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/SurfaceUtils.h>
+#include <mpeg2ts/ATSParser.h>
#include <gui/Surface.h>
-#include "ATSParser.h"
-
namespace android {
static float kDisplayRefreshingRate = 60.f; // TODO: get this from the display
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index 793014e..cb91fd9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -30,8 +30,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
-
-#include "ATSParser.h"
+#include <mpeg2ts/ATSParser.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index 4d6a483..6a17972 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -336,7 +336,7 @@
*durationUs = 0ll;
int64_t audioDurationUs;
- if (mAudioTrack != NULL
+ if (mAudioTrack != NULL && mAudioTrack->getFormat() != NULL
&& mAudioTrack->getFormat()->findInt64(
kKeyDuration, &audioDurationUs)
&& audioDurationUs > *durationUs) {
@@ -344,7 +344,7 @@
}
int64_t videoDurationUs;
- if (mVideoTrack != NULL
+ if (mVideoTrack != NULL && mVideoTrack->getFormat() != NULL
&& mVideoTrack->getFormat()->findInt64(
kKeyDuration, &videoDurationUs)
&& videoDurationUs > *durationUs) {
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/RTPSource.h
index d3021f3..7d9bb8f 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.h
@@ -29,19 +29,14 @@
#include <media/stagefright/rtsp/ASessionDescription.h>
#include <media/stagefright/Utils.h>
#include <media/BufferingSettings.h>
+#include <mpeg2ts/AnotherPacketSource.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <utils/RefBase.h>
-#include "AnotherPacketSource.h"
#include "NuPlayerSource.h"
-
-
-
-
-
namespace android {
struct ALooper;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index b52ea6b..75cedcc 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -20,13 +20,12 @@
#include "RTSPSource.h"
-#include "AnotherPacketSource.h"
-
#include <media/IMediaHTTPService.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/rtsp/MyHandler.h>
#include <media/stagefright/rtsp/SDPLoader.h>
+#include <mpeg2ts/AnotherPacketSource.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 03fce08..7497e41 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -20,7 +20,7 @@
#include "NuPlayerSource.h"
-#include "ATSParser.h"
+#include <mpeg2ts/ATSParser.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index bec27d3..9d67ca4 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -20,8 +20,6 @@
#include "StreamingSource.h"
-#include "ATSParser.h"
-#include "AnotherPacketSource.h"
#include "NuPlayerStreamListener.h"
#include <media/stagefright/MediaSource.h>
@@ -31,6 +29,8 @@
#include <media/stagefright/foundation/MediaKeys.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include <mpeg2ts/AnotherPacketSource.h>
+#include <mpeg2ts/ATSParser.h>
namespace android {
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
index 92236ea..6eb8c6f 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/Android.bp
@@ -33,10 +33,6 @@
"StagefrightRecorderTest.cpp",
],
- include_dirs: [
- "frameworks/av/media/libmediaplayerservice",
- ],
-
static_libs: [
"libmediaplayerservice",
"libstagefright_httplive",
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 7c7fcac..3784dde 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -470,6 +470,7 @@
void writeHdlrBox();
void writeTkhdBox(uint32_t now);
void writeColrBox();
+ void writeMdcvAndClliBoxes();
void writeMp4aEsdsBox();
void writeMp4vEsdsBox();
void writeAudioFourCCBox();
@@ -4341,6 +4342,7 @@
writePaspBox();
writeColrBox();
+ writeMdcvAndClliBoxes();
mOwner->endBox(); // mp4v, s263 or avc1
}
@@ -4375,6 +4377,54 @@
}
}
+void MPEG4Writer::Track::writeMdcvAndClliBoxes() {
+ sp<MetaData> meta = mSource->getFormat();
+ uint32_t type;
+ const uint8_t* data;
+ size_t size;
+ bool found =
+ meta->findData(kKeyHdrStaticInfo, &type, reinterpret_cast<const void**>(&data), &size);
+ if (found && size == 25) {
+ uint16_t displayPrimariesRX = U16LE_AT(&data[1]);
+ uint16_t displayPrimariesRY = U16LE_AT(&data[3]);
+
+ uint16_t displayPrimariesGX = U16LE_AT(&data[5]);
+ uint16_t displayPrimariesGY = U16LE_AT(&data[7]);
+
+ uint16_t displayPrimariesBX = U16LE_AT(&data[9]);
+ uint16_t displayPrimariesBY = U16LE_AT(&data[11]);
+
+ uint16_t whitePointX = U16LE_AT(&data[13]);
+ uint16_t whitePointY = U16LE_AT(&data[15]);
+
+ uint16_t maxDisplayMasteringLuminance = U16LE_AT(&data[17]);
+ uint16_t minDisplayMasteringLuminance = U16LE_AT(&data[19]);
+
+ uint16_t maxContentLightLevel = U16LE_AT(&data[21]);
+ uint16_t maxPicAverageLightLevel = U16LE_AT(&data[23]);
+
+ mOwner->beginBox("mdcv");
+ mOwner->writeInt16(displayPrimariesGX);
+ mOwner->writeInt16(displayPrimariesGY);
+ mOwner->writeInt16(displayPrimariesBX);
+ mOwner->writeInt16(displayPrimariesBY);
+ mOwner->writeInt16(displayPrimariesRX);
+ mOwner->writeInt16(displayPrimariesRY);
+ mOwner->writeInt16(whitePointX);
+ mOwner->writeInt16(whitePointY);
+ mOwner->writeInt32(maxDisplayMasteringLuminance * 10000);
+ mOwner->writeInt32(minDisplayMasteringLuminance * 10000);
+ mOwner->endBox(); // mdcv.
+
+ mOwner->beginBox("clli");
+ mOwner->writeInt16(maxContentLightLevel);
+ mOwner->writeInt16(maxPicAverageLightLevel);
+ mOwner->endBox(); // clli.
+ } else {
+ ALOGW("Ignoring HDR static info with unexpected size %d", (int)size);
+ }
+}
+
void MPEG4Writer::Track::writeAudioFourCCBox() {
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 2ffe728..a3040f4 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -18,8 +18,6 @@
#define LOG_TAG "MediaCodecList"
#include <utils/Log.h>
-#include "MediaCodecListOverrides.h"
-
#include <binder/IServiceManager.h>
#include <media/IMediaCodecList.h>
@@ -34,6 +32,7 @@
#include <media/stagefright/CCodec.h>
#include <media/stagefright/Codec2InfoBuilder.h>
#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaCodecListOverrides.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/OmxInfoBuilder.h>
#include <media/stagefright/PersistentSurface.h>
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 4a167d1..9304e45 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -18,8 +18,6 @@
#define LOG_TAG "MediaCodecListOverrides"
#include <utils/Log.h>
-#include "MediaCodecListOverrides.h"
-
#include <cutils/properties.h>
#include <gui/Surface.h>
#include <mediadrm/ICrypto.h>
@@ -30,6 +28,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaCodecListOverrides.h>
namespace android {
diff --git a/media/libstagefright/TEST_MAPPING b/media/libstagefright/TEST_MAPPING
index 53181cc..91a44d1 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -42,6 +42,17 @@
]
},
{
+ "name": "CtsMediaDecoderTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaEncoderTestCases",
"options": [
{
@@ -53,6 +64,17 @@
]
},
{
+ "name": "CtsMediaCodecTestCases",
+ "options": [
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
+ }
+ ]
+ },
+ {
"name": "CtsMediaPlayerTestCases",
"options": [
{
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
index b46a271..e6d59ad 100644
--- a/media/libstagefright/filters/Android.bp
+++ b/media/libstagefright/filters/Android.bp
@@ -22,6 +22,14 @@
"ZeroFilter.cpp",
],
+ export_include_dirs: [
+ "include",
+ ],
+
+ local_include_dirs: [
+ "include/filters",
+ ],
+
cflags: [
"-Wno-multichar",
"-Werror",
diff --git a/media/libstagefright/filters/ColorConvert.h b/media/libstagefright/filters/include/filters/ColorConvert.h
similarity index 100%
rename from media/libstagefright/filters/ColorConvert.h
rename to media/libstagefright/filters/include/filters/ColorConvert.h
diff --git a/media/libstagefright/filters/GraphicBufferListener.h b/media/libstagefright/filters/include/filters/GraphicBufferListener.h
similarity index 100%
rename from media/libstagefright/filters/GraphicBufferListener.h
rename to media/libstagefright/filters/include/filters/GraphicBufferListener.h
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
similarity index 100%
rename from media/libstagefright/filters/IntrinsicBlurFilter.h
rename to media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
diff --git a/media/libstagefright/filters/RSFilter.h b/media/libstagefright/filters/include/filters/RSFilter.h
similarity index 100%
rename from media/libstagefright/filters/RSFilter.h
rename to media/libstagefright/filters/include/filters/RSFilter.h
diff --git a/media/libstagefright/filters/SaturationFilter.h b/media/libstagefright/filters/include/filters/SaturationFilter.h
similarity index 100%
rename from media/libstagefright/filters/SaturationFilter.h
rename to media/libstagefright/filters/include/filters/SaturationFilter.h
diff --git a/media/libstagefright/filters/SimpleFilter.h b/media/libstagefright/filters/include/filters/SimpleFilter.h
similarity index 100%
rename from media/libstagefright/filters/SimpleFilter.h
rename to media/libstagefright/filters/include/filters/SimpleFilter.h
diff --git a/media/libstagefright/filters/ZeroFilter.h b/media/libstagefright/filters/include/filters/ZeroFilter.h
similarity index 100%
rename from media/libstagefright/filters/ZeroFilter.h
rename to media/libstagefright/filters/include/filters/ZeroFilter.h
diff --git a/media/libstagefright/http/Android.bp b/media/libstagefright/http/Android.bp
index f4d6d99..f25318d 100644
--- a/media/libstagefright/http/Android.bp
+++ b/media/libstagefright/http/Android.bp
@@ -12,10 +12,8 @@
srcs: ["HTTPHelper.cpp"],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- "frameworks/native/include/media/openmax",
- "frameworks/base/core/jni",
+ header_libs: [
+ "libstagefright_headers",
],
shared_libs: [
diff --git a/media/libstagefright/httplive/Android.bp b/media/libstagefright/httplive/Android.bp
index 7acf735..7e26bd6 100644
--- a/media/libstagefright/httplive/Android.bp
+++ b/media/libstagefright/httplive/Android.bp
@@ -28,10 +28,6 @@
"PlaylistFetcher.cpp",
],
- include_dirs: [
- "frameworks/native/include/media/openmax",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 0d7cadd..09ca1c9 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -23,7 +23,7 @@
#include "M3UParser.h"
#include "PlaylistFetcher.h"
-#include <AnotherPacketSource.h>
+#include <mpeg2ts/AnotherPacketSource.h>
#include <cutils/properties.h>
#include <media/MediaHTTPService.h>
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index ceea41d..ed38a2e 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -24,7 +24,7 @@
#include <utils/String8.h>
-#include <ATSParser.h>
+#include <mpeg2ts/ATSParser.h>
namespace android {
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 907b326..b339fd2 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -25,8 +25,8 @@
#include "LiveSession.h"
#include "M3UParser.h"
#include <ID3.h>
-#include <AnotherPacketSource.h>
-#include <HlsSampleDecryptor.h>
+#include <mpeg2ts/AnotherPacketSource.h>
+#include <mpeg2ts/HlsSampleDecryptor.h>
#include <datasource/DataURISource.h>
#include <media/stagefright/foundation/ABitReader.h>
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index 2e28164..716df63 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -21,7 +21,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <openssl/aes.h>
-#include <ATSParser.h>
+#include <mpeg2ts/ATSParser.h>
#include "LiveSession.h"
namespace android {
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 3a01925..656267c 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -684,6 +684,7 @@
}
constexpr char FEATURE_AdaptivePlayback[] = "adaptive-playback";
+constexpr char FEATURE_EncodingStatistics[] = "encoding-statistics";
constexpr char FEATURE_IntraRefresh[] = "intra-refresh";
constexpr char FEATURE_PartialFrame[] = "partial-frame";
constexpr char FEATURE_QpBounds[] = "qp-bounds";
@@ -737,6 +738,14 @@
constexpr int32_t COLOR_TRANSFER_SDR_VIDEO = 3;
constexpr int32_t COLOR_TRANSFER_ST2084 = 6;
+constexpr int32_t PICTURE_TYPE_I = 1;
+constexpr int32_t PICTURE_TYPE_P = 2;
+constexpr int32_t PICTURE_TYPE_B = 3;
+constexpr int32_t PICTURE_TYPE_UNKNOWN = 0;
+
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1;
+constexpr int32_t VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0;
+
constexpr char KEY_AAC_DRC_ALBUM_MODE[] = "aac-drc-album-mode";
constexpr char KEY_AAC_DRC_ATTENUATION_FACTOR[] = "aac-drc-cut-level";
constexpr char KEY_AAC_DRC_BOOST_FACTOR[] = "aac-drc-boost-level";
@@ -795,6 +804,7 @@
constexpr char KEY_OPERATING_RATE[] = "operating-rate";
constexpr char KEY_OUTPUT_REORDER_DEPTH[] = "output-reorder-depth";
constexpr char KEY_PCM_ENCODING[] = "pcm-encoding";
+constexpr char KEY_PICTURE_TYPE[] = "picture_type";
constexpr char KEY_PIXEL_ASPECT_RATIO_HEIGHT[] = "sar-height";
constexpr char KEY_PIXEL_ASPECT_RATIO_WIDTH[] = "sar-width";
constexpr char KEY_PREPEND_HEADER_TO_SYNC_FRAMES[] = "prepend-sps-pps-to-idr-frames";
@@ -811,6 +821,8 @@
constexpr char KEY_TILE_HEIGHT[] = "tile-height";
constexpr char KEY_TILE_WIDTH[] = "tile-width";
constexpr char KEY_TRACK_ID[] = "track-id";
+constexpr char KEY_VIDEO_ENCODING_STATISTICS_LEVEL[] = "video-encoding-statistics-level";
+constexpr char KEY_VIDEO_QP_AVERAGE[] = "video-qp-average";
constexpr char KEY_VIDEO_QP_B_MAX[] = "video-qp-b-max";
constexpr char KEY_VIDEO_QP_B_MIN[] = "video-qp-b-min";
constexpr char KEY_VIDEO_QP_I_MAX[] = "video-qp-i-max";
diff --git a/media/libstagefright/MediaCodecListOverrides.h b/media/libstagefright/include/media/stagefright/MediaCodecListOverrides.h
similarity index 100%
rename from media/libstagefright/MediaCodecListOverrides.h
rename to media/libstagefright/include/media/stagefright/MediaCodecListOverrides.h
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index fbfa8cc..283df1e 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -54,16 +54,21 @@
"libstagefright_foundation_headers",
],
- export_include_dirs: ["."],
+ export_include_dirs: ["include"],
+
+ local_include_dirs: ["include/mpeg2ts"],
whole_static_libs: [
"libstagefright_metadatautils",
],
+}
+
+cc_defaults {
+ name: "libstagefright_mpeg2support_sdk_defaults",
+
min_sdk_version: "29",
-
host_supported: true,
-
target: {
darwin: {
enabled: false,
@@ -71,10 +76,19 @@
},
}
+cc_library_headers {
+ name: "libstagefright_mpeg2support_headers",
+ defaults: [
+ "libstagefright_mpeg2support_sdk_defaults",
+ ],
+ export_include_dirs: ["include"],
+}
+
cc_library_static {
name: "libstagefright_mpeg2support",
defaults: [
"libstagefright_mpeg2support_defaults",
+ "libstagefright_mpeg2support_sdk_defaults",
],
cflags: [
"-DENABLE_CRYPTO",
@@ -91,6 +105,7 @@
name: "libstagefright_mpeg2support_nocrypto",
defaults: [
"libstagefright_mpeg2support_defaults",
+ "libstagefright_mpeg2support_sdk_defaults",
],
apex_available: [
"com.android.media",
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/ATSParser.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/AnotherPacketSource.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
diff --git a/media/libstagefright/mpeg2ts/CasManager.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/CasManager.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/ESQueue.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/HlsSampleDecryptor.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/SampleDecryptor.h b/media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/SampleDecryptor.h
rename to media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
index 7f25d78..9e24a99 100644
--- a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
+++ b/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
@@ -26,9 +26,8 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
#include <media/stagefright/foundation/AUtils.h>
-
-#include <ATSParser.h>
-#include <AnotherPacketSource.h>
+#include <mpeg2ts/AnotherPacketSource.h>
+#include <mpeg2ts/ATSParser.h>
#include "Mpeg2tsUnitTestEnvironment.h"
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index a799a13..e6b67ce 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -32,11 +32,6 @@
"liblog",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- "frameworks/av/media/libstagefright/include",
- ],
-
cflags: [
"-Werror",
"-Wall",
diff --git a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
index 0c22a42..20737db 100644
--- a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
+++ b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
@@ -20,11 +20,10 @@
#include <gtest/gtest.h>
-#include "MediaCodecListOverrides.h"
-
#include <media/MediaCodecInfo.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaCodecListOverrides.h>
#include <vector>
diff --git a/media/libstagefright/tests/fuzzers/Android.bp b/media/libstagefright/tests/fuzzers/Android.bp
index 250ffb9..2bcfd67 100644
--- a/media/libstagefright/tests/fuzzers/Android.bp
+++ b/media/libstagefright/tests/fuzzers/Android.bp
@@ -32,9 +32,6 @@
"liblog",
"media_permission-aidl-cpp",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
- ],
}
cc_fuzz {
@@ -86,6 +83,9 @@
],
dictionary: "dictionaries/formats.dict",
defaults: ["libstagefright_fuzzer_defaults"],
+ header_libs: [
+ "libstagefright_webm_headers",
+ ],
static_libs: [
"libdatasource",
],
diff --git a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
index b346718..4218d2d 100644
--- a/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/FrameDecoderFuzzer.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "include/FrameDecoder.h"
+#include <FrameDecoder.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <media/IMediaSource.h>
#include <media/stagefright/MetaData.h>
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
index 810ae95..d94c8ff 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -23,7 +23,8 @@
#include <media/stagefright/OggWriter.h>
#include "MediaMimeTypes.h"
-#include "webm/WebmWriter.h"
+
+#include <webm/WebmWriter.h>
namespace android {
std::string genMimeType(FuzzedDataProvider *dataProvider) {
@@ -121,4 +122,4 @@
}
return writer;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/media/libstagefright/tests/writer/WriterTest.cpp b/media/libstagefright/tests/writer/WriterTest.cpp
index 398c592..d170e7c 100644
--- a/media/libstagefright/tests/writer/WriterTest.cpp
+++ b/media/libstagefright/tests/writer/WriterTest.cpp
@@ -36,7 +36,7 @@
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OggWriter.h>
-#include <WebmWriter.h>
+#include <webm/WebmWriter.h>
#include "WriterTestEnvironment.h"
#include "WriterUtility.h"
diff --git a/media/libstagefright/timedtext/Android.bp b/media/libstagefright/timedtext/Android.bp
index 6590ef7..619e06b 100644
--- a/media/libstagefright/timedtext/Android.bp
+++ b/media/libstagefright/timedtext/Android.bp
@@ -35,8 +35,16 @@
cfi: true,
},
- include_dirs: [
- "frameworks/av/media/libstagefright",
+ export_include_dirs: [
+ "include",
+ ],
+
+ local_include_dirs: [
+ "include/timedtext",
+ ],
+
+ header_libs: [
+ "libstagefright_headers",
],
shared_libs: ["libmedia"],
diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/include/timedtext/TextDescriptions.h
similarity index 100%
rename from media/libstagefright/timedtext/TextDescriptions.h
rename to media/libstagefright/timedtext/include/timedtext/TextDescriptions.h
diff --git a/media/libstagefright/timedtext/test/Android.bp b/media/libstagefright/timedtext/test/Android.bp
index 0b632bf..58c68ef 100644
--- a/media/libstagefright/timedtext/test/Android.bp
+++ b/media/libstagefright/timedtext/test/Android.bp
@@ -39,8 +39,8 @@
"libstagefright_foundation",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
+ header_libs: [
+ "libstagefright_headers",
],
shared_libs: [
diff --git a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
index d85ae39..f934b54 100644
--- a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
@@ -27,7 +27,7 @@
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/ByteUtils.h>
-#include "timedtext/TextDescriptions.h"
+#include <timedtext/TextDescriptions.h>
#include "TimedTextTestEnvironment.h"
diff --git a/media/libstagefright/webm/Android.bp b/media/libstagefright/webm/Android.bp
index 4209aea..9d5f430 100644
--- a/media/libstagefright/webm/Android.bp
+++ b/media/libstagefright/webm/Android.bp
@@ -33,7 +33,11 @@
"WebmWriter.cpp",
],
- export_include_dirs: ["."],
+ local_include_dirs: [
+ "include/webm",
+ ],
+
+ export_include_dirs: ["include"],
shared_libs: [
"libdatasource",
@@ -49,3 +53,16 @@
"media_ndk_headers",
],
}
+
+
+cc_library_headers {
+ name: "libstagefright_webm_headers",
+ export_include_dirs: ["include"],
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}
diff --git a/media/libstagefright/webm/EbmlUtil.h b/media/libstagefright/webm/include/webm/EbmlUtil.h
similarity index 100%
rename from media/libstagefright/webm/EbmlUtil.h
rename to media/libstagefright/webm/include/webm/EbmlUtil.h
diff --git a/media/libstagefright/webm/LinkedBlockingQueue.h b/media/libstagefright/webm/include/webm/LinkedBlockingQueue.h
similarity index 100%
rename from media/libstagefright/webm/LinkedBlockingQueue.h
rename to media/libstagefright/webm/include/webm/LinkedBlockingQueue.h
diff --git a/media/libstagefright/webm/WebmConstants.h b/media/libstagefright/webm/include/webm/WebmConstants.h
similarity index 100%
rename from media/libstagefright/webm/WebmConstants.h
rename to media/libstagefright/webm/include/webm/WebmConstants.h
diff --git a/media/libstagefright/webm/WebmElement.h b/media/libstagefright/webm/include/webm/WebmElement.h
similarity index 100%
rename from media/libstagefright/webm/WebmElement.h
rename to media/libstagefright/webm/include/webm/WebmElement.h
diff --git a/media/libstagefright/webm/WebmFrame.h b/media/libstagefright/webm/include/webm/WebmFrame.h
similarity index 100%
rename from media/libstagefright/webm/WebmFrame.h
rename to media/libstagefright/webm/include/webm/WebmFrame.h
diff --git a/media/libstagefright/webm/WebmFrameThread.h b/media/libstagefright/webm/include/webm/WebmFrameThread.h
similarity index 100%
rename from media/libstagefright/webm/WebmFrameThread.h
rename to media/libstagefright/webm/include/webm/WebmFrameThread.h
diff --git a/media/libstagefright/webm/WebmWriter.h b/media/libstagefright/webm/include/webm/WebmWriter.h
similarity index 100%
rename from media/libstagefright/webm/WebmWriter.h
rename to media/libstagefright/webm/include/webm/WebmWriter.h
diff --git a/media/libstagefright/webm/tests/Android.bp b/media/libstagefright/webm/tests/Android.bp
index 4443766..629ee47 100644
--- a/media/libstagefright/webm/tests/Android.bp
+++ b/media/libstagefright/webm/tests/Android.bp
@@ -31,8 +31,8 @@
"WebmFrameThreadUnitTest.cpp",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
+ header_libs: [
+ "libstagefright_headers",
],
static_libs: [
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index a33b888..b81f27e 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -119,7 +119,7 @@
"libstagefright_webm",
"libdatasource",
],
- include_dirs: [
- "frameworks/av/media/libstagefright",
+ header_libs: [
+ "libstagefright_headers",
],
}
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 116999e..537df76 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -47,10 +47,6 @@
"libregistermsext",
],
- include_dirs: [
- "frameworks/av/media/libmediaplayerservice",
- ],
-
// By default mediaserver runs in 32-bit to save memory, except
// on 64-bit-only lunch targets.
// ****************************************************************
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 58e2d2a..026847a 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -25,9 +25,8 @@
#include <utils/Log.h>
#include "RegisterExtensions.h"
-// from LOCAL_C_INCLUDES
-#include "MediaPlayerService.h"
-#include "ResourceManagerService.h"
+#include <MediaPlayerService.h>
+#include <ResourceManagerService.h>
using namespace android;
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 69ab242..923453a 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -361,6 +361,7 @@
"mpegh-reference-channel-layout";
EXPORT const char* AMEDIAFORMAT_KEY_OPERATING_RATE = "operating-rate";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_ENCODING = "pcm-encoding";
+EXPORT const char* AMEDIAFORMAT_KEY_PICTURE_TYPE = "picture-type";
EXPORT const char* AMEDIAFORMAT_KEY_PRIORITY = "priority";
EXPORT const char* AMEDIAFORMAT_KEY_PROFILE = "profile";
EXPORT const char* AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN = "pcm-big-endian";
@@ -394,6 +395,9 @@
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_VALID_SAMPLES = "valid-samples";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL =
+ "video-encoding-statistics-level";
+EXPORT const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE = "video-qp-average";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MAX = "video-qp-b-max";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_B_MIN = "video-qp-b-min";
EXPORT const char* AMEDIAFORMAT_VIDEO_QP_I_MAX = "video-qp-i-max";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 2d2fcc0..2195657 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -311,6 +311,10 @@
extern const char* AMEDIAFORMAT_KEY_LAST_SAMPLE_INDEX_IN_CHUNK __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_KEY_SAMPLE_TIME_BEFORE_APPEND __INTRODUCED_IN(31);
+extern const char* AMEDIAFORMAT_KEY_PICTURE_TYPE __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_ENCODING_STATISTICS_LEVEL __INTRODUCED_IN(33);
+extern const char* AMEDIAFORMAT_KEY_VIDEO_QP_AVERAGE __INTRODUCED_IN(33);
+
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MAX __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_B_MIN __INTRODUCED_IN(31);
extern const char* AMEDIAFORMAT_VIDEO_QP_I_MAX __INTRODUCED_IN(31);
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 15d6d3697..1ab5bc1 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -220,6 +220,17 @@
return ok;
}
+bool accessUltrasoundAllowed(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));
+ if (isAudioServerOrRootUid(uid)) return true;
+ static const String16 sAccessUltrasound(
+ "android.permission.ACCESS_ULTRASOUND");
+ bool ok = PermissionCache::checkPermission(sAccessUltrasound, pid, uid);
+ if (!ok) ALOGE("Request requires android.permission.ACCESS_ULTRASOUND");
+ return ok;
+}
+
bool captureHotwordAllowed(const AttributionSourceState& attributionSource) {
// CAPTURE_AUDIO_HOTWORD permission implies RECORD_AUDIO permission
bool ok = recordingAllowed(attributionSource);
diff --git a/media/utils/fuzzers/Android.bp b/media/utils/fuzzers/Android.bp
index c4dc24f..d26e6c2 100644
--- a/media/utils/fuzzers/Android.bp
+++ b/media/utils/fuzzers/Android.bp
@@ -32,11 +32,6 @@
"bionic_libc_platform_headers",
"libmedia_headers",
],
-
- include_dirs: [
- // For DEBUGGER_SIGNAL
- "system/core/debuggerd/include",
- ],
}
cc_fuzz {
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 2fe2451..de20d55 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -61,6 +61,7 @@
// Used for calls that should come from system server or internal.
// Note: system server is multiprocess for multiple users. audioserver is not.
+// Note: if this method is modified, also update the same method in SensorService.h.
static inline bool isAudioServerOrSystemServerUid(uid_t uid) {
return multiuser_get_app_id(uid) == AID_SYSTEM || uid == AID_AUDIOSERVER;
}
@@ -95,6 +96,7 @@
bool captureMediaOutputAllowed(const AttributionSourceState& attributionSource);
bool captureTunerAudioInputAllowed(const AttributionSourceState& attributionSource);
bool captureVoiceCommunicationOutputAllowed(const AttributionSourceState& attributionSource);
+bool accessUltrasoundAllowed(const AttributionSourceState& attributionSource);
bool captureHotwordAllowed(const AttributionSourceState& attributionSource);
bool settingsAllowed();
bool modifyAudioRoutingAllowed();
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 577f641..3d3e0cf 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -133,6 +133,7 @@
* - AUDIO_SOURCE_FM_TUNER
* - AUDIO_SOURCE_VOICE_RECOGNITION
* - AUDIO_SOURCE_HOTWORD
+ * - AUDIO_SOURCE_ULTRASOUND
*
* @return the corresponding input source priority or 0 if priority is irrelevant for this source.
* This happens when the specified source cannot share a given input stream (e.g remote submix)
@@ -142,22 +143,24 @@
{
switch (inputSource) {
case AUDIO_SOURCE_VOICE_COMMUNICATION:
- return 9;
+ return 10;
case AUDIO_SOURCE_CAMCORDER:
- return 8;
+ return 9;
case AUDIO_SOURCE_VOICE_PERFORMANCE:
- return 7;
+ return 8;
case AUDIO_SOURCE_UNPROCESSED:
- return 6;
+ return 7;
case AUDIO_SOURCE_MIC:
- return 5;
+ return 6;
case AUDIO_SOURCE_ECHO_REFERENCE:
- return 4;
+ return 5;
case AUDIO_SOURCE_FM_TUNER:
- return 3;
+ return 4;
case AUDIO_SOURCE_VOICE_RECOGNITION:
- return 2;
+ return 3;
case AUDIO_SOURCE_HOTWORD:
+ return 2;
+ case AUDIO_SOURCE_ULTRASOUND:
return 1;
default:
break;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 235e4aa..999c321 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -569,6 +569,11 @@
audio_output_flags_t halFlags = mFlags;
if ((mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
halFlags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
+ // If no mixer config is specified for a spatializer output, default to 5.1 for proper
+ // configuration of the final downmixer or spatializer
+ if (mixerConfig == nullptr) {
+ lMixerConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
+ }
}
ALOGV("opening output for device %s profile %p name %s",
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 665c2dd..b036e12 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -122,8 +122,12 @@
{"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
{
{"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
- {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
- AUDIO_FLAG_BEACON, ""}}
+ {
+ {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_BEACON, ""},
+ {AUDIO_CONTENT_TYPE_ULTRASOUND, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
+ AUDIO_FLAG_NONE, ""}
+ }
}
},
}
diff --git a/services/audiopolicy/engineconfigurable/src/InputSource.cpp b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
index 5779c00..6fd2b70 100644
--- a/services/audiopolicy/engineconfigurable/src/InputSource.cpp
+++ b/services/audiopolicy/engineconfigurable/src/InputSource.cpp
@@ -26,7 +26,8 @@
status_t Element<audio_source_t>::setIdentifier(audio_source_t identifier)
{
if (identifier > AUDIO_SOURCE_MAX && identifier != AUDIO_SOURCE_HOTWORD
- && identifier != AUDIO_SOURCE_FM_TUNER && identifier != AUDIO_SOURCE_ECHO_REFERENCE) {
+ && identifier != AUDIO_SOURCE_FM_TUNER && identifier != AUDIO_SOURCE_ECHO_REFERENCE
+ && identifier != AUDIO_SOURCE_ULTRASOUND) {
return BAD_VALUE;
}
mIdentifier = identifier;
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index c73c17d..4c3d92c 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -460,6 +460,7 @@
case AUDIO_SOURCE_HOTWORD:
case AUDIO_SOURCE_CAMCORDER:
case AUDIO_SOURCE_VOICE_PERFORMANCE:
+ case AUDIO_SOURCE_ULTRASOUND:
inputSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
break;
default:
@@ -586,6 +587,10 @@
device = availableDevices.getDevice(
AUDIO_DEVICE_IN_ECHO_REFERENCE, String8(""), AUDIO_FORMAT_DEFAULT);
break;
+ case AUDIO_SOURCE_ULTRASOUND:
+ device = availableDevices.getFirstExistingDevice({
+ AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BACK_MIC});
+ break;
default:
ALOGW("getDeviceForInputSource() invalid input source %d", inputSource);
break;
@@ -645,7 +650,7 @@
// there is a preferred device, is it available?
preferredAvailableDevVec =
availableOutputDevices.getDevicesFromDeviceTypeAddrVec(preferredStrategyDevices);
- if (preferredAvailableDevVec.size() == preferredAvailableDevVec.size()) {
+ if (preferredAvailableDevVec.size() == preferredStrategyDevices.size()) {
ALOGVV("%s using pref device %s for strategy %u",
__func__, preferredAvailableDevVec.toString().c_str(), strategy);
return preferredAvailableDevVec;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index cc1012c..92074a6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1386,8 +1386,14 @@
ALOGV("Set VoIP and Direct output flags for PCM format");
}
+ // Attach the Ultrasound flag for the AUDIO_CONTENT_TYPE_ULTRASOUND
+ if (attr->content_type == AUDIO_CONTENT_TYPE_ULTRASOUND) {
+ *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_ULTRASOUND);
+ }
+
if (mSpatializerOutput != nullptr
- && canBeSpatialized(attr, config, devices.toTypeAddrVector())) {
+ && canBeSpatializedInt(attr, config,
+ devices.toTypeAddrVector(), false /* allowCurrentOutputReconfig */)) {
return mSpatializerOutput->mIoHandle;
}
@@ -1683,7 +1689,7 @@
// other criteria
static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t)
(AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC |
- AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM);
+ AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM | AUDIO_OUTPUT_FLAG_ULTRASOUND);
// Flags expressing a performance request: have lower priority than serving
// requested sampling rate or channel mask
static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t)
@@ -2371,6 +2377,10 @@
flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX);
}
+ if (attributes.source == AUDIO_SOURCE_ULTRASOUND) {
+ flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_ULTRASOUND);
+ }
+
// find a compatible input profile (not necessarily identical in parameters)
sp<IOProfile> profile;
// sampling rate and flags may be updated by getInputProfile
@@ -3690,7 +3700,8 @@
const audio_attributes_t& attributes) {
audio_output_flags_t output_flags = AUDIO_OUTPUT_FLAG_NONE;
audio_flags_to_audio_output_flags(attributes.flags, &output_flags);
- sp<IOProfile> profile = getProfileForOutput(DeviceVector() /*ignore device */,
+ DeviceVector outputDevices = mEngine->getOutputDevicesForAttributes(attributes);
+ sp<IOProfile> profile = getProfileForOutput(outputDevices,
config.sample_rate,
config.format,
config.channel_mask,
@@ -3782,9 +3793,10 @@
}
flags = (audio_output_flags_t)((flags & relevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
+ DeviceVector outputDevices = mEngine->getOutputDevicesForAttributes(*attr);
for (const auto& hwModule : mHwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
- if (!curProfile->isCompatibleProfile(DeviceVector(),
+ if (!curProfile->isCompatibleProfile(outputDevices,
config->sample_rate, nullptr /*updatedSamplingRate*/,
config->format, nullptr /*updatedFormat*/,
config->channel_mask, nullptr /*updatedChannelMask*/,
@@ -4947,9 +4959,10 @@
}
}
-bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr,
+bool AudioPolicyManager::canBeSpatializedInt(const audio_attributes_t *attr,
const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices) const
+ const AudioDeviceTypeAddrVector &devices,
+ bool allowCurrentOutputReconfig) const
{
// The caller can have the audio attributes criteria ignored by either passing a null ptr or
// the AUDIO_ATTRIBUTES_INITIALIZER value.
@@ -4985,7 +4998,8 @@
if (!isChannelMaskSpatialized(config->channel_mask)) {
return false;
}
- if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile) {
+ if (!allowCurrentOutputReconfig && mSpatializerOutput != nullptr
+ && mSpatializerOutput->mProfile == profile) {
if ((config->channel_mask & mSpatializerOutput->mMixerChannelMask)
!= config->channel_mask) {
return false;
@@ -5006,7 +5020,8 @@
audio_config_base_t clientConfig = client->config();
audio_config_t config = audio_config_initializer(&clientConfig);
if (desc != mSpatializerOutput
- && canBeSpatialized(&attr, &config, devicesTypeAddress)) {
+ && canBeSpatializedInt(&attr, &config,
+ devicesTypeAddress, false /* allowCurrentOutputReconfig */)) {
streamsToInvalidate.insert(client->stream());
}
}
@@ -5030,7 +5045,8 @@
config = audio_config_initializer(mixerConfig);
configPtr = &config;
}
- if (!canBeSpatialized(attr, configPtr, devicesTypeAddress)) {
+ if (!canBeSpatializedInt(
+ attr, configPtr, devicesTypeAddress)) {
ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
return BAD_VALUE;
}
@@ -5053,6 +5069,7 @@
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
if (!desc->isDuplicated() && desc->mProfile == profile) {
+ ALOGV("%s found output %d for spatializer profile", __func__, desc->mIoHandle);
mSpatializerOutput = desc;
break;
}
@@ -5072,39 +5089,29 @@
};
DeviceVector savedDevices = mSpatializerOutput->devices();
- closeOutput(mSpatializerOutput->mIoHandle);
- mSpatializerOutput.clear();
+ ALOGV("%s reopening spatializer output to match channel mask %#x (current mask %#x)",
+ __func__, configPtr->channel_mask, mSpatializerOutput->mMixerChannelMask);
- const sp<SwAudioOutputDescriptor> desc =
- new SwAudioOutputDescriptor(profile, mpClientInterface);
- status_t status = desc->open(nullptr, mixerConfig, devices,
- mEngine->getStreamTypeForAttributes(*attr),
- AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (status != NO_ERROR) {
- ALOGW("%s failed opening output: status %d, output %d", __func__, status, *output);
- if (*output != AUDIO_IO_HANDLE_NONE) {
- desc->close();
- }
+ closeOutput(mSpatializerOutput->mIoHandle);
+ //from now on mSpatializerOutput is null
+
+ sp<SwAudioOutputDescriptor> desc =
+ openOutputWithProfileAndDevice(profile, devices, mixerConfig);
+ if (desc == nullptr) {
// re open the spatializer output with previous channel mask
- status_t newStatus = desc->open(nullptr, &savedMixerConfig, savedDevices,
- mEngine->getStreamTypeForAttributes(*attr),
- AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (newStatus != NO_ERROR) {
- if (*output != AUDIO_IO_HANDLE_NONE) {
- desc->close();
- }
- ALOGE("%s failed to re-open mSpatializerOutput, status %d", __func__, newStatus);
+ desc = openOutputWithProfileAndDevice(profile, savedDevices, &savedMixerConfig);
+ if (desc == nullptr) {
+ ALOGE("%s failed to restore mSpatializerOutput with previous config", __func__);
} else {
mSpatializerOutput = desc;
- addOutput(*output, desc);
}
mPreviousOutputs = mOutputs;
mpClientInterface->onAudioPortListUpdate();
*output = AUDIO_IO_HANDLE_NONE;
- return status;
+ ALOGW("%s could not open spatializer output with requested config", __func__);
+ return BAD_VALUE;
}
mSpatializerOutput = desc;
- addOutput(*output, desc);
mPreviousOutputs = mOutputs;
mpClientInterface->onAudioPortListUpdate();
}
@@ -5776,6 +5783,9 @@
removeOutput(output);
mPreviousOutputs = mOutputs;
+ if (closingOutput == mSpatializerOutput) {
+ mSpatializerOutput.clear();
+ }
// MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if
// no direct outputs are open.
@@ -7329,7 +7339,8 @@
}
sp<SwAudioOutputDescriptor> AudioPolicyManager::openOutputWithProfileAndDevice(
- const sp<IOProfile>& profile, const DeviceVector& devices)
+ const sp<IOProfile>& profile, const DeviceVector& devices,
+ const audio_config_base_t *mixerConfig)
{
for (const auto& device : devices) {
// TODO: This should be checking if the profile supports the device combo.
@@ -7339,7 +7350,7 @@
}
sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr /* halConfig */, nullptr /* mixerConfig */, devices,
+ status_t status = desc->open(nullptr /* halConfig */, mixerConfig, devices,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
return nullptr;
@@ -7369,7 +7380,7 @@
config.offload_info.channel_mask = config.channel_mask;
config.offload_info.format = config.format;
- status = desc->open(&config, nullptr /* mixerConfig */, devices,
+ status = desc->open(&config, mixerConfig, devices,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
return nullptr;
@@ -7377,6 +7388,7 @@
}
addOutput(output, desc);
+
if (audio_is_remote_submix_device(deviceType) && address != "0") {
sp<AudioPolicyMix> policyMix;
if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
@@ -7387,9 +7399,13 @@
address.string());
}
- } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) && hasPrimaryOutput()) {
- // no duplicated output for direct outputs and
- // outputs used by dynamic policy mixes
+ } else if (hasPrimaryOutput() && profile->getModule()
+ != mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)
+ && ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
+ // no duplicated output for:
+ // - direct outputs
+ // - outputs used by dynamic policy mixes
+ // - outputs opened on the primary HW module
audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
//TODO: configure audio effect output stage here
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bdeba3d..30ca9b3 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -358,7 +358,9 @@
virtual bool canBeSpatialized(const audio_attributes_t *attr,
const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices) const;
+ const AudioDeviceTypeAddrVector &devices) const {
+ return canBeSpatializedInt(attr, config, devices);
+ }
virtual status_t getSpatializerOutput(const audio_config_base_t *config,
const audio_attributes_t *attr,
@@ -964,6 +966,30 @@
const DeviceVector &devices,
audio_io_handle_t *output);
+ /**
+ * @brief Queries if some kind of spatialization will be performed if the audio playback
+ * context described by the provided arguments is present.
+ * The context is made of:
+ * - The audio attributes describing the playback use case.
+ * - The audio configuration describing the audio format, channels, sampling rate ...
+ * - The devices describing the sink audio device selected for playback.
+ * All arguments are optional and only the specified arguments are used to match against
+ * supported criteria. For instance, supplying no argument will tell if spatialization is
+ * supported or not in general.
+ * @param attr audio attributes describing the playback use case
+ * @param config audio configuration describing the audio format, channels, sample rate...
+ * @param devices the sink audio device selected for playback
+ * @param allowCurrentOutputReconfig if true, the result will be considering it is possible
+ * to close and reopen an existing spatializer output stream to match the requested
+ * criteria. If false, the criteria must be compatible with the opened sptializer
+ * output.
+ * @return true if spatialization is possible for this context, false otherwise.
+ */
+ virtual bool canBeSpatializedInt(const audio_attributes_t *attr,
+ const audio_config_t *config,
+ const AudioDeviceTypeAddrVector &devices,
+ bool allowCurrentOutputReconfig = true) const;
+
sp<IOProfile> getSpatializerOutputProfile(const audio_config_t *config,
const AudioDeviceTypeAddrVector &devices) const;
@@ -1059,8 +1085,20 @@
bool areAllActiveTracksRerouted(const sp<SwAudioOutputDescriptor>& output);
- sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(const sp<IOProfile>& profile,
- const DeviceVector& devices);
+ /**
+ * @brief Opens an output stream from the supplied IOProfile and route it to the
+ * supplied audio devices. If a mixer config is specified, it is forwarded to audio
+ * flinger. If not, a default config is derived from the output stream config.
+ * Also opens a duplicating output if needed and queries the audio HAL for supported
+ * audio profiles if the IOProfile is dynamic.
+ * @param[in] profile IOProfile to use as template
+ * @param[in] devices initial route to apply to this output stream
+ * @param[in] mixerConfig if not null, use this to configure the mixer
+ * @return an output descriptor for the newly opened stream or null in case of error.
+ */
+ sp<SwAudioOutputDescriptor> openOutputWithProfileAndDevice(
+ const sp<IOProfile>& profile, const DeviceVector& devices,
+ const audio_config_base_t *mixerConfig = nullptr);
bool isOffloadPossible(const audio_offload_info_t& offloadInfo,
bool durationIgnored = false);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 3f01de9..858a3fd 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -345,7 +345,8 @@
(source > AUDIO_SOURCE_MAX &&
source != AUDIO_SOURCE_HOTWORD &&
source != AUDIO_SOURCE_FM_TUNER &&
- source != AUDIO_SOURCE_ECHO_REFERENCE)) {
+ source != AUDIO_SOURCE_ECHO_REFERENCE &&
+ source != AUDIO_SOURCE_ULTRASOUND)) {
ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
return BAD_VALUE;
}
@@ -544,6 +545,7 @@
CAMCORDER_SRC_TAG,
VOICE_REC_SRC_TAG,
VOICE_COMM_SRC_TAG,
+ REMOTE_SUBMIX_SRC_TAG,
UNPROCESSED_SRC_TAG,
VOICE_PERFORMANCE_SRC_TAG
};
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 8ddd2a4..a30768a 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -376,6 +376,15 @@
attr.flags = static_cast<audio_flags_mask_t>(
attr.flags & ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE));
}
+
+ if (attr.content_type == AUDIO_CONTENT_TYPE_ULTRASOUND) {
+ if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
+ __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+ }
+
AutoCallerClear acc;
AudioPolicyInterface::output_type_t outputType;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
@@ -596,7 +605,8 @@
|| (inputSource >= AUDIO_SOURCE_CNT
&& inputSource != AUDIO_SOURCE_HOTWORD
&& inputSource != AUDIO_SOURCE_FM_TUNER
- && inputSource != AUDIO_SOURCE_ECHO_REFERENCE)) {
+ && inputSource != AUDIO_SOURCE_ECHO_REFERENCE
+ && inputSource != AUDIO_SOURCE_ULTRASOUND)) {
return binderStatusFromStatusT(BAD_VALUE);
}
@@ -677,6 +687,14 @@
return binderStatusFromStatusT(PERMISSION_DENIED);
}
+ if (attr.source == AUDIO_SOURCE_ULTRASOUND) {
+ if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
+ __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+ }
+
sp<AudioPolicyEffects>audioPolicyEffects;
{
status_t status;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index ef7a83b..8add137 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -392,7 +392,8 @@
audio_config_base_t config = mSpatializer->getAudioInConfig();
status_t status =
mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
-
+ ALOGV("%s currentOutput %d newOutput %d channel_mask %#x",
+ __func__, currentOutput, newOutput, config.channel_mask);
if (status == NO_ERROR && currentOutput == newOutput) {
return;
}
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 0fdbe20..54d9094 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -227,12 +227,8 @@
if (status != NO_ERROR) {
return status;
}
- status = getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
+ return getHalParameter<true>(effect, SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS,
&mChannelMasks);
- if (status != NO_ERROR) {
- return status;
- }
- return NO_ERROR;
}
/** Gets the channel mask, sampling rate and format set for the spatializer input. */
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 80a3d29..440a7ff 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -35,10 +35,10 @@
namespace {
// This is how fast, in m/s, we allow position to shift during rate-limiting.
-constexpr auto kMaxTranslationalVelocity = 2;
+constexpr float kMaxTranslationalVelocity = 2;
// This is how fast, in rad/s, we allow rotation angle to shift during rate-limiting.
-constexpr auto kMaxRotationalVelocity = 4 * M_PI;
+constexpr float kMaxRotationalVelocity = 8;
// This should be set to the typical time scale that the translation sensors used drift in. This
// means, loosely, for how long we can trust the reading to be "accurate enough". This would
@@ -65,23 +65,23 @@
constexpr auto kMaxLostSamples = 4;
// Auto-recenter kicks in after the head has been still for this long.
-constexpr auto kAutoRecenterWindowDuration = 10s;
+constexpr auto kAutoRecenterWindowDuration = 6s;
// Auto-recenter considers head not still if translated by this much (in meters, approx).
constexpr float kAutoRecenterTranslationThreshold = 0.1f;
// Auto-recenter considers head not still if rotated by this much (in radians, approx).
-constexpr float kAutoRecenterRotationThreshold = 5.0f / 180 * M_PI;
+constexpr float kAutoRecenterRotationThreshold = 7.0f / 180 * M_PI;
// Screen is considered to be unstable (not still) if it has moved significantly within the last
// time window of this duration.
-constexpr auto kScreenStillnessWindowDuration = 10s;
+constexpr auto kScreenStillnessWindowDuration = 3s;
// Screen is considered to have moved significantly if translated by this much (in meter, approx).
constexpr float kScreenStillnessTranslationThreshold = 0.1f;
// Screen is considered to have moved significantly if rotated by this much (in radians, approx).
-constexpr float kScreenStillnessRotationThreshold = 5.0f / 180 * M_PI;
+constexpr float kScreenStillnessRotationThreshold = 7.0f / 180 * M_PI;
// Time units for system clock ticks. This is what the Sensor Framework timestamps represent and
// what we use for pose filtering.
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 1b54e75..8428881 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -48,6 +48,7 @@
"common/CameraOfflineSessionBase.cpp",
"common/CameraProviderManager.cpp",
"common/FrameProcessorBase.cpp",
+ "common/hidl/HidlProviderInfo.cpp",
"api1/Camera2Client.cpp",
"api1/client2/Parameters.cpp",
"api1/client2/FrameProcessor.cpp",
@@ -80,6 +81,9 @@
"device3/Camera3DeviceInjectionMethods.cpp",
"device3/UHRCropAndMeteringRegionMapper.cpp",
"device3/PreviewFrameScheduler.cpp",
+ "device3/hidl/HidlCamera3Device.cpp",
+ "device3/hidl/HidlCamera3OfflineSession.cpp",
+ "device3/hidl/HidlCamera3OutputUtils.cpp",
"gui/RingBufferConsumer.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",
"hidl/AidlCameraServiceListener.cpp",
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 015ae2f..ffd38be 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -32,8 +32,6 @@
namespace android {
-using hardware::camera::common::V1_0::TorchModeStatus;
-
/////////////////////////////////////////////////////////////////////
// CameraFlashlight implementation begins
// used by camera service to control flashflight.
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a593500..5740038 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -91,8 +91,6 @@
using hardware::ICamera;
using hardware::ICameraClient;
using hardware::ICameraServiceListener;
-using hardware::camera::common::V1_0::CameraDeviceStatus;
-using hardware::camera::common::V1_0::TorchModeStatus;
using hardware::camera2::ICameraInjectionCallback;
using hardware::camera2::ICameraInjectionSession;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
@@ -363,7 +361,7 @@
void CameraService::addStates(const String8 id) {
std::string cameraId(id.c_str());
- hardware::camera::common::V1_0::CameraResourceCost cost;
+ CameraResourceCost cost;
status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
if (res != OK) {
ALOGE("Failed to query device resource cost: %s (%d)", strerror(-res), res);
@@ -2335,6 +2333,13 @@
doUserSwitch(/*newUserIds*/ args);
break;
}
+ case ICameraService::EVENT_USB_DEVICE_ATTACHED:
+ case ICameraService::EVENT_USB_DEVICE_DETACHED: {
+ // Notify CameraProviderManager for lazy HALs
+ mCameraProviderManager->notifyUsbDeviceEvent(eventId,
+ std::to_string(args[0]));
+ break;
+ }
case ICameraService::EVENT_NONE:
default: {
ALOGW("%s: Received invalid system event from system_server: %d", __FUNCTION__,
@@ -2377,23 +2382,7 @@
ATRACE_CALL();
- using hardware::camera::provider::V2_5::DeviceState;
- hardware::hidl_bitfield<DeviceState> newDeviceState{};
- if (newState & ICameraService::DEVICE_STATE_BACK_COVERED) {
- newDeviceState |= DeviceState::BACK_COVERED;
- }
- if (newState & ICameraService::DEVICE_STATE_FRONT_COVERED) {
- newDeviceState |= DeviceState::FRONT_COVERED;
- }
- if (newState & ICameraService::DEVICE_STATE_FOLDED) {
- newDeviceState |= DeviceState::FOLDED;
- }
- // Only map vendor bits directly
- uint64_t vendorBits = static_cast<uint64_t>(newState) & 0xFFFFFFFF00000000l;
- newDeviceState |= vendorBits;
-
- ALOGV("%s: New device state 0x%" PRIx64, __FUNCTION__, newDeviceState);
- mCameraProviderManager->notifyDeviceStateChange(newDeviceState);
+ mCameraProviderManager->notifyDeviceStateChange(newState);
return Status::ok();
}
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 701d6b7..c73d28a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -106,19 +106,19 @@
// HAL Callbacks - implements CameraProviderManager::StatusListener
virtual void onDeviceStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+ CameraDeviceStatus newHalStatus) override;
virtual void onDeviceStatusChanged(const String8 &cameraId,
const String8 &physicalCameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newHalStatus) override;
+ CameraDeviceStatus newHalStatus) override;
// This method may hold CameraProviderManager::mInterfaceMutex as a part
// of calling getSystemCameraKind() internally. Care should be taken not to
// directly / indirectly call this from callers who also hold
// mInterfaceMutex.
virtual void onTorchStatusChanged(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
+ TorchModeStatus newStatus) override;
// Does not hold CameraProviderManager::mInterfaceMutex.
virtual void onTorchStatusChanged(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind kind) override;
virtual void onNewProviderRegistered() override;
@@ -558,8 +558,6 @@
private:
- typedef hardware::camera::common::V1_0::CameraDeviceStatus CameraDeviceStatus;
-
/**
* Typesafe version of device status, containing both the HAL-layer and the service interface-
* layer values.
@@ -1102,7 +1100,7 @@
// guard mTorchUidMap
Mutex mTorchUidMapMutex;
// camera id -> torch status
- KeyedVector<String8, hardware::camera::common::V1_0::TorchModeStatus>
+ KeyedVector<String8, TorchModeStatus>
mTorchStatusMap;
// camera id -> torch client binder
// only store the last client that turns on each camera's torch mode
@@ -1116,16 +1114,16 @@
// handle torch mode status change and invoke callbacks. mTorchStatusMutex
// should be locked.
void onTorchStatusChangedLocked(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind systemCameraKind);
// get a camera's torch status. mTorchStatusMutex should be locked.
status_t getTorchStatusLocked(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus *status) const;
+ TorchModeStatus *status) const;
// set a camera's torch status. mTorchStatusMutex should be locked.
status_t setTorchStatusLocked(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus status);
+ TorchModeStatus status);
// notify physical camera status when the physical camera is public.
// Expects mStatusListenerLock to be locked.
@@ -1236,14 +1234,13 @@
status_t checkCameraAccess(const String16& opPackageName);
static String8 toString(std::set<userid_t> intSet);
- static int32_t mapToInterface(hardware::camera::common::V1_0::TorchModeStatus status);
- static StatusInternal mapToInternal(hardware::camera::common::V1_0::CameraDeviceStatus status);
+ static int32_t mapToInterface(TorchModeStatus status);
+ static StatusInternal mapToInternal(CameraDeviceStatus status);
static int32_t mapToInterface(StatusInternal status);
void broadcastTorchModeStatus(const String8& cameraId,
- hardware::camera::common::V1_0::TorchModeStatus status,
- SystemCameraKind systemCameraKind);
+ TorchModeStatus status, SystemCameraKind systemCameraKind);
void broadcastTorchStrengthLevel(const String8& cameraId, int32_t newTorchStrengthLevel);
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8c52a6a..f33ae97 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -140,6 +140,40 @@
physicalKeysEntry.data.i32 + physicalKeysEntry.count);
}
+ auto entry = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ mDynamicProfileMap.emplace(
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
+ if (entry.count > 0) {
+ const auto it = std::find(entry.data.i32, entry.data.i32 + entry.count,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT);
+ if (it != entry.data.i32 + entry.count) {
+ entry = deviceInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
+ if (entry.count > 0 || ((entry.count % 2) != 0)) {
+ int standardBitmap = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
+ for (size_t i = 0; i < entry.count; i += 2) {
+ if (entry.data.i32[i] !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
+ mDynamicProfileMap.emplace(entry.data.i32[i], entry.data.i32[i+1]);
+ if ((entry.data.i32[i+1] == 0) || (entry.data.i32[i+1] &
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD)) {
+ standardBitmap |= entry.data.i32[i];
+ }
+ } else {
+ ALOGE("%s: Device %s includes unexpected profile entry: 0x%x!",
+ __FUNCTION__, mCameraIdStr.c_str(), entry.data.i32[i]);
+ }
+ }
+ mDynamicProfileMap.emplace(
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
+ standardBitmap);
+ } else {
+ ALOGE("%s: Device %s supports 10-bit output but doesn't include a dynamic range"
+ " profile map!", __FUNCTION__, mCameraIdStr.c_str());
+ }
+ }
+ }
+
mProviderManager = providerPtr;
// Cache physical camera ids corresponding to this device and also the high
// resolution sensors in this device + physical camera ids
@@ -297,6 +331,7 @@
SurfaceMap surfaceMap;
Vector<int32_t> outputStreamIds;
std::vector<std::string> requestedPhysicalIds;
+ int dynamicProfileBitmap = 0;
if (request.mSurfaceList.size() > 0) {
for (const sp<Surface>& surface : request.mSurfaceList) {
if (surface == 0) continue;
@@ -313,6 +348,8 @@
String8 requestedPhysicalId(
mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
requestedPhysicalIds.push_back(requestedPhysicalId.string());
+ dynamicProfileBitmap |=
+ mConfiguredOutputs.valueAt(index).getDynamicRangeProfile();
} else {
ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
}
@@ -348,6 +385,41 @@
String8 requestedPhysicalId(
mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
requestedPhysicalIds.push_back(requestedPhysicalId.string());
+ dynamicProfileBitmap |=
+ mConfiguredOutputs.valueAt(index).getDynamicRangeProfile();
+ }
+ }
+
+ if (dynamicProfileBitmap !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
+ for (int i = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
+ i < ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX; i <<= 1) {
+ if ((dynamicProfileBitmap & i) == 0) {
+ continue;
+ }
+
+ const auto& it = mDynamicProfileMap.find(i);
+ if (it != mDynamicProfileMap.end()) {
+ if ((it->second == 0) ||
+ ((it->second & dynamicProfileBitmap) == dynamicProfileBitmap)) {
+ continue;
+ } else {
+ ALOGE("%s: Camera %s: Tried to submit a request with a surfaces that"
+ " reference an unsupported dynamic range profile combination"
+ " 0x%x!", __FUNCTION__, mCameraIdStr.string(),
+ dynamicProfileBitmap);
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Request targets an unsupported dynamic range profile"
+ " combination");
+ }
+ } else {
+ ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
+ " references unsupported dynamic range profile 0x%x!",
+ __FUNCTION__, mCameraIdStr.string(), i);
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+ "Request targets 10-bit Surface with unsupported dynamic range"
+ " profile");
+ }
}
}
@@ -638,27 +710,9 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
- hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
- bool earlyExit = false;
- camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
- return mDevice->infoPhysical(id);};
- std::vector<std::string> physicalCameraIds;
- mProviderManager->isLogicalCamera(mCameraIdStr.string(), &physicalCameraIds);
- res = SessionConfigurationUtils::convertToHALStreamCombination(sessionConfiguration,
- mCameraIdStr, mDevice->info(), getMetadata, physicalCameraIds, streamConfiguration,
- mOverrideForPerfClass, &earlyExit);
- if (!res.isOk()) {
- return res;
- }
-
- if (earlyExit) {
- *status = false;
- return binder::Status::ok();
- }
-
*status = false;
ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
- streamConfiguration, status);
+ sessionConfiguration, mOverrideForPerfClass, status);
switch (ret) {
case OK:
// Expected, do nothing.
@@ -801,6 +855,7 @@
String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
bool isMultiResolution = outputConfiguration.isMultiResolution();
+ int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
outputConfiguration.getSurfaceType());
@@ -844,7 +899,7 @@
sp<Surface> surface;
res = SessionConfigurationUtils::createSurfaceFromGbp(streamInfo,
isStreamInfoValid, surface, bufferProducer, mCameraIdStr,
- mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed);
+ mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile);
if (!res.isOk())
return res;
@@ -888,7 +943,8 @@
streamInfo.height, streamInfo.format, streamInfo.dataSpace,
static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, streamInfo.sensorPixelModesUsed, &surfaceIds,
- outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution);
+ outputConfiguration.getSurfaceSetID(), isShared, isMultiResolution,
+ streamInfo.dynamicRangeProfile);
}
if (err != OK) {
@@ -982,7 +1038,8 @@
overriddenSensorPixelModesUsed,
&surfaceIds,
outputConfiguration.getSurfaceSetID(), isShared,
- outputConfiguration.isMultiResolution(), consumerUsage);
+ outputConfiguration.isMultiResolution(), consumerUsage,
+ outputConfiguration.getDynamicRangeProfile());
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -995,7 +1052,8 @@
mDeferredStreams.push_back(streamId);
mStreamInfoMap.emplace(std::piecewise_construct, std::forward_as_tuple(streamId),
std::forward_as_tuple(width, height, format, dataSpace, consumerUsage,
- overriddenSensorPixelModesUsed));
+ overriddenSensorPixelModesUsed,
+ outputConfiguration.getDynamicRangeProfile()));
ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
" (%d x %d) stream with format 0x%x.",
@@ -1184,12 +1242,14 @@
const std::vector<int32_t> &sensorPixelModesUsed =
outputConfiguration.getSensorPixelModesUsed();
+ int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
+
for (size_t i = 0; i < newOutputsMap.size(); i++) {
OutputStreamInfo outInfo;
sp<Surface> surface;
res = SessionConfigurationUtils::createSurfaceFromGbp(outInfo,
/*isStreamInfoValid*/ false, surface, newOutputsMap.valueAt(i), mCameraIdStr,
- mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed);
+ mDevice->infoPhysical(physicalCameraId), sensorPixelModesUsed, dynamicRangeProfile);
if (!res.isOk())
return res;
@@ -1546,6 +1606,7 @@
std::vector<sp<Surface>> consumerSurfaces;
const std::vector<int32_t> &sensorPixelModesUsed =
outputConfiguration.getSensorPixelModesUsed();
+ int dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
for (auto& bufferProducer : bufferProducers) {
// Don't create multiple streams for the same target surface
ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
@@ -1558,7 +1619,7 @@
sp<Surface> surface;
res = SessionConfigurationUtils::createSurfaceFromGbp(mStreamInfoMap[streamId],
true /*isStreamInfoValid*/, surface, bufferProducer, mCameraIdStr,
- mDevice->infoPhysical(physicalId), sensorPixelModesUsed);
+ mDevice->infoPhysical(physicalId), sensorPixelModesUsed, dynamicRangeProfile);
if (!res.isOk())
return res;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 288f2d7..77cdf9c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -22,6 +22,7 @@
#include <camera/camera2/OutputConfiguration.h>
#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/SubmitInfo.h>
+#include <unordered_map>
#include "CameraOfflineSessionClient.h"
#include "CameraService.h"
@@ -303,6 +304,10 @@
// Stream ID -> OutputConfiguration. Used for looking up Surface by stream/surface index
KeyedVector<int32_t, hardware::camera2::params::OutputConfiguration> mConfiguredOutputs;
+ // Dynamic range profile id -> Supported dynamic profiles bitmap within an single capture
+ // request
+ std::unordered_map<int, int> mDynamicProfileMap;
+
struct InputStreamConfiguration {
bool configured;
int32_t width;
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 5d17c11..55c7579 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -34,6 +34,7 @@
#include "api2/CameraDeviceClient.h"
#include "device3/Camera3Device.h"
+#include "device3/hidl/HidlCamera3Device.h"
#include "utils/CameraThreadState.h"
#include "utils/CameraServiceProxyWrapper.h"
@@ -62,14 +63,14 @@
servicePid),
mSharedCameraCallbacks(remoteCallback),
mDeviceVersion(cameraService->getDeviceVersion(TClientBase::mCameraIdStr)),
- mDevice(new Camera3Device(cameraId, overrideForPerfClass, legacyClient)),
mDeviceActive(false), mApi1CameraId(api1CameraId)
{
ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
String8(clientPackageName).string(), clientPid, clientUid);
mInitialClientPid = clientPid;
- LOG_ALWAYS_FATAL_IF(mDevice == 0, "Device should never be NULL here.");
+ mOverrideForPerfClass = overrideForPerfClass;
+ mLegacyClient = legacyClient;
}
template <typename TClientBase>
@@ -104,7 +105,26 @@
if (res != OK) {
return res;
}
-
+ IPCTransport providerTransport = IPCTransport::INVALID;
+ res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr.string(),
+ &providerTransport);
+ if (res != OK) {
+ return res;
+ }
+ switch (providerTransport) {
+ case IPCTransport::HIDL:
+ mDevice =
+ new HidlCamera3Device(TClientBase::mCameraIdStr, mOverrideForPerfClass,
+ mLegacyClient);
+ break;
+ case IPCTransport::AIDL:
+ ALOGE("%s: AIDL camera3Devices not available yet", __FUNCTION__);
+ return NO_INIT;
+ default:
+ ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
+ TClientBase::mCameraIdStr.string());
+ return NO_INIT;
+ }
if (mDevice == NULL) {
ALOGE("%s: Camera %s: No device connected",
__FUNCTION__, TClientBase::mCameraIdStr.string());
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 4688502..296ef43 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -126,6 +126,8 @@
// The PID provided in the constructor call
pid_t mInitialClientPid;
+ bool mOverrideForPerfClass = false;
+ bool mLegacyClient = false;
virtual sp<IBinder> asBinderWrapper() {
return IInterface::asBinder(this);
@@ -145,9 +147,12 @@
const int mDeviceVersion;
- // Set to const to avoid mDevice being updated (update of sp<> is racy) during
- // dumpDevice (which is important to be lock free for debugging purpose)
- const sp<CameraDeviceBase> mDevice;
+ // Note: This was previously set to const to avoid mDevice being updated -
+ // b/112639939 (update of sp<> is racy) during dumpDevice (which is important to be lock free
+ // for debugging purpose). The const has been removed since CameraDeviceBase
+ // needs to be set during initializeImpl(). This must not be set / cleared
+ // anywhere else.
+ sp<CameraDeviceBase> mDevice;
/** Utility members */
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index c454716..e936cb6 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -182,7 +182,8 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) = 0;
+ uint64_t consumerUsage = 0,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) = 0;
/**
* Create an output stream of the requested size, format, rotation and
@@ -199,7 +200,8 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) = 0;
+ uint64_t consumerUsage = 0,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) = 0;
/**
* Create an input stream of width, height, and format.
@@ -220,10 +222,12 @@
android_dataspace dataSpace;
bool dataSpaceOverridden;
android_dataspace originalDataSpace;
+ uint32_t dynamicRangeProfile;
StreamInfo() : width(0), height(0), format(0), formatOverridden(false), originalFormat(0),
dataSpace(HAL_DATASPACE_UNKNOWN), dataSpaceOverridden(false),
- originalDataSpace(HAL_DATASPACE_UNKNOWN) {}
+ originalDataSpace(HAL_DATASPACE_UNKNOWN),
+ dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD){}
/**
* Check whether the format matches the current or the original one in case
* it got overridden.
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 2cdf696..4227d28 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -25,6 +25,7 @@
#include <algorithm>
#include <chrono>
#include "common/DepthPhotoProcessor.h"
+#include "hidl/HidlProviderInfo.h"
#include <dlfcn.h>
#include <future>
#include <inttypes.h>
@@ -45,26 +46,27 @@
namespace android {
using namespace ::android::hardware::camera;
-using namespace ::android::hardware::camera::common::V1_0;
using namespace ::android::camera3;
+using android::hardware::camera::common::V1_0::Status;
+using namespace camera3::SessionConfigurationUtils;
using std::literals::chrono_literals::operator""s;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
-using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+const std::string kExternalProviderName = "external/0";
} // anonymous namespace
const float CameraProviderManager::kDepthARTolerance = .1f;
-CameraProviderManager::HardwareServiceInteractionProxy
-CameraProviderManager::sHardwareServiceInteractionProxy{};
+CameraProviderManager::HidlServiceInteractionProxyImpl
+CameraProviderManager::sHidlServiceInteractionProxy{};
CameraProviderManager::~CameraProviderManager() {
}
hardware::hidl_vec<hardware::hidl_string>
-CameraProviderManager::HardwareServiceInteractionProxy::listServices() {
+CameraProviderManager::HidlServiceInteractionProxyImpl::listServices() {
hardware::hidl_vec<hardware::hidl_string> ret;
auto manager = hardware::defaultServiceManager1_2();
if (manager != nullptr) {
@@ -77,19 +79,18 @@
}
status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
- ServiceInteractionProxy* proxy) {
+ HidlServiceInteractionProxy* hidlProxy) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- if (proxy == nullptr) {
+ if (hidlProxy == nullptr) {
ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
return BAD_VALUE;
}
mListener = listener;
- mServiceProxy = proxy;
- mDeviceState = static_cast<hardware::hidl_bitfield<provider::V2_5::DeviceState>>(
- provider::V2_5::DeviceState::NORMAL);
+ mHidlServiceProxy = hidlProxy;
+ mDeviceState = 0;
// Registering will trigger notifications for all already-known providers
- bool success = mServiceProxy->registerForNotifications(
+ bool success = mHidlServiceProxy->registerForNotifications(
/* instance name, empty means no filter */ "",
this);
if (!success) {
@@ -98,9 +99,8 @@
return INVALID_OPERATION;
}
-
- for (const auto& instance : mServiceProxy->listServices()) {
- this->addProviderLocked(instance);
+ for (const auto& instance : mHidlServiceProxy->listServices()) {
+ this->addHidlProviderLocked(instance);
}
IPCThreadState::self()->flushCommands();
@@ -267,7 +267,7 @@
}
status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const SessionConfiguration &configuration, bool overrideForPerfClass,
bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
@@ -275,7 +275,22 @@
return NAME_NOT_FOUND;
}
- return deviceInfo->isSessionConfigurationSupported(configuration, status);
+ return deviceInfo->isSessionConfigurationSupported(configuration, overrideForPerfClass, status);
+}
+
+status_t CameraProviderManager::getCameraIdIPCTransport(const std::string &id,
+ IPCTransport *providerTransport) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) {
+ return NAME_NOT_FOUND;
+ }
+ sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
+ if (parentProvider == nullptr) {
+ return DEAD_OBJECT;
+ }
+ *providerTransport = parentProvider->getIPCTransport();
+ return OK;
}
status_t CameraProviderManager::getCameraCharacteristics(const std::string &id,
@@ -284,6 +299,9 @@
return getCameraCharacteristicsLocked(id, overrideForPerfClass, characteristics);
}
+// Till hidl is removed from the android source tree, we use this for aidl as
+// well. We artificially give aidl camera device version 1 a major version 3 and minor
+// version 8.
status_t CameraProviderManager::getHighestSupportedVersion(const std::string &id,
hardware::hidl_version *v) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -374,11 +392,25 @@
if (parentProvider == nullptr) {
return DEAD_OBJECT;
}
- const sp<provider::V2_4::ICameraProvider> interface = parentProvider->startProviderInterface();
- if (interface == nullptr) {
- return DEAD_OBJECT;
+ std::shared_ptr<HalCameraProvider> halCameraProvider = nullptr;
+ IPCTransport providerTransport = parentProvider->getIPCTransport();
+ if (providerTransport == IPCTransport::HIDL) {
+ HidlProviderInfo * hidlProviderInfo = static_cast<HidlProviderInfo *>(parentProvider.get());
+ const sp<provider::V2_4::ICameraProvider> hidlInterface =
+ hidlProviderInfo->startProviderInterface();
+ if (hidlInterface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ halCameraProvider =
+ std::make_shared<HidlHalCameraProvider>(hidlInterface, hidlInterface->descriptor);
+ } else if (providerTransport == IPCTransport::AIDL) {
+ ALOGE("%s AIDL hal providers not supported yet", __FUNCTION__);
+ return INVALID_OPERATION;
+ } else {
+ ALOGE("%s Invalid provider transport", __FUNCTION__);
+ return INVALID_OPERATION;
}
- saveRef(DeviceMode::TORCH, deviceInfo->mId, interface);
+ saveRef(DeviceMode::TORCH, deviceInfo->mId, halCameraProvider);
return deviceInfo->setTorchMode(enabled);
}
@@ -395,8 +427,72 @@
return OK;
}
-status_t CameraProviderManager::notifyDeviceStateChange(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newState) {
+sp<CameraProviderManager::ProviderInfo> CameraProviderManager::startExternalLazyProvider() const {
+ std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ for (const auto& providerInfo : mProviders) {
+ if (providerInfo->isExternalLazyHAL()) {
+ if (!providerInfo->successfullyStartedProviderInterface()) {
+ return nullptr;
+ } else {
+ return providerInfo;
+ }
+ }
+ }
+ return nullptr;
+}
+
+status_t CameraProviderManager::notifyUsbDeviceEvent(int32_t eventId,
+ const std::string& usbDeviceId) {
+ if (!kEnableLazyHal) {
+ return OK;
+ }
+
+ ALOGV("notifySystemEvent: %d usbDeviceId : %s", eventId, usbDeviceId.c_str());
+
+ if (eventId == android::hardware::ICameraService::EVENT_USB_DEVICE_ATTACHED) {
+ sp<ProviderInfo> externalProvider = startExternalLazyProvider();
+ if (externalProvider != nullptr) {
+ auto usbDevices = mExternalUsbDevicesForProvider.first;
+ usbDevices.push_back(usbDeviceId);
+ mExternalUsbDevicesForProvider = {usbDevices, externalProvider};
+ }
+ } else if (eventId
+ == android::hardware::ICameraService::EVENT_USB_DEVICE_DETACHED) {
+ usbDeviceDetached(usbDeviceId);
+ }
+
+ return OK;
+}
+
+status_t CameraProviderManager::usbDeviceDetached(const std::string &usbDeviceId) {
+ std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
+ std::lock_guard<std::mutex> interfaceLock(mInterfaceMutex);
+
+ auto usbDevices = mExternalUsbDevicesForProvider.first;
+ auto foundId = std::find(usbDevices.begin(), usbDevices.end(), usbDeviceId);
+ if (foundId != usbDevices.end()) {
+ sp<ProviderInfo> providerInfo = mExternalUsbDevicesForProvider.second;
+ if (providerInfo == nullptr) {
+ ALOGE("%s No valid external provider for USB device: %s",
+ __FUNCTION__,
+ usbDeviceId.c_str());
+ mExternalUsbDevicesForProvider = {std::vector<std::string>(), nullptr};
+ return DEAD_OBJECT;
+ } else {
+ mInterfaceMutex.unlock();
+ providerInfo->removeAllDevices();
+ mInterfaceMutex.lock();
+ mExternalUsbDevicesForProvider = {std::vector<std::string>(), nullptr};
+ }
+ } else {
+ return DEAD_OBJECT;
+ }
+ return OK;
+}
+
+status_t CameraProviderManager::notifyDeviceStateChange(int64_t newState) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
mDeviceState = newState;
status_t res = OK;
@@ -422,7 +518,7 @@
return res;
}
-status_t CameraProviderManager::openSession(const std::string &id,
+status_t CameraProviderManager::openHidlSession(const std::string &id,
const sp<device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<device::V3_2::ICameraDeviceSession> *session) {
@@ -433,21 +529,23 @@
/*minVersion*/ {3,0}, /*maxVersion*/ {4,0});
if (deviceInfo == nullptr) return NAME_NOT_FOUND;
- auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
+ auto *hidlDeviceInfo3 = static_cast<HidlProviderInfo::HidlDeviceInfo3*>(deviceInfo);
sp<ProviderInfo> parentProvider = deviceInfo->mParentProvider.promote();
if (parentProvider == nullptr) {
return DEAD_OBJECT;
}
- const sp<provider::V2_4::ICameraProvider> provider = parentProvider->startProviderInterface();
+ const sp<provider::V2_4::ICameraProvider> provider =
+ static_cast<HidlProviderInfo *>(parentProvider.get())->startProviderInterface();
if (provider == nullptr) {
return DEAD_OBJECT;
}
- saveRef(DeviceMode::CAMERA, id, provider);
+ std::shared_ptr<HalCameraProvider> halCameraProvider =
+ std::make_shared<HidlHalCameraProvider>(provider, provider->descriptor);
+ saveRef(DeviceMode::CAMERA, id, halCameraProvider);
Status status;
hardware::Return<void> ret;
- auto interface = deviceInfo3->startDeviceInterface<
- CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+ auto interface = hidlDeviceInfo3->startDeviceInterface();
if (interface == nullptr) {
return DEAD_OBJECT;
}
@@ -465,17 +563,18 @@
__FUNCTION__, id.c_str(), ret.description().c_str());
return DEAD_OBJECT;
}
- return mapToStatusT(status);
+ return HidlProviderInfo::mapToStatusT(status);
}
void CameraProviderManager::saveRef(DeviceMode usageType, const std::string &cameraId,
- sp<provider::V2_4::ICameraProvider> provider) {
+ std::shared_ptr<HalCameraProvider> provider) {
if (!kEnableLazyHal) {
return;
}
- ALOGV("Saving camera provider %s for camera device %s", provider->descriptor, cameraId.c_str());
+ ALOGV("Saving camera provider %s for camera device %s", provider->mDescriptor.c_str(),
+ cameraId.c_str());
std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
- std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *primaryMap, *alternateMap;
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>> *primaryMap, *alternateMap;
if (usageType == DeviceMode::TORCH) {
primaryMap = &mTorchProviderByCameraId;
alternateMap = &mCameraProviderByCameraId;
@@ -498,7 +597,7 @@
return;
}
ALOGV("Removing camera device %s", cameraId.c_str());
- std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *providerMap;
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>> *providerMap;
if (usageType == DeviceMode::TORCH) {
providerMap = &mTorchProviderByCameraId;
} else {
@@ -532,7 +631,7 @@
{
std::lock_guard<std::mutex> lock(mInterfaceMutex);
- res = addProviderLocked(name, preexisting);
+ res = addHidlProviderLocked(name, preexisting);
}
sp<StatusListener> listener = getStatusListener();
@@ -1288,10 +1387,10 @@
return falseRet;
}
-status_t CameraProviderManager::tryToInitializeProviderLocked(
+status_t CameraProviderManager::tryToInitializeHidlProviderLocked(
const std::string& providerName, const sp<ProviderInfo>& providerInfo) {
sp<provider::V2_4::ICameraProvider> interface;
- interface = mServiceProxy->tryGetService(providerName);
+ interface = mHidlServiceProxy->tryGetService(providerName);
if (interface == nullptr) {
// The interface may not be started yet. In that case, this is not a
@@ -1301,10 +1400,11 @@
return BAD_VALUE;
}
- return providerInfo->initialize(interface, mDeviceState);
+ HidlProviderInfo *hidlProviderInfo = static_cast<HidlProviderInfo *>(providerInfo.get());
+ return hidlProviderInfo->initializeHidlProvider(interface, mDeviceState);
}
-status_t CameraProviderManager::addProviderLocked(const std::string& newProvider,
+status_t CameraProviderManager::addHidlProviderLocked(const std::string& newProvider,
bool preexisting) {
// Several camera provider instances can be temporarily present.
// Defer initialization of a new instance until the older instance is properly removed.
@@ -1314,9 +1414,10 @@
if (providerInfo->mProviderName == newProvider) {
ALOGW("%s: Camera provider HAL with name '%s' already registered",
__FUNCTION__, newProvider.c_str());
- if (preexisting) {
+ // Do not add new instances for lazy HAL external provider
+ if (preexisting || providerInfo->isExternalLazyHAL()) {
return ALREADY_EXISTS;
- } else{
+ } else {
ALOGW("%s: The new provider instance will get initialized immediately after the"
" currently present instance is removed!", __FUNCTION__);
providerPresent = true;
@@ -1325,9 +1426,9 @@
}
}
- sp<ProviderInfo> providerInfo = new ProviderInfo(newProvider, providerInstance, this);
+ sp<HidlProviderInfo> providerInfo = new HidlProviderInfo(newProvider, providerInstance, this);
if (!providerPresent) {
- status_t res = tryToInitializeProviderLocked(newProvider, providerInfo);
+ status_t res = tryToInitializeHidlProviderLocked(newProvider, providerInfo);
if (res != OK) {
return res;
}
@@ -1365,7 +1466,13 @@
// initialize.
for (const auto& providerInfo : mProviders) {
if (providerInfo->mProviderName == removedProviderName) {
- return tryToInitializeProviderLocked(removedProviderName, providerInfo);
+ IPCTransport providerTransport = providerInfo->getIPCTransport();
+ switch(providerTransport) {
+ case IPCTransport::HIDL:
+ return tryToInitializeHidlProviderLocked(removedProviderName, providerInfo);
+ default:
+ ALOGE("%s Unsupported Transport %d", __FUNCTION__, providerTransport);
+ }
}
}
@@ -1387,7 +1494,6 @@
sp<CameraProviderManager::StatusListener> CameraProviderManager::getStatusListener() const {
return mListener.promote();
}
-
/**** Methods for ProviderInfo ****/
@@ -1403,322 +1509,60 @@
(void) mManager;
}
-status_t CameraProviderManager::ProviderInfo::initialize(
- sp<provider::V2_4::ICameraProvider>& interface,
- hardware::hidl_bitfield<provider::V2_5::DeviceState> currentDeviceState) {
- status_t res = parseProviderName(mProviderName, &mType, &mId);
- if (res != OK) {
- ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
- return BAD_VALUE;
- }
- ALOGI("Connecting to new camera provider: %s, isRemote? %d",
- mProviderName.c_str(), interface->isRemote());
-
- // Determine minor version
- mMinorVersion = 4;
- auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
- sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
- if (cast2_6.isOk()) {
- interface2_6 = cast2_6;
- if (interface2_6 != nullptr) {
- mMinorVersion = 6;
- }
- }
- // We need to check again since cast2_6.isOk() succeeds even if the provider
- // version isn't actually 2.6.
- if (interface2_6 == nullptr){
- auto cast2_5 =
- provider::V2_5::ICameraProvider::castFrom(interface);
- sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
- if (cast2_5.isOk()) {
- interface2_5 = cast2_5;
- if (interface != nullptr) {
- mMinorVersion = 5;
- }
- }
- } else {
- auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
- if (cast2_7.isOk()) {
- sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
- if (interface2_7 != nullptr) {
- mMinorVersion = 7;
- }
- }
- }
-
- // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
- // before setCallback returns
- hardware::Return<Status> status = interface->setCallback(this);
- if (!status.isOk()) {
- ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), status.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to register callbacks with camera provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
-
- hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
- if (!linked.isOk()) {
- ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- return DEAD_OBJECT;
- } else if (!linked) {
- ALOGW("%s: Unable to link to provider '%s' death notifications",
- __FUNCTION__, mProviderName.c_str());
- }
-
- if (!kEnableLazyHal) {
- // Save HAL reference indefinitely
- mSavedInterface = interface;
- } else {
- mActiveInterface = interface;
- }
-
- ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
- __FUNCTION__, mProviderName.c_str(), mDeviceState);
- notifyDeviceStateChange(currentDeviceState);
-
- res = setUpVendorTags();
- if (res != OK) {
- ALOGE("%s: Unable to set up vendor tags from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return res;
- }
-
- // Get initial list of camera devices, if any
- std::vector<std::string> devices;
- hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
- Status idStatus,
- const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
- status = idStatus;
- if (status == Status::OK) {
- for (auto& name : cameraDeviceNames) {
- uint16_t major, minor;
- std::string type, id;
- status_t res = parseDeviceName(name, &major, &minor, &type, &id);
- if (res != OK) {
- ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
- status = Status::INTERNAL_ERROR;
- } else {
- devices.push_back(name);
- mProviderPublicCameraIds.push_back(id);
- }
- }
- } });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to query for camera devices from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
-
- // Get list of concurrent streaming camera device combinations
- if (mMinorVersion >= 6) {
- res = getConcurrentCameraIdsInternalLocked(interface2_6);
- if (res != OK) {
- return res;
- }
- }
-
- ret = interface->isSetTorchModeSupported(
- [this](auto status, bool supported) {
- if (status == Status::OK) {
- mSetTorchModeSupported = supported;
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error checking torch mode support '%s': %s",
- __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
- return DEAD_OBJECT;
- }
-
- mIsRemote = interface->isRemote();
-
- sp<StatusListener> listener = mManager->getStatusListener();
- for (auto& device : devices) {
- std::string id;
- status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
- if (res != OK) {
- ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
- __FUNCTION__, device.c_str(), strerror(-res), res);
- continue;
- }
- }
-
- ALOGI("Camera provider %s ready with %zu camera devices",
- mProviderName.c_str(), mDevices.size());
-
- // Process cached status callbacks
- std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
- std::make_unique<std::vector<CameraStatusInfoT>>();
- {
- std::lock_guard<std::mutex> lock(mInitLock);
-
- for (auto& statusInfo : mCachedStatus) {
- std::string id, physicalId;
- status_t res = OK;
- if (statusInfo.isPhysicalCameraStatus) {
- res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
- statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
- } else {
- res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
- }
- if (res == OK) {
- cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
- id.c_str(), physicalId.c_str(), statusInfo.status);
- }
- }
- mCachedStatus.clear();
-
- mInitialized = true;
- }
-
- // The cached status change callbacks cannot be fired directly from this
- // function, due to same-thread deadlock trying to acquire mInterfaceMutex
- // twice.
- if (listener != nullptr) {
- mInitialStatusCallbackFuture = std::async(std::launch::async,
- &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
- listener, std::move(cachedStatus));
- }
-
- return OK;
-}
-
-const sp<provider::V2_4::ICameraProvider>
-CameraProviderManager::ProviderInfo::startProviderInterface() {
- ATRACE_CALL();
- ALOGV("Request to start camera provider: %s", mProviderName.c_str());
- if (mSavedInterface != nullptr) {
- return mSavedInterface;
- }
- if (!kEnableLazyHal) {
- ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
- return nullptr;
- }
-
- auto interface = mActiveInterface.promote();
- if (interface == nullptr) {
- ALOGI("Camera HAL provider needs restart, calling getService(%s)", mProviderName.c_str());
- interface = mManager->mServiceProxy->getService(mProviderName);
- interface->setCallback(this);
- hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
- if (!linked.isOk()) {
- ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
- __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
- mManager->removeProvider(mProviderName);
- return nullptr;
- } else if (!linked) {
- ALOGW("%s: Unable to link to provider '%s' death notifications",
- __FUNCTION__, mProviderName.c_str());
- }
- // Send current device state
- if (mMinorVersion >= 5) {
- auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
- if (interface_2_5 != nullptr) {
- ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
- __FUNCTION__, mProviderName.c_str(), mDeviceState);
- interface_2_5->notifyDeviceStateChange(mDeviceState);
- }
- }
- }
-
- mActiveInterface = interface;
- } else {
- ALOGV("Camera provider (%s) already in use. Re-using instance.", mProviderName.c_str());
- }
- return interface;
-}
-
const std::string& CameraProviderManager::ProviderInfo::getType() const {
return mType;
}
-status_t CameraProviderManager::ProviderInfo::addDevice(const std::string& name,
- CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
-
- ALOGI("Enumerating new camera device: %s", name.c_str());
-
- uint16_t major, minor;
- std::string type, id;
-
- status_t res = parseDeviceName(name, &major, &minor, &type, &id);
- if (res != OK) {
- return res;
- }
- if (type != mType) {
- ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
- type.c_str(), mType.c_str());
- return BAD_VALUE;
- }
- if (mManager->isValidDeviceLocked(id, major)) {
- ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
- name.c_str(), id.c_str(), major);
- return BAD_VALUE;
- }
-
- std::unique_ptr<DeviceInfo> deviceInfo;
- switch (major) {
- case 1:
- ALOGE("%s: Device %s: Unsupported HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), major);
- return BAD_VALUE;
- case 3:
- deviceInfo = initializeDeviceInfo<DeviceInfo3>(name, mProviderTagid,
- id, minor);
- break;
- default:
- ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), major);
- return BAD_VALUE;
- }
- if (deviceInfo == nullptr) return BAD_VALUE;
- deviceInfo->notifyDeviceStateChange(mDeviceState);
- deviceInfo->mStatus = initialStatus;
- bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
-
- mDevices.push_back(std::move(deviceInfo));
-
- mUniqueCameraIds.insert(id);
- if (isAPI1Compatible) {
- // addDevice can be called more than once for the same camera id if HAL
- // supports openLegacy.
- if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
- id) == mUniqueAPI1CompatibleCameraIds.end()) {
- mUniqueAPI1CompatibleCameraIds.push_back(id);
- }
- }
-
- if (parsedId != nullptr) {
- *parsedId = id;
- }
- return OK;
-}
-
void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
if ((*it)->mId == id) {
mUniqueCameraIds.erase(id);
if ((*it)->isAPI1Compatible()) {
mUniqueAPI1CompatibleCameraIds.erase(std::remove(
- mUniqueAPI1CompatibleCameraIds.begin(),
- mUniqueAPI1CompatibleCameraIds.end(), id));
+ mUniqueAPI1CompatibleCameraIds.begin(),
+ mUniqueAPI1CompatibleCameraIds.end(), id));
}
+
+ // Remove reference to camera provider to avoid pointer leak when
+ // unplugging external camera while in use with lazy HALs
+ mManager->removeRef(DeviceMode::CAMERA, id);
+ mManager->removeRef(DeviceMode::TORCH, id);
+
mDevices.erase(it);
break;
}
}
}
+void CameraProviderManager::ProviderInfo::removeAllDevices() {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ auto itDevices = mDevices.begin();
+ while (itDevices != mDevices.end()) {
+ std::string id = (*itDevices)->mId;
+ std::string deviceName = (*itDevices)->mName;
+ removeDevice(id);
+ // device was removed, reset iterator
+ itDevices = mDevices.begin();
+
+ //notify CameraService of status change
+ sp<StatusListener> listener = mManager->getStatusListener();
+ if (listener != nullptr) {
+ mLock.unlock();
+ ALOGV("%s: notify device not_present: %s",
+ __FUNCTION__,
+ deviceName.c_str());
+ listener->onDeviceStatusChanged(String8(id.c_str()),
+ CameraDeviceStatus::NOT_PRESENT);
+ mLock.lock();
+ }
+ }
+}
+
+bool CameraProviderManager::ProviderInfo::isExternalLazyHAL() const {
+ return kEnableLazyHal && (mProviderName == kExternalProviderName);
+}
+
status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
dprintf(fd, "== Camera Provider HAL %s (v2.%d, %s) static info: %zu devices: ==\n",
mProviderInstance.c_str(),
@@ -1793,416 +1637,20 @@
return OK;
}
-status_t CameraProviderManager::ProviderInfo::getConcurrentCameraIdsInternalLocked(
- sp<provider::V2_6::ICameraProvider> &interface2_6) {
- if (interface2_6 == nullptr) {
- ALOGE("%s: null interface provided", __FUNCTION__);
- return BAD_VALUE;
- }
- Status status = Status::OK;
- hardware::Return<void> ret =
- interface2_6->getConcurrentStreamingCameraIds([&status, this](
- Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
- const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
- cameraDeviceIdCombinations) {
- status = concurrentIdStatus;
- if (status == Status::OK) {
- mConcurrentCameraIdCombinations.clear();
- for (auto& combination : cameraDeviceIdCombinations) {
- std::unordered_set<std::string> deviceIds;
- for (auto &cameraDeviceId : combination) {
- deviceIds.insert(cameraDeviceId.c_str());
- }
- mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
- }
- } });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to query for camera devices from provider '%s'",
- __FUNCTION__, mProviderName.c_str());
- return mapToStatusT(status);
- }
- return OK;
-}
-
-status_t CameraProviderManager::ProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
- if (mMinorVersion < 6) {
- // Unsupported operation, nothing to do here
- return OK;
- }
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface == nullptr) {
- ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
- mProviderName.c_str());
- return INVALID_OPERATION;
- }
- auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
-
- if (castResult.isOk()) {
- sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
- if (interface2_6 != nullptr) {
- return getConcurrentCameraIdsInternalLocked(interface2_6);
- } else {
- // This should not happen since mMinorVersion >= 6
- ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
- return UNKNOWN_ERROR;
- }
- }
- return OK;
-}
-
std::vector<std::unordered_set<std::string>>
CameraProviderManager::ProviderInfo::getConcurrentCameraIdCombinations() {
std::lock_guard<std::mutex> lock(mLock);
return mConcurrentCameraIdCombinations;
}
-hardware::Return<void> CameraProviderManager::ProviderInfo::cameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- CameraDeviceStatus newStatus) {
- sp<StatusListener> listener;
- std::string id;
- std::lock_guard<std::mutex> lock(mInitLock);
-
- if (!mInitialized) {
- mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
- cameraDeviceName.c_str(), std::string().c_str(), newStatus);
- return hardware::Void();
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
- return hardware::Void();
- }
- listener = mManager->getStatusListener();
- }
-
- // Call without lock held to allow reentrancy into provider manager
- if (listener != nullptr) {
- listener->onDeviceStatusChanged(String8(id.c_str()), newStatus);
- }
-
- return hardware::Void();
-}
-
-status_t CameraProviderManager::ProviderInfo::cameraDeviceStatusChangeLocked(
- std::string* id, const hardware::hidl_string& cameraDeviceName,
- CameraDeviceStatus newStatus) {
- bool known = false;
- std::string cameraId;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
- deviceStatusToString(newStatus), deviceStatusToString(deviceInfo->mStatus));
- deviceInfo->mStatus = newStatus;
- // TODO: Handle device removal (NOT_PRESENT)
- cameraId = deviceInfo->mId;
- known = true;
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str());
- return BAD_VALUE;
- }
- addDevice(cameraDeviceName, newStatus, &cameraId);
- } else if (newStatus == CameraDeviceStatus::NOT_PRESENT) {
- removeDevice(cameraId);
- }
- if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
- ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
- __FUNCTION__, mProviderName.c_str());
- }
- *id = cameraId;
- return OK;
-}
-
-hardware::Return<void> CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- CameraDeviceStatus newStatus) {
- sp<StatusListener> listener;
- std::string id;
- std::string physicalId;
- std::lock_guard<std::mutex> lock(mInitLock);
-
- if (!mInitialized) {
- mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
- physicalCameraDeviceName, newStatus);
- return hardware::Void();
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
-
- if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
- physicalCameraDeviceName, newStatus)) {
- return hardware::Void();
- }
-
- listener = mManager->getStatusListener();
- }
- // Call without lock held to allow reentrancy into provider manager
- if (listener != nullptr) {
- listener->onDeviceStatusChanged(String8(id.c_str()),
- String8(physicalId.c_str()), newStatus);
- }
- return hardware::Void();
-}
-
-status_t CameraProviderManager::ProviderInfo::physicalCameraDeviceStatusChangeLocked(
- std::string* id, std::string* physicalId,
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- CameraDeviceStatus newStatus) {
- bool known = false;
- std::string cameraId;
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- cameraId = deviceInfo->mId;
- if (!deviceInfo->mIsLogicalCamera) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
- if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
- physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
- ALOGE("%s: Invalid combination of camera id %s, physical id %s",
- __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
- ALOGI("Camera device %s physical device %s status is now %s",
- cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
- deviceStatusToString(newStatus));
- known = true;
- break;
- }
- }
- // Previously unseen device; status must not be NOT_PRESENT
- if (!known) {
- ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str(),
- physicalCameraDeviceName.c_str());
- return BAD_VALUE;
- }
-
- *id = cameraId;
- *physicalId = physicalCameraDeviceName.c_str();
- return OK;
-}
-
-hardware::Return<void> CameraProviderManager::ProviderInfo::torchModeStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- TorchModeStatus newStatus) {
- sp<StatusListener> listener;
- SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
- std::string id;
- bool known = false;
- {
- // Hold mLock for accessing mDevices
- std::lock_guard<std::mutex> lock(mLock);
- for (auto& deviceInfo : mDevices) {
- if (deviceInfo->mName == cameraDeviceName) {
- ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
- torchStatusToString(newStatus));
- id = deviceInfo->mId;
- known = true;
- systemCameraKind = deviceInfo->mSystemCameraKind;
- if (TorchModeStatus::AVAILABLE_ON != newStatus) {
- mManager->removeRef(DeviceMode::TORCH, id);
- }
- break;
- }
- }
- if (!known) {
- ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
- mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
- return hardware::Void();
- }
- // no lock needed since listener is set up only once during
- // CameraProviderManager initialization and then never changed till it is
- // destructed.
- listener = mManager->getStatusListener();
- }
- // Call without lock held to allow reentrancy into provider manager
- // The problem with holding mLock here is that we
- // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
- // back into CameraProviderManager which might try to hold mLock again (eg:
- // findDeviceInfo, which should be holding mLock while iterating through
- // each provider's devices).
- if (listener != nullptr) {
- listener->onTorchStatusChanged(String8(id.c_str()), newStatus, systemCameraKind);
- }
- return hardware::Void();
-}
-
-void CameraProviderManager::ProviderInfo::serviceDied(uint64_t cookie,
- const wp<hidl::base::V1_0::IBase>& who) {
- (void) who;
- ALOGI("Camera provider '%s' has died; removing it", mProviderInstance.c_str());
- if (cookie != mId) {
- ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
- __FUNCTION__, cookie, mId);
- }
- mManager->removeProvider(mProviderInstance);
-}
-
-status_t CameraProviderManager::ProviderInfo::setUpVendorTags() {
- if (mVendorTagDescriptor != nullptr)
- return OK;
-
- hardware::hidl_vec<VendorTagSection> vts;
- Status status;
- hardware::Return<void> ret;
- const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- ret = interface->getVendorTags(
- [&](auto s, const auto& vendorTagSecs) {
- status = s;
- if (s == Status::OK) {
- vts = vendorTagSecs;
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
- __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
- return DEAD_OBJECT;
- }
- if (status != Status::OK) {
- return mapToStatusT(status);
- }
-
- // Read all vendor tag definitions into a descriptor
- status_t res;
- if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
- != OK) {
- ALOGE("%s: Could not generate descriptor from vendor tag operations,"
- "received error %s (%d). Camera clients will not be able to use"
- "vendor tags", __FUNCTION__, strerror(res), res);
- return res;
- }
-
- return OK;
-}
-
void CameraProviderManager::ProviderInfo::notifyDeviceInfoStateChangeLocked(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
+ int64_t newDeviceState) {
std::lock_guard<std::mutex> lock(mLock);
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
(*it)->notifyDeviceStateChange(newDeviceState);
}
}
-status_t CameraProviderManager::ProviderInfo::notifyDeviceStateChange(
- hardware::hidl_bitfield<provider::V2_5::DeviceState> newDeviceState) {
- mDeviceState = newDeviceState;
- if (mMinorVersion >= 5) {
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface != nullptr) {
- // Send current device state
- auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
- if (interface_2_5 != nullptr) {
- interface_2_5->notifyDeviceStateChange(mDeviceState);
- }
- }
- }
- }
- return OK;
-}
-
-status_t CameraProviderManager::ProviderInfo::isConcurrentSessionConfigurationSupported(
- const hardware::hidl_vec<CameraIdAndStreamCombination> &halCameraIdsAndStreamCombinations,
- bool *isSupported) {
- status_t res = OK;
- if (mMinorVersion >= 6) {
- // Check if the provider is currently active - not going to start it up for this notification
- auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
- if (interface == nullptr) {
- // TODO: This might be some other problem
- return INVALID_OPERATION;
- }
- auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
- auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
- Status callStatus;
- auto cb =
- [&isSupported, &callStatus](Status s, bool supported) {
- callStatus = s;
- *isSupported = supported; };
-
- ::android::hardware::Return<void> ret;
- sp<provider::V2_7::ICameraProvider> interface_2_7;
- sp<provider::V2_6::ICameraProvider> interface_2_6;
- if (mMinorVersion >= 7 && castResult2_7.isOk()) {
- interface_2_7 = castResult2_7;
- if (interface_2_7 != nullptr) {
- ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
- halCameraIdsAndStreamCombinations, cb);
- }
- } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
- interface_2_6 = castResult2_6;
- if (interface_2_6 != nullptr) {
- hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
- halCameraIdsAndStreamCombinations_2_6;
- size_t numStreams = halCameraIdsAndStreamCombinations.size();
- halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
- for (size_t i = 0; i < numStreams; i++) {
- using namespace camera3;
- auto const& combination = halCameraIdsAndStreamCombinations[i];
- halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
- bool success =
- SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
- combination.streamConfiguration);
- if (!success) {
- *isSupported = false;
- return OK;
- }
- }
- ret = interface_2_6->isConcurrentStreamCombinationSupported(
- halCameraIdsAndStreamCombinations_2_6, cb);
- }
- }
-
- if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
- callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
- return res;
- }
- }
- // unsupported operation
- return INVALID_OPERATION;
-}
-
void CameraProviderManager::ProviderInfo::notifyInitialStatusChange(
sp<StatusListener> listener,
std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus) {
@@ -2217,306 +1665,16 @@
}
}
-template<class DeviceInfoT>
-std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
- CameraProviderManager::ProviderInfo::initializeDeviceInfo(
- const std::string &name, const metadata_vendor_id_t tagId,
- const std::string &id, uint16_t minorVersion) {
- Status status;
-
- auto cameraInterface =
- startDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
- if (cameraInterface == nullptr) return nullptr;
-
- CameraResourceCost resourceCost;
- cameraInterface->getResourceCost([&status, &resourceCost](
- Status s, CameraResourceCost cost) {
- status = s;
- resourceCost = cost;
- });
- if (status != Status::OK) {
- ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
- name.c_str(), statusToString(status));
- return nullptr;
- }
-
- for (auto& conflictName : resourceCost.conflictingDevices) {
- uint16_t major, minor;
- std::string type, id;
- status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
- if (res != OK) {
- ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
- return nullptr;
- }
- conflictName = id;
- }
-
- return std::unique_ptr<DeviceInfo>(
- new DeviceInfoT(name, tagId, id, minorVersion, resourceCost, this,
- mProviderPublicCameraIds, cameraInterface));
-}
-
-template<class InterfaceT>
-sp<InterfaceT>
-CameraProviderManager::ProviderInfo::startDeviceInterface(const std::string &name) {
- ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
- name.c_str(), InterfaceT::version.get_major());
- return nullptr;
-}
-
-template<>
-sp<device::V3_2::ICameraDevice>
-CameraProviderManager::ProviderInfo::startDeviceInterface
- <device::V3_2::ICameraDevice>(const std::string &name) {
- Status status;
- sp<device::V3_2::ICameraDevice> cameraInterface;
- hardware::Return<void> ret;
- const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
- if (interface == nullptr) {
- return nullptr;
- }
- ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
- Status s, sp<device::V3_2::ICameraDevice> interface) {
- status = s;
- cameraInterface = interface;
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
- __FUNCTION__, name.c_str(), ret.description().c_str());
- return nullptr;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
- name.c_str(), statusToString(status));
- return nullptr;
- }
- return cameraInterface;
-}
-
-CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}
-
-template<class InterfaceT>
-sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
- sp<InterfaceT> device;
- ATRACE_CALL();
- if (mSavedInterface == nullptr) {
- sp<ProviderInfo> parentProvider = mParentProvider.promote();
- if (parentProvider != nullptr) {
- device = parentProvider->startDeviceInterface<InterfaceT>(mName);
- }
- } else {
- device = (InterfaceT *) mSavedInterface.get();
- }
- return device;
-}
-
-template<class InterfaceT>
-status_t CameraProviderManager::ProviderInfo::DeviceInfo::setTorchMode(InterfaceT& interface,
- bool enabled) {
- Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
- return mapToStatusT(s);
-}
-
CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& name,
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
- const std::vector<std::string>& publicCameraIds,
- sp<InterfaceT> interface) :
+ const std::vector<std::string>& publicCameraIds) :
DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
- publicCameraIds, resourceCost, parentProvider) {
- // Get camera characteristics and initialize flash unit availability
- Status status;
- hardware::Return<void> ret;
- ret = interface->getCameraCharacteristics([&status, this](Status s,
- device::V3_2::CameraMetadata metadata) {
- status = s;
- if (s == Status::OK) {
- camera_metadata_t *buffer =
- reinterpret_cast<camera_metadata_t*>(metadata.data());
- size_t expectedSize = metadata.size();
- int res = validate_camera_metadata_structure(buffer, &expectedSize);
- if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
- set_camera_metadata_vendor_id(buffer, mProviderTagid);
- mCameraCharacteristics = buffer;
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = Status::INTERNAL_ERROR;
- }
- }
- });
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting camera characteristics for device %s"
- " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
- ret.description().c_str());
- return;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
- __FUNCTION__, id.c_str(), CameraProviderManager::statusToString(status), status);
- return;
- }
+ publicCameraIds, resourceCost, parentProvider) { }
- if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
- const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
- if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
- for (size_t i = 0; i < stateMap.count; i += 2) {
- mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
- }
- } else {
- ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
- stateMap.count);
- }
- }
-
- mSystemCameraKind = getSystemCameraKind();
-
- status_t res = fixupMonochromeTags();
- if (OK != res) {
- ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return;
- }
- auto stat = addDynamicDepthTags();
- if (OK != stat) {
- ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
- stat);
- }
- res = deriveHeicTags();
- if (OK != res) {
- ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
-
- 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)",
- __FUNCTION__, strerror(-status), status);
- }
-
- status = deriveHeicTags(/*maxResolution*/true);
- if (OK != status) {
- ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
- "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
- }
- }
-
- res = addRotateCropTags();
- if (OK != res) {
- ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
- strerror(-res), res);
- }
- res = addPreCorrectionActiveArraySize();
- if (OK != res) {
- ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
- strerror(-res), res);
- }
- res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
- &mCameraCharacteristics, &mSupportNativeZoomRatio);
- if (OK != res) {
- ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
-
- camera_metadata_entry flashAvailable =
- mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
- if (flashAvailable.count == 1 &&
- flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
- mHasFlashUnit = true;
- } else {
- mHasFlashUnit = false;
- }
-
- camera_metadata_entry entry =
- mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
- if (entry.count == 1) {
- mTorchDefaultStrengthLevel = entry.data.i32[0];
- } else {
- mTorchDefaultStrengthLevel = 0;
- }
-
- entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
- if (entry.count == 1) {
- mTorchMaximumStrengthLevel = entry.data.i32[0];
- } else {
- mTorchMaximumStrengthLevel = 0;
- }
-
- mTorchStrengthLevel = 0;
- queryPhysicalCameraIds();
-
- // Get physical camera characteristics if applicable
- auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
- if (!castResult.isOk()) {
- ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
- return;
- }
- sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
- if (interface_3_5 == nullptr) {
- ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
- return;
- }
-
- if (mIsLogicalCamera) {
- for (auto& id : mPhysicalIds) {
- if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
- mPublicCameraIds.end()) {
- continue;
- }
-
- hardware::hidl_string hidlId(id);
- ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
- [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
- status = s;
- if (s == Status::OK) {
- camera_metadata_t *buffer =
- reinterpret_cast<camera_metadata_t*>(metadata.data());
- size_t expectedSize = metadata.size();
- int res = validate_camera_metadata_structure(buffer, &expectedSize);
- if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
- set_camera_metadata_vendor_id(buffer, mProviderTagid);
- mPhysicalCameraCharacteristics[id] = buffer;
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = Status::INTERNAL_ERROR;
- }
- }
- });
-
- if (!ret.isOk()) {
- ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
- __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
- return;
- }
- if (status != Status::OK) {
- ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
- __FUNCTION__, id.c_str(), mId.c_str(),
- CameraProviderManager::statusToString(status), status);
- return;
- }
-
- res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
- &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
- if (OK != res) {
- ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- }
- }
- }
-
- if (!kEnableLazyHal) {
- // Save HAL reference indefinitely
- mSavedInterface = interface;
- }
-}
-
-CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
-
-void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> newState) {
-
+void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(int64_t newState) {
if (!mDeviceStateOrientationMap.empty() &&
(mDeviceStateOrientationMap.find(newState) != mDeviceStateOrientationMap.end())) {
mCameraCharacteristics.update(ANDROID_SENSOR_ORIENTATION,
@@ -2524,84 +1682,6 @@
}
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
- return setTorchModeForDevice<InterfaceT>(enabled);
-}
-
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::turnOnTorchWithStrengthLevel(
- int32_t torchStrength) {
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
- auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
- if (castResult_3_8.isOk()) {
- interface_3_8 = castResult_3_8;
- }
-
- if (interface_3_8 == nullptr) {
- return INVALID_OPERATION;
- }
-
- Status s = interface_3_8->turnOnTorchWithStrengthLevel(torchStrength);
- if (s == Status::OK) {
- mTorchStrengthLevel = torchStrength;
- }
- return mapToStatusT(s);
-}
-
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getTorchStrengthLevel(
- int32_t *torchStrength) {
- if (torchStrength == nullptr) {
- return BAD_VALUE;
- }
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
- if (castResult_3_8.isOk()) {
- interface_3_8 = castResult_3_8;
- }
-
- if (interface_3_8 == nullptr) {
- return INVALID_OPERATION;
- }
-
- Status callStatus;
- status_t res;
- hardware::Return<void> ret = interface_3_8->getTorchStrengthLevel([&callStatus, &torchStrength]
- (Status status, const int32_t& torchStrengthLevel) {
- callStatus = status;
- if (status == Status::OK) {
- *torchStrength = torchStrengthLevel;
- } });
-
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Get torch strength level failed: %d", __FUNCTION__, callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
-
- return res;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
hardware::CameraInfo *info) const {
if (info == nullptr) return BAD_VALUE;
@@ -2657,21 +1737,6 @@
return isBackwardCompatible;
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) {
- native_handle_t* handle = native_handle_create(1,0);
- handle->data[0] = fd;
- const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto ret = interface->dumpState(handle);
- native_handle_delete(handle);
- if (!ret.isOk()) {
- return INVALID_OPERATION;
- }
- return OK;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraCharacteristics(
bool overrideForPerfClass, CameraMetadata *characteristics) const {
if (characteristics == nullptr) return BAD_VALUE;
@@ -2697,63 +1762,6 @@
return OK;
}
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
- bool *status /*out*/) {
-
- const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
- this->startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
- if (interface == nullptr) {
- return DEAD_OBJECT;
- }
- auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
- auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
-
- status_t res;
- Status callStatus;
- ::android::hardware::Return<void> ret;
- auto halCb =
- [&callStatus, &status] (Status s, bool combStatus) {
- callStatus = s;
- *status = combStatus;
- };
- if (interface_3_7 != nullptr) {
- 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 = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- configuration_3_4, configuration);
- if (!success) {
- *status = false;
- return OK;
- }
- ret = interface_3_5->isStreamCombinationSupported(configuration_3_4, halCb);
- } else {
- return INVALID_OPERATION;
- }
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
-
- return res;
-}
-
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::filterSmallJpegSizes() {
int32_t thresholdW = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_W;
int32_t thresholdH = SessionConfigurationUtils::PERF_CLASS_JPEG_THRESH_H;
@@ -3005,8 +2013,6 @@
return OK;
}
-
-
CameraProviderManager::ProviderInfo::~ProviderInfo() {
if (mInitialStatusCallbackFuture.valid()) {
mInitialStatusCallbackFuture.wait();
@@ -3015,167 +2021,6 @@
// CameraProvider interface dies, so do not unregister callbacks.
}
-status_t CameraProviderManager::mapToStatusT(const Status& s) {
- switch(s) {
- case Status::OK:
- return OK;
- case Status::ILLEGAL_ARGUMENT:
- return BAD_VALUE;
- case Status::CAMERA_IN_USE:
- return -EBUSY;
- case Status::MAX_CAMERAS_IN_USE:
- return -EUSERS;
- case Status::METHOD_NOT_SUPPORTED:
- return UNKNOWN_TRANSACTION;
- case Status::OPERATION_NOT_SUPPORTED:
- return INVALID_OPERATION;
- case Status::CAMERA_DISCONNECTED:
- return DEAD_OBJECT;
- case Status::INTERNAL_ERROR:
- return INVALID_OPERATION;
- }
- ALOGW("Unexpected HAL status code %d", s);
- return INVALID_OPERATION;
-}
-
-const char* CameraProviderManager::statusToString(const Status& s) {
- switch(s) {
- case Status::OK:
- return "OK";
- case Status::ILLEGAL_ARGUMENT:
- return "ILLEGAL_ARGUMENT";
- case Status::CAMERA_IN_USE:
- return "CAMERA_IN_USE";
- case Status::MAX_CAMERAS_IN_USE:
- return "MAX_CAMERAS_IN_USE";
- case Status::METHOD_NOT_SUPPORTED:
- return "METHOD_NOT_SUPPORTED";
- case Status::OPERATION_NOT_SUPPORTED:
- return "OPERATION_NOT_SUPPORTED";
- case Status::CAMERA_DISCONNECTED:
- return "CAMERA_DISCONNECTED";
- case Status::INTERNAL_ERROR:
- return "INTERNAL_ERROR";
- }
- ALOGW("Unexpected HAL status code %d", s);
- return "UNKNOWN_ERROR";
-}
-
-const char* CameraProviderManager::deviceStatusToString(const CameraDeviceStatus& s) {
- switch(s) {
- case CameraDeviceStatus::NOT_PRESENT:
- return "NOT_PRESENT";
- case CameraDeviceStatus::PRESENT:
- return "PRESENT";
- case CameraDeviceStatus::ENUMERATING:
- return "ENUMERATING";
- }
- ALOGW("Unexpected HAL device status code %d", s);
- return "UNKNOWN_STATUS";
-}
-
-const char* CameraProviderManager::torchStatusToString(const TorchModeStatus& s) {
- switch(s) {
- case TorchModeStatus::NOT_AVAILABLE:
- return "NOT_AVAILABLE";
- case TorchModeStatus::AVAILABLE_OFF:
- return "AVAILABLE_OFF";
- case TorchModeStatus::AVAILABLE_ON:
- return "AVAILABLE_ON";
- }
- ALOGW("Unexpected HAL torch mode status code %d", s);
- return "UNKNOWN_STATUS";
-}
-
-
-status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
- const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
- /*out*/
- sp<VendorTagDescriptor>& descriptor) {
-
- int tagCount = 0;
-
- for (size_t s = 0; s < vts.size(); s++) {
- tagCount += vts[s].tags.size();
- }
-
- if (tagCount < 0 || tagCount > INT32_MAX) {
- ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
- return BAD_VALUE;
- }
-
- Vector<uint32_t> tagArray;
- LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
- "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
-
-
- sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
- desc->mTagCount = tagCount;
-
- SortedVector<String8> sections;
- KeyedVector<uint32_t, String8> tagToSectionMap;
-
- int idx = 0;
- for (size_t s = 0; s < vts.size(); s++) {
- const common::V1_0::VendorTagSection& section = vts[s];
- const char *sectionName = section.sectionName.c_str();
- if (sectionName == NULL) {
- ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
- return BAD_VALUE;
- }
- String8 sectionString(sectionName);
- sections.add(sectionString);
-
- for (size_t j = 0; j < section.tags.size(); j++) {
- uint32_t tag = section.tags[j].tagId;
- if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
- ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
- return BAD_VALUE;
- }
-
- tagArray.editItemAt(idx++) = section.tags[j].tagId;
-
- const char *tagName = section.tags[j].tagName.c_str();
- if (tagName == NULL) {
- ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
- return BAD_VALUE;
- }
- desc->mTagToNameMap.add(tag, String8(tagName));
- tagToSectionMap.add(tag, sectionString);
-
- int tagType = (int) section.tags[j].tagType;
- if (tagType < 0 || tagType >= NUM_TYPES) {
- ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
- return BAD_VALUE;
- }
- desc->mTagToTypeMap.add(tag, tagType);
- }
- }
-
- desc->mSections = sections;
-
- for (size_t i = 0; i < tagArray.size(); ++i) {
- uint32_t tag = tagArray[i];
- String8 sectionString = tagToSectionMap.valueFor(tag);
-
- // Set up tag to section index map
- ssize_t index = sections.indexOf(sectionString);
- LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
- desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
-
- // Set up reverse mapping
- ssize_t reverseIndex = -1;
- if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
- KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
- reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
- }
- desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
- }
-
- descriptor = std::move(desc);
- return OK;
-}
-
// Expects to have mInterfaceMutex locked
std::vector<std::unordered_set<std::string>>
CameraProviderManager::getConcurrentCameraIds() const {
@@ -3189,59 +2034,6 @@
return deviceIdCombinations;
}
-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();
- std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
- 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;
- bool overrideForPerfClass =
- SessionConfigurationUtils::targetPerfClassPrimaryCamera(
- perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
- res = getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
- if (res != OK) {
- return res;
- }
- camera3::metadataGetter getMetadata =
- [this](const String8 &id, bool overrideForPerfClass) {
- CameraMetadata physicalDeviceInfo;
- getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
- &physicalDeviceInfo);
- return physicalDeviceInfo;
- };
- std::vector<std::string> physicalCameraIds;
- isLogicalCameraLocked(cameraId, &physicalCameraIds);
- bStatus =
- SessionConfigurationUtils::convertToHALStreamCombination(
- cameraIdAndSessionConfig.mSessionConfiguration,
- String8(cameraId.c_str()), deviceInfo, getMetadata,
- physicalCameraIds, streamConfiguration,
- overrideForPerfClass, &shouldExit);
- if (!bStatus.isOk()) {
- ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
- return INVALID_OPERATION;
- }
- if (shouldExit) {
- *earlyExit = true;
- return OK;
- }
- CameraIdAndStreamCombination halCameraIdAndStream;
- halCameraIdAndStream.cameraId = cameraId;
- halCameraIdAndStream.streamConfiguration = streamConfiguration;
- halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
- }
- *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
- return OK;
-}
-
// Checks if the containing vector of sets has any set that contains all of the
// camera ids in cameraIdsAndSessionConfigs.
static bool checkIfSetContainsAll(
@@ -3276,27 +2068,9 @@
for (auto &provider : mProviders) {
if (checkIfSetContainsAll(cameraIdsAndSessionConfigs,
provider->getConcurrentCameraIdCombinations())) {
- // For each camera device in cameraIdsAndSessionConfigs collect
- // the streamConfigs and create the HAL
- // CameraIdAndStreamCombination, exit early if needed
- hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
- bool knowUnsupported = false;
- status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
- cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
- targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
- if (res != OK) {
- ALOGE("%s unable to convert session configurations provided to HAL stream"
- "combinations", __FUNCTION__);
- return res;
- }
- if (knowUnsupported) {
- // We got to know the streams aren't valid before doing the HAL
- // call itself.
- *isSupported = false;
- return OK;
- }
return provider->isConcurrentSessionConfigurationSupported(
- halCameraIdsAndStreamCombinations, isSupported);
+ cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds, targetSdkVersion,
+ isSupported);
}
}
*isSupported = false;
@@ -3306,7 +2080,7 @@
status_t CameraProviderManager::getCameraCharacteristicsLocked(const std::string &id,
bool overrideForPerfClass, CameraMetadata* characteristics) const {
- auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3,0}, /*maxVersion*/ {5,0});
+ auto deviceInfo = findDeviceInfoLocked(id, /*minVersion*/ {3, 0}, /*maxVersion*/ {5, 0});
if (deviceInfo != nullptr) {
return deviceInfo->getCameraCharacteristics(overrideForPerfClass, characteristics);
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index b03ca62..64f5abf 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -29,34 +29,40 @@
#include <camera/CameraParameters2.h>
#include <camera/CameraMetadata.h>
#include <camera/CameraBase.h>
+#include <utils/Condition.h>
#include <utils/Errors.h>
+#include <android/hardware/ICameraService.h>
+#include <utils/IPCTransport.h>
#include <android/hardware/camera/common/1.0/types.h>
#include <android/hardware/camera/provider/2.5/ICameraProvider.h>
#include <android/hardware/camera/provider/2.6/ICameraProviderCallback.h>
#include <android/hardware/camera/provider/2.6/ICameraProvider.h>
#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
#include <android/hardware/camera/device/3.7/types.h>
+#include <android/hardware/camera/device/3.8/types.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
+#include <binder/IServiceManager.h>
#include <camera/VendorTagDescriptor.h>
namespace android {
-/**
- * The vendor tag descriptor class that takes HIDL vendor tag information as
- * input. Not part of VendorTagDescriptor class because that class is used
- * in AIDL generated sources which don't have access to HIDL headers.
- */
-class HidlVendorTagDescriptor : public VendorTagDescriptor {
-public:
- /**
- * Create a VendorTagDescriptor object from the HIDL VendorTagSection
- * vector.
- *
- * Returns OK on success, or a negative error code.
- */
- static status_t createDescriptorFromHidl(
- const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
- /*out*/
- sp<VendorTagDescriptor>& descriptor);
+
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+
+enum class CameraDeviceStatus : uint32_t {
+ NOT_PRESENT = 0,
+ PRESENT = 1,
+ ENUMERATING = 2
+};
+
+enum class TorchModeStatus : uint32_t {
+ NOT_AVAILABLE = 0,
+ AVAILABLE_OFF = 1,
+ AVAILABLE_ON = 2
+};
+
+struct CameraResourceCost {
+ uint32_t resourceCost;
+ std::vector<std::string> conflictingDevices;
};
enum SystemCameraKind {
@@ -102,12 +108,14 @@
*/
class CameraProviderManager : virtual public hidl::manager::V1_0::IServiceNotification {
public:
-
+ // needs to be made friend strict since HidlProviderInfo needs to inherit
+ // from CameraProviderManager::ProviderInfo which isn't a public member.
+ friend struct HidlProviderInfo;
~CameraProviderManager();
// Tiny proxy for the static methods in a HIDL interface that communicate with the hardware
// service manager, to be replacable in unit tests with a fake.
- struct ServiceInteractionProxy {
+ struct HidlServiceInteractionProxy {
virtual bool registerForNotifications(
const std::string &serviceName,
const sp<hidl::manager::V1_0::IServiceNotification>
@@ -119,12 +127,12 @@
virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
const std::string &serviceName) = 0;
virtual hardware::hidl_vec<hardware::hidl_string> listServices() = 0;
- virtual ~ServiceInteractionProxy() {}
+ virtual ~HidlServiceInteractionProxy() {}
};
// Standard use case - call into the normal generated static methods which invoke
// the real hardware service manager
- struct HardwareServiceInteractionProxy : public ServiceInteractionProxy {
+ struct HidlServiceInteractionProxyImpl : public HidlServiceInteractionProxy {
virtual bool registerForNotifications(
const std::string &serviceName,
const sp<hidl::manager::V1_0::IServiceNotification>
@@ -151,15 +159,15 @@
~StatusListener() {}
virtual void onDeviceStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ CameraDeviceStatus newStatus) = 0;
virtual void onDeviceStatusChanged(const String8 &cameraId,
const String8 &physicalCameraId,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) = 0;
+ CameraDeviceStatus newStatus) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus,
+ TorchModeStatus newStatus,
SystemCameraKind kind) = 0;
virtual void onTorchStatusChanged(const String8 &cameraId,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) = 0;
+ TorchModeStatus newStatus) = 0;
virtual void onNewProviderRegistered() = 0;
};
@@ -179,7 +187,10 @@
* used for testing. The lifetime of the proxy must exceed the lifetime of the manager.
*/
status_t initialize(wp<StatusListener> listener,
- ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
+ HidlServiceInteractionProxy *hidlProxy = &sHidlServiceInteractionProxy);
+
+ status_t getCameraIdIPCTransport(const std::string &id,
+ IPCTransport *providerTransport) const;
/**
* Retrieve the total number of available cameras.
@@ -217,7 +228,7 @@
* Return the resource cost of this camera device
*/
status_t getResourceCost(const std::string &id,
- hardware::camera::common::V1_0::CameraResourceCost* cost) const;
+ CameraResourceCost* cost) const;
/**
* Return the old camera API camera info
@@ -243,7 +254,8 @@
* Check for device support of specific stream combination.
*/
status_t isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const SessionConfiguration &configuration,
+ bool overrideForPerfClass,
bool *status /*out*/) const;
/**
@@ -301,8 +313,7 @@
/**
* Inform registered providers about a device state change, such as folding or unfolding
*/
- status_t notifyDeviceStateChange(
- android::hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> newState);
+ status_t notifyDeviceStateChange(int64_t newState);
/**
* Open an active session to a camera device.
@@ -310,7 +321,7 @@
* This fully powers on the camera device hardware, and returns a handle to a
* session to be used for hardware configuration and operation.
*/
- status_t openSession(const std::string &id,
+ status_t openHidlSession(const std::string &id,
const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
/*out*/
sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session);
@@ -357,41 +368,56 @@
status_t filterSmallJpegSizes(const std::string& cameraId);
+ status_t notifyUsbDeviceEvent(int32_t eventId, const std::string &usbDeviceId);
+
static const float kDepthARTolerance;
private:
// All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
mutable std::mutex mInterfaceMutex;
wp<StatusListener> mListener;
- ServiceInteractionProxy* mServiceProxy;
+ HidlServiceInteractionProxy* mHidlServiceProxy;
// Current overall Android device physical status
- android::hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
+ int64_t mDeviceState;
// mProviderLifecycleLock is locked during onRegistration and removeProvider
mutable std::mutex mProviderLifecycleLock;
- static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;
+ static HidlServiceInteractionProxyImpl sHidlServiceInteractionProxy;
+
+ struct HalCameraProvider {
+ // Empty parent struct for storing either aidl / hidl camera provider reference
+ HalCameraProvider(const char *descriptor) : mDescriptor(descriptor) { };
+ virtual ~HalCameraProvider() {};
+ std::string mDescriptor;
+ };
+
+ struct HidlHalCameraProvider : public HalCameraProvider {
+ HidlHalCameraProvider(
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> &provider,
+ const char *descriptor) :
+ HalCameraProvider(descriptor), mCameraProvider(provider) { };
+ private:
+ sp<hardware::camera::provider::V2_4::ICameraProvider> mCameraProvider;
+ };
// Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
// ICameraProvider alive while it is in use by the camera with the given ID for camera
// capabilities
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>>
mCameraProviderByCameraId;
// Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
// ICameraProvider alive while it is in use by the camera with the given ID for torch
// capabilities
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+ std::unordered_map<std::string, std::shared_ptr<HalCameraProvider>>
mTorchProviderByCameraId;
// Lock for accessing mCameraProviderByCameraId and mTorchProviderByCameraId
std::mutex mProviderInterfaceMapLock;
-
- struct ProviderInfo :
- virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
- virtual public hardware::hidl_death_recipient
- {
+ struct ProviderInfo : public virtual RefBase {
+ friend struct HidlProviderInfo;
const std::string mProviderName;
const std::string mProviderInstance;
const metadata_vendor_id_t mProviderTagid;
@@ -400,61 +426,20 @@
bool mSetTorchModeSupported;
bool mIsRemote;
- // Current overall Android device physical status
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
-
- // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
- wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
-
- sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
-
ProviderInfo(const std::string &providerName, const std::string &providerInstance,
CameraProviderManager *manager);
~ProviderInfo();
- status_t initialize(sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- currentDeviceState);
-
- const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
+ virtual IPCTransport getIPCTransport() = 0;
const std::string& getType() const;
- status_t addDevice(const std::string& name,
- hardware::camera::common::V1_0::CameraDeviceStatus initialStatus =
- hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT,
- /*out*/ std::string *parsedId = nullptr);
-
status_t dump(int fd, const Vector<String16>& args) const;
- // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
- hardware::Return<void> cameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
- hardware::Return<void> torchModeStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::TorchModeStatus newStatus) override;
- hardware::Return<void> physicalCameraDeviceStatusChange(
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus) override;
-
- status_t cameraDeviceStatusChangeLocked(
- std::string* id, const hardware::hidl_string& cameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
- status_t physicalCameraDeviceStatusChangeLocked(
- std::string* id, std::string* physicalId,
- const hardware::hidl_string& cameraDeviceName,
- const hardware::hidl_string& physicalCameraDeviceName,
- hardware::camera::common::V1_0::CameraDeviceStatus newStatus);
-
- // hidl_death_recipient interface - this locks the parent mInterfaceMutex
- virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
-
/**
* Setup vendor tags for this provider
*/
- status_t setUpVendorTags();
+ virtual status_t setUpVendorTags() = 0;
/**
* Notify provider about top-level device physical state changes
@@ -463,9 +448,9 @@
* It is possible for camera providers to add/remove devices and try to
* acquire it.
*/
- status_t notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newDeviceState);
+ virtual status_t notifyDeviceStateChange(int64_t newDeviceState) = 0;
+
+ virtual bool successfullyStartedProviderInterface() = 0;
std::vector<std::unordered_set<std::string>> getConcurrentCameraIdCombinations();
@@ -474,34 +459,44 @@
*
* Note that 'mInterfaceMutex' should be held when calling this method.
*/
- void notifyDeviceInfoStateChangeLocked(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newDeviceState);
+ void notifyDeviceInfoStateChangeLocked(int64_t newDeviceState);
/**
* Query the camera provider for concurrent stream configuration support
*/
- status_t isConcurrentSessionConfigurationSupported(
- const hardware::hidl_vec<
- hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
- &halCameraIdsAndStreamCombinations,
- bool *isSupported);
+ virtual status_t isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) = 0;
+
+
+ /**
+ * Remove all devices associated with this provider and notify listeners
+ * with NOT_PRESENT state.
+ */
+ void removeAllDevices();
+
+ /**
+ * Provider is an external lazy HAL
+ */
+ bool isExternalLazyHAL() const;
// Basic device information, common to all camera devices
struct DeviceInfo {
const std::string mName; // Full instance name
const std::string mId; // ID section of full name
+ //Both hidl and aidl DeviceInfos. Aidl deviceInfos get {3, 8} to
+ //start off.
const hardware::hidl_version mVersion;
const metadata_vendor_id_t mProviderTagid;
bool mIsLogicalCamera;
std::vector<std::string> mPhysicalIds;
hardware::CameraInfo mInfo;
- sp<IBase> mSavedInterface;
SystemCameraKind mSystemCameraKind = SystemCameraKind::PUBLIC;
- const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
+ const CameraResourceCost mResourceCost;
- hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
+ CameraDeviceStatus mStatus;
wp<ProviderInfo> mParentProvider;
// Torch strength default, maximum levels if the torch strength control
@@ -510,6 +505,12 @@
int32_t mTorchMaximumStrengthLevel;
int32_t mTorchDefaultStrengthLevel;
+ // Wait for lazy HALs to confirm device availability
+ static const nsecs_t kDeviceAvailableTimeout = 2000e6; // 2000 ms
+ Mutex mDeviceAvailableLock;
+ Condition mDeviceAvailableSignal;
+ bool mIsDeviceAvailable = true;
+
bool hasFlashUnit() const { return mHasFlashUnit; }
bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
virtual status_t setTorchMode(bool enabled) = 0;
@@ -532,46 +533,32 @@
}
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &/*configuration*/,
+ const SessionConfiguration &/*configuration*/,
+ bool /*overrideForPerfClass*/,
bool * /*status*/) {
return INVALID_OPERATION;
}
virtual status_t filterSmallJpegSizes() = 0;
- virtual void notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- /*newState*/) {}
-
- template<class InterfaceT>
- sp<InterfaceT> startDeviceInterface();
+ virtual void notifyDeviceStateChange(int64_t /*newState*/) {}
DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, const hardware::hidl_version& version,
const std::vector<std::string>& publicCameraIds,
- const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider) :
mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
mIsLogicalCamera(false), mResourceCost(resourceCost),
- mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
+ mStatus(CameraDeviceStatus::PRESENT),
mParentProvider(parentProvider), mTorchStrengthLevel(0),
mTorchMaximumStrengthLevel(0), mTorchDefaultStrengthLevel(0),
mHasFlashUnit(false), mSupportNativeZoomRatio(false),
mPublicCameraIds(publicCameraIds) {}
- virtual ~DeviceInfo();
+ virtual ~DeviceInfo() {}
protected:
+
bool mHasFlashUnit; // const after constructor
bool mSupportNativeZoomRatio; // const after constructor
const std::vector<std::string>& mPublicCameraIds;
-
- template<class InterfaceT>
- static status_t setTorchMode(InterfaceT& interface, bool enabled);
-
- template<class InterfaceT>
- status_t setTorchModeForDevice(bool enabled) {
- // Don't save the ICameraProvider interface here because we assume that this was
- // called from CameraProviderManager::setTorchMode(), which does save it.
- const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
- return DeviceInfo::setTorchMode(interface, enabled);
- }
};
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::unordered_set<std::string> mUniqueCameraIds;
@@ -586,36 +573,33 @@
// HALv3-specific camera fields, including the actual device interface
struct DeviceInfo3 : public DeviceInfo {
- typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
- virtual status_t setTorchMode(bool enabled) override;
- virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
- virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
-
+ virtual status_t setTorchMode(bool enabled) = 0;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) = 0;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) = 0;
virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
virtual bool isAPI1Compatible() const override;
- virtual status_t dumpState(int fd) override;
+ virtual status_t dumpState(int fd) = 0;
virtual status_t getCameraCharacteristics(
bool overrideForPerfClass,
CameraMetadata *characteristics) const override;
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
- bool *status /*out*/)
- override;
+ const SessionConfiguration &configuration, bool /*overrideForPerfClass*/,
+ bool *status /*out*/) = 0;
virtual status_t filterSmallJpegSizes() override;
virtual void notifyDeviceStateChange(
- hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState>
- newState) override;
+ int64_t newState) override;
DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
const std::string &id, uint16_t minorVersion,
- const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+ const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
- const std::vector<std::string>& publicCameraIds, sp<InterfaceT> interface);
- virtual ~DeviceInfo3();
- private:
+ const std::vector<std::string>& publicCameraIds);
+ virtual ~DeviceInfo3() {};
+ protected:
+ // Modified by derived transport specific (hidl / aidl) class
CameraMetadata mCameraCharacteristics;
// Map device states to sensor orientations
std::unordered_map<int64_t, int32_t> mDeviceStateOrientationMap;
@@ -655,8 +639,7 @@
const camera_metadata_entry& halStreamConfigs,
const camera_metadata_entry& halStreamDurations);
};
-
- private:
+ protected:
std::string mType;
uint32_t mId;
@@ -666,12 +649,12 @@
struct CameraStatusInfoT {
bool isPhysicalCameraStatus = false;
- hardware::hidl_string cameraId;
- hardware::hidl_string physicalCameraId;
- hardware::camera::common::V1_0::CameraDeviceStatus status;
- CameraStatusInfoT(bool isForPhysicalCamera, const hardware::hidl_string& id,
- const hardware::hidl_string& physicalId,
- hardware::camera::common::V1_0::CameraDeviceStatus s) :
+ std::string cameraId;
+ std::string physicalCameraId;
+ CameraDeviceStatus status;
+ CameraStatusInfoT(bool isForPhysicalCamera, const std::string& id,
+ const std::string& physicalId,
+ CameraDeviceStatus s) :
isPhysicalCameraStatus(isForPhysicalCamera), cameraId(id),
physicalCameraId(physicalId), status(s) {}
};
@@ -688,17 +671,6 @@
std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
- // Templated method to instantiate the right kind of DeviceInfo and call the
- // right CameraProvider getCameraDeviceInterface_* method.
- template<class DeviceInfoT>
- std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
- const metadata_vendor_id_t tagId, const std::string &id,
- uint16_t minorVersion);
-
- // Helper for initializeDeviceInfo to use the right CameraProvider get method.
- template<class InterfaceT>
- sp<InterfaceT> startDeviceInterface(const std::string &name);
-
// Parse provider instance name for type and id
static status_t parseProviderName(const std::string& name,
std::string *type, uint32_t *id);
@@ -712,18 +684,13 @@
void removeDevice(std::string id);
- // Expects to have mLock locked
- status_t reCacheConcurrentStreamingCameraIdsLocked();
- // Expects to have mLock locked
- status_t getConcurrentCameraIdsInternalLocked(
- sp<hardware::camera::provider::V2_6::ICameraProvider> &interface2_6);
};
/**
* Save the ICameraProvider while it is being used by a camera or torch client
*/
void saveRef(DeviceMode usageType, const std::string &cameraId,
- sp<hardware::camera::provider::V2_4::ICameraProvider> provider);
+ std::shared_ptr<HalCameraProvider> provider);
// Utility to find a DeviceInfo by ID; pointer is only valid while mInterfaceMutex is held
// and the calling code doesn't mutate the list of providers or their lists of devices.
@@ -734,9 +701,15 @@
hardware::hidl_version minVersion = hardware::hidl_version{0,0},
hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
- status_t addProviderLocked(const std::string& newProvider, bool preexisting = false);
+ // Map external providers to USB devices in order to handle USB hotplug
+ // events for lazy HALs
+ std::pair<std::vector<std::string>, sp<ProviderInfo>>
+ mExternalUsbDevicesForProvider;
+ sp<ProviderInfo> startExternalLazyProvider() const;
- status_t tryToInitializeProviderLocked(const std::string& providerName,
+ status_t addHidlProviderLocked(const std::string& newProvider, bool preexisting = false);
+
+ status_t tryToInitializeHidlProviderLocked(const std::string& providerName,
const sp<ProviderInfo>& providerInfo);
bool isLogicalCameraLocked(const std::string& id, std::vector<std::string>* physicalCameraIds);
@@ -749,14 +722,6 @@
size_t mProviderInstanceId = 0;
std::vector<sp<ProviderInfo>> mProviders;
- void addProviderToMap(
- const std::string &cameraId,
- sp<hardware::camera::provider::V2_4::ICameraProvider> provider,
- bool isTorchUsage);
- void removeCameraIdFromMap(
- std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>> &map,
- const std::string &cameraId);
-
static const char* deviceStatusToString(
const hardware::camera::common::V1_0::CameraDeviceStatus&);
static const char* torchStatusToString(
@@ -767,20 +732,14 @@
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
status_t getSystemCameraKindLocked(const std::string& id, SystemCameraKind *kind) const;
- std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(const std::string& cameraId) const;
+ std::pair<bool, ProviderInfo::DeviceInfo *> isHiddenPhysicalCameraInternal(
+ const std::string& cameraId) const;
void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& normalDeviceIds,
std::vector<std::string>& systemCameraDeviceIds) const;
- 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);
+ status_t usbDeviceDetached(const std::string &usbDeviceId);
};
} // namespace android
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
new file mode 100644
index 0000000..e8432a6
--- /dev/null
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -0,0 +1,1564 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "HidlProviderInfo.h"
+
+#include <cutils/properties.h>
+
+#include <android/hardware/ICameraService.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/ZoomRatioMapper.h"
+#include <utils/SessionConfigurationUtils.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera/device/3.7/ICameraDevice.h>
+#include <android/hardware/camera/device/3.8/ICameraDevice.h>
+
+namespace {
+const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+} // anonymous namespace
+
+namespace android {
+
+using namespace android::camera3;
+using namespace hardware::camera;
+using hardware::camera::common::V1_0::VendorTagSection;
+using hardware::camera::common::V1_0::Status;
+using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
+using hardware::camera2::utils::CameraIdAndSessionConfiguration;
+
+
+using StatusListener = CameraProviderManager::StatusListener;
+
+using hardware::camera::provider::V2_5::DeviceState;
+using hardware::ICameraService;
+
+status_t HidlProviderInfo::mapToStatusT(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return OK;
+ case Status::ILLEGAL_ARGUMENT:
+ return BAD_VALUE;
+ case Status::CAMERA_IN_USE:
+ return -EBUSY;
+ case Status::MAX_CAMERAS_IN_USE:
+ return -EUSERS;
+ case Status::METHOD_NOT_SUPPORTED:
+ return UNKNOWN_TRANSACTION;
+ case Status::OPERATION_NOT_SUPPORTED:
+ return INVALID_OPERATION;
+ case Status::CAMERA_DISCONNECTED:
+ return DEAD_OBJECT;
+ case Status::INTERNAL_ERROR:
+ return INVALID_OPERATION;
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return INVALID_OPERATION;
+}
+
+static hardware::hidl_bitfield<DeviceState> mapToHidlDeviceState(int64_t newState) {
+ hardware::hidl_bitfield<DeviceState> newDeviceState{};
+ if (newState & ICameraService::DEVICE_STATE_BACK_COVERED) {
+ newDeviceState |= DeviceState::BACK_COVERED;
+ }
+ if (newState & ICameraService::DEVICE_STATE_FRONT_COVERED) {
+ newDeviceState |= DeviceState::FRONT_COVERED;
+ }
+ if (newState & ICameraService::DEVICE_STATE_FOLDED) {
+ newDeviceState |= DeviceState::FOLDED;
+ }
+ // Only map vendor bits directly
+ uint64_t vendorBits = static_cast<uint64_t>(newState) & 0xFFFFFFFF00000000l;
+ newDeviceState |= vendorBits;
+
+ ALOGV("%s: New device state 0x%" PRIx64, __FUNCTION__, newDeviceState);
+ return newDeviceState;
+}
+
+const char* statusToString(const Status& s) {
+ switch(s) {
+ case Status::OK:
+ return "OK";
+ case Status::ILLEGAL_ARGUMENT:
+ return "ILLEGAL_ARGUMENT";
+ case Status::CAMERA_IN_USE:
+ return "CAMERA_IN_USE";
+ case Status::MAX_CAMERAS_IN_USE:
+ return "MAX_CAMERAS_IN_USE";
+ case Status::METHOD_NOT_SUPPORTED:
+ return "METHOD_NOT_SUPPORTED";
+ case Status::OPERATION_NOT_SUPPORTED:
+ return "OPERATION_NOT_SUPPORTED";
+ case Status::CAMERA_DISCONNECTED:
+ return "CAMERA_DISCONNECTED";
+ case Status::INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ }
+ ALOGW("Unexpected HAL status code %d", s);
+ return "UNKNOWN_ERROR";
+}
+
+static common::V1_0::CameraDeviceStatus mapToHidlCameraDeviceStatus(const CameraDeviceStatus& s) {
+ switch(s) {
+ case CameraDeviceStatus::PRESENT:
+ return common::V1_0::CameraDeviceStatus::PRESENT;
+ case CameraDeviceStatus::NOT_PRESENT:
+ return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
+ case CameraDeviceStatus::ENUMERATING:
+ return common::V1_0::CameraDeviceStatus::ENUMERATING;
+ }
+ ALOGW("Unexpectedcamera device status code %d", s);
+ return common::V1_0::CameraDeviceStatus::NOT_PRESENT;
+}
+
+static CameraDeviceStatus hidlToInternalCameraDeviceStatus(
+ const common::V1_0::CameraDeviceStatus& s) {
+ switch(s) {
+ case common::V1_0::CameraDeviceStatus::PRESENT:
+ return CameraDeviceStatus::PRESENT;
+ case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
+ return CameraDeviceStatus::NOT_PRESENT;
+ case common::V1_0::CameraDeviceStatus::ENUMERATING:
+ return CameraDeviceStatus::ENUMERATING;
+ }
+ ALOGW("Unexpectedcamera device status code %d", s);
+ return CameraDeviceStatus::NOT_PRESENT;
+}
+
+static TorchModeStatus hidlToInternalTorchModeStatus(
+ const common::V1_0::TorchModeStatus& s) {
+ switch(s) {
+ case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
+ return TorchModeStatus::NOT_AVAILABLE;
+ case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
+ return TorchModeStatus::AVAILABLE_OFF;
+ case common::V1_0::TorchModeStatus::AVAILABLE_ON:
+ return TorchModeStatus::AVAILABLE_ON;
+ }
+ ALOGW("Unexpectedcamera torch mode status code %d", s);
+ return TorchModeStatus::NOT_AVAILABLE;
+}
+
+static CameraResourceCost hidlToInternalResourceCost(
+ const common::V1_0::CameraResourceCost& s) {
+ CameraResourceCost internalResourceCost;
+ internalResourceCost.resourceCost = s.resourceCost;
+ for (const auto device : s.conflictingDevices) {
+ internalResourceCost.conflictingDevices.emplace_back(device.c_str());
+ }
+ return internalResourceCost;
+}
+
+static const char* deviceStatusToString(const common::V1_0::CameraDeviceStatus& s) {
+ switch(s) {
+ case common::V1_0::CameraDeviceStatus::NOT_PRESENT:
+ return "NOT_PRESENT";
+ case common::V1_0::CameraDeviceStatus::PRESENT:
+ return "PRESENT";
+ case common::V1_0::CameraDeviceStatus::ENUMERATING:
+ return "ENUMERATING";
+ }
+ ALOGW("Unexpected HAL device status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+static const char* torchStatusToString(const common::V1_0::TorchModeStatus& s) {
+ switch(s) {
+ case common::V1_0::TorchModeStatus::NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case common::V1_0::TorchModeStatus::AVAILABLE_OFF:
+ return "AVAILABLE_OFF";
+ case common::V1_0::TorchModeStatus::AVAILABLE_ON:
+ return "AVAILABLE_ON";
+ }
+ ALOGW("Unexpected HAL torch mode status code %d", s);
+ return "UNKNOWN_STATUS";
+}
+
+status_t HidlProviderInfo::initializeHidlProvider(
+ sp<provider::V2_4::ICameraProvider>& interface,
+ int64_t currentDeviceState) {
+ status_t res = parseProviderName(mProviderName, &mType, &mId);
+ if (res != OK) {
+ ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ ALOGI("Connecting to new camera provider: %s, isRemote? %d",
+ mProviderName.c_str(), interface->isRemote());
+
+ // Determine minor version
+ mMinorVersion = 4;
+ auto cast2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ sp<provider::V2_6::ICameraProvider> interface2_6 = nullptr;
+ if (cast2_6.isOk()) {
+ interface2_6 = cast2_6;
+ if (interface2_6 != nullptr) {
+ mMinorVersion = 6;
+ }
+ }
+ // We need to check again since cast2_6.isOk() succeeds even if the provider
+ // version isn't actually 2.6.
+ if (interface2_6 == nullptr){
+ auto cast2_5 =
+ provider::V2_5::ICameraProvider::castFrom(interface);
+ sp<provider::V2_5::ICameraProvider> interface2_5 = nullptr;
+ if (cast2_5.isOk()) {
+ interface2_5 = cast2_5;
+ if (interface != nullptr) {
+ mMinorVersion = 5;
+ }
+ }
+ } else {
+ auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ if (cast2_7.isOk()) {
+ sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
+ if (interface2_7 != nullptr) {
+ mMinorVersion = 7;
+ }
+ }
+ }
+
+ // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
+ // before setCallback returns
+ hardware::Return<Status> status = interface->setCallback(this);
+ if (!status.isOk()) {
+ ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), status.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to register callbacks with camera provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
+ hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
+ if (!linked.isOk()) {
+ ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
+ __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+ return DEAD_OBJECT;
+ } else if (!linked) {
+ ALOGW("%s: Unable to link to provider '%s' death notifications",
+ __FUNCTION__, mProviderName.c_str());
+ }
+
+ if (!kEnableLazyHal) {
+ // Save HAL reference indefinitely
+ mSavedInterface = interface;
+ } else {
+ mActiveInterface = interface;
+ }
+
+ ALOGV("%s: Setting device state for %s: 0x%" PRIx64,
+ __FUNCTION__, mProviderName.c_str(), mDeviceState);
+ notifyDeviceStateChange(currentDeviceState);
+
+ res = setUpVendorTags();
+ if (res != OK) {
+ ALOGE("%s: Unable to set up vendor tags from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return res;
+ }
+
+ // Get initial list of camera devices, if any
+ std::vector<std::string> devices;
+ hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
+ Status idStatus,
+ const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
+ status = idStatus;
+ if (status == Status::OK) {
+ for (auto& name : cameraDeviceNames) {
+ uint16_t major, minor;
+ std::string type, id;
+ status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+ if (res != OK) {
+ ALOGE("%s: Error parsing deviceName: %s: %d", __FUNCTION__, name.c_str(), res);
+ status = Status::INTERNAL_ERROR;
+ } else {
+ devices.push_back(name);
+ mProviderPublicCameraIds.push_back(id);
+ }
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting camera ID list from provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+
+ // Get list of concurrent streaming camera device combinations
+ if (mMinorVersion >= 6) {
+ res = getConcurrentCameraIdsInternalLocked(interface2_6);
+ if (res != OK) {
+ return res;
+ }
+ }
+
+ ret = interface->isSetTorchModeSupported(
+ [this](auto status, bool supported) {
+ if (status == Status::OK) {
+ mSetTorchModeSupported = supported;
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error checking torch mode support '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ mIsRemote = interface->isRemote();
+
+ sp<StatusListener> listener = mManager->getStatusListener();
+ for (auto& device : devices) {
+ std::string id;
+ status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
+ if (res != OK) {
+ ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
+ __FUNCTION__, device.c_str(), strerror(-res), res);
+ continue;
+ }
+ }
+
+ ALOGI("Camera provider %s ready with %zu camera devices",
+ mProviderName.c_str(), mDevices.size());
+
+ // Process cached status callbacks
+ std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
+ std::make_unique<std::vector<CameraStatusInfoT>>();
+ {
+ std::lock_guard<std::mutex> lock(mInitLock);
+
+ for (auto& statusInfo : mCachedStatus) {
+ std::string id, physicalId;
+ status_t res = OK;
+ if (statusInfo.isPhysicalCameraStatus) {
+ res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+ statusInfo.cameraId, statusInfo.physicalCameraId,
+ mapToHidlCameraDeviceStatus(statusInfo.status));
+ } else {
+ res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId,
+ mapToHidlCameraDeviceStatus(statusInfo.status));
+ }
+ if (res == OK) {
+ cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
+ id.c_str(), physicalId.c_str(), statusInfo.status);
+ }
+ }
+ mCachedStatus.clear();
+
+ mInitialized = true;
+ }
+
+ // The cached status change callbacks cannot be fired directly from this
+ // function, due to same-thread deadlock trying to acquire mInterfaceMutex
+ // twice.
+ if (listener != nullptr) {
+ mInitialStatusCallbackFuture = std::async(std::launch::async,
+ &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
+ listener, std::move(cachedStatus));
+ }
+
+ return OK;
+}
+
+status_t HidlProviderInfo::setUpVendorTags() {
+ if (mVendorTagDescriptor != nullptr)
+ return OK;
+
+ hardware::hidl_vec<VendorTagSection> vts;
+ Status status;
+ hardware::Return<void> ret;
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> interface =
+ startProviderInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ ret = interface->getVendorTags(
+ [&](auto s, const auto& vendorTagSecs) {
+ status = s;
+ if (s == Status::OK) {
+ vts = vendorTagSecs;
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
+ __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ return mapToStatusT(status);
+ }
+
+ // Read all vendor tag definitions into a descriptor
+ status_t res;
+ if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
+ != OK) {
+ ALOGE("%s: Could not generate descriptor from vendor tag operations,"
+ "received error %s (%d). Camera clients will not be able to use"
+ "vendor tags", __FUNCTION__, strerror(res), res);
+ return res;
+ }
+
+ return OK;
+}
+
+status_t HidlProviderInfo::notifyDeviceStateChange(int64_t newDeviceState) {
+ mDeviceState = mapToHidlDeviceState(newDeviceState);
+ if (mMinorVersion >= 5) {
+ // Check if the provider is currently active - not going to start it for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface != nullptr) {
+ // Send current device state
+ auto castResult = provider::V2_5::ICameraProvider::castFrom(interface);
+ if (castResult.isOk()) {
+ sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
+ if (interface_2_5 != nullptr) {
+ interface_2_5->notifyDeviceStateChange(mDeviceState);
+ }
+ }
+ }
+ }
+ return OK;
+}
+
+sp<device::V3_2::ICameraDevice>
+HidlProviderInfo::startDeviceInterface(const std::string &name) {
+ Status status;
+ sp<device::V3_2::ICameraDevice> cameraInterface;
+ hardware::Return<void> ret;
+ const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+ if (interface == nullptr) {
+ return nullptr;
+ }
+ ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
+ Status s, sp<device::V3_2::ICameraDevice> interface) {
+ status = s;
+ cameraInterface = interface;
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error trying to obtain interface for camera device %s: %s",
+ __FUNCTION__, name.c_str(), ret.description().c_str());
+ return nullptr;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain interface for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+ return cameraInterface;
+}
+
+bool HidlProviderInfo::successfullyStartedProviderInterface() {
+ return startProviderInterface() != nullptr;
+}
+
+const sp<provider::V2_4::ICameraProvider>
+HidlProviderInfo::startProviderInterface() {
+ ATRACE_CALL();
+ ALOGV("Request to start camera provider: %s", mProviderName.c_str());
+ if (mSavedInterface != nullptr) {
+ return mSavedInterface;
+ }
+ if (!kEnableLazyHal) {
+ ALOGE("Bad provider state! Should not be here on a non-lazy HAL!");
+ return nullptr;
+ }
+
+ auto interface = mActiveInterface.promote();
+ if (interface == nullptr) {
+ // Try to get service without starting
+ interface = mManager->mHidlServiceProxy->tryGetService(mProviderName);
+ if (interface == nullptr) {
+ ALOGV("Camera provider actually needs restart, calling getService(%s)",
+ mProviderName.c_str());
+ interface = mManager->mHidlServiceProxy->getService(mProviderName);
+
+ // Set all devices as ENUMERATING, provider should update status
+ // to PRESENT after initializing.
+ // This avoids failing getCameraDeviceInterface_V3_x before devices
+ // are ready.
+ for (auto& device : mDevices) {
+ device->mIsDeviceAvailable = false;
+ }
+
+ interface->setCallback(this);
+ hardware::Return<bool>
+ linked = interface->linkToDeath(this, /*cookie*/ mId);
+ if (!linked.isOk()) {
+ ALOGE(
+ "%s: Transaction error in linking to camera provider '%s' death: %s",
+ __FUNCTION__,
+ mProviderName.c_str(),
+ linked.description().c_str());
+ mManager->removeProvider(mProviderName);
+ return nullptr;
+ } else if (!linked) {
+ ALOGW("%s: Unable to link to provider '%s' death notifications",
+ __FUNCTION__, mProviderName.c_str());
+ }
+ // Send current device state
+ if (mMinorVersion >= 5) {
+ auto castResult =
+ provider::V2_5::ICameraProvider::castFrom(interface);
+ if (castResult.isOk()) {
+ sp<provider::V2_5::ICameraProvider> interface_2_5 = castResult;
+ if (interface_2_5 != nullptr) {
+ ALOGV("%s: Initial device state for %s: 0x %" PRIx64,
+ __FUNCTION__, mProviderName.c_str(), mDeviceState);
+ interface_2_5->notifyDeviceStateChange(mDeviceState);
+ }
+ }
+ }
+ }
+ mActiveInterface = interface;
+ } else {
+ ALOGV("Camera provider (%s) already in use. Re-using instance.",
+ mProviderName.c_str());
+ }
+
+ return interface;
+}
+
+hardware::Return<void> HidlProviderInfo::cameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ std::lock_guard<std::mutex> lock(mInitLock);
+ CameraDeviceStatus internalNewStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
+ cameraDeviceName.c_str(), std::string().c_str(),
+ internalNewStatus);
+ return hardware::Void();
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (OK != cameraDeviceStatusChangeLocked(&id, cameraDeviceName, newStatus)) {
+ return hardware::Void();
+ }
+ listener = mManager->getStatusListener();
+ }
+
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onDeviceStatusChanged(String8(id.c_str()), internalNewStatus);
+ }
+
+ return hardware::Void();
+}
+
+status_t HidlProviderInfo::addDevice(const std::string& name,
+ common::V1_0::CameraDeviceStatus initialStatus, /*out*/ std::string* parsedId) {
+
+ ALOGI("Enumerating new camera device: %s", name.c_str());
+
+ uint16_t major, minor;
+ std::string type, id;
+
+ status_t res = parseDeviceName(name, &major, &minor, &type, &id);
+ if (res != OK) {
+ return res;
+ }
+ if (type != mType) {
+ ALOGE("%s: Device type %s does not match provider type %s", __FUNCTION__,
+ type.c_str(), mType.c_str());
+ return BAD_VALUE;
+ }
+ if (mManager->isValidDeviceLocked(id, major)) {
+ ALOGE("%s: Device %s: ID %s is already in use for device major version %d", __FUNCTION__,
+ name.c_str(), id.c_str(), major);
+ return BAD_VALUE;
+ }
+
+ std::unique_ptr<DeviceInfo> deviceInfo;
+ switch (major) {
+ case 1:
+ ALOGE("%s: Device %s: Unsupported HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), major);
+ return BAD_VALUE;
+ case 3:
+ deviceInfo = initializeDeviceInfo(name, mProviderTagid, id, minor);
+ break;
+ default:
+ ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
+ name.c_str(), major);
+ return BAD_VALUE;
+ }
+ if (deviceInfo == nullptr) return BAD_VALUE;
+ deviceInfo->notifyDeviceStateChange(mDeviceState);
+ deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(initialStatus);
+ bool isAPI1Compatible = deviceInfo->isAPI1Compatible();
+
+ mDevices.push_back(std::move(deviceInfo));
+
+ mUniqueCameraIds.insert(id);
+ if (isAPI1Compatible) {
+ // addDevice can be called more than once for the same camera id if HAL
+ // supports openLegacy.
+ if (std::find(mUniqueAPI1CompatibleCameraIds.begin(), mUniqueAPI1CompatibleCameraIds.end(),
+ id) == mUniqueAPI1CompatibleCameraIds.end()) {
+ mUniqueAPI1CompatibleCameraIds.push_back(id);
+ }
+ }
+
+ if (parsedId != nullptr) {
+ *parsedId = id;
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::cameraDeviceStatusChangeLocked(
+ std::string* id, const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ Mutex::Autolock l(deviceInfo->mDeviceAvailableLock);
+ ALOGI("Camera device %s status is now %s, was %s", cameraDeviceName.c_str(),
+ deviceStatusToString(newStatus),
+ deviceStatusToString(mapToHidlCameraDeviceStatus(deviceInfo->mStatus)));
+ deviceInfo->mStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ // TODO: Handle device removal (NOT_PRESENT)
+ cameraId = deviceInfo->mId;
+ known = true;
+ deviceInfo->mIsDeviceAvailable =
+ (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT);
+ deviceInfo->mDeviceAvailableSignal.signal();
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
+ ALOGW("Camera provider %s says an unknown camera device %s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ addDevice(cameraDeviceName, newStatus, &cameraId);
+ } else if (newStatus == hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT) {
+ removeDevice(cameraId);
+ } else if (isExternalLazyHAL()) {
+ // Do not notify CameraService for PRESENT->PRESENT (lazy HAL restart)
+ // because NOT_AVAILABLE is set on CameraService::connect and a PRESENT
+ // notif. would overwrite it
+ return BAD_VALUE;
+ }
+ if (reCacheConcurrentStreamingCameraIdsLocked() != OK) {
+ ALOGE("%s: CameraProvider %s could not re-cache concurrent streaming camera id list ",
+ __FUNCTION__, mProviderName.c_str());
+ }
+ *id = cameraId;
+ return OK;
+}
+
+hardware::Return<void> HidlProviderInfo::physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ sp<StatusListener> listener;
+ std::string id;
+ std::string physicalId;
+ std::lock_guard<std::mutex> lock(mInitLock);
+ CameraDeviceStatus newInternalStatus = hidlToInternalCameraDeviceStatus(newStatus);
+ if (!mInitialized) {
+ mCachedStatus.emplace_back(true /*isPhysicalCameraStatus*/, cameraDeviceName,
+ physicalCameraDeviceName, newInternalStatus);
+ return hardware::Void();
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ if (OK != physicalCameraDeviceStatusChangeLocked(&id, &physicalId, cameraDeviceName,
+ physicalCameraDeviceName, newStatus)) {
+ return hardware::Void();
+ }
+
+ listener = mManager->getStatusListener();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ if (listener != nullptr) {
+ listener->onDeviceStatusChanged(String8(id.c_str()),
+ String8(physicalId.c_str()), newInternalStatus);
+ }
+ return hardware::Void();
+}
+
+status_t HidlProviderInfo::physicalCameraDeviceStatusChangeLocked(
+ std::string* id, std::string* physicalId,
+ const hardware::hidl_string& cameraDeviceName,
+ const hardware::hidl_string& physicalCameraDeviceName,
+ hardware::camera::common::V1_0::CameraDeviceStatus newStatus) {
+ bool known = false;
+ std::string cameraId;
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ cameraId = deviceInfo->mId;
+ if (!deviceInfo->mIsLogicalCamera) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ if (std::find(deviceInfo->mPhysicalIds.begin(), deviceInfo->mPhysicalIds.end(),
+ physicalCameraDeviceName) == deviceInfo->mPhysicalIds.end()) {
+ ALOGE("%s: Invalid combination of camera id %s, physical id %s",
+ __FUNCTION__, cameraId.c_str(), physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+ ALOGI("Camera device %s physical device %s status is now %s",
+ cameraDeviceName.c_str(), physicalCameraDeviceName.c_str(),
+ deviceStatusToString(newStatus));
+ known = true;
+ break;
+ }
+ }
+ // Previously unseen device; status must not be NOT_PRESENT
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera device %s-%s is not present. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(),
+ physicalCameraDeviceName.c_str());
+ return BAD_VALUE;
+ }
+
+ *id = cameraId;
+ *physicalId = physicalCameraDeviceName.c_str();
+ return OK;
+}
+
+hardware::Return<void> HidlProviderInfo::torchModeStatusChange(
+ const hardware::hidl_string& cameraDeviceName,
+ hardware::camera::common::V1_0::TorchModeStatus newStatus) {
+ sp<StatusListener> listener;
+ SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+ std::string id;
+ bool known = false;
+ {
+ // Hold mLock for accessing mDevices
+ std::lock_guard<std::mutex> lock(mLock);
+ for (auto& deviceInfo : mDevices) {
+ if (deviceInfo->mName == cameraDeviceName) {
+ ALOGI("Camera device %s torch status is now %s", cameraDeviceName.c_str(),
+ torchStatusToString(newStatus));
+ id = deviceInfo->mId;
+ known = true;
+ systemCameraKind = deviceInfo->mSystemCameraKind;
+ if (hardware::camera::common::V1_0::TorchModeStatus::AVAILABLE_ON != newStatus) {
+ mManager->removeRef(CameraProviderManager::DeviceMode::TORCH, id);
+ }
+ break;
+ }
+ }
+ if (!known) {
+ ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
+ mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
+ return hardware::Void();
+ }
+ // no lock needed since listener is set up only once during
+ // CameraProviderManager initialization and then never changed till it is
+ // destructed.
+ listener = mManager->getStatusListener();
+ }
+ // Call without lock held to allow reentrancy into provider manager
+ // The problem with holding mLock here is that we
+ // might be limiting re-entrancy : CameraService::onTorchStatusChanged calls
+ // back into CameraProviderManager which might try to hold mLock again (eg:
+ // findDeviceInfo, which should be holding mLock while iterating through
+ // each provider's devices).
+ if (listener != nullptr) {
+ listener->onTorchStatusChanged(String8(id.c_str()),
+ hidlToInternalTorchModeStatus(newStatus), systemCameraKind);
+ }
+ return hardware::Void();
+}
+
+void HidlProviderInfo::serviceDied(uint64_t cookie,
+ const wp<hidl::base::V1_0::IBase>& who) {
+ (void) who;
+ ALOGI("Camera provider '%s' has died; removing it", mProviderInstance.c_str());
+ if (cookie != mId) {
+ ALOGW("%s: Unexpected serviceDied cookie %" PRIu64 ", expected %" PRIu32,
+ __FUNCTION__, cookie, mId);
+ }
+ mManager->removeProvider(mProviderInstance);
+}
+
+std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
+ HidlProviderInfo::initializeDeviceInfo(
+ const std::string &name, const metadata_vendor_id_t tagId,
+ const std::string &id, uint16_t minorVersion) {
+ Status status;
+
+ auto cameraInterface = startDeviceInterface(name);
+ if (cameraInterface == nullptr) return nullptr;
+
+ common::V1_0::CameraResourceCost resourceCost;
+ cameraInterface->getResourceCost([&status, &resourceCost](
+ Status s, common::V1_0::CameraResourceCost cost) {
+ status = s;
+ resourceCost = cost;
+ });
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to obtain resource costs for camera device %s: %s", __FUNCTION__,
+ name.c_str(), statusToString(status));
+ return nullptr;
+ }
+
+ for (auto& conflictName : resourceCost.conflictingDevices) {
+ uint16_t major, minor;
+ std::string type, id;
+ status_t res = parseDeviceName(conflictName, &major, &minor, &type, &id);
+ if (res != OK) {
+ ALOGE("%s: Failed to parse conflicting device %s", __FUNCTION__, conflictName.c_str());
+ return nullptr;
+ }
+ conflictName = id;
+ }
+
+ return std::unique_ptr<DeviceInfo3>(
+ new HidlDeviceInfo3(name, tagId, id, minorVersion, hidlToInternalResourceCost(resourceCost),
+ this, mProviderPublicCameraIds, cameraInterface));
+}
+
+status_t HidlProviderInfo::reCacheConcurrentStreamingCameraIdsLocked() {
+ if (mMinorVersion < 6) {
+ // Unsupported operation, nothing to do here
+ return OK;
+ }
+ // Check if the provider is currently active - not going to start it up for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ ALOGE("%s: camera provider interface for %s is not valid", __FUNCTION__,
+ mProviderName.c_str());
+ return INVALID_OPERATION;
+ }
+ auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
+
+ if (castResult.isOk()) {
+ sp<provider::V2_6::ICameraProvider> interface2_6 = castResult;
+ if (interface2_6 != nullptr) {
+ return getConcurrentCameraIdsInternalLocked(interface2_6);
+ } else {
+ // This should not happen since mMinorVersion >= 6
+ ALOGE("%s: mMinorVersion was >= 6, but interface2_6 was nullptr", __FUNCTION__);
+ return UNKNOWN_ERROR;
+ }
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::getConcurrentCameraIdsInternalLocked(
+ sp<provider::V2_6::ICameraProvider> &interface2_6) {
+ if (interface2_6 == nullptr) {
+ ALOGE("%s: null interface provided", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ Status status = Status::OK;
+ hardware::Return<void> ret =
+ interface2_6->getConcurrentStreamingCameraIds([&status, this](
+ Status concurrentIdStatus, // TODO: Move all instances of hidl_string to 'using'
+ const hardware::hidl_vec<hardware::hidl_vec<hardware::hidl_string>>&
+ cameraDeviceIdCombinations) {
+ status = concurrentIdStatus;
+ if (status == Status::OK) {
+ mConcurrentCameraIdCombinations.clear();
+ for (auto& combination : cameraDeviceIdCombinations) {
+ std::unordered_set<std::string> deviceIds;
+ for (auto &cameraDeviceId : combination) {
+ deviceIds.insert(cameraDeviceId.c_str());
+ }
+ mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
+ }
+ } });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error in getting concurrent camera ID list from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return DEAD_OBJECT;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to query for camera devices from provider '%s'",
+ __FUNCTION__, mProviderName.c_str());
+ return mapToStatusT(status);
+ }
+ return OK;
+}
+
+HidlProviderInfo::HidlDeviceInfo3::HidlDeviceInfo3(
+ const std::string& name,
+ const metadata_vendor_id_t tagId,
+ const std::string &id, uint16_t minorVersion,
+ const CameraResourceCost& resourceCost,
+ sp<CameraProviderManager::ProviderInfo> parentProvider,
+ const std::vector<std::string>& publicCameraIds,
+ sp<hardware::camera::device::V3_2::ICameraDevice> interface) :
+ DeviceInfo3(name, tagId, id, minorVersion, resourceCost, parentProvider, publicCameraIds) {
+
+ // Get camera characteristics and initialize flash unit availability
+ Status status;
+ hardware::Return<void> ret;
+ ret = interface->getCameraCharacteristics([&status, this](Status s,
+ device::V3_2::CameraMetadata metadata) {
+ status = s;
+ if (s == Status::OK) {
+ camera_metadata_t *buffer =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ size_t expectedSize = metadata.size();
+ int res = validate_camera_metadata_structure(buffer, &expectedSize);
+ if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ set_camera_metadata_vendor_id(buffer, mProviderTagid);
+ mCameraCharacteristics = buffer;
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = Status::INTERNAL_ERROR;
+ }
+ }
+ });
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting camera characteristics for device %s"
+ " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
+ ret.description().c_str());
+ return;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
+ __FUNCTION__, id.c_str(), statusToString(status), status);
+ return;
+ }
+
+ if (mCameraCharacteristics.exists(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS)) {
+ const auto &stateMap = mCameraCharacteristics.find(ANDROID_INFO_DEVICE_STATE_ORIENTATIONS);
+ if ((stateMap.count > 0) && ((stateMap.count % 2) == 0)) {
+ for (size_t i = 0; i < stateMap.count; i += 2) {
+ mDeviceStateOrientationMap.emplace(stateMap.data.i64[i], stateMap.data.i64[i+1]);
+ }
+ } else {
+ ALOGW("%s: Invalid ANDROID_INFO_DEVICE_STATE_ORIENTATIONS map size: %zu", __FUNCTION__,
+ stateMap.count);
+ }
+ }
+
+ mSystemCameraKind = getSystemCameraKind();
+
+ status_t res = fixupMonochromeTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to fix up monochrome tags based for older HAL version: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return;
+ }
+ auto stat = addDynamicDepthTags();
+ if (OK != stat) {
+ ALOGE("%s: Failed appending dynamic depth tags: %s (%d)", __FUNCTION__, strerror(-stat),
+ stat);
+ }
+ res = deriveHeicTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+
+ 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)",
+ __FUNCTION__, strerror(-status), status);
+ }
+
+ status = deriveHeicTags(/*maxResolution*/true);
+ if (OK != status) {
+ ALOGE("%s: Unable to derive HEIC tags based on camera and media capabilities for"
+ "maximum resolution mode: %s (%d)", __FUNCTION__, strerror(-status), status);
+ }
+ }
+
+ res = addRotateCropTags();
+ if (OK != res) {
+ ALOGE("%s: Unable to add default SCALER_ROTATE_AND_CROP tags: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+ res = addPreCorrectionActiveArraySize();
+ if (OK != res) {
+ ALOGE("%s: Unable to add PRE_CORRECTION_ACTIVE_ARRAY_SIZE: %s (%d)", __FUNCTION__,
+ strerror(-res), res);
+ }
+ res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+ &mCameraCharacteristics, &mSupportNativeZoomRatio);
+ if (OK != res) {
+ ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+
+ camera_metadata_entry flashAvailable =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_AVAILABLE);
+ if (flashAvailable.count == 1 &&
+ flashAvailable.data.u8[0] == ANDROID_FLASH_INFO_AVAILABLE_TRUE) {
+ mHasFlashUnit = true;
+ } else {
+ mHasFlashUnit = false;
+ }
+
+ camera_metadata_entry entry =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
+ if (entry.count == 1) {
+ mTorchDefaultStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchDefaultStrengthLevel = 0;
+ }
+ entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
+ if (entry.count == 1) {
+ mTorchMaximumStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchMaximumStrengthLevel = 0;
+ }
+
+ mTorchStrengthLevel = 0;
+
+ queryPhysicalCameraIds();
+
+ // Get physical camera characteristics if applicable
+ auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
+ if (!castResult.isOk()) {
+ ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
+ return;
+ }
+ sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
+ if (interface_3_5 == nullptr) {
+ ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
+ return;
+ }
+
+ if (mIsLogicalCamera) {
+ for (auto& id : mPhysicalIds) {
+ if (std::find(mPublicCameraIds.begin(), mPublicCameraIds.end(), id) !=
+ mPublicCameraIds.end()) {
+ continue;
+ }
+
+ hardware::hidl_string hidlId(id);
+ ret = interface_3_5->getPhysicalCameraCharacteristics(hidlId,
+ [&status, &id, this](Status s, device::V3_2::CameraMetadata metadata) {
+ status = s;
+ if (s == Status::OK) {
+ camera_metadata_t *buffer =
+ reinterpret_cast<camera_metadata_t*>(metadata.data());
+ size_t expectedSize = metadata.size();
+ int res = validate_camera_metadata_structure(buffer, &expectedSize);
+ if (res == OK || res == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ set_camera_metadata_vendor_id(buffer, mProviderTagid);
+ mPhysicalCameraCharacteristics[id] = buffer;
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = Status::INTERNAL_ERROR;
+ }
+ }
+ });
+
+ if (!ret.isOk()) {
+ ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
+ __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
+ return;
+ }
+ if (status != Status::OK) {
+ ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
+ __FUNCTION__, id.c_str(), mId.c_str(),
+ statusToString(status), status);
+ return;
+ }
+
+ res = camera3::ZoomRatioMapper::overrideZoomRatioTags(
+ &mPhysicalCameraCharacteristics[id], &mSupportNativeZoomRatio);
+ if (OK != res) {
+ ALOGE("%s: Unable to override zoomRatio related tags: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ }
+ }
+
+ if (!kEnableLazyHal) {
+ // Save HAL reference indefinitely
+ mSavedInterface = interface;
+ }
+
+
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::setTorchMode(bool enabled) {
+ using hardware::camera::common::V1_0::TorchMode;
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
+ return mapToStatusT(s);
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::turnOnTorchWithStrengthLevel(
+ int32_t torchStrength) {
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status s = interface_3_8->turnOnTorchWithStrengthLevel(torchStrength);
+ if (s == Status::OK) {
+ mTorchStrengthLevel = torchStrength;
+ }
+ return mapToStatusT(s);
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::getTorchStrengthLevel(int32_t *torchStrength) {
+ if (torchStrength == nullptr) {
+ return BAD_VALUE;
+ }
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface = startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status callStatus;
+ status_t res;
+ hardware::Return<void> ret = interface_3_8->getTorchStrengthLevel([&callStatus, &torchStrength]
+ (Status status, const int32_t& torchStrengthLevel) {
+ callStatus = status;
+ if (status == Status::OK) {
+ *torchStrength = torchStrengthLevel;
+ } });
+
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Get torch strength level failed: %d", __FUNCTION__, callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+
+ return res;
+}
+
+sp<hardware::camera::device::V3_2::ICameraDevice>
+HidlProviderInfo::HidlDeviceInfo3::startDeviceInterface() {
+ Mutex::Autolock l(mDeviceAvailableLock);
+ sp<hardware::camera::device::V3_2::ICameraDevice> device;
+ ATRACE_CALL();
+ if (mSavedInterface == nullptr) {
+ sp<HidlProviderInfo> parentProvider =
+ static_cast<HidlProviderInfo *>(mParentProvider.promote().get());
+ if (parentProvider != nullptr) {
+ // Wait for lazy HALs to confirm device availability
+ if (parentProvider->isExternalLazyHAL() && !mIsDeviceAvailable) {
+ ALOGV("%s: Wait for external device to become available %s",
+ __FUNCTION__,
+ mId.c_str());
+
+ auto res = mDeviceAvailableSignal.waitRelative(mDeviceAvailableLock,
+ kDeviceAvailableTimeout);
+ if (res != OK) {
+ ALOGE("%s: Failed waiting for device to become available",
+ __FUNCTION__);
+ return nullptr;
+ }
+ }
+
+ device = parentProvider->startDeviceInterface(mName);
+ }
+ } else {
+ device = (hardware::camera::device::V3_2::ICameraDevice *) mSavedInterface.get();
+ }
+ return device;
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::dumpState(int fd) {
+ native_handle_t* handle = native_handle_create(1,0);
+ handle->data[0] = fd;
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
+ startDeviceInterface();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ auto ret = interface->dumpState(handle);
+ native_handle_delete(handle);
+ if (!ret.isOk()) {
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+status_t HidlProviderInfo::HidlDeviceInfo3::isSessionConfigurationSupported(
+ const SessionConfiguration &configuration, bool overrideForPerfClass, bool *status) {
+
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
+ bool earlyExit = false;
+ camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+ CameraMetadata physicalChars;
+ getPhysicalCameraCharacteristics(id.c_str(), &physicalChars);
+ return physicalChars;
+ };
+ auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
+ String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
+ streamConfiguration, overrideForPerfClass, &earlyExit);
+
+ if (!bRes.isOk()) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (earlyExit) {
+ *status = false;
+ return OK;
+ }
+
+ const sp<hardware::camera::device::V3_2::ICameraDevice> interface =
+ startDeviceInterface();
+
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+
+ auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
+ auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = castResult_3_8;
+
+ status_t res;
+ Status callStatus;
+ ::android::hardware::Return<void> ret;
+ auto halCb =
+ [&callStatus, &status] (Status s, bool combStatus) {
+ callStatus = s;
+ *status = combStatus;
+ };
+ if (interface_3_8 != nullptr) {
+ ret = interface_3_8->isStreamCombinationSupported_3_8(streamConfiguration, halCb);
+ } else if (interface_3_7 != nullptr) {
+ hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ configuration_3_7, streamConfiguration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ ret = interface_3_7->isStreamCombinationSupported_3_7(configuration_3_7, halCb);
+ } else if (interface_3_5 != nullptr) {
+ hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ configuration_3_7, streamConfiguration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
+ success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ configuration_3_4, configuration_3_7);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+ ret = interface_3_5->isStreamCombinationSupported(configuration_3_4, halCb);
+ } else {
+ return INVALID_OPERATION;
+ }
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+
+ return res;
+}
+
+status_t HidlProviderInfo::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();
+ std::vector<CameraIdAndStreamCombination> halCameraIdsAndStreamsV;
+ bool shouldExit = false;
+ status_t res = OK;
+ for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
+ const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
+ CameraMetadata deviceInfo;
+ bool overrideForPerfClass =
+ SessionConfigurationUtils::targetPerfClassPrimaryCamera(
+ perfClassPrimaryCameraIds, cameraId, targetSdkVersion);
+ res = mManager->getCameraCharacteristicsLocked(cameraId, overrideForPerfClass, &deviceInfo);
+ if (res != OK) {
+ return res;
+ }
+ camera3::metadataGetter getMetadata =
+ [this](const String8 &id, bool overrideForPerfClass) {
+ CameraMetadata physicalDeviceInfo;
+ mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+ &physicalDeviceInfo);
+ return physicalDeviceInfo;
+ };
+ std::vector<std::string> physicalCameraIds;
+ mManager->isLogicalCameraLocked(cameraId, &physicalCameraIds);
+ bStatus =
+ SessionConfigurationUtils::convertToHALStreamCombination(
+ cameraIdAndSessionConfig.mSessionConfiguration,
+ String8(cameraId.c_str()), deviceInfo, getMetadata,
+ physicalCameraIds, streamConfiguration,
+ overrideForPerfClass, &shouldExit);
+ if (!bStatus.isOk()) {
+ ALOGE("%s: convertToHALStreamCombination failed", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (shouldExit) {
+ *earlyExit = true;
+ return OK;
+ }
+ CameraIdAndStreamCombination halCameraIdAndStream;
+ halCameraIdAndStream.cameraId = cameraId;
+ SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ halCameraIdAndStream.streamConfiguration, streamConfiguration);
+ halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
+ }
+ *halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
+ return OK;
+}
+
+status_t HidlProviderInfo::isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) {
+
+ hardware::hidl_vec<CameraIdAndStreamCombination> halCameraIdsAndStreamCombinations;
+ bool knowUnsupported = false;
+ status_t res = convertToHALStreamCombinationAndCameraIdsLocked(
+ cameraIdsAndSessionConfigs, perfClassPrimaryCameraIds,
+ targetSdkVersion, &halCameraIdsAndStreamCombinations, &knowUnsupported);
+ if (res != OK) {
+ ALOGE("%s unable to convert session configurations provided to HAL stream"
+ "combinations", __FUNCTION__);
+ return res;
+ }
+ if (knowUnsupported) {
+ // We got to know the streams aren't valid before doing the HAL
+ // call itself.
+ *isSupported = false;
+ return OK;
+ }
+
+ if (mMinorVersion >= 6) {
+ // Check if the provider is currently active - not going to start it for this notification
+ auto interface = mSavedInterface != nullptr ? mSavedInterface : mActiveInterface.promote();
+ if (interface == nullptr) {
+ // TODO: This might be some other problem
+ return INVALID_OPERATION;
+ }
+ auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ Status callStatus;
+ auto cb =
+ [&isSupported, &callStatus](Status s, bool supported) {
+ callStatus = s;
+ *isSupported = supported; };
+
+ ::android::hardware::Return<void> ret;
+ sp<provider::V2_7::ICameraProvider> interface_2_7;
+ sp<provider::V2_6::ICameraProvider> interface_2_6;
+ if (mMinorVersion >= 7 && castResult2_7.isOk()) {
+ interface_2_7 = castResult2_7;
+ if (interface_2_7 != nullptr) {
+ ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
+ halCameraIdsAndStreamCombinations, cb);
+ }
+ } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
+ interface_2_6 = castResult2_6;
+ if (interface_2_6 != nullptr) {
+ hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
+ halCameraIdsAndStreamCombinations_2_6;
+ size_t numStreams = halCameraIdsAndStreamCombinations.size();
+ halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
+ for (size_t i = 0; i < numStreams; i++) {
+ using namespace camera3;
+ auto const& combination = halCameraIdsAndStreamCombinations[i];
+ halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
+ bool success =
+ SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
+ combination.streamConfiguration);
+ if (!success) {
+ *isSupported = false;
+ return OK;
+ }
+ }
+ ret = interface_2_6->isConcurrentStreamCombinationSupported(
+ halCameraIdsAndStreamCombinations_2_6, cb);
+ }
+ }
+
+ if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
+ callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+ return res;
+ }
+ }
+ // unsupported operation
+ return INVALID_OPERATION;
+}
+
+status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
+ const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
+ sp<VendorTagDescriptor>& descriptor) {
+
+ int tagCount = 0;
+
+ for (size_t s = 0; s < vts.size(); s++) {
+ tagCount += vts[s].tags.size();
+ }
+
+ if (tagCount < 0 || tagCount > INT32_MAX) {
+ ALOGE("%s: tag count %d from vendor tag sections is invalid.", __FUNCTION__, tagCount);
+ return BAD_VALUE;
+ }
+
+ Vector<uint32_t> tagArray;
+ LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+ "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+
+ sp<HidlVendorTagDescriptor> desc = new HidlVendorTagDescriptor();
+ desc->mTagCount = tagCount;
+
+ SortedVector<String8> sections;
+ KeyedVector<uint32_t, String8> tagToSectionMap;
+
+ int idx = 0;
+ for (size_t s = 0; s < vts.size(); s++) {
+ const common::V1_0::VendorTagSection& section = vts[s];
+ const char *sectionName = section.sectionName.c_str();
+ if (sectionName == NULL) {
+ ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
+ return BAD_VALUE;
+ }
+ String8 sectionString(sectionName);
+ sections.add(sectionString);
+
+ for (size_t j = 0; j < section.tags.size(); j++) {
+ uint32_t tag = section.tags[j].tagId;
+ if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+ ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+ return BAD_VALUE;
+ }
+
+ tagArray.editItemAt(idx++) = section.tags[j].tagId;
+
+ const char *tagName = section.tags[j].tagName.c_str();
+ if (tagName == NULL) {
+ ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
+ return BAD_VALUE;
+ }
+ desc->mTagToNameMap.add(tag, String8(tagName));
+ tagToSectionMap.add(tag, sectionString);
+
+ int tagType = (int) section.tags[j].tagType;
+ if (tagType < 0 || tagType >= NUM_TYPES) {
+ ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+ return BAD_VALUE;
+ }
+ desc->mTagToTypeMap.add(tag, tagType);
+ }
+ }
+
+ desc->mSections = sections;
+
+ for (size_t i = 0; i < tagArray.size(); ++i) {
+ uint32_t tag = tagArray[i];
+ String8 sectionString = tagToSectionMap.valueFor(tag);
+
+ // Set up tag to section index map
+ ssize_t index = sections.indexOf(sectionString);
+ LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+ desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+ // Set up reverse mapping
+ ssize_t reverseIndex = -1;
+ if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+ KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+ reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+ }
+ desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+ }
+
+ descriptor = std::move(desc);
+ return OK;
+}
+
+} //namespace android
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
new file mode 100644
index 0000000..0ba2aff
--- /dev/null
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_HIDLPROVIDERINFOH
+#define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_HIDLPROVIDERINFOH
+
+#include "common/CameraProviderManager.h"
+
+namespace android {
+
+/**
+ * The vendor tag descriptor class that takes HIDL vendor tag information as
+ * input. Not part of VendorTagDescriptor class because that class is used
+ * in AIDL generated sources which don't have access to HIDL headers.
+ */
+class HidlVendorTagDescriptor : public VendorTagDescriptor {
+public:
+ /**
+ * Create a VendorTagDescriptor object from the HIDL VendorTagSection
+ * vector.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ static status_t createDescriptorFromHidl(
+ const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
+ /*out*/
+ sp<VendorTagDescriptor>& descriptor);
+};
+
+struct HidlProviderInfo : public CameraProviderManager::ProviderInfo,
+ virtual public hardware::camera::provider::V2_6::ICameraProviderCallback,
+ virtual public hardware::hidl_death_recipient {
+ // Current overall Android device physical status
+ hardware::hidl_bitfield<hardware::camera::provider::V2_5::DeviceState> mDeviceState;
+
+ // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
+ wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
+
+ sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
+ HidlProviderInfo(
+ const std::string &providerName,
+ const std::string &providerInstance,
+ CameraProviderManager *manager) :
+ CameraProviderManager::ProviderInfo(providerName, providerInstance, manager) {}
+
+ virtual ~HidlProviderInfo() {}
+
+ static status_t mapToStatusT(const hardware::camera::common::V1_0::Status &status);
+
+ status_t initializeHidlProvider(
+ sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
+ int64_t currentDeviceState);
+
+ IPCTransport getIPCTransport() override {return IPCTransport::HIDL;}
+
+ const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
+
+ virtual bool successfullyStartedProviderInterface() override;
+
+ virtual status_t setUpVendorTags() override;
+ virtual status_t notifyDeviceStateChange(int64_t) override;
+
+ /**
+ * Query the camera provider for concurrent stream configuration support
+ */
+ virtual status_t isConcurrentSessionConfigurationSupported(
+ const std::vector<CameraIdAndSessionConfiguration> &cameraIdsAndSessionConfigs,
+ const std::set<std::string>& perfClassPrimaryCameraIds,
+ int targetSdkVersion, bool *isSupported) override;
+
+ // Helper for initializeDeviceInfo to use the right CameraProvider get method.
+ sp<hardware::camera::device::V3_2::ICameraDevice>
+ startDeviceInterface(const std::string &deviceName);
+
+ // ICameraProviderCallbacks interface - these lock the parent mInterfaceMutex
+ hardware::Return<void> cameraDeviceStatusChange(
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ) override;
+ hardware::Return<void> torchModeStatusChange(
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::TorchModeStatus ) override;
+ hardware::Return<void> physicalCameraDeviceStatusChange(
+ const hardware::hidl_string& ,
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ) override;
+
+ // hidl_death_recipient interface - this locks the parent mInterfaceMutex
+ virtual void serviceDied(uint64_t , const wp<hidl::base::V1_0::IBase>& ) override;
+
+ struct HidlDeviceInfo3 : public CameraProviderManager::ProviderInfo::DeviceInfo3 {
+
+ const hardware::hidl_version mVersion = hardware::hidl_version{3, 2};
+ sp<IBase> mSavedInterface = nullptr;
+
+ HidlDeviceInfo3(const std::string& , const metadata_vendor_id_t ,
+ const std::string &, uint16_t ,
+ const CameraResourceCost& ,
+ sp<ProviderInfo> ,
+ const std::vector<std::string>& ,
+ sp<hardware::camera::device::V3_2::ICameraDevice>);
+
+ ~HidlDeviceInfo3() {}
+
+ virtual status_t setTorchMode(bool enabled) override;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
+
+ virtual status_t dumpState(int fd) override;
+
+ virtual status_t isSessionConfigurationSupported(
+ const SessionConfiguration &/*configuration*/,
+ bool overrideForPerfClass,
+ bool *status/*status*/);
+ sp<hardware::camera::device::V3_2::ICameraDevice> startDeviceInterface();
+ };
+
+ private:
+
+ status_t cameraDeviceStatusChangeLocked(
+ std::string* , const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus );
+
+ status_t physicalCameraDeviceStatusChangeLocked(
+ std::string* , std::string* ,
+ const hardware::hidl_string& ,
+ const hardware::hidl_string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus );
+
+ status_t addDevice(const std::string& ,
+ hardware::camera::common::V1_0::CameraDeviceStatus ,
+ /*out*/ std::string *);
+
+ std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &,
+ const metadata_vendor_id_t , const std::string &,
+ uint16_t );
+ status_t reCacheConcurrentStreamingCameraIdsLocked();
+
+ //Expects to have mLock locked
+ status_t getConcurrentCameraIdsInternalLocked(
+ sp<hardware::camera::provider::V2_6::ICameraProvider> &);
+
+ //expects to have mManager->mInterfaceMutex locked
+ 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);
+}; // HidlProviderInfo
+
+} // namespace android
+#endif
diff --git a/services/camera/libcameraservice/device3/BufferUtils.cpp b/services/camera/libcameraservice/device3/BufferUtils.cpp
index f3adf20..c0d47d5 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.cpp
+++ b/services/camera/libcameraservice/device3/BufferUtils.cpp
@@ -28,16 +28,6 @@
namespace android {
namespace camera3 {
-camera_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
- using hardware::camera::device::V3_2::BufferStatus;
-
- switch (status) {
- case BufferStatus::OK: return CAMERA_BUFFER_STATUS_OK;
- case BufferStatus::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
- }
- return CAMERA_BUFFER_STATUS_ERROR;
-}
-
void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
std::lock_guard<std::mutex> oLock(other.mInflightLock);
std::lock_guard<std::mutex> lock(mInflightLock);
diff --git a/services/camera/libcameraservice/device3/BufferUtils.h b/services/camera/libcameraservice/device3/BufferUtils.h
index 03112ec..96fc111 100644
--- a/services/camera/libcameraservice/device3/BufferUtils.h
+++ b/services/camera/libcameraservice/device3/BufferUtils.h
@@ -154,9 +154,6 @@
}; // class BufferRecords
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
-
- camera_buffer_status_t mapHidlBufferStatus(
- hardware::camera::device::V3_2::BufferStatus status);
} // namespace camera3
} // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2f571a6..992027a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -65,6 +65,8 @@
#include "utils/TraceHFR.h"
#include "utils/CameraServiceProxyWrapper.h"
+#include "../common/hidl/HidlProviderInfo.h"
+
#include <algorithm>
#include <tuple>
@@ -112,164 +114,6 @@
return mId;
}
-status_t Camera3Device::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
- ATRACE_CALL();
- Mutex::Autolock il(mInterfaceLock);
- Mutex::Autolock l(mLock);
-
- ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
- if (mStatus != STATUS_UNINITIALIZED) {
- CLOGE("Already initialized!");
- return INVALID_OPERATION;
- }
- if (manager == nullptr) return INVALID_OPERATION;
-
- sp<ICameraDeviceSession> session;
- ATRACE_BEGIN("CameraHal::openSession");
- status_t res = manager->openSession(mId.string(), this,
- /*out*/ &session);
- ATRACE_END();
- if (res != OK) {
- SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
- return res;
- }
-
- 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();
- return res;
- }
- mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
-
- std::vector<std::string> physicalCameraIds;
- bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
- if (isLogical) {
- for (auto& physicalId : physicalCameraIds) {
- // Do not override characteristics for physical cameras
- res = manager->getCameraCharacteristics(
- 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);
- session->close();
- return res;
- }
-
- bool usePrecorrectArray =
- DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
- if (usePrecorrectArray) {
- res = mDistortionMappers[physicalId].setupStaticInfo(
- mPhysicalDeviceInfoMap[physicalId]);
- if (res != OK) {
- SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
- "correction", physicalId.c_str());
- session->close();
- return res;
- }
- }
-
- mZoomRatioMappers[physicalId] = ZoomRatioMapper(
- &mPhysicalDeviceInfoMap[physicalId],
- mSupportNativeZoomRatio, usePrecorrectArray);
-
- if (SessionConfigurationUtils::isUltraHighResolutionSensor(
- mPhysicalDeviceInfoMap[physicalId])) {
- mUHRCropAndMeteringRegionMappers[physicalId] =
- UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
- usePrecorrectArray);
- }
- }
- }
-
- std::shared_ptr<RequestMetadataQueue> queue;
- auto requestQueueRet = session->getCaptureRequestMetadataQueue(
- [&queue](const auto& descriptor) {
- queue = std::make_shared<RequestMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty request metadata fmq, not use it");
- queue = nullptr;
- // don't use the queue onwards.
- }
- });
- if (!requestQueueRet.isOk()) {
- ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
- requestQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
-
- std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
- auto resultQueueRet = session->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty result metadata fmq, not use it");
- resQueue = nullptr;
- // Don't use the resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Transaction error when getting result metadata queue from camera session: %s",
- resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- IF_ALOGV() {
- session->interfaceChain([](
- ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
- ALOGV("Session interface chain:");
- for (const auto& iface : interfaceChain) {
- ALOGV(" %s", iface.c_str());
- }
- });
- }
-
- camera_metadata_entry bufMgrMode =
- mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
- if (bufMgrMode.count > 0) {
- mUseHalBufManager = (bufMgrMode.data.u8[0] ==
- ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
- }
-
- camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
- for (size_t i = 0; i < capabilities.count; i++) {
- uint8_t capability = capabilities.data.u8[i];
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
- mSupportOfflineProcessing = true;
- }
- }
-
- mInterface = new HalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
- std::string providerType;
- mVendorTagId = manager->getProviderTagIdLocked(mId.string());
- mTagMonitor.initialize(mVendorTagId);
- if (!monitorTags.isEmpty()) {
- mTagMonitor.parseTagsToMonitor(String8(monitorTags));
- }
-
- // Metadata tags needs fixup for monochrome camera device version less
- // than 3.5.
- hardware::hidl_version maxVersion{0,0};
- res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
- if (res != OK) {
- ALOGE("%s: Error in getting camera device version id: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
- int deviceVersion = HARDWARE_DEVICE_API_VERSION(
- maxVersion.get_major(), maxVersion.get_minor());
-
- bool isMonochrome = false;
- for (size_t i = 0; i < capabilities.count; i++) {
- uint8_t capability = capabilities.data.u8[i];
- if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
- isMonochrome = true;
- }
- }
- mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
-
- return initializeCommonLocked();
-}
-
status_t Camera3Device::initializeCommonLocked() {
/** Start up status tracker thread */
@@ -323,7 +167,7 @@
}
/** Start up request queue thread */
- mRequestThread = new RequestThread(
+ mRequestThread = createNewRequestThread(
this, mStatusTracker, mInterface, sessionParamKeys,
mUseHalBufManager, mSupportCameraMute);
res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
@@ -381,7 +225,8 @@
mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
}
- mInjectionMethods = new Camera3DeviceInjectionMethods(this);
+ // Hidl/AidlCamera3DeviceInjectionMethods
+ mInjectionMethods = createCamera3DeviceInjectionMethods(this);
return OK;
}
@@ -531,77 +376,6 @@
return measured;
}
-hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
- int frameworkFormat) {
- return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
-}
-
-DataspaceFlags Camera3Device::mapToHidlDataspace(
- android_dataspace dataSpace) {
- return dataSpace;
-}
-
-BufferUsageFlags Camera3Device::mapToConsumerUsage(
- uint64_t usage) {
- return usage;
-}
-
-StreamRotation Camera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
- switch (rotation) {
- case CAMERA_STREAM_ROTATION_0:
- return StreamRotation::ROTATION_0;
- case CAMERA_STREAM_ROTATION_90:
- return StreamRotation::ROTATION_90;
- case CAMERA_STREAM_ROTATION_180:
- return StreamRotation::ROTATION_180;
- case CAMERA_STREAM_ROTATION_270:
- return StreamRotation::ROTATION_270;
- }
- ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
- return StreamRotation::ROTATION_0;
-}
-
-status_t Camera3Device::mapToStreamConfigurationMode(
- camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
- if (mode == nullptr) return BAD_VALUE;
- if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
- switch(operationMode) {
- case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
- *mode = StreamConfigurationMode::NORMAL_MODE;
- break;
- case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
- *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
- break;
- default:
- ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
- return BAD_VALUE;
- }
- } else {
- *mode = static_cast<StreamConfigurationMode>(operationMode);
- }
- return OK;
-}
-
-int Camera3Device::mapToFrameworkFormat(
- hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
- return static_cast<uint32_t>(pixelFormat);
-}
-
-android_dataspace Camera3Device::mapToFrameworkDataspace(
- DataspaceFlags dataSpace) {
- return static_cast<android_dataspace>(dataSpace);
-}
-
-uint64_t Camera3Device::mapConsumerToFrameworkUsage(
- BufferUsageFlags usage) {
- return usage;
-}
-
-uint64_t Camera3Device::mapProducerToFrameworkUsage(
- BufferUsageFlags usage) {
- return usage;
-}
-
ssize_t Camera3Device::getJpegBufferSize(const CameraMetadata &info, uint32_t width,
uint32_t height) const {
// Get max jpeg size (area-wise) for default sensor pixel mode
@@ -1044,186 +818,6 @@
return res;
}
-hardware::Return<void> Camera3Device::requestStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) {
- RequestBufferStates states {
- mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
- *this, *mInterface, *this};
- camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::returnStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- ReturnBufferStates states {
- mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *mInterface};
- camera3::returnStreamBuffers(states, buffers);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) {
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received capture result in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- if (mProcessCaptureResultLock.tryLock() != OK) {
- // This should never happen; it indicates a wrong client implementation
- // that doesn't follow the contract. But, we can be tolerant here.
- ALOGE("%s: callback overlapped! waiting 1s...",
- __FUNCTION__);
- if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
- ALOGE("%s: cannot acquire lock in 1s, dropping results",
- __FUNCTION__);
- // really don't know what to do, so bail out.
- return hardware::Void();
- }
- }
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
-
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
- }
- mProcessCaptureResultLock.unlock();
- return hardware::Void();
-}
-
-// Only one processCaptureResult should be called at a time, so
-// the locks won't block. The locks are present here simply to enforce this.
-hardware::Return<void> Camera3Device::processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) {
- hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
-
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received capture result in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- if (mProcessCaptureResultLock.tryLock() != OK) {
- // This should never happen; it indicates a wrong client implementation
- // that doesn't follow the contract. But, we can be tolerant here.
- ALOGE("%s: callback overlapped! waiting 1s...",
- __FUNCTION__);
- if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
- ALOGE("%s: cannot acquire lock in 1s, dropping results",
- __FUNCTION__);
- // really don't know what to do, so bail out.
- return hardware::Void();
- }
- }
-
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
-
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result, noPhysMetadata);
- }
- mProcessCaptureResultLock.unlock();
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3Device::notify(
- const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
- return notifyHelper<hardware::camera::device::V3_2::NotifyMsg>(msgs);
-}
-
-hardware::Return<void> Camera3Device::notify_3_8(
- const hardware::hidl_vec<hardware::camera::device::V3_8::NotifyMsg>& msgs) {
- return notifyHelper<hardware::camera::device::V3_8::NotifyMsg>(msgs);
-}
-
-template<typename NotifyMsgType>
-hardware::Return<void> Camera3Device::notifyHelper(const hardware::hidl_vec<NotifyMsgType>& msgs) {
- // Ideally we should grab mLock, but that can lead to deadlock, and
- // it's not super important to get up to date value of mStatus for this
- // warning print, hence skipping the lock here
- if (mStatus == STATUS_ERROR) {
- // Per API contract, HAL should act as closed after device error
- // But mStatus can be set to error by framework as well, so just log
- // a warning here.
- ALOGW("%s: received notify message in error state.", __FUNCTION__);
- }
-
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> l(mOutputLock);
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mInFlightLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- *mInterface, mLegacyClient
- };
- for (const auto& msg : msgs) {
- camera3::notify(states, msg);
- }
- return hardware::Void();
-}
-
status_t Camera3Device::captureList(const List<const PhysicalCameraSettingsList> &requestsList,
const std::list<const SurfaceMap> &surfaceMaps,
int64_t *lastFrameNumber) {
@@ -1384,7 +978,7 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage) {
+ uint64_t consumerUsage, int dynamicRangeProfile) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1397,7 +991,7 @@
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
format, dataSpace, rotation, id, physicalCameraId, sensorPixelModesUsed, surfaceIds,
- streamSetId, isShared, isMultiResolution, consumerUsage);
+ streamSetId, isShared, isMultiResolution, consumerUsage, dynamicRangeProfile);
}
static bool isRawFormat(int format) {
@@ -1417,7 +1011,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
- uint64_t consumerUsage) {
+ uint64_t consumerUsage, int dynamicRangeProfile) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
@@ -1495,7 +1089,7 @@
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, blobBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
bool maxResolution =
sensorPixelModesUsed.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -1509,22 +1103,22 @@
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- mUseHalBufManager);
+ mUseHalBufManager, dynamicRangeProfile);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
mTimestampOffset, physicalCameraId, sensorPixelModesUsed, streamSetId,
- isMultiResolution);
+ isMultiResolution, dynamicRangeProfile);
}
size_t consumerCount = consumers.size();
@@ -1611,6 +1205,7 @@
streamInfo->originalFormat = stream->getOriginalFormat();
streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
streamInfo->originalDataSpace = stream->getOriginalDataSpace();
+ streamInfo->dynamicRangeProfile = stream->getDynamicRangeProfile();
return OK;
}
@@ -2223,7 +1818,8 @@
streamStats.emplace_back(stream->getWidth(), stream->getHeight(),
stream->getFormat(), stream->getDataSpace(), usage,
stream->getMaxHalBuffers(),
- stream->getMaxTotalBuffers() - stream->getMaxHalBuffers());
+ stream->getMaxTotalBuffers() - stream->getMaxHalBuffers(),
+ stream->getDynamicRangeProfile());
}
}
}
@@ -3133,702 +2729,6 @@
* HalInterface inner class methods
*/
-Camera3Device::HalInterface::HalInterface(
- sp<ICameraDeviceSession> &session,
- std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager, bool supportOfflineProcessing) :
- mHidlSession(session),
- mRequestMetadataQueue(queue),
- mUseHalBufManager(useHalBufManager),
- mIsReconfigurationQuerySupported(true),
- mSupportOfflineProcessing(supportOfflineProcessing) {
- // Check with hardware service manager if we can downcast these interfaces
- // Somewhat expensive, so cache the results at startup
- auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_7.isOk()) {
- mHidlSession_3_7 = castResult_3_7;
- }
- auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_6.isOk()) {
- mHidlSession_3_6 = castResult_3_6;
- }
- auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_5.isOk()) {
- mHidlSession_3_5 = castResult_3_5;
- }
- auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_4.isOk()) {
- mHidlSession_3_4 = castResult_3_4;
- }
- auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_3.isOk()) {
- mHidlSession_3_3 = castResult_3_3;
- }
-}
-
-Camera3Device::HalInterface::HalInterface() :
- mUseHalBufManager(false),
- mSupportOfflineProcessing(false) {}
-
-Camera3Device::HalInterface::HalInterface(const HalInterface& other) :
- mHidlSession(other.mHidlSession),
- mRequestMetadataQueue(other.mRequestMetadataQueue),
- mUseHalBufManager(other.mUseHalBufManager),
- mSupportOfflineProcessing(other.mSupportOfflineProcessing) {}
-
-bool Camera3Device::HalInterface::valid() {
- return (mHidlSession != nullptr);
-}
-
-void Camera3Device::HalInterface::clear() {
- mHidlSession_3_7.clear();
- mHidlSession_3_6.clear();
- mHidlSession_3_5.clear();
- mHidlSession_3_4.clear();
- mHidlSession_3_3.clear();
- mHidlSession.clear();
-}
-
-status_t Camera3Device::HalInterface::constructDefaultRequestSettings(
- camera_request_template_t templateId,
- /*out*/ camera_metadata_t **requestTemplate) {
- ATRACE_NAME("CameraHal::constructDefaultRequestSettings");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- common::V1_0::Status status;
-
- auto requestCallback = [&status, &requestTemplate]
- (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
- status = s;
- if (status == common::V1_0::Status::OK) {
- const camera_metadata *r =
- reinterpret_cast<const camera_metadata_t*>(request.data());
- size_t expectedSize = request.size();
- int ret = validate_camera_metadata_structure(r, &expectedSize);
- if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
- *requestTemplate = clone_camera_metadata(r);
- if (*requestTemplate == nullptr) {
- ALOGE("%s: Unable to clone camera metadata received from HAL",
- __FUNCTION__);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
- } else {
- ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
- }
- };
- hardware::Return<void> err;
- RequestTemplate id;
- switch (templateId) {
- case CAMERA_TEMPLATE_PREVIEW:
- id = RequestTemplate::PREVIEW;
- break;
- case CAMERA_TEMPLATE_STILL_CAPTURE:
- id = RequestTemplate::STILL_CAPTURE;
- break;
- case CAMERA_TEMPLATE_VIDEO_RECORD:
- id = RequestTemplate::VIDEO_RECORD;
- break;
- case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
- id = RequestTemplate::VIDEO_SNAPSHOT;
- break;
- case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
- id = RequestTemplate::ZERO_SHUTTER_LAG;
- break;
- case CAMERA_TEMPLATE_MANUAL:
- id = RequestTemplate::MANUAL;
- break;
- default:
- // Unknown template ID, or this HAL is too old to support it
- return BAD_VALUE;
- }
- err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
-
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(status);
- }
-
- return res;
-}
-
-bool Camera3Device::HalInterface::isReconfigurationRequired(CameraMetadata& oldSessionParams,
- CameraMetadata& newSessionParams) {
- // We do reconfiguration by default;
- bool ret = true;
- if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
- android::hardware::hidl_vec<uint8_t> oldParams, newParams;
- camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
- oldSessionParams.getAndLock());
- camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
- newSessionParams.getAndLock());
- oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
- get_camera_metadata_size(oldSessioMeta));
- newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
- get_camera_metadata_size(newSessioMeta));
- hardware::camera::common::V1_0::Status callStatus;
- bool required;
- auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
- bool requiredFlag) {
- callStatus = s;
- required = requiredFlag;
- };
- auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
- oldSessionParams.unlock(oldSessioMeta);
- newSessionParams.unlock(newSessioMeta);
- if (err.isOk()) {
- switch (callStatus) {
- case hardware::camera::common::V1_0::Status::OK:
- ret = required;
- break;
- case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
- mIsReconfigurationQuerySupported = false;
- ret = true;
- break;
- default:
- ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
- ret = true;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
- ret = true;
- }
- }
-
- return ret;
-}
-
-status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
- camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
- ATRACE_NAME("CameraHal::configureStreams");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
- ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
- return BAD_VALUE;
- }
-
- // Convert stream config to HIDL
- std::set<int> activeStreams;
- device::V3_2::StreamConfiguration requestedConfiguration3_2;
- device::V3_4::StreamConfiguration requestedConfiguration3_4;
- device::V3_7::StreamConfiguration requestedConfiguration3_7;
- requestedConfiguration3_2.streams.resize(config->num_streams);
- requestedConfiguration3_4.streams.resize(config->num_streams);
- requestedConfiguration3_7.streams.resize(config->num_streams);
- for (size_t i = 0; i < config->num_streams; i++) {
- device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
- device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
- device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
- camera3::camera_stream_t *src = config->streams[i];
-
- Camera3Stream* cam3stream = Camera3Stream::cast(src);
- cam3stream->setBufferFreedListener(this);
- int streamId = cam3stream->getId();
- StreamType streamType;
- switch (src->stream_type) {
- case CAMERA_STREAM_OUTPUT:
- streamType = StreamType::OUTPUT;
- break;
- case CAMERA_STREAM_INPUT:
- streamType = StreamType::INPUT;
- break;
- default:
- ALOGE("%s: Stream %d: Unsupported stream type %d",
- __FUNCTION__, streamId, config->streams[i]->stream_type);
- return BAD_VALUE;
- }
- dst3_2.id = streamId;
- dst3_2.streamType = streamType;
- dst3_2.width = src->width;
- dst3_2.height = src->height;
- dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
- // For HidlSession version 3.5 or newer, the format and dataSpace sent
- // to HAL are original, not the overridden ones.
- if (mHidlSession_3_5 != nullptr) {
- dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
- cam3stream->getOriginalFormat() : src->format);
- dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
- cam3stream->getOriginalDataSpace() : src->data_space);
- } else {
- dst3_2.format = mapToPixelFormat(src->format);
- dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
- }
- dst3_4.v3_2 = dst3_2;
- dst3_4.bufferSize = bufferSizes[i];
- if (src->physical_camera_id != nullptr) {
- dst3_4.physicalCameraId = src->physical_camera_id;
- }
- dst3_7.v3_4 = dst3_4;
- dst3_7.groupId = cam3stream->getHalStreamGroupId();
- dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
- size_t j = 0;
- for (int mode : src->sensor_pixel_modes_used) {
- dst3_7.sensorPixelModesUsed[j++] =
- static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
- }
- activeStreams.insert(streamId);
- // Create Buffer ID map if necessary
- mBufferRecords.tryCreateBufferCache(streamId);
- }
- // remove BufferIdMap for deleted streams
- mBufferRecords.removeInactiveBufferCaches(activeStreams);
-
- StreamConfigurationMode operationMode;
- res = mapToStreamConfigurationMode(
- (camera_stream_configuration_mode_t) config->operation_mode,
- /*out*/ &operationMode);
- if (res != OK) {
- return res;
- }
- requestedConfiguration3_2.operationMode = operationMode;
- requestedConfiguration3_4.operationMode = operationMode;
- requestedConfiguration3_7.operationMode = operationMode;
- size_t sessionParamSize = get_camera_metadata_size(sessionParams);
- requestedConfiguration3_4.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
- requestedConfiguration3_7.operationMode = operationMode;
- requestedConfiguration3_7.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
-
- // Invoke configureStreams
- device::V3_3::HalStreamConfiguration finalConfiguration;
- device::V3_4::HalStreamConfiguration finalConfiguration3_4;
- device::V3_6::HalStreamConfiguration finalConfiguration3_6;
- common::V1_0::Status status;
-
- auto configStream34Cb = [&status, &finalConfiguration3_4]
- (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
- finalConfiguration3_4 = halConfiguration;
- status = s;
- };
-
- auto configStream36Cb = [&status, &finalConfiguration3_6]
- (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
- finalConfiguration3_6 = halConfiguration;
- status = s;
- };
-
- auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
- (hardware::Return<void>& err) -> status_t {
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
- for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
- finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
- }
- return OK;
- };
-
- auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
- (hardware::Return<void>& err) -> status_t {
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
- for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
- finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
- }
- return OK;
- };
-
- // See which version of HAL we have
- if (mHidlSession_3_7 != nullptr) {
- ALOGV("%s: v3.7 device found", __FUNCTION__);
- requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
- requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
- auto err = mHidlSession_3_7->configureStreams_3_7(
- requestedConfiguration3_7, configStream36Cb);
- res = postprocConfigStream36(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_6 != nullptr) {
- ALOGV("%s: v3.6 device found", __FUNCTION__);
- device::V3_5::StreamConfiguration requestedConfiguration3_5;
- requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
- requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
- auto err = mHidlSession_3_6->configureStreams_3_6(
- requestedConfiguration3_5, configStream36Cb);
- res = postprocConfigStream36(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_5 != nullptr) {
- ALOGV("%s: v3.5 device found", __FUNCTION__);
- device::V3_5::StreamConfiguration requestedConfiguration3_5;
- requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
- requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
- auto err = mHidlSession_3_5->configureStreams_3_5(
- requestedConfiguration3_5, configStream34Cb);
- res = postprocConfigStream34(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_4 != nullptr) {
- // We do; use v3.4 for the call
- ALOGV("%s: v3.4 device found", __FUNCTION__);
- auto err = mHidlSession_3_4->configureStreams_3_4(
- requestedConfiguration3_4, configStream34Cb);
- res = postprocConfigStream34(err);
- if (res != OK) {
- return res;
- }
- } else if (mHidlSession_3_3 != nullptr) {
- // We do; use v3.3 for the call
- ALOGV("%s: v3.3 device found", __FUNCTION__);
- auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
- [&status, &finalConfiguration]
- (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
- finalConfiguration = halConfiguration;
- status = s;
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- } else {
- // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
- ALOGV("%s: v3.2 device found", __FUNCTION__);
- HalStreamConfiguration finalConfiguration_3_2;
- auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
- [&status, &finalConfiguration_3_2]
- (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
- finalConfiguration_3_2 = halConfiguration;
- status = s;
- });
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
- finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
- for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
- finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
- finalConfiguration.streams[i].overrideDataSpace =
- requestedConfiguration3_2.streams[i].dataSpace;
- }
- }
-
- if (status != common::V1_0::Status::OK ) {
- return CameraProviderManager::mapToStatusT(status);
- }
-
- // And convert output stream configuration from HIDL
-
- for (size_t i = 0; i < config->num_streams; i++) {
- camera3::camera_stream_t *dst = config->streams[i];
- int streamId = Camera3Stream::cast(dst)->getId();
-
- // Start scan at i, with the assumption that the stream order matches
- size_t realIdx = i;
- bool found = false;
- size_t halStreamCount = finalConfiguration.streams.size();
- for (size_t idx = 0; idx < halStreamCount; idx++) {
- if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
- found = true;
- break;
- }
- realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
- }
- if (!found) {
- ALOGE("%s: Stream %d not found in stream configuration response from HAL",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
- device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
-
- Camera3Stream* dstStream = Camera3Stream::cast(dst);
- int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
- android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
-
- if (mHidlSession_3_6 != nullptr) {
- dstStream->setOfflineProcessingSupport(src_36.supportOffline);
- }
-
- if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
- dstStream->setFormatOverride(false);
- dstStream->setDataSpaceOverride(false);
- if (dst->format != overrideFormat) {
- ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
- streamId, dst->format);
- }
- if (dst->data_space != overrideDataSpace) {
- ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
- streamId, dst->format);
- }
- } else {
- bool needFormatOverride =
- requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
- bool needDataspaceOverride =
- requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
- // Override allowed with IMPLEMENTATION_DEFINED
- dstStream->setFormatOverride(needFormatOverride);
- dstStream->setDataSpaceOverride(needDataspaceOverride);
- dst->format = overrideFormat;
- dst->data_space = overrideDataSpace;
- }
-
- if (dst->stream_type == CAMERA_STREAM_INPUT) {
- if (src.v3_2.producerUsage != 0) {
- ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dstStream->setUsage(
- mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
- } else {
- // OUTPUT
- if (src.v3_2.consumerUsage != 0) {
- ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
- __FUNCTION__, streamId);
- return INVALID_OPERATION;
- }
- dstStream->setUsage(
- mapProducerToFrameworkUsage(src.v3_2.producerUsage));
- }
- dst->max_buffers = src.v3_2.maxBuffers;
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::configureInjectedStreams(
- const camera_metadata_t* sessionParams, camera_stream_configuration* config,
- const std::vector<uint32_t>& bufferSizes,
- const CameraMetadata& cameraCharacteristics) {
- ATRACE_NAME("InjectionCameraHal::configureStreams");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- if (config->input_is_multi_resolution) {
- ALOGE("%s: Injection camera device doesn't support multi-resolution input "
- "stream", __FUNCTION__);
- return BAD_VALUE;
- }
-
- // Convert stream config to HIDL
- std::set<int> activeStreams;
- device::V3_2::StreamConfiguration requestedConfiguration3_2;
- device::V3_4::StreamConfiguration requestedConfiguration3_4;
- device::V3_7::StreamConfiguration requestedConfiguration3_7;
- requestedConfiguration3_2.streams.resize(config->num_streams);
- requestedConfiguration3_4.streams.resize(config->num_streams);
- requestedConfiguration3_7.streams.resize(config->num_streams);
- for (size_t i = 0; i < config->num_streams; i++) {
- device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
- device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
- device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
- camera3::camera_stream_t* src = config->streams[i];
-
- Camera3Stream* cam3stream = Camera3Stream::cast(src);
- cam3stream->setBufferFreedListener(this);
- int streamId = cam3stream->getId();
- StreamType streamType;
- switch (src->stream_type) {
- case CAMERA_STREAM_OUTPUT:
- streamType = StreamType::OUTPUT;
- break;
- case CAMERA_STREAM_INPUT:
- streamType = StreamType::INPUT;
- break;
- default:
- ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
- streamId, config->streams[i]->stream_type);
- return BAD_VALUE;
- }
- dst3_2.id = streamId;
- dst3_2.streamType = streamType;
- dst3_2.width = src->width;
- dst3_2.height = src->height;
- dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.rotation =
- mapToStreamRotation((camera_stream_rotation_t)src->rotation);
- // For HidlSession version 3.5 or newer, the format and dataSpace sent
- // to HAL are original, not the overridden ones.
- if (mHidlSession_3_5 != nullptr) {
- dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
- ? cam3stream->getOriginalFormat()
- : src->format);
- dst3_2.dataSpace =
- mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
- ? cam3stream->getOriginalDataSpace()
- : src->data_space);
- } else {
- dst3_2.format = mapToPixelFormat(src->format);
- dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
- }
- dst3_4.v3_2 = dst3_2;
- dst3_4.bufferSize = bufferSizes[i];
- if (src->physical_camera_id != nullptr) {
- dst3_4.physicalCameraId = src->physical_camera_id;
- }
- dst3_7.v3_4 = dst3_4;
- dst3_7.groupId = cam3stream->getHalStreamGroupId();
- dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
- size_t j = 0;
- for (int mode : src->sensor_pixel_modes_used) {
- dst3_7.sensorPixelModesUsed[j++] =
- static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
- }
- activeStreams.insert(streamId);
- // Create Buffer ID map if necessary
- mBufferRecords.tryCreateBufferCache(streamId);
- }
- // remove BufferIdMap for deleted streams
- mBufferRecords.removeInactiveBufferCaches(activeStreams);
-
- StreamConfigurationMode operationMode;
- res = mapToStreamConfigurationMode(
- (camera_stream_configuration_mode_t)config->operation_mode,
- /*out*/ &operationMode);
- if (res != OK) {
- return res;
- }
- requestedConfiguration3_7.operationMode = operationMode;
- size_t sessionParamSize = get_camera_metadata_size(sessionParams);
- requestedConfiguration3_7.operationMode = operationMode;
- requestedConfiguration3_7.sessionParams.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
- sessionParamSize);
-
- // See which version of HAL we have
- if (mHidlSession_3_7 != nullptr) {
- requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
- requestedConfiguration3_7.multiResolutionInputImage =
- config->input_is_multi_resolution;
-
- const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
- ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
- hidlChars.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
- get_camera_metadata_size(rawMetadata));
- cameraCharacteristics.unlock(rawMetadata);
-
- sp<hardware::camera::device::V3_7::ICameraInjectionSession>
- hidlInjectionSession_3_7;
- auto castInjectionResult_3_7 =
- device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
- if (castInjectionResult_3_7.isOk()) {
- hidlInjectionSession_3_7 = castInjectionResult_3_7;
- } else {
- ALOGE("%s: Transaction error: %s", __FUNCTION__,
- castInjectionResult_3_7.description().c_str());
- return DEAD_OBJECT;
- }
-
- auto err = hidlInjectionSession_3_7->configureInjectionStreams(
- requestedConfiguration3_7, hidlChars);
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__,
- err.description().c_str());
- return DEAD_OBJECT;
- }
- } else {
- ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
- "session is 3.7", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
- /*out*/device::V3_2::CaptureRequest* captureRequest,
- /*out*/std::vector<native_handle_t*>* handlesCreated,
- /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
- ATRACE_CALL();
- if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
- ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
- "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
- return BAD_VALUE;
- }
-
- captureRequest->frameNumber = request->frame_number;
-
- captureRequest->fmqSettingsSize = 0;
-
- {
- if (request->input_buffer != nullptr) {
- int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
- buffer_handle_t buf = *(request->input_buffer->buffer);
- auto pair = getBufferId(buf, streamId);
- bool isNewBuffer = pair.first;
- uint64_t bufferId = pair.second;
- captureRequest->inputBuffer.streamId = streamId;
- captureRequest->inputBuffer.bufferId = bufferId;
- captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
- captureRequest->inputBuffer.status = BufferStatus::OK;
- native_handle_t *acquireFence = nullptr;
- if (request->input_buffer->acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = request->input_buffer->acquire_fence;
- handlesCreated->push_back(acquireFence);
- }
- captureRequest->inputBuffer.acquireFence = acquireFence;
- captureRequest->inputBuffer.releaseFence = nullptr;
-
- mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
- request->input_buffer->buffer);
- inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
- } else {
- captureRequest->inputBuffer.streamId = -1;
- captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
- }
-
- captureRequest->outputBuffers.resize(request->num_output_buffers);
- for (size_t i = 0; i < request->num_output_buffers; i++) {
- const camera_stream_buffer_t *src = request->output_buffers + i;
- StreamBuffer &dst = captureRequest->outputBuffers[i];
- int32_t streamId = Camera3Stream::cast(src->stream)->getId();
- if (src->buffer != nullptr) {
- buffer_handle_t buf = *(src->buffer);
- auto pair = getBufferId(buf, streamId);
- bool isNewBuffer = pair.first;
- dst.bufferId = pair.second;
- dst.buffer = isNewBuffer ? buf : nullptr;
- native_handle_t *acquireFence = nullptr;
- if (src->acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = src->acquire_fence;
- handlesCreated->push_back(acquireFence);
- }
- dst.acquireFence = acquireFence;
- } else if (mUseHalBufManager) {
- // HAL buffer management path
- dst.bufferId = BUFFER_ID_NO_BUFFER;
- dst.buffer = nullptr;
- dst.acquireFence = nullptr;
- } else {
- ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
- return BAD_VALUE;
- }
- dst.streamId = streamId;
- dst.status = BufferStatus::OK;
- dst.releaseFence = nullptr;
-
- // Output buffers are empty when using HAL buffer manager
- if (!mUseHalBufManager) {
- mBufferRecords.pushInflightBuffer(
- captureRequest->frameNumber, streamId, src->buffer);
- inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
- }
- }
- }
- return OK;
-}
-
void Camera3Device::HalInterface::cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd) {
if (handles == nullptr) {
@@ -3846,302 +2746,6 @@
return;
}
-status_t Camera3Device::HalInterface::processBatchCaptureRequests(
- std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
- ATRACE_NAME("CameraHal::processBatchCaptureRequests");
- if (!valid()) return INVALID_OPERATION;
-
- sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
- sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
- auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_7.isOk()) {
- hidlSession_3_7 = castResult_3_7;
- }
- auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
- if (castResult_3_4.isOk()) {
- hidlSession_3_4 = castResult_3_4;
- }
-
- hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
- hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
- hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
- size_t batchSize = requests.size();
- if (hidlSession_3_7 != nullptr) {
- captureRequests_3_7.resize(batchSize);
- } else if (hidlSession_3_4 != nullptr) {
- captureRequests_3_4.resize(batchSize);
- } else {
- captureRequests.resize(batchSize);
- }
- std::vector<native_handle_t*> handlesCreated;
- std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
-
- status_t res = OK;
- for (size_t i = 0; i < batchSize; i++) {
- if (hidlSession_3_7 != nullptr) {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- } else if (hidlSession_3_4 != nullptr) {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- } else {
- res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
- /*out*/&handlesCreated, /*out*/&inflightBuffers);
- }
- if (res != OK) {
- mBufferRecords.popInflightBuffers(inflightBuffers);
- cleanupNativeHandles(&handlesCreated);
- return res;
- }
- }
-
- std::vector<device::V3_2::BufferCache> cachesToRemove;
- {
- std::lock_guard<std::mutex> lock(mFreedBuffersLock);
- for (auto& pair : mFreedBuffers) {
- // The stream might have been removed since onBufferFreed
- if (mBufferRecords.isStreamCached(pair.first)) {
- cachesToRemove.push_back({pair.first, pair.second});
- }
- }
- mFreedBuffers.clear();
- }
-
- common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
- *numRequestProcessed = 0;
-
- // Write metadata to FMQ.
- for (size_t i = 0; i < batchSize; i++) {
- camera_capture_request_t* request = requests[i];
- device::V3_2::CaptureRequest* captureRequest;
- if (hidlSession_3_7 != nullptr) {
- captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
- } else if (hidlSession_3_4 != nullptr) {
- captureRequest = &captureRequests_3_4[i].v3_2;
- } else {
- captureRequest = &captureRequests[i];
- }
-
- if (request->settings != nullptr) {
- size_t settingsSize = get_camera_metadata_size(request->settings);
- if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
- captureRequest->settings.resize(0);
- captureRequest->fmqSettingsSize = settingsSize;
- } else {
- if (mRequestMetadataQueue != nullptr) {
- ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
- }
- captureRequest->settings.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(request->settings)),
- get_camera_metadata_size(request->settings));
- captureRequest->fmqSettingsSize = 0u;
- }
- } else {
- // A null request settings maps to a size-0 CameraMetadata
- captureRequest->settings.resize(0);
- captureRequest->fmqSettingsSize = 0u;
- }
-
- // hidl session 3.7 specific handling.
- if (hidlSession_3_7 != nullptr) {
- captureRequests_3_7[i].inputWidth = request->input_width;
- captureRequests_3_7[i].inputHeight = request->input_height;
- }
-
- // hidl session 3.7 and 3.4 specific handling.
- if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
- hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
- (hidlSession_3_7 != nullptr) ?
- captureRequests_3_7[i].v3_4.physicalCameraSettings :
- captureRequests_3_4[i].physicalCameraSettings;
- physicalCameraSettings.resize(request->num_physcam_settings);
- for (size_t j = 0; j < request->num_physcam_settings; j++) {
- if (request->physcam_settings != nullptr) {
- size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
- if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
- reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
- settingsSize)) {
- physicalCameraSettings[j].settings.resize(0);
- physicalCameraSettings[j].fmqSettingsSize = settingsSize;
- } else {
- if (mRequestMetadataQueue != nullptr) {
- ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
- }
- physicalCameraSettings[j].settings.setToExternal(
- reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
- request->physcam_settings[j])),
- get_camera_metadata_size(request->physcam_settings[j]));
- physicalCameraSettings[j].fmqSettingsSize = 0u;
- }
- } else {
- physicalCameraSettings[j].fmqSettingsSize = 0u;
- physicalCameraSettings[j].settings.resize(0);
- }
- physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
- }
- }
- }
-
- hardware::details::return_status err;
- auto resultCallback =
- [&status, &numRequestProcessed] (auto s, uint32_t n) {
- status = s;
- *numRequestProcessed = n;
- };
- if (hidlSession_3_7 != nullptr) {
- err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
- resultCallback);
- } else if (hidlSession_3_4 != nullptr) {
- err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
- resultCallback);
- } else {
- err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
- resultCallback);
- }
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- status = common::V1_0::Status::CAMERA_DISCONNECTED;
- }
-
- if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
- ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
- __FUNCTION__, *numRequestProcessed, batchSize);
- status = common::V1_0::Status::INTERNAL_ERROR;
- }
-
- res = CameraProviderManager::mapToStatusT(status);
- if (res == OK) {
- if (mHidlSession->isRemote()) {
- // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
- // sent to camera HAL processes)
- cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
- } else {
- // In passthrough mode the FDs are now owned by HAL
- cleanupNativeHandles(&handlesCreated);
- }
- } else {
- mBufferRecords.popInflightBuffers(inflightBuffers);
- cleanupNativeHandles(&handlesCreated);
- }
- return res;
-}
-
-status_t Camera3Device::HalInterface::flush() {
- ATRACE_NAME("CameraHal::flush");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- auto err = mHidlSession->flush();
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- res = DEAD_OBJECT;
- } else {
- res = CameraProviderManager::mapToStatusT(err);
- }
-
- return res;
-}
-
-status_t Camera3Device::HalInterface::dump(int /*fd*/) {
- ATRACE_NAME("CameraHal::dump");
- if (!valid()) return INVALID_OPERATION;
-
- // Handled by CameraProviderManager::dump
-
- return OK;
-}
-
-status_t Camera3Device::HalInterface::close() {
- ATRACE_NAME("CameraHal::close()");
- if (!valid()) return INVALID_OPERATION;
- status_t res = OK;
-
- auto err = mHidlSession->close();
- // Interface will be dead shortly anyway, so don't log errors
- if (!err.isOk()) {
- res = DEAD_OBJECT;
- }
-
- return res;
-}
-
-void Camera3Device::HalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
- ATRACE_NAME("CameraHal::signalPipelineDrain");
- if (!valid() || mHidlSession_3_5 == nullptr) {
- ALOGE("%s called on invalid camera!", __FUNCTION__);
- return;
- }
-
- auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return;
- }
-}
-
-status_t Camera3Device::HalInterface::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords) {
- ATRACE_NAME("CameraHal::switchToOffline");
- if (!valid() || mHidlSession_3_6 == nullptr) {
- ALOGE("%s called on invalid camera!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
- ALOGE("%s: output arguments must not be null!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
- auto resultCallback =
- [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
- status = s;
- *offlineSessionInfo = info;
- *offlineSession = session;
- };
- auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
-
- if (!err.isOk()) {
- ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
- return DEAD_OBJECT;
- }
-
- status_t ret = CameraProviderManager::mapToStatusT(status);
- if (ret != OK) {
- return ret;
- }
-
- // TODO: assert no ongoing requestBuffer/returnBuffer call here
- // TODO: update RequestBufferStateMachine to block requestBuffer/returnBuffer once HAL
- // returns from switchToOffline.
-
-
- // Validate buffer caches
- std::vector<int32_t> streams;
- streams.reserve(offlineSessionInfo->offlineStreams.size());
- for (auto offlineStream : offlineSessionInfo->offlineStreams) {
- int32_t id = offlineStream.id;
- streams.push_back(id);
- // Verify buffer caches
- std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
- offlineStream.circulatingBufferIds.end());
- if (!verifyBufferIds(id, bufIds)) {
- ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
- return UNKNOWN_ERROR;
- }
- }
-
- // Move buffer records
- bufferRecords->takeBufferCaches(mBufferRecords, streams);
- bufferRecords->takeInflightBufferMap(mBufferRecords);
- bufferRecords->takeRequestedBufferMap(mBufferRecords);
- return ret;
-}
-
void Camera3Device::HalInterface::getInflightBufferKeys(
std::vector<std::pair<int32_t, int32_t>>* out) {
mBufferRecords.getInflightBufferKeys(out);
@@ -4386,10 +2990,20 @@
}
status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
+ std::vector<int32_t> streamIds;
+ for (const auto& request : mRepeatingRequests) {
+ for (const auto& stream : request->mOutputStreams) {
+ streamIds.push_back(stream->getId());
+ }
+ }
+
mRepeatingRequests.clear();
if (lastFrameNumber != NULL) {
*lastFrameNumber = mRepeatingLastFrameNumber;
}
+
+ mInterface->repeatingRequestEnd(mRepeatingLastFrameNumber, streamIds);
+
mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
return OK;
}
@@ -5354,38 +3968,6 @@
mPrevRequest.clear();
}
-status_t Camera3Device::RequestThread::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords) {
- Mutex::Autolock l(mRequestLock);
- clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
-
- // Wait until request thread is fully stopped
- // TBD: check if request thread is being paused by other APIs (shouldn't be)
-
- // We could also check for mRepeatingRequests.empty(), but the API interface
- // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
- // new requests during the call; hence skip that check.
- bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
- while (!queueEmpty) {
- status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
- if (res == TIMED_OUT) {
- ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
- return res;
- } else if (res != OK) {
- ALOGE("%s: request thread failed to submit a request: %s (%d)!",
- __FUNCTION__, strerror(-res), res);
- return res;
- }
- queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
- }
-
- return mInterface->switchToOffline(
- streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
-}
-
status_t Camera3Device::RequestThread::setRotateAndCropAutoBehavior(
camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue) {
ATRACE_CALL();
@@ -6416,220 +4998,6 @@
return ret;
}
-status_t Camera3Device::switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/ sp<CameraOfflineSessionBase>* session) {
- ATRACE_CALL();
- if (session == nullptr) {
- ALOGE("%s: session must not be null", __FUNCTION__);
- return BAD_VALUE;
- }
-
- Mutex::Autolock il(mInterfaceLock);
-
- bool hasInputStream = mInputStream != nullptr;
- int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
- bool inputStreamSupportsOffline = hasInputStream ?
- mInputStream->getOfflineProcessingSupport() : false;
- auto outputStreamIds = mOutputStreams.getStreamIds();
- auto streamIds = outputStreamIds;
- if (hasInputStream) {
- streamIds.push_back(mInputStream->getId());
- }
-
- // Check all streams in streamsToKeep supports offline mode
- for (auto id : streamsToKeep) {
- if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
- ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
- return BAD_VALUE;
- } else if (id == inputStreamId) {
- if (!inputStreamSupportsOffline) {
- ALOGE("%s: input stream %d cannot be switched to offline",
- __FUNCTION__, id);
- return BAD_VALUE;
- }
- } else {
- sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
- if (!stream->getOfflineProcessingSupport()) {
- ALOGE("%s: output stream %d cannot be switched to offline",
- __FUNCTION__, id);
- return BAD_VALUE;
- }
- }
- }
-
- // TODO: block surface sharing and surface group streams until we can support them
-
- // Stop repeating request, wait until all remaining requests are submitted, then call into
- // HAL switchToOffline
- hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
- camera3::BufferRecords bufferRecords;
- status_t ret = mRequestThread->switchToOffline(
- streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
-
- if (ret != OK) {
- SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
- return ret;
- }
-
- bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
- if (!succ) {
- SET_ERR("HAL must not be calling requestStreamBuffers call");
- // TODO: block ALL callbacks from HAL till app configured new streams?
- return UNKNOWN_ERROR;
- }
-
- // Verify offlineSessionInfo
- std::vector<int32_t> offlineStreamIds;
- offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- // verify stream IDs
- int32_t id = offlineStream.id;
- if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
- SET_ERR("stream ID %d not found!", id);
- return UNKNOWN_ERROR;
- }
-
- // When not using HAL buf manager, only allow streams requested by app to be preserved
- if (!mUseHalBufManager) {
- if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
- SET_ERR("stream ID %d must not be switched to offline!", id);
- return UNKNOWN_ERROR;
- }
- }
-
- offlineStreamIds.push_back(id);
- sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
- static_cast<sp<Camera3StreamInterface>>(mInputStream) :
- static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
- // Verify number of outstanding buffers
- if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
- SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
- id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
- return UNKNOWN_ERROR;
- }
- }
-
- // Verify all streams to be deleted don't have any outstanding buffers
- if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
- inputStreamId) == offlineStreamIds.end()) {
- if (mInputStream->hasOutstandingBuffers()) {
- SET_ERR("Input stream %d still has %zu outstanding buffer!",
- inputStreamId, mInputStream->getOutstandingBuffersCount());
- return UNKNOWN_ERROR;
- }
- }
-
- for (const auto& outStreamId : outputStreamIds) {
- if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
- outStreamId) == offlineStreamIds.end()) {
- auto outStream = mOutputStreams.get(outStreamId);
- if (outStream->hasOutstandingBuffers()) {
- SET_ERR("Output stream %d still has %zu outstanding buffer!",
- outStreamId, outStream->getOutstandingBuffersCount());
- return UNKNOWN_ERROR;
- }
- }
- }
-
- InFlightRequestMap offlineReqs;
- // Verify inflight requests and their pending buffers
- {
- std::lock_guard<std::mutex> l(mInFlightLock);
- for (auto offlineReq : offlineSessionInfo.offlineRequests) {
- int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
- if (idx == NAME_NOT_FOUND) {
- SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
- return UNKNOWN_ERROR;
- }
-
- const auto& inflightReq = mInFlightMap.valueAt(idx);
- // TODO: check specific stream IDs
- size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
- if (numBuffersLeft != offlineReq.pendingStreams.size()) {
- SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
- inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
- return UNKNOWN_ERROR;
- }
- offlineReqs.add(offlineReq.frameNumber, inflightReq);
- }
- }
-
- // Create Camera3OfflineSession and transfer object ownership
- // (streams, inflight requests, buffer caches)
- camera3::StreamSet offlineStreamSet;
- sp<camera3::Camera3Stream> inputStream;
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- int32_t id = offlineStream.id;
- if (mInputStream != nullptr && id == mInputStream->getId()) {
- inputStream = mInputStream;
- } else {
- offlineStreamSet.add(id, mOutputStreams.get(id));
- }
- }
-
- // TODO: check if we need to lock before copying states
- // though technically no other thread should be talking to Camera3Device at this point
- Camera3OfflineStates offlineStates(
- mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
- mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mNextResultFrameNumber, mNextReprocessResultFrameNumber,
- mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
- mZoomRatioMappers, mRotateAndCropMappers);
-
- *session = new Camera3OfflineSession(mId, inputStream, offlineStreamSet,
- std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
-
- // Delete all streams that has been transferred to offline session
- Mutex::Autolock l(mLock);
- for (auto offlineStream : offlineSessionInfo.offlineStreams) {
- int32_t id = offlineStream.id;
- if (mInputStream != nullptr && id == mInputStream->getId()) {
- mInputStream.clear();
- } else {
- mOutputStreams.remove(id);
- }
- }
-
- // disconnect all other streams and switch to UNCONFIGURED state
- if (mInputStream != nullptr) {
- ret = mInputStream->disconnect();
- if (ret != OK) {
- SET_ERR_L("disconnect input stream failed!");
- return UNKNOWN_ERROR;
- }
- }
-
- for (auto streamId : mOutputStreams.getStreamIds()) {
- sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
- ret = stream->disconnect();
- if (ret != OK) {
- SET_ERR_L("disconnect output stream %d failed!", streamId);
- return UNKNOWN_ERROR;
- }
- }
-
- mInputStream.clear();
- mOutputStreams.clear();
- mNeedConfig = true;
- internalUpdateStatusLocked(STATUS_UNCONFIGURED);
- mOperatingMode = NO_MODE;
- mIsConstrainedHighSpeedConfiguration = false;
- mRequestThread->clearPreviousRequest();
-
- return OK;
- // TO be done by CameraDeviceClient/Camera3OfflineSession
- // register the offline client to camera service
- // Setup result passthing threads etc
- // Initialize offline session so HAL can start sending callback to it (result Fmq)
- // TODO: check how many onIdle callback will be sent
- // Java side to make sure the CameraCaptureSession is properly closed
-}
-
void Camera3Device::getOfflineStreamIds(std::vector<int> *offlineStreamIds) {
ATRACE_CALL();
@@ -6716,7 +5084,7 @@
}
}
- res = mInjectionMethods->injectionInitialize(injectedCamId, manager, this);
+ res = injectionCameraInitialize(injectedCamId, manager);
if (res != OK) {
ALOGE("%s: Failed to initialize the injection camera! ret != NO_ERROR: %d",
__FUNCTION__, res);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3f069f9..6c4ba49 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -29,21 +29,9 @@
#include <utils/KeyedVector.h>
#include <utils/Timers.h>
-#include <android/hardware/camera/device/3.2/ICameraDevice.h>
-#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
-#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
-#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
-#include <fmq/MessageQueue.h>
-
#include <camera/CaptureResult.h>
+#include "android/hardware/camera/metadata/3.8/types.h"
#include "common/CameraDeviceBase.h"
#include "device3/BufferUtils.h"
#include "device3/StatusTracker.h"
@@ -57,6 +45,7 @@
#include "device3/Camera3OfflineSession.h"
#include "device3/Camera3StreamInterface.h"
#include "utils/TagMonitor.h"
+#include "utils/IPCTransport.h"
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
@@ -84,11 +73,11 @@
*/
class Camera3Device :
public CameraDeviceBase,
- virtual public hardware::camera::device::V3_8::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
public camera3::FlushBufferInterface {
+ friend class HidlCamera3Device;
public:
explicit Camera3Device(const String8& id, bool overrideForPerfClass, bool legacyClient = false);
@@ -104,7 +93,9 @@
metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
// Transitions to idle state on success.
- status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+ virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
+ const String8& /*monitorTags*/) = 0;
+
status_t disconnect() override;
status_t dump(int fd, const Vector<String16> &args) override;
status_t startWatchingTags(const String8 &tags) override;
@@ -141,7 +132,9 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) override;
+ uint64_t consumerUsage = 0,
+ int dynamicRangeProfile =
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -151,7 +144,9 @@
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
bool isShared = false, bool isMultiResolution = false,
- uint64_t consumerUsage = 0) override;
+ uint64_t consumerUsage = 0,
+ int dynamicRangeProfile =
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) override;
status_t createInputStream(
uint32_t width, uint32_t height, int format, bool isMultiResolution,
@@ -229,8 +224,10 @@
nsecs_t getExpectedInFlightDuration() override;
- status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
- /*out*/ sp<CameraOfflineSessionBase>* session) override;
+ virtual status_t switchToOffline(const std::vector<int32_t>& ,
+ /*out*/ sp<CameraOfflineSessionBase>* ) override {
+ return INVALID_OPERATION;
+ };
// RequestBufferInterface
bool startRequestBuffer() override;
@@ -281,33 +278,10 @@
*/
status_t stopInjection();
- /**
- * Helper functions to map between framework and HIDL values
- */
- static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
- static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
- android_dataspace dataSpace);
- static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
- static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
- camera_stream_rotation_t rotation);
- // Returns a negative error code if the passed-in operation mode is not valid.
- static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
- /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
- static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
- static android_dataspace mapToFrameworkDataspace(
- hardware::camera::device::V3_2::DataspaceFlags);
- static uint64_t mapConsumerToFrameworkUsage(
- hardware::camera::device::V3_2::BufferUsageFlags usage);
- static uint64_t mapProducerToFrameworkUsage(
- hardware::camera::device::V3_2::BufferUsageFlags usage);
-
- private:
+ protected:
status_t disconnectImpl();
static status_t removeFwkOnlyRegionKeys(CameraMetadata *request);
- // internal typedefs
- using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-
static const size_t kDumpLockAttempts = 10;
static const size_t kDumpSleepDuration = 100000; // 0.10 sec
static const nsecs_t kActiveTimeout = 500000000; // 500 ms
@@ -353,68 +327,65 @@
// Flag indicating is the current active stream configuration is constrained high speed.
bool mIsConstrainedHighSpeedConfiguration;
- // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
-
/**** Scope for mLock ****/
- /**
- * Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
- * HIDL HALv3 interfaces.
- */
class HalInterface : public camera3::Camera3StreamBufferFreedListener,
public camera3::BufferRecordsInterface {
public:
- HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
- std::shared_ptr<RequestMetadataQueue> queue,
- bool useHalBufManager, bool supportOfflineProcessing);
+ HalInterface(bool useHalBufManager, bool supportOfflineProcessing) :
+ mUseHalBufManager(useHalBufManager),
+ mIsReconfigurationQuerySupported(true),
+ mSupportOfflineProcessing(supportOfflineProcessing)
+ {};
HalInterface(const HalInterface &other);
HalInterface();
+ virtual IPCTransport getTransportType() = 0;
+
// Returns true if constructed with a valid device or session, and not yet cleared
- bool valid();
+ virtual bool valid() = 0;
// Reset this HalInterface object (does not call close())
- void clear();
+ virtual void clear() = 0;
// Calls into the HAL interface
// Caller takes ownership of requestTemplate
- status_t constructDefaultRequestSettings(camera_request_template templateId,
- /*out*/ camera_metadata_t **requestTemplate);
- status_t configureStreams(const camera_metadata_t *sessionParams,
- /*inout*/ camera_stream_configuration_t *config,
- const std::vector<uint32_t>& bufferSizes);
+ virtual status_t constructDefaultRequestSettings(camera_request_template templateId,
+ /*out*/ camera_metadata_t **requestTemplate) = 0;
+
+ virtual status_t configureStreams(const camera_metadata_t * sessionParams,
+ /*inout*/ camera_stream_configuration_t * config,
+ const std::vector<uint32_t>& bufferSizes) = 0;
// The injection camera configures the streams to hal.
- status_t configureInjectedStreams(
+ virtual status_t configureInjectedStreams(
const camera_metadata_t* sessionParams,
/*inout*/ camera_stream_configuration_t* config,
const std::vector<uint32_t>& bufferSizes,
- const CameraMetadata& cameraCharacteristics);
+ const CameraMetadata& cameraCharacteristics) = 0;
// When the call succeeds, the ownership of acquire fences in requests is transferred to
// HalInterface. More specifically, the current implementation will send the fence to
// HAL process and close the FD in cameraserver process. When the call fails, the ownership
// of the acquire fence still belongs to the caller.
- status_t processBatchCaptureRequests(
+ virtual status_t processBatchCaptureRequests(
std::vector<camera_capture_request_t*>& requests,
- /*out*/uint32_t* numRequestProcessed);
- status_t flush();
- status_t dump(int fd);
- status_t close();
+ /*out*/uint32_t* numRequestProcessed) = 0;
- void signalPipelineDrain(const std::vector<int>& streamIds);
- bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
- CameraMetadata& newSessionParams);
+ virtual status_t flush() = 0;
- // Upon successful return, HalInterface will return buffer maps needed for offline
- // processing, and clear all its internal buffer maps.
- status_t switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords);
+ virtual status_t dump(int fd) = 0;
+
+ virtual status_t close() = 0;
+
+ virtual void signalPipelineDrain(const std::vector<int>& streamIds) = 0;
+
+ virtual bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
+ CameraMetadata& newSessionParams) = 0;
+
+ virtual status_t repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) = 0;
/////////////////////////////////////////////////////////////////////
// Implements BufferRecordsInterface
@@ -445,38 +416,36 @@
void onStreamReConfigured(int streamId);
- private:
- // Always valid
- sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
- // Valid if ICameraDeviceSession is @3.3 or newer
- sp<hardware::camera::device::V3_3::ICameraDeviceSession> mHidlSession_3_3;
- // Valid if ICameraDeviceSession is @3.4 or newer
- sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
- // Valid if ICameraDeviceSession is @3.5 or newer
- sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
- // Valid if ICameraDeviceSession is @3.6 or newer
- sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
- // Valid if ICameraDeviceSession is @3.7 or newer
- sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
-
- std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
-
- // The output HIDL request still depends on input camera_capture_request_t
- // Do not free input camera_capture_request_t before output HIDL request
- status_t wrapAsHidlRequest(camera_capture_request_t* in,
- /*out*/hardware::camera::device::V3_2::CaptureRequest* out,
- /*out*/std::vector<native_handle_t*>* handlesCreated,
- /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
-
- status_t pushInflightBufferLocked(int32_t frameNumber, int32_t streamId,
- buffer_handle_t *buffer);
-
- // Pop inflight buffers based on pairs of (frameNumber,streamId)
- void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
+ protected:
// Return true if the input caches match what we have; otherwise false
bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
+ template <typename OfflineSessionInfoT>
+ status_t verifyBufferCaches(
+ const OfflineSessionInfoT *offlineSessionInfo, camera3::BufferRecords *bufferRecords) {
+ // Validate buffer caches
+ std::vector<int32_t> streams;
+ streams.reserve(offlineSessionInfo->offlineStreams.size());
+ for (auto offlineStream : offlineSessionInfo->offlineStreams) {
+ int32_t id = offlineStream.id;
+ streams.push_back(id);
+ // Verify buffer caches
+ std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
+ offlineStream.circulatingBufferIds.end());
+ if (!verifyBufferIds(id, bufIds)) {
+ ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ // Move buffer records
+ bufferRecords->takeBufferCaches(mBufferRecords, streams);
+ bufferRecords->takeInflightBufferMap(mBufferRecords);
+ bufferRecords->takeRequestedBufferMap(mBufferRecords);
+ return OK;
+ }
+
// Delete and optionally close native handles and clear the input vector afterward
static void cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd = false);
@@ -495,7 +464,7 @@
bool mIsReconfigurationQuerySupported;
const bool mSupportOfflineProcessing;
- };
+ }; // class HalInterface
sp<HalInterface> mInterface;
@@ -621,41 +590,6 @@
bool repeating,
int64_t *lastFrameNumber = NULL);
-
- /**
- * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
- */
-
- hardware::Return<void> processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) override;
- hardware::Return<void> processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) override;
- hardware::Return<void> notify(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
-
- hardware::Return<void> requestStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) override;
-
- hardware::Return<void> returnStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
-
- hardware::Return<void> notify_3_8(
- const hardware::hidl_vec<
- hardware::camera::device::V3_8::NotifyMsg>& msgs) override;
-
- template<typename NotifyMsgType>
- hardware::Return<void> notifyHelper(
- const hardware::hidl_vec<NotifyMsgType>& msgs);
-
- // Handle one notify message
- void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
-
// lock to ensure only one processCaptureResult is called at a time.
Mutex mProcessCaptureResultLock;
@@ -673,6 +607,9 @@
*/
virtual CameraMetadata getLatestRequestLocked();
+ virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+ sp<CameraProviderManager> manager) = 0;
+
/**
* Update the current device status and wake all waiting threads.
*
@@ -921,12 +858,6 @@
void signalPipelineDrain(const std::vector<int>& streamIds);
void resetPipelineDrain();
- status_t switchToOffline(
- const std::vector<int32_t>& streamsToKeep,
- /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
- /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
- /*out*/camera3::BufferRecords* bufferRecords);
-
void clearPreviousRequest();
status_t setRotateAndCropAutoBehavior(
@@ -941,7 +872,6 @@
virtual bool threadLoop();
- private:
static const String8& getId(const wp<Camera3Device> &device);
status_t queueTriggerLocked(RequestTrigger trigger);
@@ -1106,6 +1036,14 @@
const bool mUseHalBufManager;
const bool mSupportCameraMute;
};
+
+ virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> /*parent*/,
+ sp<camera3::StatusTracker> /*statusTracker*/,
+ sp<HalInterface> /*interface*/,
+ const Vector<int32_t>& /*sessionParamKeys*/,
+ bool /*useHalBufManager*/,
+ bool /*supportCameraMute*/) = 0;
+
sp<RequestThread> mRequestThread;
/**
@@ -1381,13 +1319,6 @@
~Camera3DeviceInjectionMethods();
- // Initialize the injection camera and generate an hal interface.
- status_t injectionInitialize(
- const String8& injectedCamId, sp<CameraProviderManager> manager,
- const sp<
- android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
- callback);
-
// Injection camera will replace the internal camera and configure streams
// when device is IDLE and request thread is paused.
status_t injectCamera(
@@ -1413,7 +1344,7 @@
const camera3::camera_stream_configuration& injectionConfig,
const std::vector<uint32_t>& injectionBufferSizes);
- private:
+ protected:
// Configure the streams of injection camera, it need wait until the
// output streams are created and configured to the original camera before
// proceeding.
@@ -1426,8 +1357,8 @@
// Use injection camera hal interface to replace and backup original
// camera hal interface.
- status_t replaceHalInterface(sp<HalInterface> newHalInterface,
- bool keepBackup);
+ virtual status_t replaceHalInterface(sp<HalInterface> /*newHalInterface*/,
+ bool /*keepBackup*/) = 0;
wp<Camera3Device> mParent;
@@ -1437,13 +1368,6 @@
// Generated injection camera hal interface.
sp<HalInterface> mInjectedCamHalInterface;
- // Backup of the original camera hal result FMQ.
- std::unique_ptr<ResultMetadataQueue> mBackupResultMetadataQueue;
-
- // FMQ writes the result for the injection camera. Must be guarded by
- // mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mInjectionResultMetadataQueue;
-
// The flag indicates that the stream configuration is complete, the camera device is
// active, but the injection camera has not yet been injected.
bool mIsStreamConfigCompleteButNotInjected = false;
@@ -1464,6 +1388,10 @@
// The injection camera ID.
String8 mInjectedCamId;
};
+
+ virtual sp<Camera3DeviceInjectionMethods>
+ createCamera3DeviceInjectionMethods(wp<Camera3Device>) = 0;
+
sp<Camera3DeviceInjectionMethods> mInjectionMethods;
}; // class Camera3Device
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
index 4744a6d..6818acf 100644
--- a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -39,92 +39,6 @@
injectionDisconnectImpl();
}
-status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(
- const String8& injectedCamId, sp<CameraProviderManager> manager,
- const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
- callback) {
- ATRACE_CALL();
- Mutex::Autolock lock(mInjectionLock);
-
- if (manager == nullptr) {
- ALOGE("%s: manager does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- sp<Camera3Device> parent = mParent.promote();
- if (parent == nullptr) {
- ALOGE("%s: parent does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- mInjectedCamId = injectedCamId;
- sp<ICameraDeviceSession> session;
- ATRACE_BEGIN("Injection CameraHal::openSession");
- status_t res = manager->openSession(injectedCamId.string(), callback,
- /*out*/ &session);
- ATRACE_END();
- if (res != OK) {
- ALOGE("Injection camera could not open camera session: %s (%d)",
- strerror(-res), res);
- return res;
- }
-
- std::shared_ptr<RequestMetadataQueue> queue;
- auto requestQueueRet =
- session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
- queue = std::make_shared<RequestMetadataQueue>(descriptor);
- if (!queue->isValid() || queue->availableToWrite() <= 0) {
- ALOGE("Injection camera HAL returns empty request metadata fmq, not "
- "use it");
- queue = nullptr;
- // don't use the queue onwards.
- }
- });
- if (!requestQueueRet.isOk()) {
- ALOGE("Injection camera transaction error when getting request metadata fmq: "
- "%s, not use it", requestQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
-
- std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
- auto resultQueueRet = session->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
- "it");
- resQueue = nullptr;
- // Don't use the resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Injection camera transaction error when getting result metadata queue "
- "from camera session: %s", resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- IF_ALOGV() {
- session->interfaceChain(
- [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
- interfaceChain) {
- ALOGV("Injection camera session interface chain:");
- for (const auto& iface : interfaceChain) {
- ALOGV(" %s", iface.c_str());
- }
- });
- }
-
- ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
- mInjectedCamHalInterface =
- new HalInterface(session, queue, parent->mUseHalBufManager,
- parent->mSupportOfflineProcessing);
- if (mInjectedCamHalInterface == nullptr) {
- ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- return OK;
-}
-
status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
camera3::camera_stream_configuration& injectionConfig,
const std::vector<uint32_t>& injectionBufferSizes) {
@@ -379,37 +293,4 @@
}
}
-status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
- sp<HalInterface> newHalInterface, bool keepBackup) {
- Mutex::Autolock lock(mInjectionLock);
- if (newHalInterface.get() == nullptr) {
- ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
- __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- sp<Camera3Device> parent = mParent.promote();
- if (parent == nullptr) {
- ALOGE("%s: parent does not exist!", __FUNCTION__);
- return INVALID_OPERATION;
- }
-
- if (keepBackup) {
- if (mBackupHalInterface == nullptr) {
- mBackupHalInterface = parent->mInterface;
- }
- if (mBackupResultMetadataQueue == nullptr) {
- mBackupResultMetadataQueue = std::move(parent->mResultMetadataQueue);
- parent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
- }
- } else {
- mBackupHalInterface = nullptr;
- parent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
- mBackupResultMetadataQueue = nullptr;
- }
- parent->mInterface = newHalInterface;
-
- return OK;
-}
-
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index f4b3197..ba97367 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -34,10 +34,11 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3Stream(id, type,
width, height, maxSize, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
@@ -87,6 +88,7 @@
if (strlen(camera_stream::physical_camera_id) > 0) {
lines.appendFormat(" Physical camera id: %s\n", camera_stream::physical_camera_id);
}
+ lines.appendFormat(" Dynamic Range Profile: 0x%x", camera_stream::dynamic_range_profile);
lines.appendFormat(" Frames produced: %d, last timestamp: %" PRId64 " ns\n",
mFrameCount, mLastTimestamp);
lines.appendFormat(" Total buffers: %zu, currently dequeued: %zu\n",
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index fb73c97..518ee42 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -37,7 +37,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index b702e20..7cfa255 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -47,14 +47,12 @@
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
- const Camera3OfflineStates& offlineStates,
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
+ const Camera3OfflineStates& offlineStates) :
mId(id),
mInputStream(inputStream),
mOutputStreams(offlineStreamSet),
mBufferRecords(std::move(bufferRecords)),
mOfflineReqs(offlineReqs),
- mSession(offlineSession),
mTagMonitor(offlineStates.mTagMonitor),
mVendorTagId(offlineStates.mVendorTagId),
mUseHalBufManager(offlineStates.mUseHalBufManager),
@@ -90,43 +88,6 @@
return mId;
}
-status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
- ATRACE_CALL();
-
- if (mSession == nullptr) {
- ALOGE("%s: HIDL session is null!", __FUNCTION__);
- return DEAD_OBJECT;
- }
-
- {
- std::lock_guard<std::mutex> lock(mLock);
-
- mListener = listener;
-
- // setup result FMQ
- std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
- auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
- [&resQueue](const auto& descriptor) {
- resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
- if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
- ALOGE("HAL returns empty result metadata fmq, not use it");
- resQueue = nullptr;
- // Don't use resQueue onwards.
- }
- });
- if (!resultQueueRet.isOk()) {
- ALOGE("Transaction error when getting result metadata queue from camera session: %s",
- resultQueueRet.description().c_str());
- return DEAD_OBJECT;
- }
- mStatus = STATUS_ACTIVE;
- }
-
- mSession->setCallback(this);
-
- return OK;
-}
-
status_t Camera3OfflineSession::dump(int /*fd*/) {
ATRACE_CALL();
std::lock_guard<std::mutex> il(mInterfaceLock);
@@ -135,6 +96,7 @@
status_t Camera3OfflineSession::disconnect() {
ATRACE_CALL();
+ disconnectSession();
return disconnectImpl();
}
@@ -170,10 +132,6 @@
streams.push_back(mInputStream);
}
- if (mSession != nullptr) {
- mSession->close();
- }
-
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
@@ -182,7 +140,6 @@
{
std::lock_guard<std::mutex> lock(mLock);
- mSession.clear();
mOutputStreams.clear();
mInputStream.clear();
mStatus = STATUS_CLOSED;
@@ -235,149 +192,6 @@
return OK;
}
-hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) {
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
-
- std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) {
- // TODO: changed impl to call into processCaptureResult_3_4 instead?
- // might need to figure how to reduce copy though.
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
-
- std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
- for (const auto& result : results) {
- processOneCaptureResultLocked(states, result, noPhysMetadata);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::notify(
- const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
- sp<NotificationListener> listener;
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- listener = mListener.promote();
- }
-
- CaptureOutputStates states {
- mId,
- mOfflineReqsLock, mLastCompletedRegularFrameNumber,
- mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
- mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
- mNextShutterFrameNumber,
- mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
- mNextResultFrameNumber,
- mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
- mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
- mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
- mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
- mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
- mBufferRecords, /*legacyClient*/ false
- };
- for (const auto& msg : msgs) {
- camera3::notify(states, msg);
- }
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) {
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- }
-
- RequestBufferStates states {
- mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
- *this, mBufferRecords, *this};
- camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
- return hardware::Void();
-}
-
-hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- {
- std::lock_guard<std::mutex> lock(mLock);
- if (mStatus != STATUS_ACTIVE) {
- ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
- return hardware::Void();
- }
- }
-
- ReturnBufferStates states {
- mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords};
- camera3::returnStreamBuffers(states, buffers);
- return hardware::Void();
-}
-
void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 5581964..0f7d145 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -131,7 +131,6 @@
*/
class Camera3OfflineSession :
public CameraOfflineSessionBase,
- virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
@@ -144,12 +143,11 @@
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
- const Camera3OfflineStates& offlineStates,
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession);
+ const Camera3OfflineStates& offlineStates);
virtual ~Camera3OfflineSession();
- virtual status_t initialize(wp<NotificationListener> listener) override;
+ virtual status_t initialize(wp<NotificationListener> /*listener*/) = 0;
/**
* CameraOfflineSessionBase interface
@@ -171,38 +169,7 @@
* End of CameraOfflineSessionBase interface
*/
- /**
- * HIDL ICameraDeviceCallback interface
- */
-
- /**
- * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
- */
-
- hardware::Return<void> processCaptureResult_3_4(
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::CaptureResult>& results) override;
- hardware::Return<void> processCaptureResult(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::CaptureResult>& results) override;
- hardware::Return<void> notify(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
-
- hardware::Return<void> requestStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- requestStreamBuffers_cb _hidl_cb) override;
-
- hardware::Return<void> returnStreamBuffers(
- const hardware::hidl_vec<
- hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
-
- /**
- * End of CameraOfflineSessionBase interface
- */
-
- private:
+ protected:
// Camera device ID
const String8 mId;
sp<camera3::Camera3Stream> mInputStream;
@@ -213,8 +180,6 @@
std::mutex mOfflineReqsLock;
camera3::InFlightRequestMap mOfflineReqs;
- sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
-
TagMonitor mTagMonitor;
const metadata_vendor_id_t mVendorTagId;
@@ -269,8 +234,6 @@
// End of mLock protect scope
std::mutex mProcessCaptureResultLock;
- // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
- std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
// Tracking cause of fatal errors when in STATUS_ERROR
String8 mErrorCause;
@@ -305,6 +268,8 @@
void setErrorStateLockedV(const char *fmt, va_list args);
status_t disconnectImpl();
+ virtual void disconnectSession() = 0;
+
}; // class Camera3OfflineSession
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 0dfeac3..69723b6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -46,10 +46,11 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -74,10 +75,10 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
- setId, isMultiResolution),
+ setId, isMultiResolution, dynamicRangeProfile),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -109,10 +110,11 @@
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mConsumer(nullptr),
mTransform(0),
mTraceFirstBuffer(true),
@@ -149,11 +151,13 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage, nsecs_t timestampOffset,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution,
+ int dynamicRangeProfile) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
format, dataSpace, rotation,
- physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution),
+ physicalCameraId, sensorPixelModesUsed, setId, isMultiResolution,
+ dynamicRangeProfile),
mTransform(0),
mTraceFirstBuffer(true),
mUseMonoTimestamp(false),
@@ -379,6 +383,9 @@
__FUNCTION__, mId, strerror(-res), res);
return res;
}
+
+ queueHDRMetadata(anwBuffer->handle, currentConsumer, dynamic_range_profile);
+
res = queueBufferToConsumer(currentConsumer, anwBuffer, anwReleaseFence, surface_ids);
if (shouldLogError(res, state)) {
ALOGE("%s: Stream %d: Error queueing buffer to native window:"
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index a70b883..d9bf62a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -89,7 +89,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Set up a stream for formats that have a variable buffer size for the same
* dimensions, such as compressed JPEG.
@@ -101,7 +102,8 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Set up a stream with deferred consumer for formats that have 2 dimensions, such as
* RAW and YUV. The consumer must be set before using this stream for output. A valid
@@ -112,7 +114,8 @@
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
virtual ~Camera3OutputStream();
@@ -239,7 +242,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
- int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
/**
* Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index 5e4f38a..d8cc685 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -376,43 +376,6 @@
insertResultLocked(states, &captureResult, frameNumber);
}
-// Reading one camera metadata from result argument via fmq or from the result
-// Assuming the fmq is protected by a lock already
-status_t readOneCameraMetadataLocked(
- std::unique_ptr<ResultMetadataQueue>& fmq,
- uint64_t fmqResultSize,
- hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
- const hardware::camera::device::V3_2::CameraMetadata& result) {
- if (fmqResultSize > 0) {
- resultMetadata.resize(fmqResultSize);
- if (fmq == nullptr) {
- return NO_MEMORY; // logged in initialize()
- }
- if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
- ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
- __FUNCTION__, fmqResultSize);
- return INVALID_OPERATION;
- }
- } else {
- resultMetadata.setToExternal(const_cast<uint8_t *>(result.data()),
- result.size());
- }
-
- if (resultMetadata.size() != 0) {
- status_t res;
- const camera_metadata_t* metadata =
- reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
- size_t expected_metadata_size = resultMetadata.size();
- if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
- ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
- __FUNCTION__, strerror(-res), res);
- return INVALID_OPERATION;
- }
- }
-
- return OK;
-}
-
void removeInFlightMapEntryLocked(CaptureOutputStates& states, int idx) {
ATRACE_CALL();
InFlightRequestMap& inflightMap = states.inflightMap;
@@ -472,7 +435,7 @@
// Note down the just completed frame number
if (request.hasInputBuffer) {
states.lastCompletedReprocessFrameNumber = frameNumber;
- } else if (request.zslCapture) {
+ } else if (request.zslCapture && request.stillCapture) {
states.lastCompletedZslFrameNumber = frameNumber;
} else {
states.lastCompletedRegularFrameNumber = frameNumber;
@@ -719,153 +682,6 @@
}
}
-void processOneCaptureResultLocked(
- CaptureOutputStates& states,
- const hardware::camera::device::V3_2::CaptureResult& result,
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata) {
- using hardware::camera::device::V3_2::StreamBuffer;
- using hardware::camera::device::V3_2::BufferStatus;
- std::unique_ptr<ResultMetadataQueue>& fmq = states.fmq;
- BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
- camera_capture_result r;
- status_t res;
- r.frame_number = result.frameNumber;
-
- // Read and validate the result metadata.
- hardware::camera::device::V3_2::CameraMetadata resultMetadata;
- res = readOneCameraMetadataLocked(
- fmq, result.fmqResultSize,
- resultMetadata, result.result);
- if (res != OK) {
- ALOGE("%s: Frame %d: Failed to read capture result metadata",
- __FUNCTION__, result.frameNumber);
- return;
- }
- r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
-
- // Read and validate physical camera metadata
- size_t physResultCount = physicalCameraMetadata.size();
- std::vector<const char*> physCamIds(physResultCount);
- std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
- std::vector<hardware::camera::device::V3_2::CameraMetadata> physResultMetadata;
- physResultMetadata.resize(physResultCount);
- for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
- res = readOneCameraMetadataLocked(fmq, physicalCameraMetadata[i].fmqMetadataSize,
- physResultMetadata[i], physicalCameraMetadata[i].metadata);
- if (res != OK) {
- ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
- __FUNCTION__, result.frameNumber,
- physicalCameraMetadata[i].physicalCameraId.c_str());
- return;
- }
- physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
- phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
- physResultMetadata[i].data());
- }
- r.num_physcam_metadata = physResultCount;
- r.physcam_ids = physCamIds.data();
- r.physcam_metadata = phyCamMetadatas.data();
-
- std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
- std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
- for (size_t i = 0; i < result.outputBuffers.size(); i++) {
- auto& bDst = outputBuffers[i];
- const StreamBuffer &bSrc = result.outputBuffers[i];
-
- sp<Camera3StreamInterface> stream = states.outputStreams.get(bSrc.streamId);
- if (stream == nullptr) {
- ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- return;
- }
- bDst.stream = stream->asHalStream();
-
- bool noBufferReturned = false;
- buffer_handle_t *buffer = nullptr;
- if (states.useHalBufManager) {
- // This is suspicious most of the time but can be correct during flush where HAL
- // has to return capture result before a buffer is requested
- if (bSrc.bufferId == BUFFER_ID_NO_BUFFER) {
- if (bSrc.status == BufferStatus::OK) {
- ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- // Still proceeds so other buffers can be returned
- }
- noBufferReturned = true;
- }
- if (noBufferReturned) {
- res = OK;
- } else {
- res = bufferRecords.popInflightRequestBuffer(bSrc.bufferId, &buffer);
- }
- } else {
- res = bufferRecords.popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
- }
-
- if (res != OK) {
- ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
- __FUNCTION__, result.frameNumber, i, bSrc.streamId);
- return;
- }
-
- bDst.buffer = buffer;
- bDst.status = mapHidlBufferStatus(bSrc.status);
- bDst.acquire_fence = -1;
- if (bSrc.releaseFence == nullptr) {
- bDst.release_fence = -1;
- } else if (bSrc.releaseFence->numFds == 1) {
- if (noBufferReturned) {
- ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
- }
- bDst.release_fence = dup(bSrc.releaseFence->data[0]);
- } else {
- ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
- __FUNCTION__, result.frameNumber, i, bSrc.releaseFence->numFds);
- return;
- }
- }
- r.num_output_buffers = outputBuffers.size();
- r.output_buffers = outputBuffers.data();
-
- camera_stream_buffer_t inputBuffer;
- if (result.inputBuffer.streamId == -1) {
- r.input_buffer = nullptr;
- } else {
- if (states.inputStream->getId() != result.inputBuffer.streamId) {
- ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
- result.frameNumber, result.inputBuffer.streamId);
- return;
- }
- inputBuffer.stream = states.inputStream->asHalStream();
- buffer_handle_t *buffer;
- res = bufferRecords.popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
- &buffer);
- if (res != OK) {
- ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
- __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
- return;
- }
- inputBuffer.buffer = buffer;
- inputBuffer.status = mapHidlBufferStatus(result.inputBuffer.status);
- inputBuffer.acquire_fence = -1;
- if (result.inputBuffer.releaseFence == nullptr) {
- inputBuffer.release_fence = -1;
- } else if (result.inputBuffer.releaseFence->numFds == 1) {
- inputBuffer.release_fence = dup(result.inputBuffer.releaseFence->data[0]);
- } else {
- ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
- __FUNCTION__, result.frameNumber, result.inputBuffer.releaseFence->numFds);
- return;
- }
- r.input_buffer = &inputBuffer;
- }
-
- r.partial_result = result.partialResult;
-
- processCaptureResult(states, &r);
-}
-
void returnOutputBuffers(
bool useHalBufManager,
sp<NotificationListener> listener,
@@ -969,7 +785,8 @@
void returnAndRemovePendingOutputBuffers(bool useHalBufManager,
sp<NotificationListener> listener, InFlightRequest& request,
SessionStatsBuilder& sessionStatsBuilder) {
- bool timestampIncreasing = !(request.zslCapture || request.hasInputBuffer);
+ bool timestampIncreasing =
+ !((request.zslCapture && request.stillCapture) || request.hasInputBuffer);
returnOutputBuffers(useHalBufManager, listener,
request.pendingOutputBuffers.array(),
request.pendingOutputBuffers.size(),
@@ -1193,330 +1010,6 @@
}
}
-void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_8::NotifyMsg& msg) {
- using android::hardware::camera::device::V3_2::MsgType;
-
- hardware::camera::device::V3_2::NotifyMsg msg_3_2;
- msg_3_2.type = msg.type;
- bool hasReadoutTime = false;
- uint64_t readoutTime = 0;
- switch (msg.type) {
- case MsgType::ERROR:
- msg_3_2.msg.error = msg.msg.error;
- break;
- case MsgType::SHUTTER:
- msg_3_2.msg.shutter = msg.msg.shutter.v3_2;
- hasReadoutTime = true;
- readoutTime = msg.msg.shutter.readoutTimestamp;
- break;
- }
- notify(states, msg_3_2, hasReadoutTime, readoutTime);
-}
-
-void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_2::NotifyMsg& msg,
- bool hasReadoutTime, uint64_t readoutTime) {
-
- using android::hardware::camera::device::V3_2::MsgType;
- using android::hardware::camera::device::V3_2::ErrorCode;
-
- ATRACE_CALL();
- camera_notify_msg m;
- switch (msg.type) {
- case MsgType::ERROR:
- m.type = CAMERA_MSG_ERROR;
- m.message.error.frame_number = msg.msg.error.frameNumber;
- if (msg.msg.error.errorStreamId >= 0) {
- sp<Camera3StreamInterface> stream =
- states.outputStreams.get(msg.msg.error.errorStreamId);
- if (stream == nullptr) {
- ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
- m.message.error.frame_number, msg.msg.error.errorStreamId);
- return;
- }
- m.message.error.error_stream = stream->asHalStream();
- } else {
- m.message.error.error_stream = nullptr;
- }
- switch (msg.msg.error.errorCode) {
- case ErrorCode::ERROR_DEVICE:
- m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
- break;
- case ErrorCode::ERROR_REQUEST:
- m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
- break;
- case ErrorCode::ERROR_RESULT:
- m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
- break;
- case ErrorCode::ERROR_BUFFER:
- m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
- break;
- }
- break;
- case MsgType::SHUTTER:
- m.type = CAMERA_MSG_SHUTTER;
- m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
- m.message.shutter.timestamp = msg.msg.shutter.timestamp;
- m.message.shutter.readout_timestamp = hasReadoutTime ?
- readoutTime : m.message.shutter.timestamp;
- break;
- }
- notify(states, &m);
-}
-
-// The buffers requested through this call are not tied to any CaptureRequest in
-// particular. They may used by the hal for a particular frame's output buffer
-// or for its internal use as well. In the case that the hal does use any buffer
-// from the requested list here, for a particular frame's output buffer, the
-// buffer will be returned with the processCaptureResult call corresponding to
-// the frame. The other buffers will be returned through returnStreamBuffers.
-// The buffers returned via returnStreamBuffers will not have a valid
-// timestamp(0) and will be dropped by the bufferqueue.
-void requestStreamBuffers(RequestBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
- using android::hardware::camera::device::V3_2::BufferStatus;
- using android::hardware::camera::device::V3_2::StreamBuffer;
- using android::hardware::camera::device::V3_5::BufferRequestStatus;
- using android::hardware::camera::device::V3_5::StreamBufferRet;
- using android::hardware::camera::device::V3_5::StreamBufferRequestError;
-
- std::lock_guard<std::mutex> lock(states.reqBufferLock);
-
- hardware::hidl_vec<StreamBufferRet> bufRets;
- if (!states.useHalBufManager) {
- ALOGE("%s: Camera %s does not support HAL buffer management",
- __FUNCTION__, states.cameraId.string());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- SortedVector<int32_t> streamIds;
- ssize_t sz = streamIds.setCapacity(bufReqs.size());
- if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
- ALOGE("%s: failed to allocate memory for %zu buffer requests",
- __FUNCTION__, bufReqs.size());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- if (bufReqs.size() > states.outputStreams.size()) {
- ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
- __FUNCTION__, bufReqs.size(), states.outputStreams.size());
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
-
- // Check for repeated streamId
- for (const auto& bufReq : bufReqs) {
- if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
- ALOGE("%s: Stream %d appear multiple times in buffer requests",
- __FUNCTION__, bufReq.streamId);
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
- return;
- }
- streamIds.add(bufReq.streamId);
- }
-
- if (!states.reqBufferIntf.startRequestBuffer()) {
- ALOGE("%s: request buffer disallowed while camera service is configuring",
- __FUNCTION__);
- _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
- return;
- }
-
- bufRets.resize(bufReqs.size());
-
- bool allReqsSucceeds = true;
- bool oneReqSucceeds = false;
- for (size_t i = 0; i < bufReqs.size(); i++) {
- const auto& bufReq = bufReqs[i];
- auto& bufRet = bufRets[i];
- int32_t streamId = bufReq.streamId;
- sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
- if (outputStream == nullptr) {
- ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
- hardware::hidl_vec<StreamBufferRet> emptyBufRets;
- _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
- states.reqBufferIntf.endRequestBuffer();
- return;
- }
-
- bufRet.streamId = streamId;
- if (outputStream->isAbandoned()) {
- bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
- allReqsSucceeds = false;
- continue;
- }
-
- size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
- uint32_t numBuffersRequested = bufReq.numBuffersRequested;
- size_t totalHandout = handOutBufferCount + numBuffersRequested;
- uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
- if (totalHandout > maxBuffers) {
- // Not able to allocate enough buffer. Exit early for this stream
- ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
- " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
- numBuffersRequested, maxBuffers);
- bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
- allReqsSucceeds = false;
- continue;
- }
-
- hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
- bool currentReqSucceeds = true;
- std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
- std::vector<buffer_handle_t> newBuffers;
- size_t numAllocatedBuffers = 0;
- size_t numPushedInflightBuffers = 0;
- for (size_t b = 0; b < numBuffersRequested; b++) {
- camera_stream_buffer_t& sb = streamBuffers[b];
- // Since this method can run concurrently with request thread
- // We need to update the wait duration everytime we call getbuffer
- nsecs_t waitDuration = states.reqBufferIntf.getWaitDuration();
- status_t res = outputStream->getBuffer(&sb, waitDuration);
- if (res != OK) {
- if (res == NO_INIT || res == DEAD_OBJECT) {
- ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
- states.sessionStatsBuilder.stopCounter(streamId);
- } else {
- ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- if (res == TIMED_OUT || res == NO_MEMORY) {
- bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
- } else {
- bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
- }
- }
- currentReqSucceeds = false;
- break;
- }
- numAllocatedBuffers++;
-
- buffer_handle_t *buffer = sb.buffer;
- auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
- bool isNewBuffer = pair.first;
- uint64_t bufferId = pair.second;
- StreamBuffer& hBuf = tmpRetBuffers[b];
-
- hBuf.streamId = streamId;
- hBuf.bufferId = bufferId;
- hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
- hBuf.status = BufferStatus::OK;
- hBuf.releaseFence = nullptr;
- if (isNewBuffer) {
- newBuffers.push_back(*buffer);
- }
-
- native_handle_t *acquireFence = nullptr;
- if (sb.acquire_fence != -1) {
- acquireFence = native_handle_create(1,0);
- acquireFence->data[0] = sb.acquire_fence;
- }
- hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
- hBuf.releaseFence = nullptr;
-
- res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
- if (res != OK) {
- ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
- currentReqSucceeds = false;
- break;
- }
- numPushedInflightBuffers++;
- }
- if (currentReqSucceeds) {
- bufRet.val.buffers(std::move(tmpRetBuffers));
- oneReqSucceeds = true;
- } else {
- allReqsSucceeds = false;
- for (size_t b = 0; b < numPushedInflightBuffers; b++) {
- StreamBuffer& hBuf = tmpRetBuffers[b];
- buffer_handle_t* buffer;
- status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
- hBuf.bufferId, &buffer);
- if (res != OK) {
- SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
- __FUNCTION__, streamId, strerror(-res), res);
- }
- }
- for (size_t b = 0; b < numAllocatedBuffers; b++) {
- camera_stream_buffer_t& sb = streamBuffers[b];
- sb.acquire_fence = -1;
- sb.status = CAMERA_BUFFER_STATUS_ERROR;
- }
- returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
- streamBuffers.data(), numAllocatedBuffers, /*timestamp*/0,
- /*readoutTimestamp*/0, /*requested*/false,
- /*requestTimeNs*/0, states.sessionStatsBuilder);
- for (auto buf : newBuffers) {
- states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
- }
- }
- }
-
- _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
- oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
- BufferRequestStatus::FAILED_UNKNOWN,
- bufRets);
- states.reqBufferIntf.endRequestBuffer();
-}
-
-void returnStreamBuffers(ReturnBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
- if (!states.useHalBufManager) {
- ALOGE("%s: Camera %s does not support HAL buffer managerment",
- __FUNCTION__, states.cameraId.string());
- return;
- }
-
- for (const auto& buf : buffers) {
- if (buf.bufferId == BUFFER_ID_NO_BUFFER) {
- ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
- continue;
- }
-
- buffer_handle_t* buffer;
- status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(buf.bufferId, &buffer);
-
- if (res != OK) {
- ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
- __FUNCTION__, buf.bufferId, buf.streamId);
- continue;
- }
-
- camera_stream_buffer_t streamBuffer;
- streamBuffer.buffer = buffer;
- streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
- streamBuffer.acquire_fence = -1;
- streamBuffer.release_fence = -1;
-
- if (buf.releaseFence == nullptr) {
- streamBuffer.release_fence = -1;
- } else if (buf.releaseFence->numFds == 1) {
- streamBuffer.release_fence = dup(buf.releaseFence->data[0]);
- } else {
- ALOGE("%s: Invalid release fence, fd count is %d, not 1",
- __FUNCTION__, buf.releaseFence->numFds);
- continue;
- }
-
- sp<Camera3StreamInterface> stream = states.outputStreams.get(buf.streamId);
- if (stream == nullptr) {
- ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
- continue;
- }
- streamBuffer.stream = stream->asHalStream();
- returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
- &streamBuffer, /*size*/1, /*timestamp*/ 0, /*readoutTimestamp*/0,
- /*requested*/false, /*requestTimeNs*/0, states.sessionStatsBuilder);
- }
-}
-
void flushInflightRequests(FlushInflightReqStates& states) {
ATRACE_CALL();
{ // First return buffers cached in inFlightMap
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 51899ee..4d1eb75 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -40,8 +40,6 @@
namespace android {
-using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
-
namespace camera3 {
/**
@@ -97,7 +95,6 @@
const metadata_vendor_id_t vendorTagId;
const CameraMetadata& deviceInfo;
const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap;
- std::unique_ptr<ResultMetadataQueue>& fmq;
std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers;
std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers;
std::unordered_map<std::string, camera3::RotateAndCropMapper>& rotateAndCropMappers;
@@ -112,20 +109,8 @@
bool legacyClient;
};
- // Handle one capture result. Assume callers hold the lock to serialize all
- // processCaptureResult calls
- void processOneCaptureResultLocked(
- CaptureOutputStates& states,
- const hardware::camera::device::V3_2::CaptureResult& result,
- const hardware::hidl_vec<
- hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
-
- // Handle one notify message
- void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_2::NotifyMsg& msg,
- bool hasReadoutTime = false, uint64_t readoutTime = 0LL);
- void notify(CaptureOutputStates& states,
- const hardware::camera::device::V3_8::NotifyMsg& msg);
+ void processCaptureResult(CaptureOutputStates& states, const camera_capture_result *result);
+ void notify(CaptureOutputStates& states, const camera_notify_msg *msg);
struct RequestBufferStates {
const String8& cameraId;
@@ -138,10 +123,6 @@
RequestBufferInterface& reqBufferIntf;
};
- void requestStreamBuffers(RequestBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
- hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb);
-
struct ReturnBufferStates {
const String8& cameraId;
const bool useHalBufManager;
@@ -150,9 +131,6 @@
BufferRecordsInterface& bufferRecordsIntf;
};
- void returnStreamBuffers(ReturnBufferStates& states,
- const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
-
struct FlushInflightReqStates {
const String8& cameraId;
std::mutex& inflightLock;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
new file mode 100644
index 0000000..7dc8e10
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA3_OUTPUT_TEMPLUTILS_H
+#define ANDROID_SERVERS_CAMERA3_OUTPUT_TEMPLUTILS_H
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <aidl/android/hardware/common/NativeHandle.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+
+#include <camera/CameraUtils.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/Camera3OutputUtils.h"
+
+#include "system/camera_metadata.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+template <class BufferStatusType>
+camera_buffer_status_t mapBufferStatus(BufferStatusType status) {
+ switch (status) {
+ case BufferStatusType::OK: return CAMERA_BUFFER_STATUS_OK;
+ case BufferStatusType::ERROR: return CAMERA_BUFFER_STATUS_ERROR;
+ }
+ return CAMERA_BUFFER_STATUS_ERROR;
+}
+
+inline void readBufferFromVec(hardware::hidl_vec<uint8_t> &dst,
+ const hardware::hidl_vec<uint8_t> &src) {
+ // Not cloning here since that will be done in processCaptureResult whil
+ // assigning to CameraMetadata.
+ dst.setToExternal(const_cast<uint8_t *>(src.data()), src.size());
+}
+
+inline void readBufferFromVec(std::vector<uint8_t> &dst, const std::vector<uint8_t> &src) {
+ // TODO: Check if we're really supposed to copy
+ dst = src;
+}
+// Reading one camera metadata from result argument via fmq or from the result
+// Assuming the fmq is protected by a lock already
+template <class FmqType, class MetadataType>
+status_t readOneCameraMetadataLockedT(
+ std::unique_ptr<FmqType>& fmq,
+ uint64_t fmqResultSize,
+ MetadataType& resultMetadata,
+ const MetadataType& result) {
+ if (fmqResultSize > 0) {
+ resultMetadata.resize(fmqResultSize);
+ if (fmq == nullptr) {
+ return NO_MEMORY; // logged in initialize()
+ }
+ if (!fmq->read(resultMetadata.data(), fmqResultSize)) {
+ ALOGE("%s: Cannot read camera metadata from fmq, size = %" PRIu64,
+ __FUNCTION__, fmqResultSize);
+ return INVALID_OPERATION;
+ }
+ } else {
+ readBufferFromVec(resultMetadata, result);
+ }
+
+ if (resultMetadata.size() != 0) {
+ status_t res;
+ const camera_metadata_t* metadata =
+ reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+ size_t expected_metadata_size = resultMetadata.size();
+ if ((res = validate_camera_metadata_structure(metadata, &expected_metadata_size)) != OK) {
+ ALOGE("%s: Invalid camera metadata received by camera service from HAL: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ }
+
+ return OK;
+}
+
+inline bool isHandleNull(const hardware::hidl_handle &handle) {
+ return handle == nullptr;
+}
+
+inline bool isHandleNull(const aidl::android::hardware::common::NativeHandle &handle) {
+ return (handle.fds.size() == 0) && (handle.ints.size() == 0);
+}
+
+inline size_t numFdsInHandle(const hardware::hidl_handle &handle) {
+ return handle->numFds;
+}
+
+inline size_t numFdsInHandle(const aidl::android::hardware::common::NativeHandle &handle) {
+ return handle.fds.size();
+}
+
+inline int32_t getHandleFirstFd(const hardware::hidl_handle &handle) {
+ if (handle->numFds != 1) {
+ return -1;
+ }
+ return handle->data[0];
+}
+
+inline int32_t getHandleFirstFd(const aidl::android::hardware::common::NativeHandle &handle) {
+ if (handle.fds.size() != 1) {
+ return -1;
+ }
+ return handle.fds[0].get();
+}
+
+template <class StatesType, class CaptureResultType, class PhysMetadataType, class MetadataType,
+ class FmqType, class BufferStatusType>
+void processOneCaptureResultLockedT(
+ StatesType& states,
+ const CaptureResultType& result,
+ const PhysMetadataType &physicalCameraMetadata) {
+ std::unique_ptr<FmqType>& fmq = states.fmq;
+ BufferRecordsInterface& bufferRecords = states.bufferRecordsIntf;
+ camera_capture_result r;
+ status_t res;
+ r.frame_number = result.frameNumber;
+
+ // Read and validate the result metadata.
+ MetadataType resultMetadata;
+ res = readOneCameraMetadataLockedT(
+ fmq, result.fmqResultSize,
+ resultMetadata, result.result);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Failed to read capture result metadata",
+ __FUNCTION__, result.frameNumber);
+ return;
+ }
+ r.result = reinterpret_cast<const camera_metadata_t*>(resultMetadata.data());
+
+ // Read and validate physical camera metadata
+ size_t physResultCount = physicalCameraMetadata.size();
+ std::vector<const char*> physCamIds(physResultCount);
+ std::vector<const camera_metadata_t *> phyCamMetadatas(physResultCount);
+ std::vector<MetadataType> physResultMetadata;
+ physResultMetadata.resize(physResultCount);
+ for (size_t i = 0; i < physicalCameraMetadata.size(); i++) {
+ res = readOneCameraMetadataLockedT(fmq, physicalCameraMetadata[i].fmqMetadataSize,
+ physResultMetadata[i], physicalCameraMetadata[i].metadata);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Failed to read capture result metadata for camera %s",
+ __FUNCTION__, result.frameNumber,
+ physicalCameraMetadata[i].physicalCameraId.c_str());
+ return;
+ }
+ physCamIds[i] = physicalCameraMetadata[i].physicalCameraId.c_str();
+ phyCamMetadatas[i] = reinterpret_cast<const camera_metadata_t*>(
+ physResultMetadata[i].data());
+ }
+ r.num_physcam_metadata = physResultCount;
+ r.physcam_ids = physCamIds.data();
+ r.physcam_metadata = phyCamMetadatas.data();
+
+ std::vector<camera_stream_buffer_t> outputBuffers(result.outputBuffers.size());
+ std::vector<buffer_handle_t> outputBufferHandles(result.outputBuffers.size());
+ for (size_t i = 0; i < result.outputBuffers.size(); i++) {
+ auto& bDst = outputBuffers[i];
+ const auto &bSrc = result.outputBuffers[i];
+
+ sp<Camera3StreamInterface> stream = states.outputStreams.get(bSrc.streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Frame %d: Buffer %zu: Invalid output stream id %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ return;
+ }
+ bDst.stream = stream->asHalStream();
+
+ bool noBufferReturned = false;
+ buffer_handle_t *buffer = nullptr;
+ if (states.useHalBufManager) {
+ // This is suspicious most of the time but can be correct during flush where HAL
+ // has to return capture result before a buffer is requested
+ if (bSrc.bufferId == BUFFER_ID_NO_BUFFER) {
+ if (bSrc.status == BufferStatusType::OK) {
+ ALOGE("%s: Frame %d: Buffer %zu: No bufferId for stream %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ // Still proceeds so other buffers can be returned
+ }
+ noBufferReturned = true;
+ }
+ if (noBufferReturned) {
+ res = OK;
+ } else {
+ res = bufferRecords.popInflightRequestBuffer(bSrc.bufferId, &buffer);
+ }
+ } else {
+ res = bufferRecords.popInflightBuffer(result.frameNumber, bSrc.streamId, &buffer);
+ }
+
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Buffer %zu: No in-flight buffer for stream %d",
+ __FUNCTION__, result.frameNumber, i, bSrc.streamId);
+ return;
+ }
+
+ bDst.buffer = buffer;
+ bDst.status = mapBufferStatus<BufferStatusType>(bSrc.status);
+ bDst.acquire_fence = -1;
+ if (isHandleNull(bSrc.releaseFence)) {
+ bDst.release_fence = -1;
+ } else if (numFdsInHandle(bSrc.releaseFence) == 1) {
+ if (noBufferReturned) {
+ ALOGE("%s: got releaseFence without output buffer!", __FUNCTION__);
+ }
+ bDst.release_fence = dup(getHandleFirstFd(bSrc.releaseFence));
+ } else {
+ ALOGE("%s: Frame %d: Invalid release fence for buffer %zu, fd count is %d, not 1",
+ __FUNCTION__, result.frameNumber, i, (int)numFdsInHandle(bSrc.releaseFence));
+ return;
+ }
+ }
+ r.num_output_buffers = outputBuffers.size();
+ r.output_buffers = outputBuffers.data();
+
+ camera_stream_buffer_t inputBuffer;
+ if (result.inputBuffer.streamId == -1) {
+ r.input_buffer = nullptr;
+ } else {
+ if (states.inputStream->getId() != result.inputBuffer.streamId) {
+ ALOGE("%s: Frame %d: Invalid input stream id %d", __FUNCTION__,
+ result.frameNumber, result.inputBuffer.streamId);
+ return;
+ }
+ inputBuffer.stream = states.inputStream->asHalStream();
+ buffer_handle_t *buffer;
+ res = bufferRecords.popInflightBuffer(result.frameNumber, result.inputBuffer.streamId,
+ &buffer);
+ if (res != OK) {
+ ALOGE("%s: Frame %d: Input buffer: No in-flight buffer for stream %d",
+ __FUNCTION__, result.frameNumber, result.inputBuffer.streamId);
+ return;
+ }
+ inputBuffer.buffer = buffer;
+ inputBuffer.status = mapBufferStatus<BufferStatusType>(result.inputBuffer.status);
+ inputBuffer.acquire_fence = -1;
+ if (isHandleNull(result.inputBuffer.releaseFence)) {
+ inputBuffer.release_fence = -1;
+ } else if (numFdsInHandle(result.inputBuffer.releaseFence) == 1) {
+ inputBuffer.release_fence = dup(getHandleFirstFd(result.inputBuffer.releaseFence));
+ } else {
+ ALOGE("%s: Frame %d: Invalid release fence for input buffer, fd count is %d, not 1",
+ __FUNCTION__, result.frameNumber,
+ (int)numFdsInHandle(result.inputBuffer.releaseFence));
+ return;
+ }
+ r.input_buffer = &inputBuffer;
+ }
+
+ r.partial_result = result.partialResult;
+
+ processCaptureResult(states, &r);
+}
+
+template <class VecStreamBufferType>
+void returnStreamBuffersT(ReturnBufferStates& states,
+ const VecStreamBufferType& buffers) {
+ if (!states.useHalBufManager) {
+ ALOGE("%s: Camera %s does not support HAL buffer managerment",
+ __FUNCTION__, states.cameraId.string());
+ return;
+ }
+
+ for (const auto& buf : buffers) {
+ if (buf.bufferId == BUFFER_ID_NO_BUFFER) {
+ ALOGE("%s: cannot return a buffer without bufferId", __FUNCTION__);
+ continue;
+ }
+
+ buffer_handle_t* buffer;
+ status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(buf.bufferId, &buffer);
+
+ if (res != OK) {
+ ALOGE("%s: cannot find in-flight buffer %" PRIu64 " for stream %d",
+ __FUNCTION__, buf.bufferId, buf.streamId);
+ continue;
+ }
+
+ camera_stream_buffer_t streamBuffer;
+ streamBuffer.buffer = buffer;
+ streamBuffer.status = CAMERA_BUFFER_STATUS_ERROR;
+ streamBuffer.acquire_fence = -1;
+ streamBuffer.release_fence = -1;
+
+ if (isHandleNull(buf.releaseFence)) {
+ streamBuffer.release_fence = -1;
+ } else if (numFdsInHandle(buf.releaseFence) == 1) {
+ streamBuffer.release_fence = dup(getHandleFirstFd(buf.releaseFence));
+ } else {
+ ALOGE("%s: Invalid release fence, fd count is %d, not 1",
+ __FUNCTION__, (int)numFdsInHandle(buf.releaseFence));
+ continue;
+ }
+
+ sp<Camera3StreamInterface> stream = states.outputStreams.get(buf.streamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Output stream id %d not found!", __FUNCTION__, buf.streamId);
+ continue;
+ }
+ streamBuffer.stream = stream->asHalStream();
+ returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+ &streamBuffer, /*size*/1, /*timestamp*/ 0, /*readoutTimestamp*/0,
+ /*requested*/false, /*requestTimeNs*/0, states.sessionStatsBuilder);
+ }
+}
+
+} // camera3
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 9e0c8f3..0e2671a 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -33,10 +33,10 @@
camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool useHalBufManager) :
+ int setId, bool useHalBufManager, int dynamicProfile) :
Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
- consumerUsage, timestampOffset, setId),
+ consumerUsage, timestampOffset, setId, dynamicProfile),
mUseHalBufManager(useHalBufManager) {
size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
if (surfaces.size() > consumerCount) {
@@ -67,7 +67,7 @@
}
res = mStreamSplitter->connect(initialSurfaces, usage, mUsage, camera_stream::max_buffers,
- getWidth(), getHeight(), getFormat(), &mConsumer);
+ getWidth(), getHeight(), getFormat(), &mConsumer, camera_stream::dynamic_range_profile);
if (res != OK) {
ALOGE("%s: Failed to connect to stream splitter: %s(%d)",
__FUNCTION__, strerror(-res), res);
@@ -388,13 +388,15 @@
bool sizeMismatch = ((static_cast<uint32_t>(infoIt.width) != getWidth()) ||
(static_cast<uint32_t> (infoIt.height) != getHeight())) ?
true : false;
- if ((imgReaderUsage && sizeMismatch) ||
+ bool dynamicRangeMismatch = dynamic_range_profile != infoIt.dynamicRangeProfile;
+ if ((imgReaderUsage && sizeMismatch) || dynamicRangeMismatch ||
(infoIt.format != getOriginalFormat() && infoIt.format != getFormat()) ||
(infoIt.dataSpace != getDataSpace() &&
infoIt.dataSpace != getOriginalDataSpace())) {
- ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x "
- " don't match source stream format: 0x%x dataSpace: 0x%x", __FUNCTION__,
- infoIt.format, infoIt.dataSpace, getFormat(), getDataSpace());
+ ALOGE("%s: Shared surface parameters format: 0x%x dataSpace: 0x%x dynamic range 0x%x "
+ " don't match source stream format: 0x%x dataSpace: 0x%x dynamic range 0x%x"
+ , __FUNCTION__, infoIt.format, infoIt.dataSpace, infoIt.dynamicRangeProfile,
+ getFormat(), getDataSpace(), dynamic_range_profile);
return BAD_VALUE;
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 4b6341b..fafa26f 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -40,7 +40,8 @@
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
int setId = CAMERA3_STREAM_SET_ID_INVALID,
- bool useHalBufManager = false);
+ bool useHalBufManager = false,
+ int dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
virtual ~Camera3SharedOutputStream();
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 1405fa1..83f9a98 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <vector>
+#include "system/window.h"
#define LOG_TAG "Camera3-Stream"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
@@ -23,6 +25,7 @@
#include "device3/Camera3Stream.h"
#include "device3/StatusTracker.h"
#include "utils/TraceHFR.h"
+#include "ui/GraphicBufferMapper.h"
#include <cutils/properties.h>
@@ -51,7 +54,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution) :
+ int setId, bool isMultiResolution, int dynamicRangeProfile) :
camera_stream(),
mId(id),
mSetId(setId),
@@ -87,6 +90,7 @@
camera_stream::max_buffers = 0;
camera_stream::physical_camera_id = mPhysicalCameraId.string();
camera_stream::sensor_pixel_modes_used = sensorPixelModesUsed;
+ camera_stream::dynamic_range_profile = dynamicRangeProfile;
if ((format == HAL_PIXEL_FORMAT_BLOB || format == HAL_PIXEL_FORMAT_RAW_OPAQUE) &&
maxSize == 0) {
@@ -147,6 +151,10 @@
return mOriginalFormat;
}
+int Camera3Stream::getDynamicRangeProfile() const {
+ return camera_stream::dynamic_range_profile;
+}
+
void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
mDataSpaceOverridden = dataSpaceOverridden;
}
@@ -1078,6 +1086,52 @@
return res;
}
+void Camera3Stream::queueHDRMetadata(buffer_handle_t buffer, sp<ANativeWindow>& anw,
+ int dynamicRangeProfile) {
+ auto& mapper = GraphicBufferMapper::get();
+ switch (dynamicRangeProfile) {
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10: {
+ std::optional<ui::Smpte2086> smpte2086;
+ auto res = mapper.getSmpte2086(buffer, &smpte2086);
+ if ((res == OK) && smpte2086.has_value()) {
+ const auto& metaValue = smpte2086.value();
+ android_smpte2086_metadata meta = {
+ .displayPrimaryRed.x = metaValue.primaryRed.x,
+ .displayPrimaryRed.y = metaValue.primaryRed.y,
+ .displayPrimaryGreen.x = metaValue.primaryGreen.x,
+ .displayPrimaryGreen.y = metaValue.primaryGreen.y,
+ .displayPrimaryBlue.x = metaValue.primaryBlue.x,
+ .displayPrimaryBlue.y = metaValue.primaryBlue.y,
+ .whitePoint.x = metaValue.whitePoint.x,
+ .whitePoint.y = metaValue.whitePoint.y,
+ .maxLuminance = metaValue.maxLuminance,
+ .minLuminance = metaValue.minLuminance};
+ native_window_set_buffers_smpte2086_metadata(anw.get(), &meta);
+ } else {
+ ALOGE("%s Couldn't retrieve Smpte2086 metadata %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ break;
+ }
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS: {
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ auto res = mapper.getSmpte2094_40(buffer, &smpte2094_40);
+ if ((res == OK) && smpte2094_40.has_value()) {
+ native_window_set_buffers_hdr10_plus_metadata(anw.get(),
+ smpte2094_40.value().size(), smpte2094_40.value().data());
+ } else {
+ ALOGE("%s Couldn't retrieve Smpte2094_40 metadata %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ }
+ break;
+ }
+ default:
+ // No-op
+ break;
+ }
+}
+
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 17041de..bbbea8d 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -138,6 +138,10 @@
static Camera3Stream* cast(camera_stream *stream);
static const Camera3Stream* cast(const camera_stream *stream);
+ // Queue corresponding HDR metadata to given native window.
+ static void queueHDRMetadata(buffer_handle_t buffer, sp<ANativeWindow>& anw,
+ int dynamicRangeProfile);
+
/**
* Get the stream's ID
*/
@@ -168,6 +172,7 @@
void setFormatOverride(bool formatOverriden);
bool isFormatOverridden() const;
int getOriginalFormat() const;
+ int getDynamicRangeProfile() const;
void setDataSpaceOverride(bool dataSpaceOverriden);
bool isDataSpaceOverridden() const;
android_dataspace getOriginalDataSpace() const;
@@ -500,7 +505,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
- int setId, bool isMultiResolution);
+ int setId, bool isMultiResolution, int dynamicRangeProfile);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 5f20f17..ef10f0d 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -64,6 +64,7 @@
const char* physical_camera_id;
std::unordered_set<int32_t> sensor_pixel_modes_used;
+ int dynamic_range_profile;
} camera_stream_t;
typedef struct camera_stream_buffer {
@@ -107,14 +108,17 @@
bool finalized = false;
bool supportsOffline = false;
std::unordered_set<int32_t> sensorPixelModesUsed;
+ int dynamicRangeProfile;
OutputStreamInfo() :
width(-1), height(-1), format(-1), dataSpace(HAL_DATASPACE_UNKNOWN),
- consumerUsage(0) {}
+ consumerUsage(0),
+ dynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {}
OutputStreamInfo(int _width, int _height, int _format, android_dataspace _dataSpace,
- uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed) :
+ uint64_t _consumerUsage, const std::unordered_set<int32_t>& _sensorPixelModesUsed,
+ int _dynamicRangeProfile) :
width(_width), height(_height), format(_format),
dataSpace(_dataSpace), consumerUsage(_consumerUsage),
- sensorPixelModesUsed(_sensorPixelModesUsed) {}
+ sensorPixelModesUsed(_sensorPixelModesUsed), dynamicRangeProfile(_dynamicRangeProfile){}
};
/**
@@ -154,6 +158,7 @@
virtual uint32_t getWidth() const = 0;
virtual uint32_t getHeight() const = 0;
virtual int getFormat() const = 0;
+ virtual int getDynamicRangeProfile() const = 0;
virtual android_dataspace getDataSpace() const = 0;
virtual void setFormatOverride(bool formatOverriden) = 0;
virtual bool isFormatOverridden() const = 0;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 5c6c518..1149d13 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -34,13 +34,16 @@
#include <cutils/atomic.h>
+#include "Camera3Stream.h"
+
#include "Camera3StreamSplitter.h"
namespace android {
status_t Camera3StreamSplitter::connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
- uint32_t height, android::PixelFormat format, sp<Surface>* consumer) {
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
+ int dynamicRangeProfile) {
ATRACE_CALL();
if (consumer == nullptr) {
SP_LOGE("%s: consumer pointer is NULL", __FUNCTION__);
@@ -61,6 +64,7 @@
mMaxHalBuffers = halMaxBuffers;
mConsumerName = getUniqueConsumerName();
+ mDynamicRangeProfile = dynamicRangeProfile;
// Add output surfaces. This has to be before creating internal buffer queue
// in order to get max consumer side buffers.
for (auto &it : surfaces) {
@@ -136,6 +140,7 @@
}
}
mOutputs.clear();
+ mOutputSurfaces.clear();
mOutputSlots.clear();
mConsumerBufferCount.clear();
@@ -258,6 +263,7 @@
// Add new entry into mOutputs
mOutputs[surfaceId] = gbp;
+ mOutputSurfaces[surfaceId] = outputQueue;
mConsumerBufferCount[surfaceId] = maxConsumerBuffers;
if (mConsumerBufferCount[surfaceId] > mMaxHalBuffers) {
SP_LOGW("%s: Consumer buffer count %zu larger than max. Hal buffers: %zu", __FUNCTION__,
@@ -316,6 +322,7 @@
}
}
mOutputs[surfaceId] = nullptr;
+ mOutputSurfaces[surfaceId] = nullptr;
mOutputSlots[gbp] = nullptr;
for (const auto &id : pendingBufferIds) {
decrementBufRefCountLocked(id, surfaceId);
@@ -356,6 +363,14 @@
const BufferTracker& tracker = *(mBuffers[bufferId]);
int slot = getSlotForOutputLocked(output, tracker.getBuffer());
+ if (mOutputSurfaces[surfaceId] != nullptr) {
+ sp<ANativeWindow> anw = mOutputSurfaces[surfaceId];
+ camera3::Camera3Stream::queueHDRMetadata(
+ bufferItem.mGraphicBuffer->getNativeBuffer()->handle, anw, mDynamicRangeProfile);
+ } else {
+ SP_LOGE("%s: Invalid surface id: %zu!", __FUNCTION__, surfaceId);
+ }
+
// In case the output BufferQueue has its own lock, if we hold splitter lock while calling
// queueBuffer (which will try to acquire the output lock), the output could be holding its
// own lock calling releaseBuffer (which will try to acquire the splitter lock), running into
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 4eb455a..827865c 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -19,6 +19,8 @@
#include <unordered_set>
+#include <camera/CameraMetadata.h>
+
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
#include <gui/BufferItemConsumer.h>
@@ -55,7 +57,8 @@
// with output surfaces.
status_t connect(const std::unordered_map<size_t, sp<Surface>> &surfaces,
uint64_t consumerUsage, uint64_t producerUsage, size_t halMaxBuffers, uint32_t width,
- uint32_t height, android::PixelFormat format, sp<Surface>* consumer);
+ uint32_t height, android::PixelFormat format, sp<Surface>* consumer,
+ int dynamicRangeProfile);
// addOutput adds an output BufferQueue to the splitter. The splitter
// connects to outputQueue as a CPU producer, and any buffers queued
@@ -232,6 +235,7 @@
uint32_t mHeight = 0;
android::PixelFormat mFormat = android::PIXEL_FORMAT_NONE;
uint64_t mProducerUsage = 0;
+ int mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
// The attachBuffer call will happen on different thread according to mUseHalBufManager and have
// different timing constraint.
@@ -251,6 +255,9 @@
//Map surface ids -> gbp outputs
std::unordered_map<int, sp<IGraphicBufferProducer> > mOutputs;
+ //Map surface ids -> gbp outputs
+ std::unordered_map<int, sp<Surface>> mOutputSurfaces;
+
//Map surface ids -> consumer buffer count
std::unordered_map<int, size_t > mConsumerBufferCount;
diff --git a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
index 1fbdb18..6135f9e 100644
--- a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
+++ b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
@@ -44,7 +44,7 @@
size_t length = AChoreographerFrameCallbackData_getFrameTimelinesLength(callbackData);
std::vector<nsecs_t> timeline(length);
for (size_t i = 0; i < length; i++) {
- nsecs_t timestamp = AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
+ nsecs_t timestamp = AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos(
callbackData, i);
timeline[i] = timestamp;
}
@@ -196,6 +196,9 @@
return res;
}
+ Camera3Stream::queueHDRMetadata(bufferHolder.anwBuffer.get()->handle, mConsumer,
+ mParent.getDynamicRangeProfile());
+
res = mConsumer->queueBuffer(mConsumer.get(), bufferHolder.anwBuffer.get(),
bufferHolder.releaseFence);
if (res != OK) {
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
new file mode 100644
index 0000000..7b7a2a2
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -0,0 +1,1893 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "HidlCamera3-Device"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0 // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+// Convenience macro for transient errors
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+ ##__VA_ARGS__)
+
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+#define SET_ERR_L(fmt, ...) setErrorStateLocked( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+
+#include <inttypes.h>
+
+#include <utility>
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <utils/Timers.h>
+#include <cutils/properties.h>
+
+#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
+#include <android/hardware/camera2/ICameraDeviceUser.h>
+
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/hidl/HidlCamera3OfflineSession.h"
+#include "utils/SessionConfigurationUtils.h"
+#include "utils/TraceHFR.h"
+
+#include "../../common/hidl/HidlProviderInfo.h"
+#include "HidlCamera3Device.h"
+
+#include <algorithm>
+#include <tuple>
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+using namespace android::hardware::camera::device::V3_2;
+using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
+
+namespace android {
+
+CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap
+HidlCamera3Device::mapToHidlDynamicProfile(int dynamicRangeProfile) {
+ return static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
+ dynamicRangeProfile);
+}
+
+hardware::graphics::common::V1_0::PixelFormat HidlCamera3Device::mapToPixelFormat(
+ int frameworkFormat) {
+ return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
+}
+
+DataspaceFlags HidlCamera3Device::mapToHidlDataspace(
+ android_dataspace dataSpace) {
+ return dataSpace;
+}
+
+BufferUsageFlags HidlCamera3Device::mapToConsumerUsage(
+ uint64_t usage) {
+ return usage;
+}
+
+StreamRotation HidlCamera3Device::mapToStreamRotation(camera_stream_rotation_t rotation) {
+ switch (rotation) {
+ case CAMERA_STREAM_ROTATION_0:
+ return StreamRotation::ROTATION_0;
+ case CAMERA_STREAM_ROTATION_90:
+ return StreamRotation::ROTATION_90;
+ case CAMERA_STREAM_ROTATION_180:
+ return StreamRotation::ROTATION_180;
+ case CAMERA_STREAM_ROTATION_270:
+ return StreamRotation::ROTATION_270;
+ }
+ ALOGE("%s: Unknown stream rotation %d", __FUNCTION__, rotation);
+ return StreamRotation::ROTATION_0;
+}
+
+status_t HidlCamera3Device::mapToStreamConfigurationMode(
+ camera_stream_configuration_mode_t operationMode, StreamConfigurationMode *mode) {
+ if (mode == nullptr) return BAD_VALUE;
+ if (operationMode < CAMERA_VENDOR_STREAM_CONFIGURATION_MODE_START) {
+ switch(operationMode) {
+ case CAMERA_STREAM_CONFIGURATION_NORMAL_MODE:
+ *mode = StreamConfigurationMode::NORMAL_MODE;
+ break;
+ case CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE:
+ *mode = StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE;
+ break;
+ default:
+ ALOGE("%s: Unknown stream configuration mode %d", __FUNCTION__, operationMode);
+ return BAD_VALUE;
+ }
+ } else {
+ *mode = static_cast<StreamConfigurationMode>(operationMode);
+ }
+ return OK;
+}
+
+int HidlCamera3Device::mapToFrameworkFormat(
+ hardware::graphics::common::V1_0::PixelFormat pixelFormat) {
+ return static_cast<uint32_t>(pixelFormat);
+}
+
+android_dataspace HidlCamera3Device::mapToFrameworkDataspace(
+ DataspaceFlags dataSpace) {
+ return static_cast<android_dataspace>(dataSpace);
+}
+
+uint64_t HidlCamera3Device::mapConsumerToFrameworkUsage(
+ BufferUsageFlags usage) {
+ return usage;
+}
+
+uint64_t HidlCamera3Device::mapProducerToFrameworkUsage(
+ BufferUsageFlags usage) {
+ return usage;
+}
+
+status_t HidlCamera3Device::initialize(sp<CameraProviderManager> manager,
+ const String8& monitorTags) {
+ ATRACE_CALL();
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
+ if (mStatus != STATUS_UNINITIALIZED) {
+ CLOGE("Already initialized!");
+ return INVALID_OPERATION;
+ }
+ if (manager == nullptr) return INVALID_OPERATION;
+
+ sp<ICameraDeviceSession> session;
+ ATRACE_BEGIN("CameraHal::openSession");
+ status_t res = manager->openHidlSession(mId.string(), this,
+ /*out*/ &session);
+ ATRACE_END();
+ if (res != OK) {
+ SET_ERR_L("Could not open camera session: %s (%d)", strerror(-res), res);
+ return res;
+ }
+
+ 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();
+ return res;
+ }
+ mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
+
+ std::vector<std::string> physicalCameraIds;
+ bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
+ if (isLogical) {
+ for (auto& physicalId : physicalCameraIds) {
+ // Do not override characteristics for physical cameras
+ res = manager->getCameraCharacteristics(
+ 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);
+ session->close();
+ return res;
+ }
+
+ bool usePrecorrectArray =
+ DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId]);
+ if (usePrecorrectArray) {
+ res = mDistortionMappers[physicalId].setupStaticInfo(
+ mPhysicalDeviceInfoMap[physicalId]);
+ if (res != OK) {
+ SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
+ "correction", physicalId.c_str());
+ session->close();
+ return res;
+ }
+ }
+
+ mZoomRatioMappers[physicalId] = ZoomRatioMapper(
+ &mPhysicalDeviceInfoMap[physicalId],
+ mSupportNativeZoomRatio, usePrecorrectArray);
+
+ if (SessionConfigurationUtils::isUltraHighResolutionSensor(
+ mPhysicalDeviceInfoMap[physicalId])) {
+ mUHRCropAndMeteringRegionMappers[physicalId] =
+ UHRCropAndMeteringRegionMapper(mPhysicalDeviceInfoMap[physicalId],
+ usePrecorrectArray);
+ }
+ }
+ }
+
+ std::shared_ptr<RequestMetadataQueue> queue;
+ auto requestQueueRet = session->getCaptureRequestMetadataQueue(
+ [&queue](const auto& descriptor) {
+ queue = std::make_shared<RequestMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty request metadata fmq, not use it");
+ queue = nullptr;
+ // don't use the queue onwards.
+ }
+ });
+ if (!requestQueueRet.isOk()) {
+ ALOGE("Transaction error when getting request metadata fmq: %s, not use it",
+ requestQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
+ auto resultQueueRet = session->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty result metadata fmq, not use it");
+ resQueue = nullptr;
+ // Don't use the resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+ resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ IF_ALOGV() {
+ session->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Session interface chain:");
+ for (const auto& iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ camera_metadata_entry bufMgrMode =
+ mDeviceInfo.find(ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+ if (bufMgrMode.count > 0) {
+ mUseHalBufManager = (bufMgrMode.data.u8[0] ==
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+ }
+
+ camera_metadata_entry_t capabilities = mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING) {
+ mSupportOfflineProcessing = true;
+ }
+ }
+
+ mInterface = new HidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
+
+ std::string providerType;
+ mVendorTagId = manager->getProviderTagIdLocked(mId.string());
+ mTagMonitor.initialize(mVendorTagId);
+ if (!monitorTags.isEmpty()) {
+ mTagMonitor.parseTagsToMonitor(String8(monitorTags));
+ }
+
+ // Metadata tags needs fixup for monochrome camera device version less
+ // than 3.5.
+ hardware::hidl_version maxVersion{0,0};
+ res = manager->getHighestSupportedVersion(mId.string(), &maxVersion);
+ if (res != OK) {
+ ALOGE("%s: Error in getting camera device version id: %s (%d)",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ int deviceVersion = HARDWARE_DEVICE_API_VERSION(
+ maxVersion.get_major(), maxVersion.get_minor());
+
+ bool isMonochrome = false;
+ for (size_t i = 0; i < capabilities.count; i++) {
+ uint8_t capability = capabilities.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME) {
+ isMonochrome = true;
+ }
+ }
+ mNeedFixupMonochromeTags = (isMonochrome && deviceVersion < CAMERA_DEVICE_API_VERSION_3_5);
+
+ return initializeCommonLocked();
+}
+
+hardware::Return<void> HidlCamera3Device::requestStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) {
+ RequestBufferStates states {
+ mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+ *this, *mInterface, *this};
+ camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::returnStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ ReturnBufferStates states {
+ mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, *mInterface};
+ camera3::returnStreamBuffers(states, buffers);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) {
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received capture result in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ // This should never happen; it indicates a wrong client implementation
+ // that doesn't follow the contract. But, we can be tolerant here.
+ ALOGE("%s: callback overlapped! waiting 1s...",
+ __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, dropping results",
+ __FUNCTION__);
+ // really don't know what to do, so bail out.
+ return hardware::Void();
+ }
+ }
+ HidlCaptureOutputStates states {
+ {
+ mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+
+ //HidlCaptureOutputStates hidlStates {
+ //}
+
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
+ }
+ mProcessCaptureResultLock.unlock();
+ return hardware::Void();
+}
+
+// Only one processCaptureResult should be called at a time, so
+// the locks won't block. The locks are present here simply to enforce this.
+hardware::Return<void> HidlCamera3Device::processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) {
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
+
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received capture result in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ if (mProcessCaptureResultLock.tryLock() != OK) {
+ // This should never happen; it indicates a wrong client implementation
+ // that doesn't follow the contract. But, we can be tolerant here.
+ ALOGE("%s: callback overlapped! waiting 1s...",
+ __FUNCTION__);
+ if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
+ ALOGE("%s: cannot acquire lock in 1s, dropping results",
+ __FUNCTION__);
+ // really don't know what to do, so bail out.
+ return hardware::Void();
+ }
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result, noPhysMetadata);
+ }
+ mProcessCaptureResultLock.unlock();
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3Device::notify(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+ return notifyHelper<hardware::camera::device::V3_2::NotifyMsg>(msgs);
+}
+
+hardware::Return<void> HidlCamera3Device::notify_3_8(
+ const hardware::hidl_vec<hardware::camera::device::V3_8::NotifyMsg>& msgs) {
+ return notifyHelper<hardware::camera::device::V3_8::NotifyMsg>(msgs);
+}
+
+template<typename NotifyMsgType>
+hardware::Return<void> HidlCamera3Device::notifyHelper(
+ const hardware::hidl_vec<NotifyMsgType>& msgs) {
+ // Ideally we should grab mLock, but that can lead to deadlock, and
+ // it's not super important to get up to date value of mStatus for this
+ // warning print, hence skipping the lock here
+ if (mStatus == STATUS_ERROR) {
+ // Per API contract, HAL should act as closed after device error
+ // But mStatus can be set to error by framework as well, so just log
+ // a warning here.
+ ALOGW("%s: received notify message in error state.", __FUNCTION__);
+ }
+
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> l(mOutputLock);
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mInFlightLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mInFlightMap, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ *mInterface, mLegacyClient}, mResultMetadataQueue
+ };
+ for (const auto& msg : msgs) {
+ camera3::notify(states, msg);
+ }
+ return hardware::Void();
+}
+
+status_t HidlCamera3Device::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) {
+ ATRACE_CALL();
+ if (session == nullptr) {
+ ALOGE("%s: session must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock il(mInterfaceLock);
+
+ bool hasInputStream = mInputStream != nullptr;
+ int32_t inputStreamId = hasInputStream ? mInputStream->getId() : -1;
+ bool inputStreamSupportsOffline = hasInputStream ?
+ mInputStream->getOfflineProcessingSupport() : false;
+ auto outputStreamIds = mOutputStreams.getStreamIds();
+ auto streamIds = outputStreamIds;
+ if (hasInputStream) {
+ streamIds.push_back(mInputStream->getId());
+ }
+
+ // Check all streams in streamsToKeep supports offline mode
+ for (auto id : streamsToKeep) {
+ if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+ ALOGE("%s: Unknown stream ID %d", __FUNCTION__, id);
+ return BAD_VALUE;
+ } else if (id == inputStreamId) {
+ if (!inputStreamSupportsOffline) {
+ ALOGE("%s: input stream %d cannot be switched to offline",
+ __FUNCTION__, id);
+ return BAD_VALUE;
+ }
+ } else {
+ sp<camera3::Camera3OutputStreamInterface> stream = mOutputStreams.get(id);
+ if (!stream->getOfflineProcessingSupport()) {
+ ALOGE("%s: output stream %d cannot be switched to offline",
+ __FUNCTION__, id);
+ return BAD_VALUE;
+ }
+ }
+ }
+ // TODO: block surface sharing and surface group streams until we can support them
+
+ // Stop repeating request, wait until all remaining requests are submitted, then call into
+ // HAL switchToOffline
+ hardware::camera::device::V3_6::CameraOfflineSessionInfo offlineSessionInfo;
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession;
+ camera3::BufferRecords bufferRecords;
+ status_t ret = static_cast<HidlRequestThread *>(mRequestThread.get())->switchToOffline(
+ streamsToKeep, &offlineSessionInfo, &offlineSession, &bufferRecords);
+
+ if (ret != OK) {
+ SET_ERR("Switch to offline failed: %s (%d)", strerror(-ret), ret);
+ return ret;
+ }
+
+ bool succ = mRequestBufferSM.onSwitchToOfflineSuccess();
+ if (!succ) {
+ SET_ERR("HAL must not be calling requestStreamBuffers call");
+ // TODO: block ALL callbacks from HAL till app configured new streams?
+ return UNKNOWN_ERROR;
+ }
+
+ // Verify offlineSessionInfo
+ std::vector<int32_t> offlineStreamIds;
+ offlineStreamIds.reserve(offlineSessionInfo.offlineStreams.size());
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ // verify stream IDs
+ int32_t id = offlineStream.id;
+ if (std::find(streamIds.begin(), streamIds.end(), id) == streamIds.end()) {
+ SET_ERR("stream ID %d not found!", id);
+ return UNKNOWN_ERROR;
+ }
+
+ // When not using HAL buf manager, only allow streams requested by app to be preserved
+ if (!mUseHalBufManager) {
+ if (std::find(streamsToKeep.begin(), streamsToKeep.end(), id) == streamsToKeep.end()) {
+ SET_ERR("stream ID %d must not be switched to offline!", id);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ offlineStreamIds.push_back(id);
+ sp<Camera3StreamInterface> stream = (id == inputStreamId) ?
+ static_cast<sp<Camera3StreamInterface>>(mInputStream) :
+ static_cast<sp<Camera3StreamInterface>>(mOutputStreams.get(id));
+ // Verify number of outstanding buffers
+ if (stream->getOutstandingBuffersCount() != offlineStream.numOutstandingBuffers) {
+ SET_ERR("Offline stream %d # of remaining buffer mismatch: (%zu,%d) (service/HAL)",
+ id, stream->getOutstandingBuffersCount(), offlineStream.numOutstandingBuffers);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ // Verify all streams to be deleted don't have any outstanding buffers
+ if (hasInputStream && std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+ inputStreamId) == offlineStreamIds.end()) {
+ if (mInputStream->hasOutstandingBuffers()) {
+ SET_ERR("Input stream %d still has %zu outstanding buffer!",
+ inputStreamId, mInputStream->getOutstandingBuffersCount());
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ for (const auto& outStreamId : outputStreamIds) {
+ if (std::find(offlineStreamIds.begin(), offlineStreamIds.end(),
+ outStreamId) == offlineStreamIds.end()) {
+ auto outStream = mOutputStreams.get(outStreamId);
+ if (outStream->hasOutstandingBuffers()) {
+ SET_ERR("Output stream %d still has %zu outstanding buffer!",
+ outStreamId, outStream->getOutstandingBuffersCount());
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ InFlightRequestMap offlineReqs;
+ // Verify inflight requests and their pending buffers
+ {
+ std::lock_guard<std::mutex> l(mInFlightLock);
+ for (auto offlineReq : offlineSessionInfo.offlineRequests) {
+ int idx = mInFlightMap.indexOfKey(offlineReq.frameNumber);
+ if (idx == NAME_NOT_FOUND) {
+ SET_ERR("Offline request frame number %d not found!", offlineReq.frameNumber);
+ return UNKNOWN_ERROR;
+ }
+
+ const auto& inflightReq = mInFlightMap.valueAt(idx);
+ // TODO: check specific stream IDs
+ size_t numBuffersLeft = static_cast<size_t>(inflightReq.numBuffersLeft);
+ if (numBuffersLeft != offlineReq.pendingStreams.size()) {
+ SET_ERR("Offline request # of remaining buffer mismatch: (%d,%d) (service/HAL)",
+ inflightReq.numBuffersLeft, offlineReq.pendingStreams.size());
+ return UNKNOWN_ERROR;
+ }
+ offlineReqs.add(offlineReq.frameNumber, inflightReq);
+ }
+ }
+
+ // Create Camera3OfflineSession and transfer object ownership
+ // (streams, inflight requests, buffer caches)
+ camera3::StreamSet offlineStreamSet;
+ sp<camera3::Camera3Stream> inputStream;
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ int32_t id = offlineStream.id;
+ if (mInputStream != nullptr && id == mInputStream->getId()) {
+ inputStream = mInputStream;
+ } else {
+ offlineStreamSet.add(id, mOutputStreams.get(id));
+ }
+ }
+
+ // TODO: check if we need to lock before copying states
+ // though technically no other thread should be talking to Camera3Device at this point
+ Camera3OfflineStates offlineStates(
+ mTagMonitor, mVendorTagId, mUseHalBufManager, mNeedFixupMonochromeTags,
+ mUsePartialResult, mNumPartialResults, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mNextResultFrameNumber, mNextReprocessResultFrameNumber,
+ mNextZslStillResultFrameNumber, mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mDeviceInfo, mPhysicalDeviceInfoMap, mDistortionMappers,
+ mZoomRatioMappers, mRotateAndCropMappers);
+
+ *session = new HidlCamera3OfflineSession(mId, inputStream, offlineStreamSet,
+ std::move(bufferRecords), offlineReqs, offlineStates, offlineSession);
+
+ // Delete all streams that has been transferred to offline session
+ Mutex::Autolock l(mLock);
+ for (auto offlineStream : offlineSessionInfo.offlineStreams) {
+ int32_t id = offlineStream.id;
+ if (mInputStream != nullptr && id == mInputStream->getId()) {
+ mInputStream.clear();
+ } else {
+ mOutputStreams.remove(id);
+ }
+ }
+
+ // disconnect all other streams and switch to UNCONFIGURED state
+ if (mInputStream != nullptr) {
+ ret = mInputStream->disconnect();
+ if (ret != OK) {
+ SET_ERR_L("disconnect input stream failed!");
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ for (auto streamId : mOutputStreams.getStreamIds()) {
+ sp<Camera3StreamInterface> stream = mOutputStreams.get(streamId);
+ ret = stream->disconnect();
+ if (ret != OK) {
+ SET_ERR_L("disconnect output stream %d failed!", streamId);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ mInputStream.clear();
+ mOutputStreams.clear();
+ mNeedConfig = true;
+ internalUpdateStatusLocked(STATUS_UNCONFIGURED);
+ mOperatingMode = NO_MODE;
+ mIsConstrainedHighSpeedConfiguration = false;
+ mRequestThread->clearPreviousRequest();
+
+ return OK;
+ // TO be done by CameraDeviceClient/Camera3OfflineSession
+ // register the offline client to camera service
+ // Setup result passthing threads etc
+ // Initialize offline session so HAL can start sending callback to it (result Fmq)
+ // TODO: check how many onIdle callback will be sent
+ // Java side to make sure the CameraCaptureSession is properly closed
+}
+
+sp<Camera3Device::RequestThread> HidlCamera3Device::createNewRequestThread(
+ wp<Camera3Device> parent, sp<camera3::StatusTracker> statusTracker,
+ sp<Camera3Device::HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) {
+ return new HidlRequestThread(parent, statusTracker, interface, sessionParamKeys,
+ useHalBufManager, supportCameraMute);
+};
+
+sp<Camera3Device::Camera3DeviceInjectionMethods>
+HidlCamera3Device::createCamera3DeviceInjectionMethods(wp<Camera3Device> parent) {
+ return new HidlCamera3DeviceInjectionMethods(parent);
+}
+
+status_t HidlCamera3Device::injectionCameraInitialize(const String8 &injectedCamId,
+ sp<CameraProviderManager> manager) {
+ return (static_cast<HidlCamera3DeviceInjectionMethods *>(
+ mInjectionMethods.get()))->injectionInitialize(injectedCamId, manager, this);
+};
+
+
+HidlCamera3Device::HidlHalInterface::HidlHalInterface(
+ sp<device::V3_2::ICameraDeviceSession> &session,
+ std::shared_ptr<RequestMetadataQueue> queue,
+ bool useHalBufManager, bool supportOfflineProcessing) :
+ HalInterface(useHalBufManager, supportOfflineProcessing),
+ mHidlSession(session),
+ mRequestMetadataQueue(queue) {
+ // Check with hardware service manager if we can downcast these interfaces
+ // Somewhat expensive, so cache the results at startup
+ auto castResult_3_8 = device::V3_8::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_8.isOk()) {
+ mHidlSession_3_8 = castResult_3_8;
+ }
+ auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ mHidlSession_3_7 = castResult_3_7;
+ }
+ auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_6.isOk()) {
+ mHidlSession_3_6 = castResult_3_6;
+ }
+ auto castResult_3_5 = device::V3_5::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_5.isOk()) {
+ mHidlSession_3_5 = castResult_3_5;
+ }
+ auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_4.isOk()) {
+ mHidlSession_3_4 = castResult_3_4;
+ }
+ auto castResult_3_3 = device::V3_3::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_3.isOk()) {
+ mHidlSession_3_3 = castResult_3_3;
+ }
+}
+
+bool HidlCamera3Device::HidlHalInterface::valid() {
+ return (mHidlSession != nullptr);
+}
+
+void HidlCamera3Device::HidlHalInterface::clear() {
+ mHidlSession_3_8.clear();
+ mHidlSession_3_7.clear();
+ mHidlSession_3_6.clear();
+ mHidlSession_3_5.clear();
+ mHidlSession_3_4.clear();
+ mHidlSession_3_3.clear();
+ mHidlSession.clear();
+}
+
+status_t HidlCamera3Device::HidlHalInterface::constructDefaultRequestSettings(
+ camera_request_template_t templateId,
+ /*out*/ camera_metadata_t **requestTemplate) {
+ ATRACE_NAME("CameraHidlHal::constructDefaultRequestSettings");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ common::V1_0::Status status;
+
+ auto requestCallback = [&status, &requestTemplate]
+ (common::V1_0::Status s, const device::V3_2::CameraMetadata& request) {
+ status = s;
+ if (status == common::V1_0::Status::OK) {
+ const camera_metadata *r =
+ reinterpret_cast<const camera_metadata_t*>(request.data());
+ size_t expectedSize = request.size();
+ int ret = validate_camera_metadata_structure(r, &expectedSize);
+ if (ret == OK || ret == CAMERA_METADATA_VALIDATION_SHIFTED) {
+ *requestTemplate = clone_camera_metadata(r);
+ if (*requestTemplate == nullptr) {
+ ALOGE("%s: Unable to clone camera metadata received from HAL",
+ __FUNCTION__);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+ } else {
+ ALOGE("%s: Malformed camera metadata received from HAL", __FUNCTION__);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+ }
+ };
+ hardware::Return<void> err;
+ RequestTemplate id;
+ switch (templateId) {
+ case CAMERA_TEMPLATE_PREVIEW:
+ id = RequestTemplate::PREVIEW;
+ break;
+ case CAMERA_TEMPLATE_STILL_CAPTURE:
+ id = RequestTemplate::STILL_CAPTURE;
+ break;
+ case CAMERA_TEMPLATE_VIDEO_RECORD:
+ id = RequestTemplate::VIDEO_RECORD;
+ break;
+ case CAMERA_TEMPLATE_VIDEO_SNAPSHOT:
+ id = RequestTemplate::VIDEO_SNAPSHOT;
+ break;
+ case CAMERA_TEMPLATE_ZERO_SHUTTER_LAG:
+ id = RequestTemplate::ZERO_SHUTTER_LAG;
+ break;
+ case CAMERA_TEMPLATE_MANUAL:
+ id = RequestTemplate::MANUAL;
+ break;
+ default:
+ // Unknown template ID, or this HAL is too old to support it
+ return BAD_VALUE;
+ }
+ err = mHidlSession->constructDefaultRequestSettings(id, requestCallback);
+
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
+ } else {
+ res = HidlProviderInfo::mapToStatusT(status);
+ }
+
+ return res;
+}
+
+bool HidlCamera3Device::HidlHalInterface::isReconfigurationRequired(
+ CameraMetadata& oldSessionParams, CameraMetadata& newSessionParams) {
+ // We do reconfiguration by default;
+ bool ret = true;
+ if ((mHidlSession_3_5 != nullptr) && mIsReconfigurationQuerySupported) {
+ android::hardware::hidl_vec<uint8_t> oldParams, newParams;
+ camera_metadata_t* oldSessioMeta = const_cast<camera_metadata_t*>(
+ oldSessionParams.getAndLock());
+ camera_metadata_t* newSessioMeta = const_cast<camera_metadata_t*>(
+ newSessionParams.getAndLock());
+ oldParams.setToExternal(reinterpret_cast<uint8_t*>(oldSessioMeta),
+ get_camera_metadata_size(oldSessioMeta));
+ newParams.setToExternal(reinterpret_cast<uint8_t*>(newSessioMeta),
+ get_camera_metadata_size(newSessioMeta));
+ hardware::camera::common::V1_0::Status callStatus;
+ bool required;
+ auto hidlCb = [&callStatus, &required] (hardware::camera::common::V1_0::Status s,
+ bool requiredFlag) {
+ callStatus = s;
+ required = requiredFlag;
+ };
+ auto err = mHidlSession_3_5->isReconfigurationRequired(oldParams, newParams, hidlCb);
+ oldSessionParams.unlock(oldSessioMeta);
+ newSessionParams.unlock(newSessioMeta);
+ if (err.isOk()) {
+ switch (callStatus) {
+ case hardware::camera::common::V1_0::Status::OK:
+ ret = required;
+ break;
+ case hardware::camera::common::V1_0::Status::METHOD_NOT_SUPPORTED:
+ mIsReconfigurationQuerySupported = false;
+ ret = true;
+ break;
+ default:
+ ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
+ ret = true;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, err.description().c_str());
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::configureStreams(
+ const camera_metadata_t *sessionParams,
+ camera_stream_configuration *config, const std::vector<uint32_t>& bufferSizes) {
+ ATRACE_NAME("CameraHal::configureStreams");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
+ ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ // Convert stream config to HIDL
+ std::set<int> activeStreams;
+ device::V3_2::StreamConfiguration requestedConfiguration3_2;
+ device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ device::V3_7::StreamConfiguration requestedConfiguration3_7;
+ device::V3_8::StreamConfiguration requestedConfiguration3_8;
+ requestedConfiguration3_2.streams.resize(config->num_streams);
+ requestedConfiguration3_4.streams.resize(config->num_streams);
+ requestedConfiguration3_7.streams.resize(config->num_streams);
+ requestedConfiguration3_8.streams.resize(config->num_streams);
+ for (size_t i = 0; i < config->num_streams; i++) {
+ device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
+ device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
+ device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
+ device::V3_8::Stream &dst3_8 = requestedConfiguration3_8.streams[i];
+ camera3::camera_stream_t *src = config->streams[i];
+
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
+ StreamType streamType;
+ switch (src->stream_type) {
+ case CAMERA_STREAM_OUTPUT:
+ streamType = StreamType::OUTPUT;
+ break;
+ case CAMERA_STREAM_INPUT:
+ streamType = StreamType::INPUT;
+ break;
+ default:
+ ALOGE("%s: Stream %d: Unsupported stream type %d",
+ __FUNCTION__, streamId, config->streams[i]->stream_type);
+ return BAD_VALUE;
+ }
+ dst3_2.id = streamId;
+ dst3_2.streamType = streamType;
+ dst3_2.width = src->width;
+ dst3_2.height = src->height;
+ dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst3_2.rotation = mapToStreamRotation((camera_stream_rotation_t) src->rotation);
+ // For HidlSession version 3.5 or newer, the format and dataSpace sent
+ // to HAL are original, not the overridden ones.
+ if (mHidlSession_3_5 != nullptr) {
+ dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
+ cam3stream->getOriginalFormat() : src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
+ cam3stream->getOriginalDataSpace() : src->data_space);
+ } else {
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ }
+ dst3_4.v3_2 = dst3_2;
+ dst3_4.bufferSize = bufferSizes[i];
+ if (src->physical_camera_id != nullptr) {
+ dst3_4.physicalCameraId = src->physical_camera_id;
+ }
+ dst3_7.v3_4 = dst3_4;
+ dst3_7.groupId = cam3stream->getHalStreamGroupId();
+ dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+ size_t j = 0;
+ for (int mode : src->sensor_pixel_modes_used) {
+ dst3_7.sensorPixelModesUsed[j++] =
+ static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+ }
+ if ((src->dynamic_range_profile !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) &&
+ (mHidlSession_3_8 == nullptr)) {
+ ALOGE("%s: Camera device doesn't support non-standard dynamic range profiles: %d",
+ __FUNCTION__, src->dynamic_range_profile);
+ return BAD_VALUE;
+ }
+ dst3_8.v3_7 = dst3_7;
+ dst3_8.dynamicRangeProfile = mapToHidlDynamicProfile(src->dynamic_range_profile);
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ mBufferRecords.tryCreateBufferCache(streamId);
+ }
+ // remove BufferIdMap for deleted streams
+ mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+ StreamConfigurationMode operationMode;
+ res = mapToStreamConfigurationMode(
+ (camera_stream_configuration_mode_t) config->operation_mode,
+ /*out*/ &operationMode);
+ if (res != OK) {
+ return res;
+ }
+ requestedConfiguration3_2.operationMode = operationMode;
+ requestedConfiguration3_4.operationMode = operationMode;
+ requestedConfiguration3_7.operationMode = operationMode;
+ size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+ requestedConfiguration3_4.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+ requestedConfiguration3_7.operationMode = operationMode;
+ requestedConfiguration3_7.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+ requestedConfiguration3_8.operationMode = operationMode;
+ requestedConfiguration3_8.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+
+ // Invoke configureStreams
+ device::V3_3::HalStreamConfiguration finalConfiguration;
+ device::V3_4::HalStreamConfiguration finalConfiguration3_4;
+ device::V3_6::HalStreamConfiguration finalConfiguration3_6;
+ common::V1_0::Status status;
+
+ auto configStream34Cb = [&status, &finalConfiguration3_4]
+ (common::V1_0::Status s, const device::V3_4::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration3_4 = halConfiguration;
+ status = s;
+ };
+
+ auto configStream36Cb = [&status, &finalConfiguration3_6]
+ (common::V1_0::Status s, const device::V3_6::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration3_6 = halConfiguration;
+ status = s;
+ };
+
+ auto postprocConfigStream34 = [&finalConfiguration, &finalConfiguration3_4]
+ (hardware::Return<void>& err) -> status_t {
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration3_4.streams.size());
+ for (size_t i = 0; i < finalConfiguration3_4.streams.size(); i++) {
+ finalConfiguration.streams[i] = finalConfiguration3_4.streams[i].v3_3;
+ }
+ return OK;
+ };
+
+ auto postprocConfigStream36 = [&finalConfiguration, &finalConfiguration3_6]
+ (hardware::Return<void>& err) -> status_t {
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration3_6.streams.size());
+ for (size_t i = 0; i < finalConfiguration3_6.streams.size(); i++) {
+ finalConfiguration.streams[i] = finalConfiguration3_6.streams[i].v3_4.v3_3;
+ }
+ return OK;
+ };
+
+ // See which version of HAL we have
+ if (mHidlSession_3_8 != nullptr) {
+ ALOGV("%s: v3.8 device found", __FUNCTION__);
+ requestedConfiguration3_8.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_8.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_8->configureStreams_3_8(requestedConfiguration3_8,
+ configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_7 != nullptr) {
+ ALOGV("%s: v3.7 device found", __FUNCTION__);
+ requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_7->configureStreams_3_7(
+ requestedConfiguration3_7, configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_6 != nullptr) {
+ ALOGV("%s: v3.6 device found", __FUNCTION__);
+ device::V3_5::StreamConfiguration requestedConfiguration3_5;
+ requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
+ requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
+ auto err = mHidlSession_3_6->configureStreams_3_6(
+ requestedConfiguration3_5, configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_5 != nullptr) {
+ ALOGV("%s: v3.5 device found", __FUNCTION__);
+ device::V3_5::StreamConfiguration requestedConfiguration3_5;
+ requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
+ requestedConfiguration3_5.streamConfigCounter = mNextStreamConfigCounter++;
+ auto err = mHidlSession_3_5->configureStreams_3_5(
+ requestedConfiguration3_5, configStream34Cb);
+ res = postprocConfigStream34(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_4 != nullptr) {
+ // We do; use v3.4 for the call
+ ALOGV("%s: v3.4 device found", __FUNCTION__);
+ auto err = mHidlSession_3_4->configureStreams_3_4(
+ requestedConfiguration3_4, configStream34Cb);
+ res = postprocConfigStream34(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_3 != nullptr) {
+ // We do; use v3.3 for the call
+ ALOGV("%s: v3.3 device found", __FUNCTION__);
+ auto err = mHidlSession_3_3->configureStreams_3_3(requestedConfiguration3_2,
+ [&status, &finalConfiguration]
+ (common::V1_0::Status s, const device::V3_3::HalStreamConfiguration& halConfiguration) {
+ finalConfiguration = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ } else {
+ // We don't; use v3.2 call and construct a v3.3 HalStreamConfiguration
+ ALOGV("%s: v3.2 device found", __FUNCTION__);
+ HalStreamConfiguration finalConfiguration_3_2;
+ auto err = mHidlSession->configureStreams(requestedConfiguration3_2,
+ [&status, &finalConfiguration_3_2]
+ (common::V1_0::Status s, const HalStreamConfiguration& halConfiguration) {
+ finalConfiguration_3_2 = halConfiguration;
+ status = s;
+ });
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ finalConfiguration.streams.resize(finalConfiguration_3_2.streams.size());
+ for (size_t i = 0; i < finalConfiguration_3_2.streams.size(); i++) {
+ finalConfiguration.streams[i].v3_2 = finalConfiguration_3_2.streams[i];
+ finalConfiguration.streams[i].overrideDataSpace =
+ requestedConfiguration3_2.streams[i].dataSpace;
+ }
+ }
+
+ if (status != common::V1_0::Status::OK ) {
+ return HidlProviderInfo::mapToStatusT(status);
+ }
+
+ // And convert output stream configuration from HIDL
+
+ for (size_t i = 0; i < config->num_streams; i++) {
+ camera3::camera_stream_t *dst = config->streams[i];
+ int streamId = Camera3Stream::cast(dst)->getId();
+
+ // Start scan at i, with the assumption that the stream order matches
+ size_t realIdx = i;
+ bool found = false;
+ size_t halStreamCount = finalConfiguration.streams.size();
+ for (size_t idx = 0; idx < halStreamCount; idx++) {
+ if (finalConfiguration.streams[realIdx].v3_2.id == streamId) {
+ found = true;
+ break;
+ }
+ realIdx = (realIdx >= halStreamCount - 1) ? 0 : realIdx + 1;
+ }
+ if (!found) {
+ ALOGE("%s: Stream %d not found in stream configuration response from HAL",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
+ device::V3_6::HalStream &src_36 = finalConfiguration3_6.streams[realIdx];
+
+ Camera3Stream* dstStream = Camera3Stream::cast(dst);
+ int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
+ android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
+
+ if (mHidlSession_3_6 != nullptr) {
+ dstStream->setOfflineProcessingSupport(src_36.supportOffline);
+ }
+
+ if (dstStream->getOriginalFormat() != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ dstStream->setFormatOverride(false);
+ dstStream->setDataSpaceOverride(false);
+ if (dst->format != overrideFormat) {
+ ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
+ }
+ if (dst->data_space != overrideDataSpace) {
+ ALOGE("%s: Stream %d: DataSpace override not allowed for format 0x%x", __FUNCTION__,
+ streamId, dst->format);
+ }
+ } else {
+ bool needFormatOverride =
+ requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
+ bool needDataspaceOverride =
+ requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
+ // Override allowed with IMPLEMENTATION_DEFINED
+ dstStream->setFormatOverride(needFormatOverride);
+ dstStream->setDataSpaceOverride(needDataspaceOverride);
+ dst->format = overrideFormat;
+ dst->data_space = overrideDataSpace;
+ }
+
+ if (dst->stream_type == CAMERA_STREAM_INPUT) {
+ if (src.v3_2.producerUsage != 0) {
+ ALOGE("%s: Stream %d: INPUT streams must have 0 for producer usage",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ dstStream->setUsage(
+ mapConsumerToFrameworkUsage(src.v3_2.consumerUsage));
+ } else {
+ // OUTPUT
+ if (src.v3_2.consumerUsage != 0) {
+ ALOGE("%s: Stream %d: OUTPUT streams must have 0 for consumer usage",
+ __FUNCTION__, streamId);
+ return INVALID_OPERATION;
+ }
+ dstStream->setUsage(
+ mapProducerToFrameworkUsage(src.v3_2.producerUsage));
+ }
+ dst->max_buffers = src.v3_2.maxBuffers;
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::configureInjectedStreams(
+ const camera_metadata_t* sessionParams, camera_stream_configuration* config,
+ const std::vector<uint32_t>& bufferSizes,
+ const CameraMetadata& cameraCharacteristics) {
+ ATRACE_NAME("InjectionCameraHal::configureStreams");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ if (config->input_is_multi_resolution) {
+ ALOGE("%s: Injection camera device doesn't support multi-resolution input "
+ "stream", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ // Convert stream config to HIDL
+ std::set<int> activeStreams;
+ device::V3_2::StreamConfiguration requestedConfiguration3_2;
+ device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ device::V3_7::StreamConfiguration requestedConfiguration3_7;
+ requestedConfiguration3_2.streams.resize(config->num_streams);
+ requestedConfiguration3_4.streams.resize(config->num_streams);
+ requestedConfiguration3_7.streams.resize(config->num_streams);
+ for (size_t i = 0; i < config->num_streams; i++) {
+ device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
+ device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
+ device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
+ camera3::camera_stream_t* src = config->streams[i];
+
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
+ StreamType streamType;
+ switch (src->stream_type) {
+ case CAMERA_STREAM_OUTPUT:
+ streamType = StreamType::OUTPUT;
+ break;
+ case CAMERA_STREAM_INPUT:
+ streamType = StreamType::INPUT;
+ break;
+ default:
+ ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
+ streamId, config->streams[i]->stream_type);
+ return BAD_VALUE;
+ }
+ dst3_2.id = streamId;
+ dst3_2.streamType = streamType;
+ dst3_2.width = src->width;
+ dst3_2.height = src->height;
+ dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
+ dst3_2.rotation =
+ mapToStreamRotation((camera_stream_rotation_t)src->rotation);
+ // For HidlSession version 3.5 or newer, the format and dataSpace sent
+ // to HAL are original, not the overridden ones.
+ if (mHidlSession_3_5 != nullptr) {
+ dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
+ ? cam3stream->getOriginalFormat()
+ : src->format);
+ dst3_2.dataSpace =
+ mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
+ ? cam3stream->getOriginalDataSpace()
+ : src->data_space);
+ } else {
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ }
+ dst3_4.v3_2 = dst3_2;
+ dst3_4.bufferSize = bufferSizes[i];
+ if (src->physical_camera_id != nullptr) {
+ dst3_4.physicalCameraId = src->physical_camera_id;
+ }
+ dst3_7.v3_4 = dst3_4;
+ dst3_7.groupId = cam3stream->getHalStreamGroupId();
+ dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
+ size_t j = 0;
+ for (int mode : src->sensor_pixel_modes_used) {
+ dst3_7.sensorPixelModesUsed[j++] =
+ static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
+ }
+ activeStreams.insert(streamId);
+ // Create Buffer ID map if necessary
+ mBufferRecords.tryCreateBufferCache(streamId);
+ }
+ // remove BufferIdMap for deleted streams
+ mBufferRecords.removeInactiveBufferCaches(activeStreams);
+
+ StreamConfigurationMode operationMode;
+ res = mapToStreamConfigurationMode(
+ (camera_stream_configuration_mode_t)config->operation_mode,
+ /*out*/ &operationMode);
+ if (res != OK) {
+ return res;
+ }
+ requestedConfiguration3_7.operationMode = operationMode;
+ size_t sessionParamSize = get_camera_metadata_size(sessionParams);
+ requestedConfiguration3_7.operationMode = operationMode;
+ requestedConfiguration3_7.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ sessionParamSize);
+
+ // See which version of HAL we have
+ if (mHidlSession_3_7 != nullptr) {
+ requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_7.multiResolutionInputImage =
+ config->input_is_multi_resolution;
+
+ const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
+ ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
+ hidlChars.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
+ get_camera_metadata_size(rawMetadata));
+ cameraCharacteristics.unlock(rawMetadata);
+
+ sp<hardware::camera::device::V3_7::ICameraInjectionSession>
+ hidlInjectionSession_3_7;
+ auto castInjectionResult_3_7 =
+ device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
+ if (castInjectionResult_3_7.isOk()) {
+ hidlInjectionSession_3_7 = castInjectionResult_3_7;
+ } else {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__,
+ castInjectionResult_3_7.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ auto err = hidlInjectionSession_3_7->configureInjectionStreams(
+ requestedConfiguration3_7, hidlChars);
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__,
+ err.description().c_str());
+ return DEAD_OBJECT;
+ }
+ } else {
+ ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
+ "session is 3.7", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
+ /*out*/device::V3_2::CaptureRequest* captureRequest,
+ /*out*/std::vector<native_handle_t*>* handlesCreated,
+ /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers) {
+ ATRACE_CALL();
+ if (captureRequest == nullptr || handlesCreated == nullptr || inflightBuffers == nullptr) {
+ ALOGE("%s: captureRequest (%p), handlesCreated (%p), and inflightBuffers(%p) "
+ "must not be null", __FUNCTION__, captureRequest, handlesCreated, inflightBuffers);
+ return BAD_VALUE;
+ }
+
+ captureRequest->frameNumber = request->frame_number;
+
+ captureRequest->fmqSettingsSize = 0;
+
+ {
+ if (request->input_buffer != nullptr) {
+ int32_t streamId = Camera3Stream::cast(request->input_buffer->stream)->getId();
+ buffer_handle_t buf = *(request->input_buffer->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
+ uint64_t bufferId = pair.second;
+ captureRequest->inputBuffer.streamId = streamId;
+ captureRequest->inputBuffer.bufferId = bufferId;
+ captureRequest->inputBuffer.buffer = (isNewBuffer) ? buf : nullptr;
+ captureRequest->inputBuffer.status = BufferStatus::OK;
+ native_handle_t *acquireFence = nullptr;
+ if (request->input_buffer->acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = request->input_buffer->acquire_fence;
+ handlesCreated->push_back(acquireFence);
+ }
+ captureRequest->inputBuffer.acquireFence = acquireFence;
+ captureRequest->inputBuffer.releaseFence = nullptr;
+
+ mBufferRecords.pushInflightBuffer(captureRequest->frameNumber, streamId,
+ request->input_buffer->buffer);
+ inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+ } else {
+ captureRequest->inputBuffer.streamId = -1;
+ captureRequest->inputBuffer.bufferId = BUFFER_ID_NO_BUFFER;
+ }
+
+ captureRequest->outputBuffers.resize(request->num_output_buffers);
+ for (size_t i = 0; i < request->num_output_buffers; i++) {
+ const camera_stream_buffer_t *src = request->output_buffers + i;
+ StreamBuffer &dst = captureRequest->outputBuffers[i];
+ int32_t streamId = Camera3Stream::cast(src->stream)->getId();
+ if (src->buffer != nullptr) {
+ buffer_handle_t buf = *(src->buffer);
+ auto pair = getBufferId(buf, streamId);
+ bool isNewBuffer = pair.first;
+ dst.bufferId = pair.second;
+ dst.buffer = isNewBuffer ? buf : nullptr;
+ native_handle_t *acquireFence = nullptr;
+ if (src->acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = src->acquire_fence;
+ handlesCreated->push_back(acquireFence);
+ }
+ dst.acquireFence = acquireFence;
+ } else if (mUseHalBufManager) {
+ // HAL buffer management path
+ dst.bufferId = BUFFER_ID_NO_BUFFER;
+ dst.buffer = nullptr;
+ dst.acquireFence = nullptr;
+ } else {
+ ALOGE("%s: cannot send a null buffer in capture request!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ dst.streamId = streamId;
+ dst.status = BufferStatus::OK;
+ dst.releaseFence = nullptr;
+
+ // Output buffers are empty when using HAL buffer manager
+ if (!mUseHalBufManager) {
+ mBufferRecords.pushInflightBuffer(
+ captureRequest->frameNumber, streamId, src->buffer);
+ inflightBuffers->push_back(std::make_pair(captureRequest->frameNumber, streamId));
+ }
+ }
+ }
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::flush() {
+ ATRACE_NAME("CameraHal::flush");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ auto err = mHidlSession->flush();
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ res = DEAD_OBJECT;
+ } else {
+ res = HidlProviderInfo::mapToStatusT(err);
+ }
+
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::dump(int /*fd*/) {
+ ATRACE_NAME("CameraHal::dump");
+ if (!valid()) return INVALID_OPERATION;
+
+ // Handled by CameraProviderManager::dump
+
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) {
+ ATRACE_NAME("CameraHal::repeatingRequestEnd");
+ if (!valid()) return INVALID_OPERATION;
+
+ if (mHidlSession_3_8.get() != nullptr) {
+ mHidlSession_3_8->repeatingRequestEnd(frameNumber, streamIds);
+ }
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::close() {
+ ATRACE_NAME("CameraHal::close()");
+ if (!valid()) return INVALID_OPERATION;
+ status_t res = OK;
+
+ auto err = mHidlSession->close();
+ // Interface will be dead shortly anyway, so don't log errors
+ if (!err.isOk()) {
+ res = DEAD_OBJECT;
+ }
+
+ return res;
+}
+
+void HidlCamera3Device::HidlHalInterface::signalPipelineDrain(const std::vector<int>& streamIds) {
+ ATRACE_NAME("CameraHal::signalPipelineDrain");
+ if (!valid() || mHidlSession_3_5 == nullptr) {
+ ALOGE("%s called on invalid camera!", __FUNCTION__);
+ return;
+ }
+
+ auto err = mHidlSession_3_5->signalStreamFlush(streamIds, mNextStreamConfigCounter - 1);
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return;
+ }
+}
+
+status_t HidlCamera3Device::HidlHalInterface::processBatchCaptureRequests(
+ std::vector<camera_capture_request_t*>& requests,/*out*/uint32_t* numRequestProcessed) {
+ ATRACE_NAME("CameraHal::processBatchCaptureRequests");
+ if (!valid()) return INVALID_OPERATION;
+
+ sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
+ sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
+ auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ hidlSession_3_7 = castResult_3_7;
+ }
+ auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_4.isOk()) {
+ hidlSession_3_4 = castResult_3_4;
+ }
+
+ hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
+ hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
+ hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
+ size_t batchSize = requests.size();
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7.resize(batchSize);
+ } else if (hidlSession_3_4 != nullptr) {
+ captureRequests_3_4.resize(batchSize);
+ } else {
+ captureRequests.resize(batchSize);
+ }
+ std::vector<native_handle_t*> handlesCreated;
+ std::vector<std::pair<int32_t, int32_t>> inflightBuffers;
+
+ status_t res = OK;
+ for (size_t i = 0; i < batchSize; i++) {
+ if (hidlSession_3_7 != nullptr) {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ } else if (hidlSession_3_4 != nullptr) {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ } else {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i],
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ }
+ if (res != OK) {
+ mBufferRecords.popInflightBuffers(inflightBuffers);
+ cleanupNativeHandles(&handlesCreated);
+ return res;
+ }
+ }
+
+ std::vector<device::V3_2::BufferCache> cachesToRemove;
+ {
+ std::lock_guard<std::mutex> lock(mFreedBuffersLock);
+ for (auto& pair : mFreedBuffers) {
+ // The stream might have been removed since onBufferFreed
+ if (mBufferRecords.isStreamCached(pair.first)) {
+ cachesToRemove.push_back({pair.first, pair.second});
+ }
+ }
+ mFreedBuffers.clear();
+ }
+
+ common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+ *numRequestProcessed = 0;
+
+ // Write metadata to FMQ.
+ for (size_t i = 0; i < batchSize; i++) {
+ camera_capture_request_t* request = requests[i];
+ device::V3_2::CaptureRequest* captureRequest;
+ if (hidlSession_3_7 != nullptr) {
+ captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
+ } else if (hidlSession_3_4 != nullptr) {
+ captureRequest = &captureRequests_3_4[i].v3_2;
+ } else {
+ captureRequest = &captureRequests[i];
+ }
+
+ if (request->settings != nullptr) {
+ size_t settingsSize = get_camera_metadata_size(request->settings);
+ if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t*>(request->settings), settingsSize)) {
+ captureRequest->settings.resize(0);
+ captureRequest->fmqSettingsSize = settingsSize;
+ } else {
+ if (mRequestMetadataQueue != nullptr) {
+ ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+ }
+ captureRequest->settings.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+ request->settings)),
+ get_camera_metadata_size(request->settings));
+ captureRequest->fmqSettingsSize = 0u;
+ }
+ } else {
+ // A null request settings maps to a size-0 CameraMetadata
+ captureRequest->settings.resize(0);
+ captureRequest->fmqSettingsSize = 0u;
+ }
+
+ // hidl session 3.7 specific handling.
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7[i].inputWidth = request->input_width;
+ captureRequests_3_7[i].inputHeight = request->input_height;
+ }
+
+ // hidl session 3.7 and 3.4 specific handling.
+ if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
+ hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
+ (hidlSession_3_7 != nullptr) ?
+ captureRequests_3_7[i].v3_4.physicalCameraSettings :
+ captureRequests_3_4[i].physicalCameraSettings;
+ physicalCameraSettings.resize(request->num_physcam_settings);
+ for (size_t j = 0; j < request->num_physcam_settings; j++) {
+ if (request->physcam_settings != nullptr) {
+ size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
+ if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
+ reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
+ settingsSize)) {
+ physicalCameraSettings[j].settings.resize(0);
+ physicalCameraSettings[j].fmqSettingsSize = settingsSize;
+ } else {
+ if (mRequestMetadataQueue != nullptr) {
+ ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
+ }
+ physicalCameraSettings[j].settings.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
+ request->physcam_settings[j])),
+ get_camera_metadata_size(request->physcam_settings[j]));
+ physicalCameraSettings[j].fmqSettingsSize = 0u;
+ }
+ } else {
+ physicalCameraSettings[j].fmqSettingsSize = 0u;
+ physicalCameraSettings[j].settings.resize(0);
+ }
+ physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
+ }
+ }
+ }
+
+ hardware::details::return_status err;
+ auto resultCallback =
+ [&status, &numRequestProcessed] (auto s, uint32_t n) {
+ status = s;
+ *numRequestProcessed = n;
+ };
+ if (hidlSession_3_7 != nullptr) {
+ err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
+ resultCallback);
+ } else if (hidlSession_3_4 != nullptr) {
+ err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
+ resultCallback);
+ } else {
+ err = mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
+ resultCallback);
+ }
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ status = common::V1_0::Status::CAMERA_DISCONNECTED;
+ }
+
+ if (status == common::V1_0::Status::OK && *numRequestProcessed != batchSize) {
+ ALOGE("%s: processCaptureRequest returns OK but processed %d/%zu requests",
+ __FUNCTION__, *numRequestProcessed, batchSize);
+ status = common::V1_0::Status::INTERNAL_ERROR;
+ }
+
+ res = HidlProviderInfo::mapToStatusT(status);
+ if (res == OK) {
+ if (mHidlSession->isRemote()) {
+ // Only close acquire fence FDs when the HIDL transaction succeeds (so the FDs have been
+ // sent to camera HAL processes)
+ cleanupNativeHandles(&handlesCreated, /*closeFd*/true);
+ } else {
+ // In passthrough mode the FDs are now owned by HAL
+ cleanupNativeHandles(&handlesCreated);
+ }
+ } else {
+ mBufferRecords.popInflightBuffers(inflightBuffers);
+ cleanupNativeHandles(&handlesCreated);
+ }
+ return res;
+}
+
+status_t HidlCamera3Device::HidlHalInterface::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords) {
+ ATRACE_NAME("CameraHal::switchToOffline");
+ if (!valid() || mHidlSession_3_6 == nullptr) {
+ ALOGE("%s called on invalid camera!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ if (offlineSessionInfo == nullptr || offlineSession == nullptr || bufferRecords == nullptr) {
+ ALOGE("%s: output arguments must not be null!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
+ auto resultCallback =
+ [&status, &offlineSessionInfo, &offlineSession] (auto s, auto info, auto session) {
+ status = s;
+ *offlineSessionInfo = info;
+ *offlineSession = session;
+ };
+ auto err = mHidlSession_3_6->switchToOffline(streamsToKeep, resultCallback);
+
+ if (!err.isOk()) {
+ ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ status_t ret = HidlProviderInfo::mapToStatusT(status);
+ if (ret != OK) {
+ return ret;
+ }
+
+ return verifyBufferCaches(offlineSessionInfo, bufferRecords);
+}
+
+HidlCamera3Device::HidlRequestThread::HidlRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) :
+ RequestThread(parent, statusTracker, interface, sessionParamKeys, useHalBufManager,
+ supportCameraMute) {}
+
+status_t HidlCamera3Device::HidlRequestThread::switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords) {
+ Mutex::Autolock l(mRequestLock);
+ clearRepeatingRequestsLocked(/*lastFrameNumber*/nullptr);
+
+ // Wait until request thread is fully stopped
+ // TBD: check if request thread is being paused by other APIs (shouldn't be)
+
+ // We could also check for mRepeatingRequests.empty(), but the API interface
+ // is serialized by Camera3Device::mInterfaceLock so no one should be able to submit any
+ // new requests during the call; hence skip that check.
+ bool queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ while (!queueEmpty) {
+ status_t res = mRequestSubmittedSignal.waitRelative(mRequestLock, kRequestSubmitTimeout);
+ if (res == TIMED_OUT) {
+ ALOGE("%s: request thread failed to submit one request within timeout!", __FUNCTION__);
+ return res;
+ } else if (res != OK) {
+ ALOGE("%s: request thread failed to submit a request: %s (%d)!",
+ __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+ queueEmpty = mNextRequests.empty() && mRequestQueue.empty();
+ }
+ return (static_cast<HidlHalInterface *>(mInterface.get()))->switchToOffline(
+ streamsToKeep, offlineSessionInfo, offlineSession, bufferRecords);
+}
+
+status_t HidlCamera3Device::HidlCamera3DeviceInjectionMethods::injectionInitialize(
+ const String8& injectedCamId, sp<CameraProviderManager> manager,
+ const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
+ callback) {
+ ATRACE_CALL();
+ Mutex::Autolock lock(mInjectionLock);
+
+ if (manager == nullptr) {
+ ALOGE("%s: manager does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("%s: parent does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ mInjectedCamId = injectedCamId;
+ sp<ICameraDeviceSession> session;
+ ATRACE_BEGIN("Injection CameraHal::openSession");
+ status_t res = manager->openHidlSession(injectedCamId.string(), callback,
+ /*out*/ &session);
+ ATRACE_END();
+ if (res != OK) {
+ ALOGE("Injection camera could not open camera session: %s (%d)",
+ strerror(-res), res);
+ return res;
+ }
+
+ std::shared_ptr<RequestMetadataQueue> queue;
+ auto requestQueueRet =
+ session->getCaptureRequestMetadataQueue([&queue](const auto& descriptor) {
+ queue = std::make_shared<RequestMetadataQueue>(descriptor);
+ if (!queue->isValid() || queue->availableToWrite() <= 0) {
+ ALOGE("Injection camera HAL returns empty request metadata fmq, not "
+ "use it");
+ queue = nullptr;
+ // don't use the queue onwards.
+ }
+ });
+ if (!requestQueueRet.isOk()) {
+ ALOGE("Injection camera transaction error when getting request metadata fmq: "
+ "%s, not use it", requestQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
+ auto resultQueueRet = session->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("Injection camera HAL returns empty result metadata fmq, not use "
+ "it");
+ resQueue = nullptr;
+ // Don't use the resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Injection camera transaction error when getting result metadata queue "
+ "from camera session: %s", resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ IF_ALOGV() {
+ session->interfaceChain(
+ [](::android::hardware::hidl_vec<::android::hardware::hidl_string>
+ interfaceChain) {
+ ALOGV("Injection camera session interface chain:");
+ for (const auto& iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+
+ ALOGV("%s: Injection camera interface = new HalInterface()", __FUNCTION__);
+
+ mInjectedCamHalInterface =
+ new HidlHalInterface(session, queue, parent->mUseHalBufManager,
+ parent->mSupportOfflineProcessing);
+ if (mInjectedCamHalInterface == nullptr) {
+ ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ return OK;
+}
+
+status_t HidlCamera3Device::HidlCamera3DeviceInjectionMethods::replaceHalInterface(
+ sp<HalInterface> newHalInterface, bool keepBackup) {
+ Mutex::Autolock lock(mInjectionLock);
+ if (newHalInterface.get() == nullptr) {
+ ALOGE("%s: The newHalInterface does not exist, to stop replacing.",
+ __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == nullptr) {
+ ALOGE("%s: parent does not exist!", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+ if (newHalInterface->getTransportType() != IPCTransport::HIDL) {
+ ALOGE("%s Replacing HIDL HalInterface with another transport unsupported", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ HidlCamera3Device *hidlParent = static_cast<HidlCamera3Device *>(parent.get());
+ if (keepBackup) {
+ if (mBackupHalInterface == nullptr) {
+ mBackupHalInterface = parent->mInterface;
+ }
+ if (mBackupResultMetadataQueue == nullptr) {
+ mBackupResultMetadataQueue = std::move(hidlParent->mResultMetadataQueue);
+ hidlParent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
+ }
+ } else {
+ mBackupHalInterface = nullptr;
+ hidlParent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
+ mBackupResultMetadataQueue = nullptr;
+ }
+ parent->mInterface = newHalInterface;
+
+ return OK;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
new file mode 100644
index 0000000..a83080b
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_HIDLCAMERA3DEVICE_H
+#define ANDROID_SERVERS_HIDLCAMERA3DEVICE_H
+
+#include "../Camera3Device.h"
+#include "HidlCamera3OutputUtils.h"
+
+namespace android {
+
+using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
+
+/**
+ * CameraDevice for HIDL HAL devices with version CAMERA_DEVICE_API_VERSION_3_0 or higher.
+ */
+class HidlCamera3Device :
+ virtual public hardware::camera::device::V3_8::ICameraDeviceCallback,
+ public Camera3Device {
+ public:
+
+ explicit HidlCamera3Device(const String8& id, bool overrideForPerfClass,
+ bool legacyClient = false) : Camera3Device(id, overrideForPerfClass, legacyClient) { }
+
+ virtual ~HidlCamera3Device() {}
+
+ /**
+ * Helper functions to map between framework and HIDL values
+ */
+ static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
+ static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
+ android_dataspace dataSpace);
+ static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
+ static CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap mapToHidlDynamicProfile(
+ int dynamicRangeProfile);
+ static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
+ camera_stream_rotation_t rotation);
+ // Returns a negative error code if the passed-in operation mode is not valid.
+ static status_t mapToStreamConfigurationMode(camera_stream_configuration_mode_t operationMode,
+ /*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
+ static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
+ static android_dataspace mapToFrameworkDataspace(
+ hardware::camera::device::V3_2::DataspaceFlags);
+ static uint64_t mapConsumerToFrameworkUsage(
+ hardware::camera::device::V3_2::BufferUsageFlags usage);
+ static uint64_t mapProducerToFrameworkUsage(
+ hardware::camera::device::V3_2::BufferUsageFlags usage);
+
+ status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+
+ /**
+ * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+ */
+
+ hardware::Return<void> processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) override;
+ hardware::Return<void> processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) override;
+ hardware::Return<void> notify(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+ hardware::Return<void> requestStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) override;
+
+ hardware::Return<void> returnStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+ hardware::Return<void> notify_3_8(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_8::NotifyMsg>& msgs) override;
+
+ // Handle one notify message
+ void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
+
+ status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
+ /*out*/ sp<CameraOfflineSessionBase>* session) override;
+
+ using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
+
+ class HidlHalInterface : public Camera3Device::HalInterface {
+ public:
+ HidlHalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
+ std::shared_ptr<RequestMetadataQueue> queue,
+ bool useHalBufManager, bool supportOfflineProcessing);
+
+ virtual IPCTransport getTransportType() override { return IPCTransport::HIDL; }
+ // Returns true if constructed with a valid device or session, and not yet cleared
+ virtual bool valid() override;
+
+ // Reset this HalInterface object (does not call close())
+ virtual void clear() override;
+
+ // Calls into the HAL interface
+
+ // Caller takes ownership of requestTemplate
+ virtual status_t constructDefaultRequestSettings(camera_request_template templateId,
+ /*out*/ camera_metadata_t **requestTemplate) override;
+
+ virtual status_t configureStreams(const camera_metadata_t *sessionParams,
+ /*inout*/ camera_stream_configuration_t *config,
+ const std::vector<uint32_t>& bufferSizes) override;
+
+ // The injection camera configures the streams to hal.
+ virtual status_t configureInjectedStreams(
+ const camera_metadata_t* sessionParams,
+ /*inout*/ camera_stream_configuration_t* config,
+ const std::vector<uint32_t>& bufferSizes,
+ const CameraMetadata& cameraCharacteristics) override;
+
+ // When the call succeeds, the ownership of acquire fences in requests is transferred to
+ // HalInterface. More specifically, the current implementation will send the fence to
+ // HAL process and close the FD in cameraserver process. When the call fails, the ownership
+ // of the acquire fence still belongs to the caller.
+ virtual status_t processBatchCaptureRequests(
+ std::vector<camera_capture_request_t*>& requests,
+ /*out*/uint32_t* numRequestProcessed) override;
+ virtual status_t flush() override;
+ virtual status_t dump(int fd) override;
+ virtual status_t close() override;
+
+ virtual void signalPipelineDrain(const std::vector<int>& streamIds) override;
+ virtual bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
+ CameraMetadata& newSessionParams) override;
+
+ virtual status_t repeatingRequestEnd(uint32_t frameNumber,
+ const std::vector<int32_t> &streamIds) override;
+
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords);
+
+ private:
+
+ // Always valid
+ sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
+ // Valid if ICameraDeviceSession is @3.3 or newer
+ sp<hardware::camera::device::V3_3::ICameraDeviceSession> mHidlSession_3_3;
+ // Valid if ICameraDeviceSession is @3.4 or newer
+ sp<hardware::camera::device::V3_4::ICameraDeviceSession> mHidlSession_3_4;
+ // Valid if ICameraDeviceSession is @3.5 or newer
+ sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
+ // Valid if ICameraDeviceSession is @3.6 or newer
+ sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
+ // Valid if ICameraDeviceSession is @3.7 or newer
+ sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
+ // Valid if ICameraDeviceSession is @3.7 or newer
+ sp<hardware::camera::device::V3_8::ICameraDeviceSession> mHidlSession_3_8;
+
+ std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
+
+ // The output HIDL request still depends on input camera_capture_request_t
+ // Do not free input camera_capture_request_t before output HIDL request
+ status_t wrapAsHidlRequest(camera_capture_request_t* in,
+ /*out*/hardware::camera::device::V3_2::CaptureRequest* out,
+ /*out*/std::vector<native_handle_t*>* handlesCreated,
+ /*out*/std::vector<std::pair<int32_t, int32_t>>* inflightBuffers);
+ }; // class HidlHalInterface
+
+ class HidlRequestThread : public Camera3Device::RequestThread {
+ public:
+ HidlRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute);
+
+ status_t switchToOffline(
+ const std::vector<int32_t>& streamsToKeep,
+ /*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
+ /*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
+ /*out*/camera3::BufferRecords* bufferRecords);
+ }; // class HidlRequestThread
+
+ class HidlCamera3DeviceInjectionMethods : public Camera3DeviceInjectionMethods {
+ public:
+ // Initialize the injection camera and generate an hal interface.
+ status_t injectionInitialize(
+ const String8& injectedCamId, sp<CameraProviderManager> manager,
+ const sp<
+ android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
+ callback);
+ HidlCamera3DeviceInjectionMethods(wp<Camera3Device> parent) :
+ Camera3DeviceInjectionMethods(parent) { };
+ ~HidlCamera3DeviceInjectionMethods() {}
+ private:
+ // Backup of the original camera hal result FMQ.
+ std::unique_ptr<ResultMetadataQueue> mBackupResultMetadataQueue;
+
+ // FMQ writes the result for the injection camera. Must be guarded by
+ // mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mInjectionResultMetadataQueue;
+
+ // Use injection camera hal interface to replace and backup original
+ // camera hal interface.
+ virtual status_t replaceHalInterface(sp<HalInterface> newHalInterface,
+ bool keepBackup) override;
+ };
+
+ private:
+ template<typename NotifyMsgType>
+ hardware::Return<void> notifyHelper(
+ const hardware::hidl_vec<NotifyMsgType>& msgs);
+
+ virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+ sp<CameraProviderManager> manager) override;
+
+ virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> parent,
+ sp<camera3::StatusTracker> statusTracker,
+ sp<HalInterface> interface,
+ const Vector<int32_t>& sessionParamKeys,
+ bool useHalBufManager,
+ bool supportCameraMute) override;
+
+ virtual sp<Camera3DeviceInjectionMethods>
+ createCamera3DeviceInjectionMethods(wp<Camera3Device>) override;
+
+ // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+}; // class HidlCamera3Device
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
new file mode 100644
index 0000000..d517c8d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Hidl-Camera3-OffLnSsn"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <inttypes.h>
+
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include "device3/hidl/HidlCamera3OfflineSession.h"
+#include "device3/Camera3OutputStream.h"
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/Camera3InputStream.h"
+#include "device3/Camera3SharedOutputStream.h"
+#include "utils/CameraTraces.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+
+HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
+ ATRACE_CALL();
+ ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
+ HidlCamera3OfflineSession::disconnectSession();
+}
+
+status_t HidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
+ ATRACE_CALL();
+
+ if (mSession == nullptr) {
+ ALOGE("%s: HIDL session is null!", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+
+ mListener = listener;
+
+ // setup result FMQ
+ std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
+ auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
+ [&resQueue](const auto& descriptor) {
+ resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
+ if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
+ ALOGE("HAL returns empty result metadata fmq, not use it");
+ resQueue = nullptr;
+ // Don't use resQueue onwards.
+ }
+ });
+ if (!resultQueueRet.isOk()) {
+ ALOGE("Transaction error when getting result metadata queue from camera session: %s",
+ resultQueueRet.description().c_str());
+ return DEAD_OBJECT;
+ }
+ mStatus = STATUS_ACTIVE;
+ }
+
+ mSession->setCallback(this);
+
+ return OK;
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) {
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+
+ std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) {
+ // TODO: changed impl to call into processCaptureResult_3_4 instead?
+ // might need to figure how to reduce copy though.
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+
+ std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
+ for (const auto& result : results) {
+ processOneCaptureResultLocked(states, result, noPhysMetadata);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::notify(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
+ sp<NotificationListener> listener;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ listener = mListener.promote();
+ }
+
+ HidlCaptureOutputStates states {
+ {mId,
+ mOfflineReqsLock, mLastCompletedRegularFrameNumber,
+ mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
+ mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
+ mNextShutterFrameNumber,
+ mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
+ mNextResultFrameNumber,
+ mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
+ mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
+ mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
+ mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
+ mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
+ mBufferRecords, /*legacyClient*/ false}, mResultMetadataQueue
+ };
+ for (const auto& msg : msgs) {
+ camera3::notify(states, msg);
+ }
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::requestStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) {
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ }
+
+ RequestBufferStates states {
+ mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
+ *this, mBufferRecords, *this};
+ camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
+ return hardware::Void();
+}
+
+hardware::Return<void> HidlCamera3OfflineSession::returnStreamBuffers(
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mStatus != STATUS_ACTIVE) {
+ ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
+ return hardware::Void();
+ }
+ }
+
+ ReturnBufferStates states {
+ mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords};
+
+ camera3::returnStreamBuffers(states, buffers);
+ return hardware::Void();
+}
+
+void HidlCamera3OfflineSession::disconnectSession() {
+ // TODO: Make sure this locking is correct.
+ std::lock_guard<std::mutex> lock(mLock);
+ if (mSession != nullptr) {
+ mSession->close();
+ }
+ mSession.clear();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
new file mode 100644
index 0000000..597cc5d
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_HIDL_CAMERA3OFFLINESESSION_H
+#define ANDROID_SERVERS_HIDL_CAMERA3OFFLINESESSION_H
+
+#include <memory>
+#include <mutex>
+
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+#include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
+
+#include <fmq/MessageQueue.h>
+
+#include "HidlCamera3OutputUtils.h"
+#include "common/CameraOfflineSessionBase.h"
+
+#include "device3/Camera3BufferManager.h"
+#include "device3/Camera3OfflineSession.h"
+#include "device3/InFlightRequest.h"
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3Stream;
+class Camera3OutputStreamInterface;
+class Camera3StreamInterface;
+
+} // namespace camera3
+
+/**
+ * HidlCamera3OfflineSession for offline session defined in HIDL ICameraOfflineSession@3.6 or higher
+ */
+class HidlCamera3OfflineSession :
+ public Camera3OfflineSession,
+ virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
+ public:
+
+ // initialize by Camera3Device.
+ explicit HidlCamera3OfflineSession(const String8& id,
+ const sp<camera3::Camera3Stream>& inputStream,
+ const camera3::StreamSet& offlineStreamSet,
+ camera3::BufferRecords&& bufferRecords,
+ const camera3::InFlightRequestMap& offlineReqs,
+ const Camera3OfflineStates& offlineStates,
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
+ Camera3OfflineSession(id, inputStream, offlineStreamSet, std::move(bufferRecords),
+ offlineReqs, offlineStates),
+ mSession(offlineSession) {};
+
+ virtual ~HidlCamera3OfflineSession();
+
+ virtual status_t initialize(wp<NotificationListener> listener) override;
+
+ /**
+ * HIDL ICameraDeviceCallback interface
+ * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
+ */
+
+ hardware::Return<void> processCaptureResult_3_4(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::CaptureResult>& results) override;
+ hardware::Return<void> processCaptureResult(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::CaptureResult>& results) override;
+ hardware::Return<void> notify(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::NotifyMsg>& msgs) override;
+
+ hardware::Return<void> requestStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ requestStreamBuffers_cb _hidl_cb) override;
+
+ hardware::Return<void> returnStreamBuffers(
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
+
+ /**
+ * End of CameraOfflineSessionBase interface
+ */
+
+ private:
+ sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
+ // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
+ std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
+
+ virtual void disconnectSession() override;
+}; // class Camera3OfflineSession
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
new file mode 100644
index 0000000..afe9d56
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "HidlCamera3-OutputUtils"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+// Convenience macros for transitioning to the error state
+#define SET_ERR(fmt, ...) states.setErrIntf.setErrorState( \
+ "%s: " fmt, __FUNCTION__, \
+ ##__VA_ARGS__)
+
+#include <inttypes.h>
+
+#include <utils/Log.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+
+#include <camera/CameraUtils.h>
+#include <camera_metadata_hidden.h>
+
+#include "device3/hidl/HidlCamera3OutputUtils.h"
+#include "device3/Camera3OutputUtilsTemplated.h"
+
+#include "system/camera_metadata.h"
+
+using namespace android::camera3;
+using namespace android::hardware::camera;
+
+namespace android {
+namespace camera3 {
+
+void processOneCaptureResultLocked(
+ HidlCaptureOutputStates& states,
+ const hardware::camera::device::V3_2::CaptureResult& result,
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::PhysicalCameraMetadata> &physicalCameraMetadata) {
+ processOneCaptureResultLockedT<HidlCaptureOutputStates,
+ hardware::camera::device::V3_2::CaptureResult,
+ hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata>,
+ hardware::hidl_vec<uint8_t>, ResultMetadataQueue,
+ hardware::camera::device::V3_2::BufferStatus>(states, result, physicalCameraMetadata);
+}
+
+void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_8::NotifyMsg& msg) {
+ using android::hardware::camera::device::V3_2::MsgType;
+
+ hardware::camera::device::V3_2::NotifyMsg msg_3_2;
+ msg_3_2.type = msg.type;
+ bool hasReadoutTime = false;
+ uint64_t readoutTime = 0;
+ switch (msg.type) {
+ case MsgType::ERROR:
+ msg_3_2.msg.error = msg.msg.error;
+ break;
+ case MsgType::SHUTTER:
+ msg_3_2.msg.shutter = msg.msg.shutter.v3_2;
+ hasReadoutTime = true;
+ readoutTime = msg.msg.shutter.readoutTimestamp;
+ break;
+ }
+ notify(states, msg_3_2, hasReadoutTime, readoutTime);
+}
+
+void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_2::NotifyMsg& msg,
+ bool hasReadoutTime, uint64_t readoutTime) {
+
+ using android::hardware::camera::device::V3_2::MsgType;
+ using android::hardware::camera::device::V3_2::ErrorCode;
+
+ ATRACE_CALL();
+ camera_notify_msg m;
+ switch (msg.type) {
+ case MsgType::ERROR:
+ m.type = CAMERA_MSG_ERROR;
+ m.message.error.frame_number = msg.msg.error.frameNumber;
+ if (msg.msg.error.errorStreamId >= 0) {
+ sp<Camera3StreamInterface> stream =
+ states.outputStreams.get(msg.msg.error.errorStreamId);
+ if (stream == nullptr) {
+ ALOGE("%s: Frame %d: Invalid error stream id %d", __FUNCTION__,
+ m.message.error.frame_number, msg.msg.error.errorStreamId);
+ return;
+ }
+ m.message.error.error_stream = stream->asHalStream();
+ } else {
+ m.message.error.error_stream = nullptr;
+ }
+ switch (msg.msg.error.errorCode) {
+ case ErrorCode::ERROR_DEVICE:
+ m.message.error.error_code = CAMERA_MSG_ERROR_DEVICE;
+ break;
+ case ErrorCode::ERROR_REQUEST:
+ m.message.error.error_code = CAMERA_MSG_ERROR_REQUEST;
+ break;
+ case ErrorCode::ERROR_RESULT:
+ m.message.error.error_code = CAMERA_MSG_ERROR_RESULT;
+ break;
+ case ErrorCode::ERROR_BUFFER:
+ m.message.error.error_code = CAMERA_MSG_ERROR_BUFFER;
+ break;
+ }
+ break;
+ case MsgType::SHUTTER:
+ m.type = CAMERA_MSG_SHUTTER;
+ m.message.shutter.frame_number = msg.msg.shutter.frameNumber;
+ m.message.shutter.timestamp = msg.msg.shutter.timestamp;
+ m.message.shutter.readout_timestamp = hasReadoutTime ?
+ readoutTime : m.message.shutter.timestamp;
+ break;
+ }
+ notify(states, &m);
+}
+
+
+
+// The buffers requested through this call are not tied to any CaptureRequest in
+// particular. They may used by the hal for a particular frame's output buffer
+// or for its internal use as well. In the case that the hal does use any buffer
+// from the requested list here, for a particular frame's output buffer, the
+// buffer will be returned with the processCaptureResult call corresponding to
+// the frame. The other buffers will be returned through returnStreamBuffers.
+// The buffers returned via returnStreamBuffers will not have a valid
+// timestamp(0) and will be dropped by the bufferqueue.
+void requestStreamBuffers(RequestBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb) {
+ using android::hardware::camera::device::V3_2::BufferStatus;
+ using android::hardware::camera::device::V3_2::StreamBuffer;
+ using android::hardware::camera::device::V3_5::BufferRequestStatus;
+ using android::hardware::camera::device::V3_5::StreamBufferRet;
+ using android::hardware::camera::device::V3_5::StreamBufferRequestError;
+
+ std::lock_guard<std::mutex> lock(states.reqBufferLock);
+
+ hardware::hidl_vec<StreamBufferRet> bufRets;
+ if (!states.useHalBufManager) {
+ ALOGE("%s: Camera %s does not support HAL buffer management",
+ __FUNCTION__, states.cameraId.string());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ SortedVector<int32_t> streamIds;
+ ssize_t sz = streamIds.setCapacity(bufReqs.size());
+ if (sz < 0 || static_cast<size_t>(sz) != bufReqs.size()) {
+ ALOGE("%s: failed to allocate memory for %zu buffer requests",
+ __FUNCTION__, bufReqs.size());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ if (bufReqs.size() > states.outputStreams.size()) {
+ ALOGE("%s: too many buffer requests (%zu > # of output streams %zu)",
+ __FUNCTION__, bufReqs.size(), states.outputStreams.size());
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+
+ // Check for repeated streamId
+ for (const auto& bufReq : bufReqs) {
+ if (streamIds.indexOf(bufReq.streamId) != NAME_NOT_FOUND) {
+ ALOGE("%s: Stream %d appear multiple times in buffer requests",
+ __FUNCTION__, bufReq.streamId);
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, bufRets);
+ return;
+ }
+ streamIds.add(bufReq.streamId);
+ }
+
+ if (!states.reqBufferIntf.startRequestBuffer()) {
+ ALOGE("%s: request buffer disallowed while camera service is configuring",
+ __FUNCTION__);
+ _hidl_cb(BufferRequestStatus::FAILED_CONFIGURING, bufRets);
+ return;
+ }
+
+ bufRets.resize(bufReqs.size());
+
+ bool allReqsSucceeds = true;
+ bool oneReqSucceeds = false;
+ for (size_t i = 0; i < bufReqs.size(); i++) {
+ const auto& bufReq = bufReqs[i];
+ auto& bufRet = bufRets[i];
+ int32_t streamId = bufReq.streamId;
+ sp<Camera3OutputStreamInterface> outputStream = states.outputStreams.get(streamId);
+ if (outputStream == nullptr) {
+ ALOGE("%s: Output stream id %d not found!", __FUNCTION__, streamId);
+ hardware::hidl_vec<StreamBufferRet> emptyBufRets;
+ _hidl_cb(BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS, emptyBufRets);
+ states.reqBufferIntf.endRequestBuffer();
+ return;
+ }
+
+ bufRet.streamId = streamId;
+ if (outputStream->isAbandoned()) {
+ bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+ allReqsSucceeds = false;
+ continue;
+ }
+
+ size_t handOutBufferCount = outputStream->getOutstandingBuffersCount();
+ uint32_t numBuffersRequested = bufReq.numBuffersRequested;
+ size_t totalHandout = handOutBufferCount + numBuffersRequested;
+ uint32_t maxBuffers = outputStream->asHalStream()->max_buffers;
+ if (totalHandout > maxBuffers) {
+ // Not able to allocate enough buffer. Exit early for this stream
+ ALOGE("%s: request too much buffers for stream %d: at HAL: %zu + requesting: %d"
+ " > max: %d", __FUNCTION__, streamId, handOutBufferCount,
+ numBuffersRequested, maxBuffers);
+ bufRet.val.error(StreamBufferRequestError::MAX_BUFFER_EXCEEDED);
+ allReqsSucceeds = false;
+ continue;
+ }
+
+ hardware::hidl_vec<StreamBuffer> tmpRetBuffers(numBuffersRequested);
+ bool currentReqSucceeds = true;
+ std::vector<camera_stream_buffer_t> streamBuffers(numBuffersRequested);
+ std::vector<buffer_handle_t> newBuffers;
+ size_t numAllocatedBuffers = 0;
+ size_t numPushedInflightBuffers = 0;
+ for (size_t b = 0; b < numBuffersRequested; b++) {
+ camera_stream_buffer_t& sb = streamBuffers[b];
+ // Since this method can run concurrently with request thread
+ // We need to update the wait duration everytime we call getbuffer
+ nsecs_t waitDuration = states.reqBufferIntf.getWaitDuration();
+ status_t res = outputStream->getBuffer(&sb, waitDuration);
+ if (res != OK) {
+ if (res == NO_INIT || res == DEAD_OBJECT) {
+ ALOGV("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ bufRet.val.error(StreamBufferRequestError::STREAM_DISCONNECTED);
+ states.sessionStatsBuilder.stopCounter(streamId);
+ } else {
+ ALOGE("%s: Can't get output buffer for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ if (res == TIMED_OUT || res == NO_MEMORY) {
+ bufRet.val.error(StreamBufferRequestError::NO_BUFFER_AVAILABLE);
+ } else {
+ bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ }
+ }
+ currentReqSucceeds = false;
+ break;
+ }
+ numAllocatedBuffers++;
+
+ buffer_handle_t *buffer = sb.buffer;
+ auto pair = states.bufferRecordsIntf.getBufferId(*buffer, streamId);
+ bool isNewBuffer = pair.first;
+ uint64_t bufferId = pair.second;
+ StreamBuffer& hBuf = tmpRetBuffers[b];
+
+ hBuf.streamId = streamId;
+ hBuf.bufferId = bufferId;
+ hBuf.buffer = (isNewBuffer) ? *buffer : nullptr;
+ hBuf.status = BufferStatus::OK;
+ hBuf.releaseFence = nullptr;
+ if (isNewBuffer) {
+ newBuffers.push_back(*buffer);
+ }
+
+ native_handle_t *acquireFence = nullptr;
+ if (sb.acquire_fence != -1) {
+ acquireFence = native_handle_create(1,0);
+ acquireFence->data[0] = sb.acquire_fence;
+ }
+ hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
+ hBuf.releaseFence = nullptr;
+
+ res = states.bufferRecordsIntf.pushInflightRequestBuffer(bufferId, buffer, streamId);
+ if (res != OK) {
+ ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ bufRet.val.error(StreamBufferRequestError::UNKNOWN_ERROR);
+ currentReqSucceeds = false;
+ break;
+ }
+ numPushedInflightBuffers++;
+ }
+ if (currentReqSucceeds) {
+ bufRet.val.buffers(std::move(tmpRetBuffers));
+ oneReqSucceeds = true;
+ } else {
+ allReqsSucceeds = false;
+ for (size_t b = 0; b < numPushedInflightBuffers; b++) {
+ StreamBuffer& hBuf = tmpRetBuffers[b];
+ buffer_handle_t* buffer;
+ status_t res = states.bufferRecordsIntf.popInflightRequestBuffer(
+ hBuf.bufferId, &buffer);
+ if (res != OK) {
+ SET_ERR("%s: popInflightRequestBuffer failed for stream %d: %s (%d)",
+ __FUNCTION__, streamId, strerror(-res), res);
+ }
+ }
+ for (size_t b = 0; b < numAllocatedBuffers; b++) {
+ camera_stream_buffer_t& sb = streamBuffers[b];
+ sb.acquire_fence = -1;
+ sb.status = CAMERA_BUFFER_STATUS_ERROR;
+ }
+ returnOutputBuffers(states.useHalBufManager, /*listener*/nullptr,
+ streamBuffers.data(), numAllocatedBuffers, /*timestamp*/0,
+ /*readoutTimestamp*/0, /*requested*/false,
+ /*requestTimeNs*/0, states.sessionStatsBuilder);
+ for (auto buf : newBuffers) {
+ states.bufferRecordsIntf.removeOneBufferCache(streamId, buf);
+ }
+ }
+ }
+
+ _hidl_cb(allReqsSucceeds ? BufferRequestStatus::OK :
+ oneReqSucceeds ? BufferRequestStatus::FAILED_PARTIAL :
+ BufferRequestStatus::FAILED_UNKNOWN,
+ bufRets);
+ states.reqBufferIntf.endRequestBuffer();
+}
+
+void returnStreamBuffers(ReturnBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
+ returnStreamBuffersT(states, buffers);
+}
+
+} // camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h
new file mode 100644
index 0000000..583d738
--- /dev/null
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OutputUtils.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_HIDL_CAMERA3_OUTPUT_UTILS_H
+#define ANDROID_SERVERS_HIDL_CAMERA3_OUTPUT_UTILS_H
+
+#include <memory>
+#include <mutex>
+
+#include <cutils/native_handle.h>
+
+#include <fmq/MessageQueue.h>
+
+#include <common/CameraDeviceBase.h>
+
+#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
+
+#include "device3/BufferUtils.h"
+//#include "device3/DistortionMapper.h"
+//#include "device3/ZoomRatioMapper.h"
+//#include "device3/RotateAndCropMapper.h"
+#include "device3/InFlightRequest.h"
+#include "device3/Camera3Stream.h"
+//#include "device3/Camera3OutputStreamInterface.h"
+#include "device3/Camera3OutputUtils.h"
+//#include "utils/SessionStatsBuilder.h"
+//#include "utils/TagMonitor.h"
+
+namespace android {
+
+using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
+
+namespace camera3 {
+
+ /**
+ * Helper methods shared between HidlCamera3Device/HidlCamera3OfflineSession for HAL callbacks
+ */
+ // Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
+ // callbacks
+ struct HidlCaptureOutputStates : public CaptureOutputStates {
+ std::unique_ptr<ResultMetadataQueue>& fmq;
+ };
+
+ // Handle one capture result. Assume callers hold the lock to serialize all
+ // processCaptureResult calls
+ void processOneCaptureResultLocked(
+ HidlCaptureOutputStates& states,
+ const hardware::camera::device::V3_2::CaptureResult& result,
+ const hardware::hidl_vec<
+ hardware::camera::device::V3_4::PhysicalCameraMetadata>
+ &physicalCameraMetadata);
+
+ // Handle one notify message
+ void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_2::NotifyMsg& msg,
+ bool hasReadoutTime = false, uint64_t readoutTime = 0LL);
+ void notify(CaptureOutputStates& states,
+ const hardware::camera::device::V3_8::NotifyMsg& msg);
+
+ void requestStreamBuffers(RequestBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
+ hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb
+ _hidl_cb);
+ void returnStreamBuffers(ReturnBufferStates& states,
+ const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
+
+} // namespace camera3
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index 4f080fe..ca73e4c 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -59,6 +59,7 @@
"android.hardware.camera.device@3.5",
"android.hardware.camera.device@3.6",
"android.hardware.camera.device@3.7",
+ "android.hardware.camera.device@3.8",
],
fuzz_config: {
cc: [
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index 8757afa..c3f0620 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -48,6 +48,7 @@
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.7",
+ "android.hardware.camera.device@3.8",
"android.hidl.token@1.0-utils",
],
@@ -121,4 +122,4 @@
test_suites: ["device-tests"],
-}
\ No newline at end of file
+}
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index c8a6b32..e9f6979 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -212,7 +212,7 @@
* Simple test version of the interaction proxy, to use to inject onRegistered calls to the
* CameraProviderManager
*/
-struct TestInteractionProxy : public CameraProviderManager::ServiceInteractionProxy {
+struct TestInteractionProxy : public CameraProviderManager::HidlServiceInteractionProxy {
sp<hidl::manager::V1_0::IServiceNotification> mManagerNotificationInterface;
sp<TestICameraProvider> mTestCameraProvider;
@@ -269,13 +269,13 @@
~TestStatusListener() {}
void onDeviceStatusChanged(const String8 &,
- hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+ CameraDeviceStatus) override {}
void onDeviceStatusChanged(const String8 &, const String8 &,
- hardware::camera::common::V1_0::CameraDeviceStatus) override {}
+ CameraDeviceStatus) override {}
void onTorchStatusChanged(const String8 &,
- hardware::camera::common::V1_0::TorchModeStatus) override {}
+ TorchModeStatus) override {}
void onTorchStatusChanged(const String8 &,
- hardware::camera::common::V1_0::TorchModeStatus, SystemCameraKind) override {}
+ TorchModeStatus, SystemCameraKind) override {}
void onNewProviderRegistered() override {}
};
diff --git a/services/camera/libcameraservice/utils/IPCTransport.h b/services/camera/libcameraservice/utils/IPCTransport.h
new file mode 100644
index 0000000..b8e80ac
--- /dev/null
+++ b/services/camera/libcameraservice/utils/IPCTransport.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_IPC_H_
+#define ANDROID_SERVERS_IPC_H_
+
+enum class IPCTransport : uint32_t {
+ HIDL = 0,
+ AIDL = 1,
+ INVALID = 2
+};
+
+#endif
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index f6f0539..f826d83 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -19,15 +19,18 @@
#include "SessionConfigurationUtils.h"
#include "../api2/DepthCompositeStream.h"
#include "../api2/HeicCompositeStream.h"
+#include "android/hardware/camera/metadata/3.8/types.h"
#include "common/CameraDeviceBase.h"
#include "../CameraService.h"
-#include "device3/Camera3Device.h"
+#include "device3/hidl/HidlCamera3Device.h"
#include "device3/Camera3OutputStream.h"
+#include "system/graphics-base-v1.1.h"
using android::camera3::OutputStreamInfo;
using android::camera3::OutputStreamInfo;
using android::hardware::camera2::ICameraDeviceUser;
using android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
+using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
namespace android {
namespace camera3 {
@@ -206,6 +209,80 @@
return true;
}
+//check if format is 10-bit compatible
+bool is10bitCompatibleFormat(int32_t format) {
+ switch(format) {
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ case HAL_PIXEL_FORMAT_YCBCR_P010:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool isDynamicRangeProfileSupported(int dynamicRangeProfile, const CameraMetadata& staticInfo) {
+ if (dynamicRangeProfile == ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
+ // Supported by default
+ return true;
+ }
+
+ camera_metadata_ro_entry_t entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ bool is10bitDynamicRangeSupported = false;
+ for (size_t i = 0; i < entry.count; ++i) {
+ uint8_t capability = entry.data.u8[i];
+ if (capability == ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
+ is10bitDynamicRangeSupported = true;
+ break;
+ }
+ }
+
+ if (!is10bitDynamicRangeSupported) {
+ return false;
+ }
+
+ switch (dynamicRangeProfile) {
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
+ entry = staticInfo.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP);
+ for (size_t i = 0; i < entry.count; i += 2) {
+ if (dynamicRangeProfile == entry.data.i32[i]) {
+ return true;
+ }
+ }
+
+ return false;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+//check if format is 10-bit compatible
+bool is10bitDynamicRangeProfile(int32_t dynamicRangeProfile) {
+ switch (dynamicRangeProfile) {
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool isPublicFormat(int32_t format)
{
switch(format) {
@@ -237,7 +314,7 @@
OutputStreamInfo& streamInfo, bool isStreamInfoValid,
sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
- const std::vector<int32_t> &sensorPixelModesUsed){
+ const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile){
// bufferProducer must be non-null
if (gbp == nullptr) {
String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
@@ -335,6 +412,21 @@
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
+ if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
+ physicalCameraMetadata)) {
+ String8 msg = String8::format("Camera %s: Dynamic range profile 0x%x not supported,"
+ " failed to create output stream", logicalCameraId.string(), dynamicRangeProfile);
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
+ if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
+ !SessionConfigurationUtils::is10bitCompatibleFormat(format)) {
+ String8 msg = String8::format("Camera %s: No 10-bit supported stream configurations with "
+ "format %#x defined and profile %#x, failed to create output stream",
+ logicalCameraId.string(), format, dynamicRangeProfile);
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+ }
if (!isStreamInfoValid) {
streamInfo.width = width;
@@ -343,6 +435,7 @@
streamInfo.dataSpace = dataSpace;
streamInfo.consumerUsage = consumerUsage;
streamInfo.sensorPixelModesUsed = overriddenSensorPixelModes;
+ streamInfo.dynamicRangeProfile = dynamicRangeProfile;
return binder::Status::ok();
}
if (width != streamInfo.width) {
@@ -385,30 +478,34 @@
void mapStreamInfo(const OutputStreamInfo &streamInfo,
camera3::camera_stream_rotation_t rotation, String8 physicalId,
- int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
+ int32_t groupId, hardware::camera::device::V3_8::Stream *stream /*out*/) {
if (stream == nullptr) {
return;
}
- stream->v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
- stream->v3_4.v3_2.width = streamInfo.width;
- stream->v3_4.v3_2.height = streamInfo.height;
- stream->v3_4.v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
+ stream->v3_7.v3_4.v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
+ stream->v3_7.v3_4.v3_2.width = streamInfo.width;
+ stream->v3_7.v3_4.v3_2.height = streamInfo.height;
+ stream->v3_7.v3_4.v3_2.format = HidlCamera3Device::mapToPixelFormat(streamInfo.format);
auto u = streamInfo.consumerUsage;
camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
- stream->v3_4.v3_2.usage = Camera3Device::mapToConsumerUsage(u);
- stream->v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
- stream->v3_4.v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
- stream->v3_4.v3_2.id = -1; // Invalid stream id
- stream->v3_4.physicalCameraId = std::string(physicalId.string());
- stream->v3_4.bufferSize = 0;
- stream->groupId = groupId;
- stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
+ stream->v3_7.v3_4.v3_2.usage = HidlCamera3Device::mapToConsumerUsage(u);
+ stream->v3_7.v3_4.v3_2.dataSpace = HidlCamera3Device::mapToHidlDataspace(streamInfo.dataSpace);
+ stream->v3_7.v3_4.v3_2.rotation = HidlCamera3Device::mapToStreamRotation(rotation);
+ stream->v3_7.v3_4.v3_2.id = -1; // Invalid stream id
+ stream->v3_7.v3_4.physicalCameraId = std::string(physicalId.string());
+ stream->v3_7.v3_4.bufferSize = 0;
+ stream->v3_7.groupId = groupId;
+ stream->v3_7.sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
+
size_t idx = 0;
for (auto mode : streamInfo.sensorPixelModesUsed) {
- stream->sensorPixelModesUsed[idx++] =
+ stream->v3_7.sensorPixelModesUsed[idx++] =
static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
}
+ stream->dynamicRangeProfile =
+ static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> (
+ streamInfo.dynamicRangeProfile);
}
binder::Status checkPhysicalCameraId(
@@ -488,7 +585,7 @@
const SessionConfiguration& sessionConfiguration,
const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
- hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
+ hardware::camera::device::V3_8::StreamConfiguration &streamConfiguration,
bool overrideForPerfClass, bool *earlyExit) {
auto operatingMode = sessionConfiguration.getOperatingMode();
@@ -503,7 +600,7 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
*earlyExit = false;
- auto ret = Camera3Device::mapToStreamConfigurationMode(
+ auto ret = HidlCamera3Device::mapToStreamConfigurationMode(
static_cast<camera_stream_configuration_mode_t> (operatingMode),
/*out*/ &streamConfiguration.operationMode);
if (ret != OK) {
@@ -529,11 +626,11 @@
defaultSensorPixelModes[0] =
static_cast<CameraMetadataEnumAndroidSensorPixelMode>(
ANDROID_SENSOR_PIXEL_MODE_DEFAULT);
- streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
+ streamConfiguration.streams[streamIdx++].v3_7 = {{{/*streamId*/0,
hardware::camera::device::V3_2::StreamType::INPUT,
static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
- Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
+ HidlCamera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
/*usage*/ 0, HAL_DATASPACE_UNKNOWN,
hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
/*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1, defaultSensorPixelModes};
@@ -547,6 +644,7 @@
bool deferredConsumer = it.isDeferred();
String8 physicalCameraId = String8(it.getPhysicalCameraId());
+ int dynamicRangeProfile = it.getDynamicRangeProfile();
std::vector<int32_t> sensorPixelModesUsed = it.getSensorPixelModesUsed();
const CameraMetadata &physicalDeviceInfo = getMetadata(physicalCameraId,
overrideForPerfClass);
@@ -578,6 +676,7 @@
if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
}
+ streamInfo.dynamicRangeProfile = it.getDynamicRangeProfile();
if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed,
streamInfo.format, streamInfo.width,
streamInfo.height, metadataChosen, false /*flexibleConsumer*/,
@@ -599,7 +698,7 @@
for (auto& bufferProducer : bufferProducers) {
sp<Surface> surface;
res = createSurfaceFromGbp(streamInfo, isStreamInfoValid, surface, bufferProducer,
- logicalCameraId, metadataChosen, sensorPixelModesUsed);
+ logicalCameraId, metadataChosen, sensorPixelModesUsed, dynamicRangeProfile);
if (!res.isOk())
return res;
@@ -741,6 +840,25 @@
return OK;
}
+bool convertHALStreamCombinationFromV38ToV37(
+ hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37,
+ const hardware::camera::device::V3_8::StreamConfiguration &streamConfigV38) {
+ streamConfigV37.streams.resize(streamConfigV38.streams.size());
+ for (size_t i = 0; i < streamConfigV38.streams.size(); i++) {
+ if (static_cast<int32_t>(streamConfigV38.streams[i].dynamicRangeProfile) !=
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
+ // ICameraDevice older than 3.8 doesn't support 10-bit dynamic range profiles
+ // image
+ return false;
+ }
+ streamConfigV37.streams[i] = streamConfigV38.streams[i].v3_7;
+ }
+ streamConfigV37.operationMode = streamConfigV38.operationMode;
+ streamConfigV37.sessionParams = streamConfigV38.sessionParams;
+
+ return true;
+}
+
bool convertHALStreamCombinationFromV37ToV34(
hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index efba9c9..9a5dc2c 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -24,6 +24,7 @@
#include <android/hardware/camera/device/3.8/types.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
#include <device3/Camera3StreamInterface.h>
@@ -96,12 +97,20 @@
camera3::OutputStreamInfo& streamInfo, bool isStreamInfoValid,
sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
-const std::vector<int32_t> &sensorPixelModesUsed);
-
+const std::vector<int32_t> &sensorPixelModesUsed, int dynamicRangeProfile);
void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
camera3::camera_stream_rotation_t rotation, String8 physicalId, int32_t groupId,
hardware::camera::device::V3_7::Stream *stream /*out*/);
+//check if format is 10-bit output compatible
+bool is10bitCompatibleFormat(int32_t format);
+
+// check if the dynamic range requires 10-bit output
+bool is10bitDynamicRangeProfile(int32_t dynamicRangeProfile);
+
+// Check if the device supports a given dynamicRangeProfile
+bool isDynamicRangeProfileSupported(int dynamicRangeProfile, const CameraMetadata& staticMeta);
+
// Check that the physicalCameraId passed in is spported by the camera
// device.
binder::Status checkPhysicalCameraId(
@@ -122,9 +131,16 @@
convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
const String8 &cameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
- hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
+ hardware::camera::device::V3_8::StreamConfiguration &streamConfiguration,
bool overrideForPerfClass, bool *earlyExit);
+// Utility function to convert a V3_8::StreamConfiguration to
+// V3_7::StreamConfiguration. Return false if the original V3_8 configuration cannot
+// be used by older version HAL.
+bool convertHALStreamCombinationFromV38ToV37(
+ hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37,
+ const hardware::camera::device::V3_8::StreamConfiguration &streamConfigV38);
+
// Utility function to convert a V3_7::StreamConfiguration to
// V3_4::StreamConfiguration. Return false if the original V3_7 configuration cannot
// be used by older version HAL.
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index c98d5fc..0fa24cd 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -181,15 +181,16 @@
"libstatssocket",
],
+ export_include_dirs: [
+ ".",
+ ],
+
static_libs: [
"libplatformprotos",
],
header_libs: [
"libaaudio_headers",
- ],
-
- include_dirs: [
- "system/media/audio_utils/include",
+ "libaudioutils_headers",
],
}
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 9da7282..84d494e 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -59,9 +59,8 @@
"packagemanager_aidl-cpp",
],
- include_dirs: [
- "frameworks/av/services/mediametrics",
- "system/media/audio_utils/include",
+ header_libs: [
+ "libaudioutils_headers",
],
fuzz_config: {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 40a664e..2679b2e 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -280,6 +280,22 @@
AIDL_RETURN(serviceStream->unregisterAudioThread(clientThreadId));
}
+Status AAudioService::exitStandby(int32_t streamHandle, Endpoint* endpoint, int32_t *_aidl_return) {
+ static_assert(std::is_same_v<aaudio_result_t, std::decay_t<typeof(*_aidl_return)>>);
+
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
+ AIDL_RETURN(AAUDIO_ERROR_INVALID_HANDLE);
+ }
+ AudioEndpointParcelable endpointParcelable;
+ aaudio_result_t result = serviceStream->exitStandby(&endpointParcelable);
+ if (result == AAUDIO_OK) {
+ *endpoint = std::move(endpointParcelable).parcelable();
+ }
+ AIDL_RETURN(result);
+}
+
bool AAudioService::isCallerInService() {
pid_t clientPid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mAudioClient.attributionSource.pid));
uid_t clientUid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAudioClient.attributionSource.uid));
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index 7c1b796..0a111fb 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -82,6 +82,9 @@
binder::Status unregisterAudioThread(int32_t streamHandle, int32_t clientThreadId,
int32_t* _aidl_return) override;
+ binder::Status exitStandby(int32_t streamHandle, ::aaudio::Endpoint* endpoint,
+ int32_t* _aidl_return) override;
+
aaudio_result_t startClient(aaudio::aaudio_handle_t streamHandle,
const android::AudioClient& client,
const audio_attributes_t *attr,
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a7f63d3..92004c5 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -77,6 +77,16 @@
return AAUDIO_ERROR_UNAVAILABLE;
}
+ virtual aaudio_result_t standby() {
+ ALOGD("AAudioServiceEndpoint::standby() AAUDIO_ERROR_UNAVAILABLE");
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
+ virtual aaudio_result_t exitStandby(AudioEndpointParcelable* parcelable) {
+ ALOGD("AAudioServiceEndpoint::exitStandby() AAUDIO_ERROR_UNAVAILABLE");
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
/**
* @param positionFrames
* @param timeNanos
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 046b84b..a266d5b 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -186,37 +186,8 @@
ALOGD("%s() deviceId = %d, sessionId = %d", __func__, getDeviceId(), getSessionId());
// Create MMAP/NOIRQ buffer.
- int32_t minSizeFrames = getBufferCapacity();
- if (minSizeFrames <= 0) { // zero will get rejected
- minSizeFrames = AAUDIO_BUFFER_CAPACITY_MIN;
- }
- status = mMmapStream->createMmapBuffer(minSizeFrames, &mMmapBufferinfo);
- bool isBufferShareable = mMmapBufferinfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE;
- if (status != OK) {
- ALOGE("%s() - createMmapBuffer() failed with status %d %s",
- __func__, status, strerror(-status));
- result = AAUDIO_ERROR_UNAVAILABLE;
+ if (createMmapBuffer(&mAudioDataFileDescriptor) != AAUDIO_OK) {
goto error;
- } else {
- ALOGD("%s() createMmapBuffer() buffer_size = %d fr, burst_size %d fr"
- ", Sharable FD: %s",
- __func__,
- mMmapBufferinfo.buffer_size_frames,
- mMmapBufferinfo.burst_size_frames,
- isBufferShareable ? "Yes" : "No");
- }
-
- setBufferCapacity(mMmapBufferinfo.buffer_size_frames);
- if (!isBufferShareable) {
- // Exclusive mode can only be used by the service because the FD cannot be shared.
- int32_t audioServiceUid =
- VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
- if ((mMmapClient.attributionSource.uid != audioServiceUid) &&
- getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
- ALOGW("%s() - exclusive FD cannot be used by client", __func__);
- result = AAUDIO_ERROR_UNAVAILABLE;
- goto error;
- }
}
// Get information about the stream and pass it back to the caller.
@@ -224,21 +195,6 @@
config.channel_mask, getDirection() == AAUDIO_DIRECTION_INPUT,
AAudio_isChannelIndexMask(config.channel_mask)));
- // AAudio creates a copy of this FD and retains ownership of the copy.
- // Assume that AudioFlinger will close the original shared_memory_fd.
- mAudioDataFileDescriptor.reset(dup(mMmapBufferinfo.shared_memory_fd));
- if (mAudioDataFileDescriptor.get() == -1) {
- ALOGE("%s() - could not dup shared_memory_fd", __func__);
- result = AAUDIO_ERROR_INTERNAL;
- goto error;
- }
- // Call to HAL to make sure the transport FD was able to be closed by binder.
- // This is a tricky workaround for a problem in Binder.
- // TODO:[b/192048842] When that problem is fixed we may be able to remove or change this code.
- struct audio_mmap_position position;
- mMmapStream->getMmapPosition(&position);
-
- mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
setFormat(config.format);
setSampleRate(config.sample_rate);
@@ -323,6 +279,32 @@
return result;
}
+aaudio_result_t AAudioServiceEndpointMMAP::standby() {
+ if (mMmapStream == nullptr) {
+ return AAUDIO_ERROR_NULL;
+ }
+ aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->standby());
+ return result;
+}
+
+aaudio_result_t AAudioServiceEndpointMMAP::exitStandby(AudioEndpointParcelable* parcelable) {
+ if (mMmapStream == nullptr) {
+ return AAUDIO_ERROR_NULL;
+ }
+ mAudioDataFileDescriptor.reset();
+ aaudio_result_t result = createMmapBuffer(&mAudioDataFileDescriptor);
+ if (result == AAUDIO_OK) {
+ int32_t bytesPerFrame = calculateBytesPerFrame();
+ int32_t capacityInBytes = getBufferCapacity() * bytesPerFrame;
+ int fdIndex = parcelable->addFileDescriptor(mAudioDataFileDescriptor, capacityInBytes);
+ parcelable->mDownDataQueueParcelable.setupMemory(fdIndex, 0, capacityInBytes);
+ parcelable->mDownDataQueueParcelable.setBytesPerFrame(bytesPerFrame);
+ parcelable->mDownDataQueueParcelable.setFramesPerBurst(mFramesPerBurst);
+ parcelable->mDownDataQueueParcelable.setCapacityInFrames(getBufferCapacity());
+ }
+ return result;
+}
+
// Get free-running DSP or DMA hardware position from the HAL.
aaudio_result_t AAudioServiceEndpointMMAP::getFreeRunningPosition(int64_t *positionFrames,
int64_t *timeNanos) {
@@ -502,3 +484,57 @@
*timeNanos = tempTimeNanos;
return mHalExternalPositionStatus;
}
+
+aaudio_result_t AAudioServiceEndpointMMAP::createMmapBuffer(
+ android::base::unique_fd* fileDescriptor)
+{
+ memset(&mMmapBufferinfo, 0, sizeof(struct audio_mmap_buffer_info));
+ int32_t minSizeFrames = getBufferCapacity();
+ if (minSizeFrames <= 0) { // zero will get rejected
+ minSizeFrames = AAUDIO_BUFFER_CAPACITY_MIN;
+ }
+ status_t status = mMmapStream->createMmapBuffer(minSizeFrames, &mMmapBufferinfo);
+ bool isBufferShareable = mMmapBufferinfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE;
+ if (status != OK) {
+ ALOGE("%s() - createMmapBuffer() failed with status %d %s",
+ __func__, status, strerror(-status));
+ return AAUDIO_ERROR_UNAVAILABLE;
+ } else {
+ ALOGD("%s() createMmapBuffer() buffer_size = %d fr, burst_size %d fr"
+ ", Sharable FD: %s",
+ __func__,
+ mMmapBufferinfo.buffer_size_frames,
+ mMmapBufferinfo.burst_size_frames,
+ isBufferShareable ? "Yes" : "No");
+ }
+
+ setBufferCapacity(mMmapBufferinfo.buffer_size_frames);
+ if (!isBufferShareable) {
+ // Exclusive mode can only be used by the service because the FD cannot be shared.
+ int32_t audioServiceUid =
+ VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+ if ((mMmapClient.attributionSource.uid != audioServiceUid) &&
+ getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
+ ALOGW("%s() - exclusive FD cannot be used by client", __func__);
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+ }
+
+ // AAudio creates a copy of this FD and retains ownership of the copy.
+ // Assume that AudioFlinger will close the original shared_memory_fd.
+ fileDescriptor->reset(dup(mMmapBufferinfo.shared_memory_fd));
+ if (fileDescriptor->get() == -1) {
+ ALOGE("%s() - could not dup shared_memory_fd", __func__);
+ return AAUDIO_ERROR_INTERNAL;
+ }
+
+ // Call to HAL to make sure the transport FD was able to be closed by binder.
+ // This is a tricky workaround for a problem in Binder.
+ // TODO:[b/192048842] When that problem is fixed we may be able to remove or change this code.
+ struct audio_mmap_position position;
+ mMmapStream->getMmapPosition(&position);
+
+ mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
+
+ return AAUDIO_OK;
+}
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 6314e5e..3e7f2c7 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -64,6 +64,10 @@
aaudio_result_t stopClient(audio_port_handle_t clientHandle) override;
+ aaudio_result_t standby() override;
+
+ aaudio_result_t exitStandby(AudioEndpointParcelable* parcelable) override;
+
aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
aaudio_result_t getTimestamp(int64_t *positionFrames, int64_t *timeNanos) override;
@@ -91,6 +95,8 @@
aaudio_result_t openWithFormat(audio_format_t audioFormat);
+ aaudio_result_t createMmapBuffer(android::base::unique_fd* fileDescriptor);
+
MonotonicCounter mFramesTransferred;
// Interface to the AudioFlinger MMAP support.
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 8b5ccaa..9f48f80 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -41,6 +41,8 @@
using content::AttributionSourceState;
static const int64_t TIMEOUT_NANOS = 3LL * 1000 * 1000 * 1000;
+// If the stream is idle for more than `IDLE_TIMEOUT_NANOS`, the stream will be put into standby.
+static const int64_t IDLE_TIMEOUT_NANOS = 3e9;
/**
* Base class for streams in the service.
@@ -247,6 +249,12 @@
return AAUDIO_ERROR_INVALID_STATE;
}
+ if (mStandby) {
+ ALOGW("%s() the stream is standby, return ERROR_STANDBY, "
+ "expecting the client call exitStandby before start", __func__);
+ return AAUDIO_ERROR_STANDBY;
+ }
+
mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
@@ -394,6 +402,7 @@
android::sp<AAudioServiceStreamBase> holdStream(this);
TimestampScheduler timestampScheduler;
int64_t nextTime;
+ int64_t standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
// Balance the incStrong from when the thread was launched.
holdStream->decStrong(nullptr);
@@ -405,8 +414,8 @@
while (mThreadEnabled.load()) {
loopCount++;
int64_t timeoutNanos = -1;
- if (isRunning()) {
- timeoutNanos = nextTime - AudioClock::getNanoseconds();
+ if (isRunning() || (isIdle_l() && !isStandby_l())) {
+ timeoutNanos = (isRunning() ? nextTime : standbyTime) - AudioClock::getNanoseconds();
timeoutNanos = std::max<int64_t>(0, timeoutNanos);
}
@@ -425,6 +434,9 @@
nextTime = timestampScheduler.nextAbsoluteTime();
}
}
+ if (isIdle_l() && AudioClock::getNanoseconds() >= standbyTime) {
+ standby_l();
+ }
if (command != nullptr) {
std::scoped_lock<std::mutex> _commandLock(command->lock);
@@ -437,9 +449,11 @@
break;
case PAUSE:
command->result = pause_l();
+ standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
break;
case STOP:
command->result = stop_l();
+ standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
break;
case FLUSH:
command->result = flush_l();
@@ -474,6 +488,12 @@
: getDescription_l(param->mParcelable);
}
break;
+ case EXIT_STANDBY: {
+ ExitStandbyParam *param = (ExitStandbyParam *) command->parameter.get();
+ command->result = param == nullptr ? AAUDIO_ERROR_ILLEGAL_ARGUMENT
+ : exitStandby_l(param->mParcelable);
+ standbyTime = AudioClock::getNanoseconds() + IDLE_TIMEOUT_NANOS;
+ } break;
default:
ALOGE("Invalid command op code: %d", command->operationCode);
break;
@@ -673,6 +693,15 @@
return getAudioDataDescription_l(parcelable);
}
+aaudio_result_t AAudioServiceStreamBase::exitStandby(AudioEndpointParcelable *parcelable) {
+ auto command = std::make_shared<AAudioCommand>(
+ EXIT_STANDBY,
+ std::make_shared<ExitStandbyParam>(parcelable),
+ true /*waitForReply*/,
+ TIMEOUT_NANOS);
+ return mCommandQueue.sendCommand(command);
+}
+
void AAudioServiceStreamBase::onVolumeChanged(float volume) {
sendServiceEvent(AAUDIO_SERVICE_EVENT_VOLUME, volume);
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index dddd69f..b2ba725 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -116,6 +116,11 @@
*/
aaudio_result_t flush() EXCLUDES(mLock);
+ /**
+ * Exit standby mode. The MMAP buffer will be reallocated.
+ */
+ aaudio_result_t exitStandby(AudioEndpointParcelable *parcelable) EXCLUDES(mLock);
+
virtual aaudio_result_t startClient(const android::AudioClient& client,
const audio_attributes_t *attr __unused,
audio_port_handle_t *clientHandle __unused) {
@@ -314,6 +319,33 @@
mDisconnected = flag;
}
+ virtual aaudio_result_t standby_l() REQUIRES(mLock) {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+ class ExitStandbyParam : public AAudioCommandParam {
+ public:
+ ExitStandbyParam(AudioEndpointParcelable* parcelable)
+ : AAudioCommandParam(), mParcelable(parcelable) { }
+ ~ExitStandbyParam() = default;
+
+ AudioEndpointParcelable* mParcelable;
+ };
+ virtual aaudio_result_t exitStandby_l(
+ AudioEndpointParcelable* parcelable __unused) REQUIRES(mLock) {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+ bool isStandby_l() const REQUIRES(mLock) {
+ return mStandby;
+ }
+ void setStandby_l(bool standby) REQUIRES(mLock) {
+ mStandby = standby;
+ }
+
+ bool isIdle_l() const REQUIRES(mLock) {
+ return mState == AAUDIO_STREAM_STATE_OPEN || mState == AAUDIO_STREAM_STATE_PAUSED
+ || mState == AAUDIO_STREAM_STATE_STOPPED;
+ }
+
pid_t mRegisteredClientThread = ILLEGAL_THREAD_ID;
std::mutex mUpMessageQueueLock;
@@ -329,6 +361,7 @@
REGISTER_AUDIO_THREAD,
UNREGISTER_AUDIO_THREAD,
GET_DESCRIPTION,
+ EXIT_STANDBY,
};
AAudioThread mCommandThread;
std::atomic<bool> mThreadEnabled{false};
@@ -391,6 +424,8 @@
bool mDisconnected GUARDED_BY(mLock) {false};
+ bool mStandby GUARDED_BY(mLock) = false;
+
protected:
// Locking order is important.
// Acquire mLock before acquiring AAudioServiceEndpoint::mLockStreams
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index ffc16ac..ec9b2e2 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -117,6 +117,35 @@
return result;
}
+aaudio_result_t AAudioServiceStreamMMAP::standby_l() {
+ sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
+ if (endpoint == nullptr) {
+ ALOGE("%s() has no endpoint", __func__);
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ aaudio_result_t result = endpoint->standby();
+ if (result == AAUDIO_OK) {
+ setStandby_l(true);
+ }
+ return result;
+}
+
+aaudio_result_t AAudioServiceStreamMMAP::exitStandby_l(AudioEndpointParcelable* parcelable) {
+ sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
+ if (endpoint == nullptr) {
+ ALOGE("%s() has no endpoint", __func__);
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ aaudio_result_t result = endpoint->exitStandby(parcelable);
+ if (result == AAUDIO_OK) {
+ setStandby_l(false);
+ } else {
+ ALOGE("%s failed, result %d, disconnecting stream.", __func__, result);
+ disconnect_l();
+ }
+ return result;
+}
+
aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
const audio_attributes_t *attr,
audio_port_handle_t *clientHandle) {
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 28da120..cd8c91e 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -71,6 +71,10 @@
aaudio_result_t stop_l() REQUIRES(mLock) override;
+ aaudio_result_t standby_l() REQUIRES(mLock) override;
+
+ aaudio_result_t exitStandby_l(AudioEndpointParcelable* parcelable) REQUIRES(mLock) override;
+
aaudio_result_t getAudioDataDescription_l(
AudioEndpointParcelable* parcelable) REQUIRES(mLock) override;
diff --git a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
index 17e8d36..5e48955 100644
--- a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
+++ b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
@@ -180,6 +180,11 @@
return AAUDIO_ERROR_UNAVAILABLE;
}
+ aaudio_result_t exitStandby(aaudio_handle_t streamHandle UNUSED_PARAM,
+ AudioEndpointParcelable &parcelable UNUSED_PARAM) override {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {}
int getDeathCount() { return mDeathCount; }
diff --git a/services/tuner/TunerFrontend.cpp b/services/tuner/TunerFrontend.cpp
index a5ef2bb..0340573 100644
--- a/services/tuner/TunerFrontend.cpp
+++ b/services/tuner/TunerFrontend.cpp
@@ -174,6 +174,16 @@
return mFrontend->getHardwareInfo(_aidl_return);
}
+::ndk::ScopedAStatus TunerFrontend::removeOutputPid(int32_t in_pid) {
+ if (mFrontend == nullptr) {
+ ALOGD("IFrontend is not initialized");
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
+ return mFrontend->removeOutputPid(in_pid);
+}
+
/////////////// FrontendCallback ///////////////////////
::ndk::ScopedAStatus TunerFrontend::FrontendCallback::onEvent(FrontendEventType frontendEventType) {
ALOGV("FrontendCallback::onEvent, type=%d", frontendEventType);
diff --git a/services/tuner/TunerFrontend.h b/services/tuner/TunerFrontend.h
index 418a751..a96099e 100644
--- a/services/tuner/TunerFrontend.h
+++ b/services/tuner/TunerFrontend.h
@@ -63,6 +63,7 @@
vector<FrontendStatus>* _aidl_return) override;
::ndk::ScopedAStatus getFrontendId(int32_t* _aidl_return) override;
::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus removeOutputPid(int32_t in_pid) override;
struct FrontendCallback : public BnFrontendCallback {
FrontendCallback(const shared_ptr<ITunerFrontendCallback> tunerFrontendCallback)
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
index 96f285f..2887d80 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFrontend.aidl
@@ -99,4 +99,9 @@
* Request hardware information about the frontend.
*/
String getHardwareInfo();
+
+ /**
+ * Filter out unnecessary PID from frontend output.
+ */
+ void removeOutputPid(int pid);
}
diff --git a/services/tuner/hidl/TunerHidlFrontend.cpp b/services/tuner/hidl/TunerHidlFrontend.cpp
index 057f24a..9733063 100644
--- a/services/tuner/hidl/TunerHidlFrontend.cpp
+++ b/services/tuner/hidl/TunerHidlFrontend.cpp
@@ -428,6 +428,11 @@
static_cast<int32_t>(Result::UNAVAILABLE));
}
+::ndk::ScopedAStatus TunerHidlFrontend::removeOutputPid(int32_t /* in_pid */) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+}
+
void TunerHidlFrontend::setLna(bool bEnable) {
if (mFrontend == nullptr) {
ALOGD("IFrontend is not initialized");
diff --git a/services/tuner/hidl/TunerHidlFrontend.h b/services/tuner/hidl/TunerHidlFrontend.h
index 7ff278c..95d2c1a 100644
--- a/services/tuner/hidl/TunerHidlFrontend.h
+++ b/services/tuner/hidl/TunerHidlFrontend.h
@@ -83,6 +83,7 @@
vector<FrontendStatus>* _aidl_return) override;
::ndk::ScopedAStatus getFrontendId(int32_t* _aidl_return) override;
::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus removeOutputPid(int32_t in_pid) override;
void setLna(bool in_bEnable);