Merge "aaudio example: add dynamic workload test"
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/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 f23684a..f477f1c 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -59,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/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/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/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/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/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 b2d2dbd..f2f15df 100644
--- a/media/libheadtracking/HeadTrackingProcessor.cpp
+++ b/media/libheadtracking/HeadTrackingProcessor.cpp
@@ -66,6 +66,7 @@
Pose3f predictedWorldToHead =
worldToHead * integrate(headTwist, mOptions.predictionDuration);
mHeadPoseDriftCompensator.setInput(timestamp, predictedWorldToHead);
+ mHeadStillnessDetector.setInput(timestamp, predictedWorldToHead);
mWorldToHeadTimestamp = timestamp;
}
@@ -76,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;
}
@@ -93,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.
@@ -108,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/StillnessDetector-test.cpp b/media/libheadtracking/StillnessDetector-test.cpp
index 02f9d8a..b6cd479 100644
--- a/media/libheadtracking/StillnessDetector-test.cpp
+++ b/media/libheadtracking/StillnessDetector-test.cpp
@@ -83,13 +83,10 @@
EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_EQ(mDefaultValue, detector.calculate(900));
+ detector.setInput(1299, withinThreshold);
+ EXPECT_FALSE(detector.calculate(1299));
detector.setInput(1300, baseline);
- EXPECT_FALSE(detector.calculate(1300));
- detector.setInput(1500, baseline);
- EXPECT_FALSE(detector.calculate(1899));
- EXPECT_TRUE(detector.calculate(1900));
+ EXPECT_TRUE(detector.calculate(1300));
}
TEST_P(StillnessDetectorTest, NotStillRotation) {
@@ -110,13 +107,10 @@
EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
- detector.setInput(900, withinThreshold);
- EXPECT_EQ(mDefaultValue, detector.calculate(900));
+ detector.setInput(1299, withinThreshold);
+ EXPECT_FALSE(detector.calculate(1299));
detector.setInput(1300, baseline);
- EXPECT_FALSE(detector.calculate(1300));
- detector.setInput(1500, baseline);
- EXPECT_FALSE(detector.calculate(1899));
- EXPECT_TRUE(detector.calculate(1900));
+ EXPECT_TRUE(detector.calculate(1300));
}
TEST_P(StillnessDetectorTest, Suppression) {
@@ -134,10 +128,10 @@
EXPECT_TRUE(detector.calculate(1000));
detector.setInput(1100, outsideThreshold);
EXPECT_FALSE(detector.calculate(1100));
- detector.setInput(2000, middlePoint);
- EXPECT_FALSE(detector.calculate(2000));
- EXPECT_FALSE(detector.calculate(2099));
- EXPECT_TRUE(detector.calculate(2100));
+ detector.setInput(1500, middlePoint);
+ EXPECT_FALSE(detector.calculate(1500));
+ EXPECT_FALSE(detector.calculate(1999));
+ EXPECT_TRUE(detector.calculate(2000));
}
TEST_P(StillnessDetectorTest, Reset) {
@@ -150,8 +144,8 @@
const Pose3f withinThreshold =
baseline * Pose3f(Vector3f(0.3, -0.3, 0), rotateX(0.01) * rotateY(-0.01));
EXPECT_EQ(mDefaultValue, detector.calculate(0));
- detector.setInput(0, baseline);
- EXPECT_EQ(mDefaultValue, detector.calculate(0));
+ detector.setInput(300, baseline);
+ EXPECT_EQ(mDefaultValue, detector.calculate(300));
detector.reset();
detector.setInput(600, baseline);
EXPECT_EQ(mDefaultValue, detector.calculate(600));
diff --git a/media/libheadtracking/StillnessDetector.cpp b/media/libheadtracking/StillnessDetector.cpp
index 9806352..be7c893 100644
--- a/media/libheadtracking/StillnessDetector.cpp
+++ b/media/libheadtracking/StillnessDetector.cpp
@@ -36,17 +36,22 @@
bool StillnessDetector::calculate(int64_t timestamp) {
discardOld(timestamp);
- // 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.
+ // 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;
if (!mFifo.empty()) {
- for (auto iter = mFifo.begin(); iter != mFifo.end() - 1; ++iter) {
+ 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.
- mSuppressionDeadline = timestamp + mOptions.windowDuration;
+ int64_t deadline = event.timestamp + mOptions.windowDuration;
+ if (!mSuppressionDeadline.has_value() || mSuppressionDeadline.value() < deadline) {
+ mSuppressionDeadline = deadline;
+ }
moved = true;
break;
}
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.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 807b525..91a44d1 100644
--- a/media/libstagefright/TEST_MAPPING
+++ b/media/libstagefright/TEST_MAPPING
@@ -64,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/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/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 cb428ec..de20d55 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -96,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/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..88d267f 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;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index fc6e05e..1929f31 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1386,6 +1386,11 @@
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())) {
return mSpatializerOutput->mIoHandle;
@@ -1683,7 +1688,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 +2376,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
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/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a593500..97ec5d1 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2335,6 +2335,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__,
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 8c52a6a..a7ebcf4 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,7 +710,7 @@
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
- hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
bool earlyExit = false;
camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
return mDevice->infoPhysical(id);};
@@ -801,6 +873,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 +917,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 +961,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 +1056,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 +1070,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 +1260,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 +1624,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 +1637,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/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..9831328 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -53,6 +53,7 @@
namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+const std::string kExternalProviderName = "external/0";
} // anonymous namespace
const float CameraProviderManager::kDepthARTolerance = .1f;
@@ -267,7 +268,7 @@
}
status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_8::StreamConfiguration &configuration,
bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
@@ -395,6 +396,73 @@
return OK;
}
+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()) {
+ const sp<provider::V2_4::ICameraProvider>
+ interface = providerInfo->startProviderInterface();
+ if (interface == nullptr) {
+ 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(
hardware::hidl_bitfield<provider::V2_5::DeviceState> newState) {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
@@ -1314,9 +1382,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;
@@ -1606,36 +1675,56 @@
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",
+ // Try to get service without starting
+ interface = mManager->mServiceProxy->tryGetService(mProviderName);
+ if (interface == nullptr) {
+ ALOGV("Camera provider actually needs restart, calling getService(%s)",
+ mProviderName.c_str());
+ interface = mManager->mServiceProxy->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()) {
+ }
+ // 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);
+ 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());
+ ALOGV("Camera provider (%s) already in use. Re-using instance.",
+ mProviderName.c_str());
}
+
return interface;
}
@@ -1710,15 +1799,50 @@
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(),
@@ -1898,12 +2022,16 @@
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(deviceInfo->mStatus));
deviceInfo->mStatus = newStatus;
// TODO: Handle device removal (NOT_PRESENT)
cameraId = deviceInfo->mId;
known = true;
+ deviceInfo->mIsDeviceAvailable =
+ (newStatus == CameraDeviceStatus::PRESENT);
+ deviceInfo->mDeviceAvailableSignal.signal();
break;
}
}
@@ -1917,6 +2045,11 @@
addDevice(cameraDeviceName, newStatus, &cameraId);
} else if (newStatus == 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 ",
@@ -2297,11 +2430,27 @@
template<class InterfaceT>
sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
+ Mutex::Autolock l(mDeviceAvailableLock);
sp<InterfaceT> device;
ATRACE_CALL();
if (mSavedInterface == nullptr) {
sp<ProviderInfo> parentProvider = mParentProvider.promote();
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<InterfaceT>(mName);
}
} else {
@@ -2698,7 +2847,7 @@
}
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_8::StreamConfiguration &configuration,
bool *status /*out*/) {
const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
@@ -2710,6 +2859,8 @@
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;
@@ -2719,12 +2870,28 @@
callStatus = s;
*status = combStatus;
};
- if (interface_3_7 != nullptr) {
- ret = interface_3_7->isStreamCombinationSupported_3_7(configuration, halCb);
+ if (interface_3_8 != nullptr) {
+ ret = interface_3_8->isStreamCombinationSupported_3_8(configuration, halCb);
+ } else if (interface_3_7 != nullptr) {
+ hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ configuration_3_7, configuration);
+ 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, configuration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
- bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
- configuration_3_4, configuration);
+ success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ configuration_3_4, configuration_3_7);
if (!success) {
*status = false;
return OK;
@@ -3201,7 +3368,7 @@
status_t res = OK;
for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
const std::string& cameraId = cameraIdAndSessionConfig.mCameraId;
- hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
+ hardware::camera::device::V3_8::StreamConfiguration streamConfiguration;
CameraMetadata deviceInfo;
bool overrideForPerfClass =
SessionConfigurationUtils::targetPerfClassPrimaryCamera(
@@ -3235,7 +3402,8 @@
}
CameraIdAndStreamCombination halCameraIdAndStream;
halCameraIdAndStream.cameraId = cameraId;
- halCameraIdAndStream.streamConfiguration = streamConfiguration;
+ SessionConfigurationUtils::convertHALStreamCombinationFromV38ToV37(
+ halCameraIdAndStream.streamConfiguration, streamConfiguration);
halCameraIdsAndStreamsV.push_back(halCameraIdAndStream);
}
*halCameraIdsAndStreamCombinations = halCameraIdsAndStreamsV;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index b03ca62..ac710bf 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -29,13 +29,16 @@
#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 <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 <camera/VendorTagDescriptor.h>
@@ -243,7 +246,7 @@
* Check for device support of specific stream combination.
*/
status_t isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_8::StreamConfiguration &configuration,
bool *status /*out*/) const;
/**
@@ -357,6 +360,8 @@
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
@@ -487,6 +492,17 @@
&halCameraIdsAndStreamCombinations,
bool *isSupported);
+ /**
+ * 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
@@ -510,6 +526,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,7 +554,7 @@
}
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &/*configuration*/,
+ const hardware::camera::device::V3_8::StreamConfiguration &/*configuration*/,
bool * /*status*/) {
return INVALID_OPERATION;
}
@@ -601,7 +623,7 @@
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_7::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_8::StreamConfiguration &configuration,
bool *status /*out*/)
override;
virtual status_t filterSmallJpegSizes() override;
@@ -734,6 +756,12 @@
hardware::hidl_version minVersion = hardware::hidl_version{0,0},
hardware::hidl_version maxVersion = hardware::hidl_version{1000,0}) const;
+ // 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 addProviderLocked(const std::string& newProvider, bool preexisting = false);
status_t tryToInitializeProviderLocked(const std::string& providerName,
@@ -781,6 +809,8 @@
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/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 2f571a6..4c1e7f0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -531,6 +531,12 @@
return measured;
}
+CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap
+Camera3Device::mapToHidlDynamicProfile(int dynamicRangeProfile) {
+ return static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>(
+ dynamicRangeProfile);
+}
+
hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
int frameworkFormat) {
return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
@@ -1384,7 +1390,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 +1403,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 +1423,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 +1501,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 +1515,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 +1617,7 @@
streamInfo->originalFormat = stream->getOriginalFormat();
streamInfo->dataSpaceOverridden = stream->isDataSpaceOverridden();
streamInfo->originalDataSpace = stream->getOriginalDataSpace();
+ streamInfo->dynamicRangeProfile = stream->getDynamicRangeProfile();
return OK;
}
@@ -2223,7 +2230,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());
}
}
}
@@ -3144,6 +3152,10 @@
mSupportOfflineProcessing(supportOfflineProcessing) {
// 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;
@@ -3181,6 +3193,7 @@
}
void Camera3Device::HalInterface::clear() {
+ mHidlSession_3_8.clear();
mHidlSession_3_7.clear();
mHidlSession_3_6.clear();
mHidlSession_3_5.clear();
@@ -3318,13 +3331,16 @@
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);
@@ -3373,6 +3389,15 @@
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);
@@ -3398,6 +3423,10 @@
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;
@@ -3444,7 +3473,17 @@
};
// See which version of HAL we have
- if (mHidlSession_3_7 != nullptr) {
+ 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;
@@ -4052,6 +4091,18 @@
return OK;
}
+status_t Camera3Device::HalInterface::repeatingRequestEnd(uint32_t frameNumber,
+ hardware::hidl_vec<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 Camera3Device::HalInterface::close() {
ATRACE_NAME("CameraHal::close()");
if (!valid()) return INVALID_OPERATION;
@@ -4386,10 +4437,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;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 3f069f9..3ce17f9 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -36,6 +36,7 @@
#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.8/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>
@@ -44,6 +45,7 @@
#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"
@@ -68,6 +70,7 @@
using android::camera3::camera_stream_configuration_mode_t;
using android::camera3::CAMERA_TEMPLATE_COUNT;
using android::camera3::OutputStreamInfo;
+using android::hardware::camera::metadata::V3_8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
namespace android {
@@ -141,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 createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
@@ -151,7 +156,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,
@@ -287,6 +294,8 @@
static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
android_dataspace dataSpace);
+ static CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap mapToHidlDynamicProfile(
+ int dynamicRangeProfile);
static hardware::camera::device::V3_2::BufferUsageFlags mapToConsumerUsage(uint64_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
camera_stream_rotation_t rotation);
@@ -416,6 +425,8 @@
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
/*out*/camera3::BufferRecords* bufferRecords);
+ status_t repeatingRequestEnd(uint32_t frameNumber, hardware::hidl_vec<int32_t> streamIds);
+
/////////////////////////////////////////////////////////////////////
// Implements BufferRecordsInterface
@@ -458,6 +469,8 @@
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.8 or newer
+ sp<hardware::camera::device::V3_8::ICameraDeviceSession> mHidlSession_3_8;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
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/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/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 b64ec0d..6135f9e 100644
--- a/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
+++ b/services/camera/libcameraservice/device3/PreviewFrameScheduler.cpp
@@ -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/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/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index f6f0539..a35e6f3 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/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,33 @@
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 = Camera3Device::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 = Camera3Device::mapToConsumerUsage(u);
+ stream->v3_7.v3_4.v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
+ stream->v3_7.v3_4.v3_2.rotation = Camera3Device::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 +584,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();
@@ -529,7 +625,7 @@
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()),
@@ -547,6 +643,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 +675,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 +697,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 +839,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; }