Merge "Send metrics for aaudio to statsd." into sc-dev
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
index 4ff4d06..8b81090 100644
--- a/apex/testing/Android.bp
+++ b/apex/testing/Android.bp
@@ -18,8 +18,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/camera/Android.bp b/camera/Android.bp
index 71c88ab..2c01496 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -81,6 +81,7 @@
],
shared_libs: [
+ "libbase",
"libcutils",
"libutils",
"liblog",
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index f9b1b37..af3c492 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -20,14 +20,16 @@
#include <camera/CameraUtils.h>
#include <media/hardware/HardwareAPI.h>
+#include <android-base/properties.h>
#include <system/window.h>
#include <system/graphics.h>
-#include <cutils/properties.h>
#include <utils/Log.h>
namespace android {
+const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
+
status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
/*out*/int32_t* transform) {
ALOGV("%s", __FUNCTION__);
@@ -124,9 +126,7 @@
}
bool CameraUtils::isCameraServiceDisabled() {
- char value[PROPERTY_VALUE_MAX];
- property_get("config.disable_cameraservice", value, "0");
- return (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0);
+ return base::GetBoolProperty(kCameraServiceDisabledProperty, false);
}
} /* namespace android */
diff --git a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
index 28a57bd..8e1fcc0 100644
--- a/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -119,10 +119,11 @@
* @param width Width of the input buffers
* @param height Height of the input buffers
* @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*.
+ * @param isMultiResolution Whether the input stream supports variable resolution image.
*
* @return new stream ID
*/
- int createInputStream(int width, int height, int format);
+ int createInputStream(int width, int height, int format, boolean isMultiResolution);
/**
* Get the surface of the input stream.
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 4e9b27d..2f6bc30 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -68,6 +68,10 @@
return mPhysicalCameraId;
}
+bool OutputConfiguration::isMultiResolution() const {
+ return mIsMultiResolution;
+}
+
OutputConfiguration::OutputConfiguration() :
mRotation(INVALID_ROTATION),
mSurfaceSetID(INVALID_SET_ID),
@@ -75,7 +79,8 @@
mWidth(0),
mHeight(0),
mIsDeferred(false),
- mIsShared(false) {
+ mIsShared(false),
+ mIsMultiResolution(false) {
}
OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -145,6 +150,12 @@
parcel->readString16(&mPhysicalCameraId);
+ int isMultiResolution = 0;
+ if ((err = parcel->readInt32(&isMultiResolution)) != OK) {
+ ALOGE("%s: Failed to read surface isMultiResolution flag from parcel", __FUNCTION__);
+ return err;
+ }
+
mRotation = rotation;
mSurfaceSetID = setID;
mSurfaceType = surfaceType;
@@ -152,6 +163,7 @@
mHeight = height;
mIsDeferred = isDeferred != 0;
mIsShared = isShared != 0;
+ mIsMultiResolution = isMultiResolution != 0;
for (auto& surface : surfaceShims) {
ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
surface.graphicBufferProducer.get(),
@@ -160,8 +172,8 @@
}
ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
- " physicalCameraId = %s", __FUNCTION__, mRotation, mSurfaceSetID,
- mSurfaceType, String8(mPhysicalCameraId).string());
+ " physicalCameraId = %s, isMultiResolution = %d", __FUNCTION__, mRotation,
+ mSurfaceSetID, mSurfaceType, String8(mPhysicalCameraId).string(), mIsMultiResolution);
return err;
}
@@ -175,6 +187,7 @@
mIsDeferred = false;
mIsShared = isShared;
mPhysicalCameraId = physicalId;
+ mIsMultiResolution = false;
}
OutputConfiguration::OutputConfiguration(
@@ -183,7 +196,7 @@
int width, int height, bool isShared)
: mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
- mPhysicalCameraId(physicalCameraId) { }
+ mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false) { }
status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
@@ -224,6 +237,9 @@
err = parcel->writeString16(mPhysicalCameraId);
if (err != OK) return err;
+ err = parcel->writeInt32(mIsMultiResolution ? 1 : 0);
+ if (err != OK) return err;
+
return OK;
}
diff --git a/camera/camera2/SessionConfiguration.cpp b/camera/camera2/SessionConfiguration.cpp
index a431a33..7cf6087 100644
--- a/camera/camera2/SessionConfiguration.cpp
+++ b/camera/camera2/SessionConfiguration.cpp
@@ -55,6 +55,12 @@
return err;
}
+ bool inputIsMultiResolution = false;
+ if ((err = parcel->readBool(&inputIsMultiResolution)) != OK) {
+ ALOGE("%s: Failed to read input multi-resolution flag from parcel", __FUNCTION__);
+ return err;
+ }
+
std::vector<OutputConfiguration> outputStreams;
if ((err = parcel->readParcelableVector(&outputStreams)) != OK) {
ALOGE("%s: Failed to read output configurations from parcel", __FUNCTION__);
@@ -65,6 +71,7 @@
mInputWidth = inputWidth;
mInputHeight = inputHeight;
mInputFormat = inputFormat;
+ mInputIsMultiResolution = inputIsMultiResolution;
for (auto& stream : outputStreams) {
mOutputStreams.push_back(stream);
}
@@ -90,6 +97,9 @@
err = parcel->writeInt32(mInputFormat);
if (err != OK) return err;
+ err = parcel->writeBool(mInputIsMultiResolution);
+ if (err != OK) return err;
+
err = parcel->writeParcelableVector(mOutputStreams);
if (err != OK) return err;
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 9398ec3..8ca8920 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -42,6 +42,7 @@
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
"android.hardware.camera.provider@2.6",
+ "android.hardware.camera.provider@2.7",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.4",
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 95c4f39..6009370 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -47,6 +47,8 @@
bool isDeferred() const;
bool isShared() const;
String16 getPhysicalCameraId() const;
+ bool isMultiResolution() const;
+
/**
* Keep impl up-to-date with OutputConfiguration.java in frameworks/base
*/
@@ -83,7 +85,8 @@
mIsDeferred == other.mIsDeferred &&
mIsShared == other.mIsShared &&
gbpsEqual(other) &&
- mPhysicalCameraId == other.mPhysicalCameraId );
+ mPhysicalCameraId == other.mPhysicalCameraId &&
+ mIsMultiResolution == other.mIsMultiResolution);
}
bool operator != (const OutputConfiguration& other) const {
return !(*this == other);
@@ -114,6 +117,9 @@
if (mPhysicalCameraId != other.mPhysicalCameraId) {
return mPhysicalCameraId < other.mPhysicalCameraId;
}
+ if (mIsMultiResolution != other.mIsMultiResolution) {
+ return mIsMultiResolution < other.mIsMultiResolution;
+ }
return gbpsLessThan(other);
}
bool operator > (const OutputConfiguration& other) const {
@@ -133,6 +139,7 @@
bool mIsDeferred;
bool mIsShared;
String16 mPhysicalCameraId;
+ bool mIsMultiResolution;
};
} // namespace params
} // namespace camera2
diff --git a/camera/include/camera/camera2/SessionConfiguration.h b/camera/include/camera/camera2/SessionConfiguration.h
index 64288ed..29913f6 100644
--- a/camera/include/camera/camera2/SessionConfiguration.h
+++ b/camera/include/camera/camera2/SessionConfiguration.h
@@ -38,6 +38,7 @@
int getInputHeight() const { return mInputHeight; }
int getInputFormat() const { return mInputFormat; }
int getOperatingMode() const { return mOperatingMode; }
+ bool inputIsMultiResolution() const { return mInputIsMultiResolution; }
virtual status_t writeToParcel(android::Parcel* parcel) const override;
virtual status_t readFromParcel(const android::Parcel* parcel) override;
@@ -61,7 +62,8 @@
mInputWidth == other.mInputWidth &&
mInputHeight == other.mInputHeight &&
mInputFormat == other.mInputFormat &&
- mOperatingMode == other.mOperatingMode);
+ mOperatingMode == other.mOperatingMode &&
+ mInputIsMultiResolution == other.mInputIsMultiResolution);
}
bool operator != (const SessionConfiguration& other) const {
@@ -83,6 +85,10 @@
return mInputFormat < other.mInputFormat;
}
+ if (mInputIsMultiResolution != other.mInputIsMultiResolution) {
+ return mInputIsMultiResolution < other.mInputIsMultiResolution;
+ }
+
if (mOperatingMode != other.mOperatingMode) {
return mOperatingMode < other.mOperatingMode;
}
@@ -104,6 +110,7 @@
std::vector<OutputConfiguration> mOutputStreams;
int mInputWidth, mInputHeight, mInputFormat, mOperatingMode;
+ bool mInputIsMultiResolution = false;
};
} // namespace params
} // namespace camera2
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c1b2712..4e07c5c 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -3868,6 +3868,35 @@
*/
ACAMERA_SCALER_DEFAULT_SECURE_IMAGE_SIZE = // int32[2]
ACAMERA_SCALER_START + 18,
+ /**
+ * <p>The available multi-resolution stream configurations that this
+ * physical camera device supports
+ * (i.e. format, width, height, output/input stream).</p>
+ *
+ * <p>Type: int32[n*4] (acamera_metadata_enum_android_scaler_physical_camera_multi_resolution_stream_configurations_t)</p>
+ *
+ * <p>This tag may appear in:
+ * <ul>
+ * <li>ACameraMetadata from ACameraManager_getCameraCharacteristics</li>
+ * </ul></p>
+ *
+ * <p>This list contains a subset of the parent logical camera's multi-resolution stream
+ * configurations which belong to this physical camera, and it will advertise and will only
+ * advertise the maximum supported resolutions for a particular format.</p>
+ * <p>If this camera device isn't a physical camera device constituting a logical camera,
+ * but a standalone ULTRA_HIGH_RESOLUTION_SENSOR camera, this field represents the
+ * multi-resolution input/output stream configurations of default mode and max resolution
+ * modes. The sizes will be the maximum resolution of a particular format for default mode
+ * and max resolution mode.</p>
+ * <p>This field will only be advertised if the device is a physical camera of a
+ * logical multi-camera device or an ultra high resolution sensor camera. For a logical
+ * multi-camera, the camera API will derive the logical camera’s multi-resolution stream
+ * configurations from all physical cameras. For an ultra high resolution sensor camera, this
+ * is used directly as the camera’s multi-resolution stream configurations.</p>
+ */
+ ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS =
+ // int32[n*4] (acamera_metadata_enum_android_scaler_physical_camera_multi_resolution_stream_configurations_t)
+ ACAMERA_SCALER_START + 19,
ACAMERA_SCALER_END,
/**
@@ -8475,6 +8504,16 @@
} acamera_metadata_enum_android_scaler_rotate_and_crop_t;
+// ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS
+typedef enum acamera_metadata_enum_acamera_scaler_physical_camera_multi_resolution_stream_configurations {
+ ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_OUTPUT
+ = 0,
+
+ ACAMERA_SCALER_PHYSICAL_CAMERA_MULTI_RESOLUTION_STREAM_CONFIGURATIONS_INPUT
+ = 1,
+
+} acamera_metadata_enum_android_scaler_physical_camera_multi_resolution_stream_configurations_t;
+
// ACAMERA_SENSOR_REFERENCE_ILLUMINANT1
typedef enum acamera_metadata_enum_acamera_sensor_reference_illuminant1 {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index f8f2bc6..f33f5f1 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -16,13 +16,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "DrmHal"
-#include <iomanip>
-
-#include <utils/Log.h>
-
-#include <android/binder_manager.h>
#include <aidl/android/media/BnResourceManagerClient.h>
+#include <android/binder_manager.h>
#include <android/hardware/drm/1.2/types.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/ServiceManagement.h>
@@ -40,7 +36,9 @@
#include <mediadrm/DrmSessionManager.h>
#include <mediadrm/IDrmMetricsConsumer.h>
#include <mediadrm/DrmUtils.h>
+#include <utils/Log.h>
+#include <iomanip>
#include <vector>
using drm::V1_0::KeyedVector;
@@ -345,10 +343,10 @@
// must be in passthrough mode, load the default passthrough service
auto passthrough = IDrmFactory::getService();
if (passthrough != NULL) {
- ALOGI("makeDrmFactories: using default passthrough drm instance");
+ DrmUtils::LOG2BI("makeDrmFactories: using default passthrough drm instance");
factories.push_back(passthrough);
} else {
- ALOGE("Failed to find any drm factories");
+ DrmUtils::LOG2BE("Failed to find any drm factories");
}
}
return factories;
@@ -364,7 +362,7 @@
Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
[&](Status status, const sp<IDrmPlugin>& hPlugin) {
if (status != Status::OK) {
- ALOGE("Failed to make drm plugin");
+ DrmUtils::LOG2BE(uuid, "Failed to make drm plugin: %d", status);
return;
}
plugin = hPlugin;
@@ -372,7 +370,8 @@
);
if (!hResult.isOk()) {
- ALOGE("createPlugin remote call failed");
+ DrmUtils::LOG2BE(uuid, "createPlugin remote call failed: %s",
+ hResult.description().c_str());
}
return plugin;
@@ -566,7 +565,8 @@
Mutex::Autolock autoLock(mLock);
for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
- if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
+ auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
+ if (hResult.isOk() && hResult) {
auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
if (plugin != NULL) {
mPlugin = plugin;
@@ -579,6 +579,7 @@
}
if (mPlugin == NULL) {
+ DrmUtils::LOG2BE(uuid, "No supported hal instance found");
mInitCheck = ERROR_UNSUPPORTED;
} else {
mInitCheck = OK;
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 82eadd9..9b125af 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -27,6 +27,8 @@
#include <android/hardware/drm/1.2/IDrmFactory.h>
#include <android/hardware/drm/1.3/ICryptoFactory.h>
#include <android/hardware/drm/1.3/IDrmFactory.h>
+#include <android/hardware/drm/1.4/ICryptoFactory.h>
+#include <android/hardware/drm/1.4/IDrmFactory.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/HidlSupport.h>
@@ -68,15 +70,15 @@
void MakeHidlFactories(const uint8_t uuid[16], V &factories) {
sp<HServiceManager> serviceManager = HServiceManager::getService();
if (serviceManager == nullptr) {
- ALOGE("Failed to get service manager");
- exit(-1);
+ LOG2BE("Failed to get service manager");
+ return;
}
serviceManager->listManifestByInterface(Hal::descriptor, [&](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = Hal::getService(instance);
if (factory != nullptr) {
- ALOGI("found %s %s", Hal::descriptor, instance.c_str());
+ LOG2BI("found %s %s", Hal::descriptor, instance.c_str());
if (!uuid || factory->isCryptoSchemeSupported(uuid)) {
factories.push_back(factory);
}
@@ -106,6 +108,7 @@
factory->createPlugin(toHidlArray16(uuid), hidl_string(appPackageName),
[&](::V1_0::Status status, const sp<::V1_0::IDrmPlugin> &hPlugin) {
if (status != ::V1_0::Status::OK) {
+ LOG2BE(uuid, "MakeDrmPlugin failed: %d", status);
return;
}
plugin = hPlugin;
@@ -120,6 +123,7 @@
factory->createPlugin(toHidlArray16(uuid), toHidlVec(initData, initDataSize),
[&](::V1_0::Status status, const sp<::V1_0::ICryptoPlugin> &hPlugin) {
if (status != ::V1_0::Status::OK) {
+ LOG2BE(uuid, "MakeCryptoPlugin failed: %d", status);
return;
}
plugin = hPlugin;
@@ -147,6 +151,7 @@
MakeHidlFactories<::V1_1::IDrmFactory>(uuid, drmFactories);
MakeHidlFactories<::V1_2::IDrmFactory>(uuid, drmFactories);
MakeHidlFactories<::V1_3::IDrmFactory>(uuid, drmFactories);
+ MakeHidlFactories<::V1_4::IDrmFactory>(uuid, drmFactories);
return drmFactories;
}
@@ -165,6 +170,7 @@
MakeHidlFactories<::V1_1::ICryptoFactory>(uuid, cryptoFactories);
MakeHidlFactories<::V1_2::ICryptoFactory>(uuid, cryptoFactories);
MakeHidlFactories<::V1_3::ICryptoFactory>(uuid, cryptoFactories);
+ MakeHidlFactories<::V1_4::ICryptoFactory>(uuid, cryptoFactories);
return cryptoFactories;
}
@@ -265,5 +271,65 @@
return ERROR_DRM_UNKNOWN;
}
+namespace {
+char logPriorityToChar(::V1_4::LogPriority priority) {
+ char p = 'U';
+ switch (priority) {
+ case ::V1_4::LogPriority::VERBOSE: p = 'V'; break;
+ case ::V1_4::LogPriority::DEBUG: p = 'D'; break;
+ case ::V1_4::LogPriority::INFO: p = 'I'; break;
+ case ::V1_4::LogPriority::WARN: p = 'W'; break;
+ case ::V1_4::LogPriority::ERROR: p = 'E'; break;
+ case ::V1_4::LogPriority::FATAL: p = 'F'; break;
+ default: p = 'U'; break;
+ }
+ return p;
+}
+} // namespace
+
+std::string GetExceptionMessage(status_t err, const char *msg,
+ const Vector<::V1_4::LogMessage> &logs) {
+ String8 msg8;
+ if (msg) {
+ msg8 += msg;
+ msg8 += ": ";
+ }
+ auto errStr = StrCryptoError(err);
+ msg8 += errStr.c_str();
+
+ for (auto log : logs) {
+ time_t seconds = log.timeMs / 1000;
+ int ms = log.timeMs % 1000;
+ char buf[64] = {0};
+ std::string timeStr = "00-00 00:00:00";
+ if (strftime(buf, sizeof buf, "%m-%d %H:%M:%S", std::localtime(&seconds))) {
+ timeStr = buf;
+ }
+
+ char p = logPriorityToChar(log.priority);
+ msg8 += String8::format("\n%s.%03d %c %s", timeStr.c_str(), ms, p, log.message.c_str());
+ }
+
+ return msg8.c_str();
+}
+
+void LogBuffer::addLog(const ::V1_4::LogMessage &log) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mBuffer.push_back(log);
+ while (mBuffer.size() > MAX_CAPACITY) {
+ mBuffer.pop_front();
+ }
+}
+
+Vector<::V1_4::LogMessage> LogBuffer::getLogs() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ Vector<::V1_4::LogMessage> logs;
+ for (auto log : mBuffer) {
+ logs.push_back(log);
+ }
+ return logs;
+}
+
+LogBuffer gLogBuf;
} // namespace DrmUtils
} // namespace android
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index c362aa6..988cda9 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -27,7 +27,16 @@
#include <utils/String8.h>
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include <algorithm>
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
#include <ctime>
+#include <deque>
+#include <endian.h>
+#include <iterator>
+#include <mutex>
+#include <string>
#include <vector>
@@ -42,6 +51,61 @@
namespace DrmUtils {
+// Log APIs
+class LogBuffer {
+ public:
+ static const int MAX_CAPACITY = 100;
+ void addLog(const ::V1_4::LogMessage &log);
+ Vector<::V1_4::LogMessage> getLogs();
+
+ private:
+ std::deque<::V1_4::LogMessage> mBuffer;
+ std::mutex mMutex;
+};
+
+extern LogBuffer gLogBuf;
+
+static inline int formatBuffer(char *buf, size_t size, const char *msg) {
+ return snprintf(buf, size, "%s", msg);
+}
+
+template <typename First, typename... Args>
+static inline int formatBuffer(char *buf, size_t size, const char *fmt, First first, Args... args) {
+ return snprintf(buf, size, fmt, first, args...);
+}
+
+template <typename... Args>
+void LogToBuffer(android_LogPriority level, const char *fmt, Args... args) {
+ const int LOG_BUF_SIZE = 256;
+ char buf[LOG_BUF_SIZE];
+ int len = formatBuffer(buf, LOG_BUF_SIZE, fmt, args...);
+ if (len <= 0) {
+ return;
+ }
+ __android_log_write(level, LOG_TAG, buf);
+ if (level >= ANDROID_LOG_INFO) {
+ int64_t epochTimeMs =
+ std::chrono::system_clock::now().time_since_epoch() / std::chrono::milliseconds(1);
+ gLogBuf.addLog({epochTimeMs, static_cast<::V1_4::LogPriority>(level), buf});
+ }
+}
+
+template <typename... Args>
+void LogToBuffer(android_LogPriority level, const uint8_t uuid[16], const char *fmt, Args... args) {
+ const uint64_t* uuid2 = reinterpret_cast<const uint64_t*>(uuid);
+ std::string uuidFmt("uuid=[%lx %lx] ");
+ uuidFmt += fmt;
+ LogToBuffer(level, uuidFmt.c_str(), htobe64(uuid2[0]), htobe64(uuid2[1]), args...);
+}
+
+#ifndef LOG2BE
+#define LOG2BE(...) LogToBuffer(ANDROID_LOG_ERROR, __VA_ARGS__)
+#define LOG2BW(...) LogToBuffer(ANDROID_LOG_WARN, __VA_ARGS__)
+#define LOG2BI(...) LogToBuffer(ANDROID_LOG_INFO, __VA_ARGS__)
+#define LOG2BD(...) LogToBuffer(ANDROID_LOG_DEBUG, __VA_ARGS__)
+#define LOG2BV(...) LogToBuffer(ANDROID_LOG_VERBOSE, __VA_ARGS__)
+#endif
+
bool UseDrmService();
sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
@@ -119,11 +183,14 @@
template<typename T, typename U>
status_t GetLogMessages(const sp<U> &obj, Vector<::V1_4::LogMessage> &logs) {
sp<T> plugin = T::castFrom(obj);
- if (plugin == NULL) {
- return ERROR_UNSUPPORTED;
+ if (obj == NULL) {
+ LOG2BW("%s obj is null", U::descriptor);
+ } else if (plugin == NULL) {
+ LOG2BW("Cannot cast %s obj to %s plugin", U::descriptor, T::descriptor);
}
::V1_4::Status err{};
+ std::vector<::V1_4::LogMessage> pluginLogs;
::V1_4::IDrmPlugin::getLogMessages_cb cb = [&](
::V1_4::Status status,
hidl_vec<::V1_4::LogMessage> hLogs) {
@@ -131,62 +198,39 @@
err = status;
return;
}
- logs.appendArray(hLogs.data(), hLogs.size());
+ pluginLogs.assign(hLogs.data(), hLogs.data() + hLogs.size());
};
- Return<void> hResult = plugin->getLogMessages(cb);
- if (!hResult.isOk()) {
- return DEAD_OBJECT;
+ Return<void> hResult;
+ if (plugin != NULL) {
+ hResult = plugin->getLogMessages(cb);
}
- return toStatusT(err);
+ if (!hResult.isOk()) {
+ LOG2BW("%s::getLogMessages remote call failed %s",
+ T::descriptor, hResult.description().c_str());
+ }
+
+ auto allLogs(gLogBuf.getLogs());
+ LOG2BI("framework logs size %zu; plugin logs size %zu",
+ allLogs.size(), pluginLogs.size());
+ std::copy(pluginLogs.begin(), pluginLogs.end(), std::back_inserter(allLogs));
+ std::sort(allLogs.begin(), allLogs.end(),
+ [](const ::V1_4::LogMessage &a, const ::V1_4::LogMessage &b) {
+ return a.timeMs < b.timeMs;
+ });
+
+ logs.appendVector(allLogs);
+ return OK;
}
-namespace {
-static inline char logPriorityToChar(::V1_4::LogPriority priority) {
- char p = 'U';
- switch (priority) {
- case ::V1_4::LogPriority::VERBOSE: p = 'V'; break;
- case ::V1_4::LogPriority::DEBUG: p = 'D'; break;
- case ::V1_4::LogPriority::INFO: p = 'I'; break;
- case ::V1_4::LogPriority::WARN: p = 'W'; break;
- case ::V1_4::LogPriority::ERROR: p = 'E'; break;
- case ::V1_4::LogPriority::FATAL: p = 'F'; break;
- default: p = 'U'; break;
- }
- return p;
-}
-}
+std::string GetExceptionMessage(status_t err, const char *msg,
+ const Vector<::V1_4::LogMessage> &logs);
template<typename T>
std::string GetExceptionMessage(status_t err, const char *msg, const sp<T> &iface) {
- String8 msg8;
- if (msg) {
- msg8 += msg;
- msg8 += ": ";
- }
- auto errStr = StrCryptoError(err);
- msg8 += errStr.c_str();
-
Vector<::V1_4::LogMessage> logs;
- if (iface->getLogMessages(logs) != NO_ERROR) {
- return msg8.c_str();
- }
-
- for (auto log: logs) {
- time_t seconds = log.timeMs / 1000;
- int ms = log.timeMs % 1000;
- char buf[64] = {0};
- std::string timeStr = "00-00 00:00:00";
- if (strftime(buf, sizeof buf, "%m-%d %H:%M:%S", std::localtime(&seconds))) {
- timeStr = buf;
- }
-
- char p = logPriorityToChar(log.priority);
- msg8 += String8::format("\n%s.%03d %c %s",
- timeStr.c_str(), ms, p, log.message.c_str());
- }
-
- return msg8.c_str();
+ iface->getLogMessages(logs);
+ return GetExceptionMessage(err, msg, logs);
}
} // namespace DrmUtils
diff --git a/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
index c4a72ef..2b235f2 100644
--- a/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
+++ b/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
@@ -158,6 +158,11 @@
bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp,
uint32_t generation,
uint64_t bqId) {
+ uint64_t consumerUsage = 0;
+ if (igbp->getConsumerUsage(&consumerUsage) != OK) {
+ ALOGW("failed to get consumer usage");
+ }
+
size_t tryNum = 0;
size_t success = 0;
sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
@@ -183,7 +188,24 @@
}
++tryNum;
int bqSlot;
+
+ // Update buffer's generation and usage.
+ if ((mBuffers[i]->getUsage() & consumerUsage) != consumerUsage) {
+ mBuffers[i] = new GraphicBuffer(
+ mBuffers[i]->handle, GraphicBuffer::CLONE_HANDLE,
+ mBuffers[i]->width, mBuffers[i]->height,
+ mBuffers[i]->format, mBuffers[i]->layerCount,
+ mBuffers[i]->getUsage() | consumerUsage,
+ mBuffers[i]->stride);
+ if (mBuffers[i]->initCheck() != OK) {
+ ALOGW("%s() failed to update usage, original usage=%" PRIx64
+ ", consumer usage=%" PRIx64,
+ __func__, mBuffers[i]->getUsage(), consumerUsage);
+ continue;
+ }
+ }
mBuffers[i]->setGenerationNumber(generation);
+
status_t result = igbp->attachBuffer(&bqSlot, mBuffers[i]);
if (result != OK) {
continue;
diff --git a/media/codec2/sfplugin/C2OMXNode.cpp b/media/codec2/sfplugin/C2OMXNode.cpp
index dd1f485..ab73245 100644
--- a/media/codec2/sfplugin/C2OMXNode.cpp
+++ b/media/codec2/sfplugin/C2OMXNode.cpp
@@ -209,15 +209,23 @@
pDef->nBufferCountActual = 16;
- std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
- C2PortActualDelayTuning::input inputDelay(0);
- C2ActualPipelineDelayTuning pipelineDelay(0);
- c2_status_t c2err = comp->query(
- {&inputDelay, &pipelineDelay}, {}, C2_DONT_BLOCK, nullptr);
- if (c2err == C2_OK || c2err == C2_BAD_INDEX) {
- pDef->nBufferCountActual = 4;
- pDef->nBufferCountActual += (inputDelay ? inputDelay.value : 0u);
- pDef->nBufferCountActual += (pipelineDelay ? pipelineDelay.value : 0u);
+ // WORKAROUND: having more slots improve performance while consuming
+ // more memory. This is a temporary workaround to reduce memory for
+ // larger-than-4K scenario.
+ if (mWidth * mHeight > 4096 * 2340) {
+ std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
+ C2PortActualDelayTuning::input inputDelay(0);
+ C2ActualPipelineDelayTuning pipelineDelay(0);
+ c2_status_t c2err = C2_NOT_FOUND;
+ if (comp) {
+ c2err = comp->query(
+ {&inputDelay, &pipelineDelay}, {}, C2_DONT_BLOCK, nullptr);
+ }
+ if (c2err == C2_OK || c2err == C2_BAD_INDEX) {
+ pDef->nBufferCountActual = 4;
+ pDef->nBufferCountActual += (inputDelay ? inputDelay.value : 0u);
+ pDef->nBufferCountActual += (pipelineDelay ? pipelineDelay.value : 0u);
+ }
}
pDef->eDomain = OMX_PortDomainVideo;
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 452ffce..c8a1994 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -248,19 +248,14 @@
}
size_t numSlots = 16;
- // WORKAROUND: having more slots improve performance while consuming
- // more memory. This is a temporary workaround to reduce memory for
- // larger-than-4K scenario.
- if (mWidth * mHeight > 4096 * 2340) {
- constexpr OMX_U32 kPortIndexInput = 0;
+ constexpr OMX_U32 kPortIndexInput = 0;
- OMX_PARAM_PORTDEFINITIONTYPE param;
- param.nPortIndex = kPortIndexInput;
- status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
- ¶m, sizeof(param));
- if (err == OK) {
- numSlots = param.nBufferCountActual;
- }
+ OMX_PARAM_PORTDEFINITIONTYPE param;
+ param.nPortIndex = kPortIndexInput;
+ status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
+ ¶m, sizeof(param));
+ if (err == OK) {
+ numSlots = param.nBufferCountActual;
}
for (size_t i = 0; i < numSlots; ++i) {
@@ -557,13 +552,15 @@
}
// Report to MediaCodec
- // Note: for now we do not propagate the error code to MediaCodec as we would need
- // to translate to a MediaCodec error.
+ // Note: for now we do not propagate the error code to MediaCodec
+ // except for C2_NO_MEMORY, as we would need to translate to a MediaCodec error.
sp<CCodec> codec(mCodec.promote());
if (!codec || !codec->mCallback) {
return;
}
- codec->mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+ codec->mCallback->onError(
+ errorCode == C2_NO_MEMORY ? NO_MEMORY : UNKNOWN_ERROR,
+ ACTION_CODE_FATAL);
}
virtual void onDeath(
@@ -833,12 +830,14 @@
return BAD_VALUE;
}
}
+ int32_t width = 0;
+ int32_t height = 0;
if (config->mDomain & (Config::IS_IMAGE | Config::IS_VIDEO)) {
- if (!msg->findInt32(KEY_WIDTH, &i32)) {
+ if (!msg->findInt32(KEY_WIDTH, &width)) {
ALOGD("width is missing, which is required for image/video components.");
return BAD_VALUE;
}
- if (!msg->findInt32(KEY_HEIGHT, &i32)) {
+ if (!msg->findInt32(KEY_HEIGHT, &height)) {
ALOGD("height is missing, which is required for image/video components.");
return BAD_VALUE;
}
@@ -1143,6 +1142,7 @@
return BAD_VALUE;
}
+ int32_t componentColorFormat = 0;
if ((config->mDomain & (Config::IS_VIDEO | Config::IS_IMAGE))) {
// propagate HDR static info to output format for both encoders and decoders
// if component supports this info, we will update from component, but only the raw port,
@@ -1160,8 +1160,8 @@
}
if (config->mDomain & Config::IS_ENCODER) {
config->mInputFormat->setInt32(KEY_COLOR_FORMAT, format);
- if (msg->findInt32("android._color-format", &format)) {
- config->mInputFormat->setInt32("android._color-format", format);
+ if (msg->findInt32("android._color-format", &componentColorFormat)) {
+ config->mInputFormat->setInt32("android._color-format", componentColorFormat);
}
} else {
config->mOutputFormat->setInt32(KEY_COLOR_FORMAT, format);
@@ -1219,8 +1219,59 @@
config->mInputFormat->setInt32("color-transfer-request", colorTransferRequest);
}
- ALOGD("setup formats input: %s and output: %s",
- config->mInputFormat->debugString().c_str(),
+ if (componentColorFormat != 0 && componentColorFormat != COLOR_FormatSurface) {
+ // Need to get stride/vstride
+ uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
+ if (C2Mapper::mapPixelFormatFrameworkToCodec(componentColorFormat, &pixelFormat)) {
+ // TODO: retrieve these values without allocating a buffer.
+ // Currently allocating a buffer is necessary to retrieve the layout.
+ int64_t blockUsage =
+ usage.value | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE;
+ std::shared_ptr<C2GraphicBlock> block = FetchGraphicBlock(
+ width, height, pixelFormat, blockUsage, {comp->getName()});
+ sp<GraphicBlockBuffer> buffer;
+ if (block) {
+ buffer = GraphicBlockBuffer::Allocate(
+ config->mInputFormat,
+ block,
+ [](size_t size) -> sp<ABuffer> { return new ABuffer(size); });
+ } else {
+ ALOGD("Failed to allocate a graphic block "
+ "(width=%d height=%d pixelFormat=%u usage=%llx)",
+ width, height, pixelFormat, (long long)blockUsage);
+ // This means that byte buffer mode is not supported in this configuration
+ // anyway. Skip setting stride/vstride to input format.
+ }
+ if (buffer) {
+ sp<ABuffer> imageData = buffer->getImageData();
+ MediaImage2 *img = nullptr;
+ if (imageData && imageData->data()
+ && imageData->size() >= sizeof(MediaImage2)) {
+ img = (MediaImage2*)imageData->data();
+ }
+ if (img && img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
+ int32_t stride = img->mPlane[0].mRowInc;
+ config->mInputFormat->setInt32(KEY_STRIDE, stride);
+ if (img->mNumPlanes > 1 && stride > 0) {
+ int64_t offsetDelta =
+ (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
+ if (offsetDelta % stride == 0) {
+ int32_t vstride = int32_t(offsetDelta / stride);
+ config->mInputFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
+ } else {
+ ALOGD("Cannot report accurate slice height: "
+ "offsetDelta = %lld stride = %d",
+ (long long)offsetDelta, stride);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ALOGD("setup formats input: %s",
+ config->mInputFormat->debugString().c_str());
+ ALOGD("setup formats output: %s",
config->mOutputFormat->debugString().c_str());
return OK;
};
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 7214bf7..d3814fb 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -417,16 +417,17 @@
// read back default for decoders. This is needed in case the component does not support
// color aspects. In that case, these values get copied to color-* keys.
+ // TRICKY: We read these values at raw port, since that's where we want to read these.
add(ConfigMapper("default-color-range", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "range")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & D::READ)
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
.withC2Mappers<C2Color::range_t>());
add(ConfigMapper("default-color-transfer", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "transfer")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & D::READ)
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ)
.withC2Mappers<C2Color::transfer_t>());
add(ConfigMapper("default-color-primaries", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "primaries")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & D::READ));
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
add(ConfigMapper("default-color-matrix", C2_PARAMKEY_DEFAULT_COLOR_ASPECTS, "matrix")
- .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::CODED & D::READ));
+ .limitTo((D::VIDEO | D::IMAGE) & D::DECODER & D::RAW & D::READ));
// read back final for decoder output (also, configure final aspects as well. This should be
// overwritten based on coded/default values if component supports color aspects, but is used
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index 8e59df1..bee6b7f 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -546,7 +546,19 @@
status_t err = GraphicBufferMapper::get().lockYCbCr(
const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
if (err) {
- ALOGE("failed transaction: lockYCbCr");
+ ALOGE("failed transaction: lockYCbCr (err=%d)", err);
+ return C2_CORRUPTED;
+ }
+ if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
+ || ycbcrLayout.ystride == 0
+ || ycbcrLayout.cstride == 0
+ || ycbcrLayout.chroma_step == 0) {
+ ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
+ "ystride=%zu cstride=%zu chroma_step=%zu)",
+ ycbcrLayout.y ? "(non-null)" : "(null)",
+ ycbcrLayout.cb ? "(non-null)" : "(null)",
+ ycbcrLayout.cr ? "(non-null)" : "(null)",
+ ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
return C2_CORRUPTED;
}
@@ -671,7 +683,10 @@
status_t err = GraphicBufferMapper::get().lockYCbCr(
const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
- if (err == OK) {
+ if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
+ && ycbcrLayout.ystride > 0
+ && ycbcrLayout.cstride > 0
+ && ycbcrLayout.chroma_step > 0) {
addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h
index e1a8138..066f1e1 100644
--- a/media/codec2/vndk/include/C2BqBufferPriv.h
+++ b/media/codec2/vndk/include/C2BqBufferPriv.h
@@ -20,9 +20,14 @@
#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
#include <C2Buffer.h>
+#include <C2BlockInternal.h>
#include <functional>
+namespace android {
+class GraphicBuffer;
+} // namespace android
+
class C2BufferQueueBlockPool : public C2BlockPool {
public:
C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
@@ -77,4 +82,66 @@
friend struct C2BufferQueueBlockPoolData;
};
+
+struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
+public:
+ typedef ::android::hardware::graphics::bufferqueue::V2_0::
+ IGraphicBufferProducer HGraphicBufferProducer;
+
+ // Create a remote BlockPoolData.
+ C2BufferQueueBlockPoolData(
+ uint32_t generation, uint64_t bqId, int32_t bqSlot,
+ const std::shared_ptr<int> &owner,
+ const android::sp<HGraphicBufferProducer>& producer);
+
+ // Create a local BlockPoolData.
+ C2BufferQueueBlockPoolData(
+ uint32_t generation, uint64_t bqId, int32_t bqSlot,
+ const android::sp<HGraphicBufferProducer>& producer);
+
+ virtual ~C2BufferQueueBlockPoolData() override;
+
+ virtual type_t getType() const override;
+
+ int migrate(const android::sp<HGraphicBufferProducer>& producer,
+ uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
+ android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration);
+
+private:
+ friend struct _C2BlockFactory;
+
+ // Methods delegated from _C2BlockFactory.
+ void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const;
+ bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner,
+ const android::sp<HGraphicBufferProducer>& igbp);
+ bool beginTransferBlockToClient();
+ bool endTransferBlockToClient(bool transfer);
+ bool beginAttachBlockToBufferQueue();
+ bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner,
+ const android::sp<HGraphicBufferProducer>& igbp,
+ uint32_t generation, uint64_t bqId, int32_t bqSlot);
+ bool displayBlockToBufferQueue();
+
+ const bool mLocal;
+ bool mHeld;
+
+ // Data of the corresponding buffer.
+ uint32_t mGeneration;
+ uint64_t mBqId;
+ int32_t mBqSlot;
+
+ // Data of the current IGBP, updated at migrate(). If the values are
+ // mismatched, then the corresponding buffer will not be cancelled back to
+ // IGBP at the destructor.
+ uint32_t mCurrentGeneration;
+ uint64_t mCurrentBqId;
+
+ bool mTransfer; // local transfer to remote
+ bool mAttach; // attach on remote
+ bool mDisplay; // display on remote;
+ std::weak_ptr<int> mOwner;
+ android::sp<HGraphicBufferProducer> mIgbp;
+ mutable std::mutex mLock;
+};
+
#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index fff12c4..e14b4b1 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -54,59 +54,13 @@
using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0
::IGraphicBufferProducer;
-struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
-
- bool held;
- bool local;
- uint32_t generation;
- uint64_t bqId;
- int32_t bqSlot;
- bool transfer; // local transfer to remote
- bool attach; // attach on remote
- bool display; // display on remote;
- std::weak_ptr<int> owner;
- sp<HGraphicBufferProducer> igbp;
- std::shared_ptr<C2BufferQueueBlockPool::Impl> localPool;
- mutable std::mutex lock;
-
- virtual type_t getType() const override {
- return TYPE_BUFFERQUEUE;
- }
-
- // Create a remote BlockPoolData.
- C2BufferQueueBlockPoolData(
- uint32_t generation, uint64_t bqId, int32_t bqSlot,
- const std::shared_ptr<int> &owner,
- const sp<HGraphicBufferProducer>& producer);
-
- // Create a local BlockPoolData.
- C2BufferQueueBlockPoolData(
- uint32_t generation, uint64_t bqId, int32_t bqSlot,
- const std::shared_ptr<C2BufferQueueBlockPool::Impl>& pool);
-
- virtual ~C2BufferQueueBlockPoolData() override;
-
- int migrate(const sp<HGraphicBufferProducer>& producer,
- uint32_t toGeneration, uint64_t toBqId,
- sp<GraphicBuffer> *buffers, uint32_t oldGeneration);
-};
-
bool _C2BlockFactory::GetBufferQueueData(
const std::shared_ptr<const _C2BlockPoolData>& data,
uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) {
if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERQUEUE) {
- if (generation) {
- const std::shared_ptr<const C2BufferQueueBlockPoolData> poolData =
- std::static_pointer_cast<const C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- *generation = poolData->generation;
- if (bqId) {
- *bqId = poolData->bqId;
- }
- if (bqSlot) {
- *bqSlot = poolData->bqSlot;
- }
- }
+ const std::shared_ptr<const C2BufferQueueBlockPoolData> poolData =
+ std::static_pointer_cast<const C2BufferQueueBlockPoolData>(data);
+ poolData->getBufferQueueData(generation, bqId, bqSlot);
return true;
}
return false;
@@ -118,26 +72,14 @@
const sp<HGraphicBufferProducer>& igbp) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- if (!poolData->local) {
- poolData->owner = owner;
- poolData->igbp = igbp;
- }
- if (poolData->held) {
- poolData->held = true;
- return false;
- }
- poolData->held = true;
- return true;
+ return poolData->holdBlockFromBufferQueue(owner, igbp);
}
bool _C2BlockFactory::BeginTransferBlockToClient(
const std::shared_ptr<_C2BlockPoolData>& data) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- poolData->transfer = true;
- return true;
+ return poolData->beginTransferBlockToClient();
}
bool _C2BlockFactory::EndTransferBlockToClient(
@@ -145,28 +87,14 @@
bool transfer) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- poolData->transfer = false;
- if (transfer) {
- poolData->held = false;
- }
- return true;
+ return poolData->endTransferBlockToClient(transfer);
}
bool _C2BlockFactory::BeginAttachBlockToBufferQueue(
const std::shared_ptr<_C2BlockPoolData>& data) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- if (poolData->local || poolData->display ||
- poolData->attach || !poolData->held) {
- return false;
- }
- if (poolData->bqId == 0) {
- return false;
- }
- poolData->attach = true;
- return true;
+ return poolData->beginAttachBlockToBufferQueue();
}
// if display was tried during attach, buffer should be retired ASAP.
@@ -179,42 +107,14 @@
int32_t bqSlot) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- if (poolData->local || !poolData->attach ) {
- return false;
- }
- if (poolData->display) {
- poolData->attach = false;
- poolData->held = false;
- return false;
- }
- poolData->attach = false;
- poolData->held = true;
- poolData->owner = owner;
- poolData->igbp = igbp;
- poolData->generation = generation;
- poolData->bqId = bqId;
- poolData->bqSlot = bqSlot;
- return true;
+ return poolData->endAttachBlockToBufferQueue(owner, igbp, generation, bqId, bqSlot);
}
bool _C2BlockFactory::DisplayBlockToBufferQueue(
const std::shared_ptr<_C2BlockPoolData>& data) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- std::scoped_lock<std::mutex> lock(poolData->lock);
- if (poolData->local || poolData->display || !poolData->held) {
- return false;
- }
- if (poolData->bqId == 0) {
- return false;
- }
- poolData->display = true;
- if (poolData->attach) {
- return false;
- }
- poolData->held = false;
- return true;
+ return poolData->displayBlockToBufferQueue();
}
std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
@@ -267,8 +167,8 @@
return stamp;
}
-bool getGenerationNumber(const sp<HGraphicBufferProducer> &producer,
- uint32_t *generation) {
+bool getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> &producer,
+ uint32_t *generation, uint64_t *usage) {
status_t status{};
int slot{};
bool bufferNeedsReallocation{};
@@ -302,7 +202,7 @@
// instead of a new allocation.
transResult = producer->requestBuffer(
slot,
- [&status, &slotBuffer, &generation](
+ [&status, &slotBuffer, &generation, &usage](
HStatus hStatus,
HBuffer const& hBuffer,
uint32_t generationNumber){
@@ -310,6 +210,7 @@
h2b(hBuffer, &slotBuffer) &&
slotBuffer) {
*generation = generationNumber;
+ *usage = slotBuffer->getUsage();
slotBuffer->setGenerationNumber(generationNumber);
} else {
status = android::BAD_VALUE;
@@ -469,7 +370,7 @@
std::make_shared<C2BufferQueueBlockPoolData>(
slotBuffer->getGenerationNumber(),
mProducerId, slot,
- shared_from_this());
+ mProducer);
mPoolDatas[slot] = poolData;
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
return C2_OK;
@@ -537,7 +438,7 @@
}
std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::make_shared<C2BufferQueueBlockPoolData>(
- 0, (uint64_t)0, ~0, shared_from_this());
+ 0, (uint64_t)0, ~0, nullptr);
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
ALOGV("allocated a buffer successfully");
@@ -560,6 +461,7 @@
void configureProducer(const sp<HGraphicBufferProducer> &producer) {
uint64_t producerId = 0;
uint32_t generation = 0;
+ uint64_t usage = 0;
bool haveGeneration = false;
if (producer) {
Return<uint64_t> transResult = producer->getUniqueId();
@@ -569,7 +471,7 @@
}
producerId = static_cast<uint64_t>(transResult);
// TODO: provide gneration number from parameter.
- haveGeneration = getGenerationNumber(producer, &generation);
+ haveGeneration = getGenerationNumberAndUsage(producer, &generation, &usage);
if (!haveGeneration) {
ALOGW("get generationNumber failed %llu",
(unsigned long long)producerId);
@@ -609,8 +511,8 @@
mPoolDatas[i].lock();
if (data) {
int slot = data->migrate(
- mProducer, generation,
- producerId, mBuffers, oldGeneration);
+ mProducer, generation, usage,
+ producerId, mBuffers[i], oldGeneration);
if (slot >= 0) {
buffers[slot] = mBuffers[i];
poolDatas[slot] = data;
@@ -634,17 +536,6 @@
private:
friend struct C2BufferQueueBlockPoolData;
- void cancel(uint32_t generation, uint64_t igbp_id, int32_t igbp_slot) {
- bool cancelled = false;
- {
- std::scoped_lock<std::mutex> lock(mMutex);
- if (generation == mGeneration && igbp_id == mProducerId && mProducer) {
- (void)mProducer->cancelBuffer(igbp_slot, hidl_handle{}).isOk();
- cancelled = true;
- }
- }
- }
-
c2_status_t mInit;
uint64_t mProducerId;
uint32_t mGeneration;
@@ -668,65 +559,90 @@
uint32_t generation, uint64_t bqId, int32_t bqSlot,
const std::shared_ptr<int>& owner,
const sp<HGraphicBufferProducer>& producer) :
- held(producer && bqId != 0), local(false),
- generation(generation), bqId(bqId), bqSlot(bqSlot),
- transfer(false), attach(false), display(false),
- owner(owner), igbp(producer),
- localPool() {
+ mLocal(false), mHeld(producer && bqId != 0),
+ mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
+ mCurrentGeneration(generation), mCurrentBqId(bqId),
+ mTransfer(false), mAttach(false), mDisplay(false),
+ mOwner(owner), mIgbp(producer) {
}
C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
uint32_t generation, uint64_t bqId, int32_t bqSlot,
- const std::shared_ptr<C2BufferQueueBlockPool::Impl>& pool) :
- held(true), local(true),
- generation(generation), bqId(bqId), bqSlot(bqSlot),
- transfer(false), attach(false), display(false),
- igbp(pool ? pool->mProducer : nullptr),
- localPool(pool) {
+ const android::sp<HGraphicBufferProducer>& producer) :
+ mLocal(true), mHeld(true),
+ mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
+ mCurrentGeneration(generation), mCurrentBqId(bqId),
+ mTransfer(false), mAttach(false), mDisplay(false), mIgbp(producer) {
}
C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
- if (!held || bqId == 0) {
+ if (!mHeld || mBqId == 0 || !mIgbp) {
return;
}
- if (local) {
- if (localPool) {
- localPool->cancel(generation, bqId, bqSlot);
+
+ if (mLocal) {
+ if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId) {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
}
- } else if (igbp && !owner.expired()) {
- igbp->cancelBuffer(bqSlot, hidl_handle{}).isOk();
+ } else if (!mOwner.expired()) {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
}
}
+
+C2BufferQueueBlockPoolData::type_t C2BufferQueueBlockPoolData::getType() const {
+ return TYPE_BUFFERQUEUE;
+}
+
int C2BufferQueueBlockPoolData::migrate(
const sp<HGraphicBufferProducer>& producer,
- uint32_t toGeneration, uint64_t toBqId,
- sp<GraphicBuffer> *buffers, uint32_t oldGeneration) {
- std::scoped_lock<std::mutex> l(lock);
- if (!held || bqId == 0) {
+ uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
+ sp<GraphicBuffer>& graphicBuffer, uint32_t oldGeneration) {
+ std::scoped_lock<std::mutex> l(mLock);
+
+ mCurrentBqId = toBqId;
+ mCurrentGeneration = toGeneration;
+
+ if (!mHeld || mBqId == 0) {
ALOGV("buffer is not owned");
return -1;
}
- if (!local || !localPool) {
+ if (!mLocal) {
ALOGV("pool is not local");
return -1;
}
- if (bqSlot < 0 || bqSlot >= NUM_BUFFER_SLOTS || !buffers[bqSlot]) {
+ if (mBqSlot < 0 || mBqSlot >= NUM_BUFFER_SLOTS) {
ALOGV("slot is not in effect");
return -1;
}
- if (toGeneration == generation && bqId == toBqId) {
+ if (!graphicBuffer) {
+ ALOGV("buffer is null");
+ return -1;
+ }
+ if (toGeneration == mGeneration && mBqId == toBqId) {
ALOGV("cannot migrate to same bufferqueue");
return -1;
}
- if (oldGeneration != generation) {
+ if (oldGeneration != mGeneration) {
ALOGV("cannot migrate stale buffer");
}
- if (transfer) {
+ if (mTransfer) {
// either transferred or detached.
ALOGV("buffer is in transfer");
return -1;
}
- sp<GraphicBuffer> const& graphicBuffer = buffers[bqSlot];
+
+ if (toUsage != graphicBuffer->getUsage()) {
+ sp<GraphicBuffer> newBuffer = new GraphicBuffer(
+ graphicBuffer->handle, GraphicBuffer::CLONE_HANDLE,
+ graphicBuffer->width, graphicBuffer->height, graphicBuffer->format,
+ graphicBuffer->layerCount, toUsage, graphicBuffer->stride);
+ if (newBuffer->initCheck() == android::NO_ERROR) {
+ graphicBuffer = std::move(newBuffer);
+ } else {
+ ALOGW("%s() failed to update usage, original usage=%" PRIx64 ", toUsage=%" PRIx64,
+ __func__, graphicBuffer->getUsage(), toUsage);
+ }
+ }
graphicBuffer->setGenerationNumber(toGeneration);
HBuffer hBuffer{};
@@ -755,13 +671,112 @@
return -1;
}
ALOGV("local migration from gen %u : %u slot %d : %d",
- generation, toGeneration, bqSlot, slot);
- generation = toGeneration;
- bqId = toBqId;
- bqSlot = slot;
+ mGeneration, toGeneration, mBqSlot, slot);
+ mIgbp = producer;
+ mGeneration = toGeneration;
+ mBqId = toBqId;
+ mBqSlot = slot;
return slot;
}
+void C2BufferQueueBlockPoolData::getBufferQueueData(
+ uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const {
+ if (generation) {
+ std::scoped_lock<std::mutex> lock(mLock);
+ *generation = mGeneration;
+ if (bqId) {
+ *bqId = mBqId;
+ }
+ if (bqSlot) {
+ *bqSlot = mBqSlot;
+ }
+ }
+}
+
+bool C2BufferQueueBlockPoolData::holdBlockFromBufferQueue(
+ const std::shared_ptr<int>& owner,
+ const sp<HGraphicBufferProducer>& igbp) {
+ std::scoped_lock<std::mutex> lock(mLock);
+ if (!mLocal) {
+ mOwner = owner;
+ mIgbp = igbp;
+ }
+ if (mHeld) {
+ return false;
+ }
+ mHeld = true;
+ return true;
+}
+
+bool C2BufferQueueBlockPoolData::beginTransferBlockToClient() {
+ std::scoped_lock<std::mutex> lock(mLock);
+ mTransfer = true;
+ return true;
+}
+
+bool C2BufferQueueBlockPoolData::endTransferBlockToClient(bool transfer) {
+ std::scoped_lock<std::mutex> lock(mLock);
+ mTransfer = false;
+ if (transfer) {
+ mHeld = false;
+ }
+ return true;
+}
+
+bool C2BufferQueueBlockPoolData::beginAttachBlockToBufferQueue() {
+ std::scoped_lock<std::mutex> lock(mLock);
+ if (mLocal || mDisplay ||
+ mAttach || !mHeld) {
+ return false;
+ }
+ if (mBqId == 0) {
+ return false;
+ }
+ mAttach = true;
+ return true;
+}
+
+bool C2BufferQueueBlockPoolData::endAttachBlockToBufferQueue(
+ const std::shared_ptr<int>& owner,
+ const sp<HGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ uint64_t bqId,
+ int32_t bqSlot) {
+ std::scoped_lock<std::mutex> lock(mLock);
+ if (mLocal || !mAttach) {
+ return false;
+ }
+ if (mDisplay) {
+ mAttach = false;
+ mHeld = false;
+ return false;
+ }
+ mAttach = false;
+ mHeld = true;
+ mOwner = owner;
+ mIgbp = igbp;
+ mGeneration = generation;
+ mBqId = bqId;
+ mBqSlot = bqSlot;
+ return true;
+}
+
+bool C2BufferQueueBlockPoolData::displayBlockToBufferQueue() {
+ std::scoped_lock<std::mutex> lock(mLock);
+ if (mLocal || mDisplay || !mHeld) {
+ return false;
+ }
+ if (mBqId == 0) {
+ return false;
+ }
+ mDisplay = true;
+ if (mAttach) {
+ return false;
+ }
+ mHeld = false;
+ return true;
+}
+
C2BufferQueueBlockPool::C2BufferQueueBlockPool(
const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
: mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
diff --git a/media/janitors/codec_OWNERS b/media/janitors/codec_OWNERS
new file mode 100644
index 0000000..e201399
--- /dev/null
+++ b/media/janitors/codec_OWNERS
@@ -0,0 +1,5 @@
+# gerrit owner/approvers for the actual software codec libraries
+# differentiated from plugins connecting those codecs to either omx or codec2 infrastructure
+essick@google.com
+lajos@google.com
+marcone@google.com
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index fb1ffe4..7c16321 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -209,7 +209,6 @@
AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
aaudio_result_t result = streamBuilder->build(&audioStream);
if (result == AAUDIO_OK) {
- audioStream->registerPlayerBase();
*streamPtr = (AAudioStream*) audioStream;
id = audioStream->getId();
} else {
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 5078d2c..53523c5 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -119,12 +119,16 @@
void AudioStream::logOpen() {
if (mMetricsId.size() > 0) {
- android::mediametrics::LogItem(mMetricsId)
- .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
- AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
- .set(AMEDIAMETRICS_PROP_SHARINGMODE,
- AudioGlobal_convertSharingModeToText(getSharingMode()))
- .record();
+ android::mediametrics::LogItem item(mMetricsId);
+ item.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_OPEN)
+ .set(AMEDIAMETRICS_PROP_PERFORMANCEMODE,
+ AudioGlobal_convertPerformanceModeToText(getPerformanceMode()))
+ .set(AMEDIAMETRICS_PROP_SHARINGMODE,
+ AudioGlobal_convertSharingModeToText(getSharingMode()));
+ if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
+ item.set(AMEDIAMETRICS_PROP_PLAYERIID, mPlayerBase->getPlayerIId());
+ }
+ item.record();
}
}
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 510ead8..333e665 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -475,6 +475,11 @@
return mResult;
}
+ // Returns the playerIId if registered, -1 otherwise.
+ int32_t getPlayerIId() const {
+ return mPIId;
+ }
+
private:
// Use a weak pointer so the AudioStream can be deleted.
std::mutex mParentLock;
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 630b289..50a3b38 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -188,6 +188,7 @@
}
}
if (result == AAUDIO_OK) {
+ audioStream->registerPlayerBase();
audioStream->logOpen();
*streamPtr = startUsingStream(audioStream);
} // else audioStream will go out of scope and be deleted
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 112cb67..a53e664 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -35,15 +35,6 @@
#include <media/MediaMetricsItem.h>
#include <media/TypeConverter.h>
-#define VALUE_OR_FATAL(result) \
- ({ \
- auto _tmp = (result); \
- LOG_ALWAYS_FATAL_IF(!_tmp.ok(), \
- "Failed result (%d)", \
- _tmp.error()); \
- std::move(_tmp.value()); \
- })
-
#define WAIT_PERIOD_MS 10
namespace android {
@@ -114,6 +105,7 @@
mMetricsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
mMetricsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
}
+ mMetricsItem->setCString(MM_PREFIX "logSessionId", record->mLogSessionId.c_str());
}
static const char *stateToString(bool active) {
@@ -953,6 +945,7 @@
.set(AMEDIAMETRICS_PROP_ORIGINALFLAGS, toString(mOrigFlags).c_str())
.set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)mSessionId)
.set(AMEDIAMETRICS_PROP_TRACKID, mPortId)
+ .set(AMEDIAMETRICS_PROP_LOGSESSIONID, mLogSessionId)
.set(AMEDIAMETRICS_PROP_SOURCE, toString(mAttributes.source).c_str())
.set(AMEDIAMETRICS_PROP_THREADID, (int32_t)output.inputId)
.set(AMEDIAMETRICS_PROP_SELECTEDDEVICEID, (int32_t)mSelectedDeviceId)
@@ -1574,6 +1567,19 @@
}
}
+void AudioRecord::setLogSessionId(const char *logSessionId)
+{
+ AutoMutex lock(mLock);
+ if (logSessionId == nullptr) logSessionId = ""; // an empty string is an unset session id.
+ if (mLogSessionId == logSessionId) return;
+
+ mLogSessionId = logSessionId;
+ mediametrics::LogItem(mMetricsId)
+ .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETLOGSESSIONID)
+ .set(AMEDIAMETRICS_PROP_LOGSESSIONID, logSessionId)
+ .record();
+}
+
// =========================================================================
void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index a8255a5..7d6d453 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -38,15 +38,6 @@
#include <media/MediaMetricsItem.h>
#include <media/TypeConverter.h>
-#define VALUE_OR_FATAL(result) \
- ({ \
- auto _tmp = (result); \
- LOG_ALWAYS_FATAL_IF(!_tmp.ok(), \
- "Failed result (%d)", \
- _tmp.error()); \
- std::move(_tmp.value()); \
- })
-
#define WAIT_PERIOD_MS 10
#define WAIT_STREAM_END_TIMEOUT_SEC 120
static const int kMaxLoopCountNotifications = 32;
@@ -218,6 +209,7 @@
mMetricsItem->setCString(MM_PREFIX "encoding", toString(track->mFormat).c_str());
mMetricsItem->setInt32(MM_PREFIX "frameCount", (int32_t)track->mFrameCount);
mMetricsItem->setCString(MM_PREFIX "attributes", toString(track->mAttributes).c_str());
+ mMetricsItem->setCString(MM_PREFIX "logSessionId", track->mLogSessionId.c_str());
}
// hand the user a snapshot of the metrics.
@@ -3268,6 +3260,7 @@
void AudioTrack::setLogSessionId(const char *logSessionId)
{
AutoMutex lock(mLock);
+ if (logSessionId == nullptr) logSessionId = ""; // an empty string is an unset session id.
if (mLogSessionId == logSessionId) return;
mLogSessionId = logSessionId;
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 536e9fb..188f321 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -40,6 +40,7 @@
if (mAudioTrack != 0) {
mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+ mAudioTrack->setPlayerIId(mPIId); // set in PlayerBase::init().
}
}
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/libaudioclient/include/media/AidlConversionUtil.h
index bf2d800..c1a2be3 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/libaudioclient/include/media/AidlConversionUtil.h
@@ -48,6 +48,15 @@
std::move(_tmp.value()); \
})
+#define VALUE_OR_FATAL(result) \
+ ({ \
+ auto _tmp = (result); \
+ LOG_ALWAYS_FATAL_IF(!_tmp.ok(), \
+ "Function: %s Line: %d Failed result (%d)",\
+ __FUNCTION__, __LINE__, _tmp.error()); \
+ std::move(_tmp.value()); \
+ })
+
/**
* A generic template to safely cast between integral types, respecting limits of the destination
* type.
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 2f66658..d70d91e 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -578,6 +578,12 @@
*/
audio_port_handle_t getPortId() const { return mPortId; };
+ /* Sets the LogSessionId field which is used for metrics association of
+ * this object with other objects. A nullptr or empty string clears
+ * the logSessionId.
+ */
+ void setLogSessionId(const char *logSessionId);
+
/*
* Dumps the state of an audio record.
*/
@@ -701,6 +707,14 @@
audio_session_t mSessionId;
audio_port_handle_t mPortId; // Id from Audio Policy Manager
+
+ /**
+ * mLogSessionId is a string identifying this AudioRecord for the metrics service.
+ * It may be unique or shared with other objects. An empty string means the
+ * logSessionId is not set.
+ */
+ std::string mLogSessionId{};
+
transfer_type mTransfer;
// Next 5 fields may be changed if IAudioRecord is re-created, but always != 0
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 51f1445..2609ec1 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -987,7 +987,8 @@
audio_port_handle_t getPortId() const { return mPortId; };
/* Sets the LogSessionId field which is used for metrics association of
- * this object with other objects.
+ * this object with other objects. A nullptr or empty string clears
+ * the logSessionId.
*/
void setLogSessionId(const char *logSessionId);
@@ -1279,7 +1280,8 @@
/**
* mLogSessionId is a string identifying this AudioTrack for the metrics service.
- * It may be unique or shared with other objects.
+ * It may be unique or shared with other objects. An empty string means the
+ * logSessionId is not set.
*/
std::string mLogSessionId{};
diff --git a/media/libaudioclient/include/media/PlayerBase.h b/media/libaudioclient/include/media/PlayerBase.h
index 62cc21d..23b6bfd 100644
--- a/media/libaudioclient/include/media/PlayerBase.h
+++ b/media/libaudioclient/include/media/PlayerBase.h
@@ -71,6 +71,10 @@
float mPanMultiplierL, mPanMultiplierR;
float mVolumeMultiplierL, mVolumeMultiplierR;
+ // player interface ID, uniquely identifies the player in the system
+ // effectively const after PlayerBase::init().
+ audio_unique_id_t mPIId;
+
private:
// report events to AudioService
void servicePlayerEvent(player_state_t event, audio_port_handle_t deviceId);
@@ -79,9 +83,6 @@
// native interface to AudioService
android::sp<android::IAudioManager> mAudioManager;
- // player interface ID, uniquely identifies the player in the system
- audio_unique_id_t mPIId;
-
// Mutex for state reporting
Mutex mPlayerStateLock;
player_state_t mLastReportedEvent;
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
index 9b93659..f2245b1 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.cpp
@@ -101,6 +101,16 @@
context->param.audioChannelCount = 0;
context->param.maxHapticIntensity = os::HapticScale::MUTE;
+ context->param.resonantFrequency = 150.0f;
+ context->param.bpfQ = 1.0f;
+ context->param.slowEnvNormalizationPower = -0.8f;
+ context->param.bsfZeroQ = 8.0f;
+ context->param.bsfPoleQ = 4.0f;
+ context->param.distortionCornerFrequency = 300.0f;
+ context->param.distortionInputGain = 0.3f;
+ context->param.distortionCubeThreshold = 0.1f;
+ context->param.distortionOutputGain = 1.5f;
+
context->state = HAPTICGENERATOR_STATE_INITIALIZED;
return 0;
}
@@ -128,16 +138,17 @@
*/
void HapticGenerator_buildProcessingChain(
std::vector<std::function<void(float*, const float*, size_t)>>& processingChain,
- struct HapticGeneratorProcessorsRecord& processorsRecord,
- float sampleRate, size_t channelCount) {
- float highPassCornerFrequency = 100.0f;
+ struct HapticGeneratorProcessorsRecord& processorsRecord, float sampleRate,
+ const struct HapticGeneratorParam* param) {
+ const size_t channelCount = param->hapticChannelCount;
+ float highPassCornerFrequency = 50.0f;
auto hpf = createHPF2(highPassCornerFrequency, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, hpf);
- float lowPassCornerFrequency = 3000.0f;
+ float lowPassCornerFrequency = 9000.0f;
auto lpf = createLPF2(lowPassCornerFrequency, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, lpf);
- auto ramp = std::make_shared<Ramp>(channelCount);
+ auto ramp = std::make_shared<Ramp>(channelCount); // ramp = half-wave rectifier.
// The process chain captures the shared pointer of the ramp in lambda. It will be the only
// reference to the ramp.
// The process record will keep a weak pointer to the ramp so that it is possible to access
@@ -154,19 +165,6 @@
lpf = createLPF2(lowPassCornerFrequency, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, lpf);
- lowPassCornerFrequency = 5.0f;
- float normalizationPower = -0.3f;
- // The process chain captures the shared pointer of the slow envelope in lambda. It will
- // be the only reference to the slow envelope.
- // The process record will keep a weak pointer to the slow envelope so that it is possible
- // to access the slow envelope outside of the process chain.
- auto slowEnv = std::make_shared<SlowEnvelope>(
- lowPassCornerFrequency, sampleRate, normalizationPower, channelCount);
- processorsRecord.slowEnvs.push_back(slowEnv);
- processingChain.push_back([slowEnv](float *out, const float *in, size_t frameCount) {
- slowEnv->process(out, in, frameCount);
- });
-
lowPassCornerFrequency = 400.0f;
lpf = createLPF2(lowPassCornerFrequency, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, lpf);
@@ -174,23 +172,38 @@
lpf = createLPF2(lowPassCornerFrequency, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, lpf);
- auto apf = createAPF2(400.0f, 200.0f, sampleRate, channelCount);
- addBiquadFilter(processingChain, processorsRecord, apf);
- apf = createAPF2(100.0f, 50.0f, sampleRate, channelCount);
- addBiquadFilter(processingChain, processorsRecord, apf);
- float allPassCornerFrequency = 25.0f;
- apf = createAPF(allPassCornerFrequency, sampleRate, channelCount);
- addBiquadFilter(processingChain, processorsRecord, apf);
-
- float resonantFrequency = 150.0f;
- float bandpassQ = 1.0f;
- auto bpf = createBPF(resonantFrequency, bandpassQ, sampleRate, channelCount);
+ auto bpf = createBPF(param->resonantFrequency, param->bpfQ, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, bpf);
- float zeroQ = 8.0f;
- float poleQ = 4.0f;
- auto bsf = createBSF(resonantFrequency, zeroQ, poleQ, sampleRate, channelCount);
+ float normalizationPower = param->slowEnvNormalizationPower;
+ // The process chain captures the shared pointer of the slow envelope in lambda. It will
+ // be the only reference to the slow envelope.
+ // The process record will keep a weak pointer to the slow envelope so that it is possible
+ // to access the slow envelope outside of the process chain.
+ auto slowEnv = std::make_shared<SlowEnvelope>( // SlowEnvelope = partial normalizer, or AGC.
+ 5.0f /*envCornerFrequency*/, sampleRate, normalizationPower,
+ 0.01f /*envOffset*/, channelCount);
+ processorsRecord.slowEnvs.push_back(slowEnv);
+ processingChain.push_back([slowEnv](float *out, const float *in, size_t frameCount) {
+ slowEnv->process(out, in, frameCount);
+ });
+
+
+ auto bsf = createBSF(
+ param->resonantFrequency, param->bsfZeroQ, param->bsfPoleQ, sampleRate, channelCount);
addBiquadFilter(processingChain, processorsRecord, bsf);
+
+ // The process chain captures the shared pointer of the Distortion in lambda. It will
+ // be the only reference to the Distortion.
+ // The process record will keep a weak pointer to the Distortion so that it is possible
+ // to access the Distortion outside of the process chain.
+ auto distortion = std::make_shared<Distortion>(
+ param->distortionCornerFrequency, sampleRate, param->distortionInputGain,
+ param->distortionCubeThreshold, param->distortionOutputGain, channelCount);
+ processorsRecord.distortions.push_back(distortion);
+ processingChain.push_back([distortion](float *out, const float *in, size_t frameCount) {
+ distortion->process(out, in, frameCount);
+ });
}
int HapticGenerator_Configure(struct HapticGeneratorContext *context, effect_config_t *config) {
@@ -206,6 +219,7 @@
context->processorsRecord.filters.clear();
context->processorsRecord.ramps.clear();
context->processorsRecord.slowEnvs.clear();
+ context->processorsRecord.distortions.clear();
memcpy(&context->config, config, sizeof(effect_config_t));
context->param.audioChannelCount = audio_channel_count_from_out_mask(
((audio_channel_mask_t) config->inputCfg.channels) & ~AUDIO_CHANNEL_HAPTIC_ALL);
@@ -224,7 +238,7 @@
HapticGenerator_buildProcessingChain(context->processingChain,
context->processorsRecord,
config->inputCfg.samplingRate,
- context->param.hapticChannelCount);
+ &context->param);
}
return 0;
}
@@ -236,6 +250,9 @@
for (auto& slowEnv : context->processorsRecord.slowEnvs) {
slowEnv->clear();
}
+ for (auto& distortion : context->processorsRecord.distortions) {
+ distortion->clear();
+ }
return 0;
}
diff --git a/media/libeffects/hapticgenerator/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
index 57b4338..d2d7afe 100644
--- a/media/libeffects/hapticgenerator/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/EffectHapticGenerator.h
@@ -51,6 +51,16 @@
// A map from track id to haptic intensity.
std::map<int, os::HapticScale> id2Intensity;
os::HapticScale maxHapticIntensity; // max intensity will be used to scale haptic data.
+
+ float resonantFrequency;
+ float bpfQ;
+ float slowEnvNormalizationPower;
+ float bsfZeroQ;
+ float bsfPoleQ;
+ float distortionCornerFrequency;
+ float distortionInputGain;
+ float distortionCubeThreshold;
+ float distortionOutputGain;
};
// A structure to keep all shared pointers for all processors in HapticGenerator.
@@ -58,6 +68,7 @@
std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
std::vector<std::shared_ptr<Ramp>> ramps;
std::vector<std::shared_ptr<SlowEnvelope>> slowEnvs;
+ std::vector<std::shared_ptr<Distortion>> distortions;
};
// A structure to keep all the context for HapticGenerator.
diff --git a/media/libeffects/hapticgenerator/Processors.cpp b/media/libeffects/hapticgenerator/Processors.cpp
index 3157b35..79a4e2c 100644
--- a/media/libeffects/hapticgenerator/Processors.cpp
+++ b/media/libeffects/hapticgenerator/Processors.cpp
@@ -83,30 +83,92 @@
float cornerFrequency,
float sampleRate,
float normalizationPower,
+ float envOffset,
size_t channelCount)
: mLpf(createLPF(cornerFrequency, sampleRate, channelCount)),
mNormalizationPower(normalizationPower),
- mChannelCount(channelCount),
- mEnv(0.25 * (sampleRate / (2 * M_PI * cornerFrequency))) {}
+ mEnvOffset(envOffset),
+ mChannelCount(channelCount) {}
void SlowEnvelope::process(float* out, const float* in, size_t frameCount) {
size_t sampleCount = frameCount * mChannelCount;
- if (sampleCount > mLpfInBuffer.size()) {
- mLpfInBuffer.resize(sampleCount, mEnv);
+ if (sampleCount > mLpfOutBuffer.size()) {
mLpfOutBuffer.resize(sampleCount);
+ mLpfInBuffer.resize(sampleCount);
+ }
+ for (size_t i = 0; i < sampleCount; ++i) {
+ mLpfInBuffer[i] = fabs(in[i]);
}
mLpf->process(mLpfOutBuffer.data(), mLpfInBuffer.data(), frameCount);
for (size_t i = 0; i < sampleCount; ++i) {
- *out = *in * pow(mLpfOutBuffer[i], mNormalizationPower);
- out++;
- in++;
+ out[i] = in[i] * pow(mLpfOutBuffer[i] + mEnvOffset, mNormalizationPower);
}
}
+void SlowEnvelope::setNormalizationPower(float normalizationPower) {
+ mNormalizationPower = normalizationPower;
+}
+
void SlowEnvelope::clear() {
mLpf->clear();
}
+// Implementation of distortion
+
+Distortion::Distortion(
+ float cornerFrequency,
+ float sampleRate,
+ float inputGain,
+ float cubeThreshold,
+ float outputGain,
+ size_t channelCount)
+ : mLpf(createLPF2(cornerFrequency, sampleRate, channelCount)),
+ mSampleRate(sampleRate),
+ mCornerFrequency(cornerFrequency),
+ mInputGain(inputGain),
+ mCubeThreshold(cubeThreshold),
+ mOutputGain(outputGain),
+ mChannelCount(channelCount) {}
+
+void Distortion::process(float *out, const float *in, size_t frameCount) {
+ size_t sampleCount = frameCount * mChannelCount;
+ if (sampleCount > mLpfInBuffer.size()) {
+ mLpfInBuffer.resize(sampleCount);
+ }
+ for (size_t i = 0; i < sampleCount; ++i) {
+ const float x = mInputGain * in[i];
+ mLpfInBuffer[i] = x * x * x / (mCubeThreshold + x * x); // "Coring" nonlinearity.
+ }
+ mLpf->process(out, mLpfInBuffer.data(), frameCount); // Reduce 3*F components.
+ for (size_t i = 0; i < sampleCount; ++i) {
+ const float x = out[i];
+ out[i] = mOutputGain * x / (1.0f + fabs(x)); // Soft limiter.
+ }
+}
+
+void Distortion::setCornerFrequency(float cornerFrequency) {
+ mCornerFrequency = cornerFrequency;
+ BiquadFilterCoefficients coefficient = lpfCoefs(cornerFrequency, mSampleRate);
+ mLpf->setCoefficients(coefficient);
+}
+
+void Distortion::setInputGain(float inputGain) {
+ mInputGain = inputGain;
+}
+
+void Distortion::setCubeThrehold(float cubeThreshold) {
+ mCubeThreshold = cubeThreshold;
+}
+
+void Distortion::setOutputGain(float outputGain) {
+ mOutputGain = outputGain;
+}
+
+void Distortion::clear() {
+ mLpf->clear();
+}
+
+
// Implementation of helper functions
BiquadFilterCoefficients cascadeFirstOrderFilters(const BiquadFilterCoefficients &coefs1,
@@ -134,6 +196,40 @@
return coefficient;
}
+BiquadFilterCoefficients bpfCoefs(const float ringingFrequency,
+ const float q,
+ const float sampleRate) {
+ BiquadFilterCoefficients coefficient;
+ const auto [real, img] = getComplexPoleZ(ringingFrequency, q, sampleRate);
+ // Note: this is not a standard cookbook BPF, but a low pass filter with zero at DC
+ coefficient[0] = 1.0f;
+ coefficient[1] = -1.0f;
+ coefficient[2] = 0.0f;
+ coefficient[3] = -2 * real;
+ coefficient[4] = real * real + img * img;
+ return coefficient;
+}
+
+BiquadFilterCoefficients bsfCoefs(const float ringingFrequency,
+ const float sampleRate,
+ const float zq,
+ const float pq) {
+ BiquadFilterCoefficients coefficient;
+ const auto [zeroReal, zeroImg] = getComplexPoleZ(ringingFrequency, zq, sampleRate);
+ float zeroCoeff1 = -2 * zeroReal;
+ float zeroCoeff2 = zeroReal* zeroReal + zeroImg * zeroImg;
+ const auto [poleReal, poleImg] = getComplexPoleZ(ringingFrequency, pq, sampleRate);
+ float poleCoeff1 = -2 * poleReal;
+ float poleCoeff2 = poleReal * poleReal + poleImg * poleImg;
+ const float norm = (1.0f + poleCoeff1 + poleCoeff2) / (1.0f + zeroCoeff1 + zeroCoeff2);
+ coefficient[0] = 1.0f * norm;
+ coefficient[1] = zeroCoeff1 * norm;
+ coefficient[2] = zeroCoeff2 * norm;
+ coefficient[3] = poleCoeff1;
+ coefficient[4] = poleCoeff2;
+ return coefficient;
+}
+
std::shared_ptr<HapticBiquadFilter> createLPF(const float cornerFrequency,
const float sampleRate,
const size_t channelCount) {
@@ -166,47 +262,11 @@
channelCount, cascadeFirstOrderFilters(coefficient, coefficient));
}
-BiquadFilterCoefficients apfCoefs(const float cornerFrequency, const float sampleRate) {
- BiquadFilterCoefficients coefficient;
- float realPoleZ = getRealPoleZ(cornerFrequency, sampleRate);
- float zeroZ = 1.0f / realPoleZ;
- coefficient[0] = (1.0f - realPoleZ) / (1.0f - zeroZ);
- coefficient[1] = -coefficient[0] * zeroZ;
- coefficient[2] = 0.0f;
- coefficient[3] = -realPoleZ;
- coefficient[4] = 0.0f;
- return coefficient;
-}
-
-std::shared_ptr<HapticBiquadFilter> createAPF(const float cornerFrequency,
- const float sampleRate,
- const size_t channelCount) {
- BiquadFilterCoefficients coefficient = apfCoefs(cornerFrequency, sampleRate);
- return std::make_shared<HapticBiquadFilter>(channelCount, coefficient);
-}
-
-std::shared_ptr<HapticBiquadFilter> createAPF2(const float cornerFrequency1,
- const float cornerFrequency2,
- const float sampleRate,
- const size_t channelCount) {
- BiquadFilterCoefficients coefs1 = apfCoefs(cornerFrequency1, sampleRate);
- BiquadFilterCoefficients coefs2 = apfCoefs(cornerFrequency2, sampleRate);
- return std::make_shared<HapticBiquadFilter>(
- channelCount, cascadeFirstOrderFilters(coefs1, coefs2));
-}
-
std::shared_ptr<HapticBiquadFilter> createBPF(const float ringingFrequency,
const float q,
const float sampleRate,
const size_t channelCount) {
- BiquadFilterCoefficients coefficient;
- const auto [real, img] = getComplexPoleZ(ringingFrequency, q, sampleRate);
- // Note: this is not a standard cookbook BPF, but a low pass filter with zero at DC
- coefficient[0] = 1.0f;
- coefficient[1] = -1.0f;
- coefficient[2] = 0.0f;
- coefficient[3] = -2 * real;
- coefficient[4] = real * real + img * img;
+ BiquadFilterCoefficients coefficient = bpfCoefs(ringingFrequency, q, sampleRate);
return std::make_shared<HapticBiquadFilter>(channelCount, coefficient);
}
@@ -215,19 +275,7 @@
const float pq,
const float sampleRate,
const size_t channelCount) {
- BiquadFilterCoefficients coefficient;
- const auto [zeroReal, zeroImg] = getComplexPoleZ(ringingFrequency, zq, sampleRate);
- float zeroCoeff1 = -2 * zeroReal;
- float zeroCoeff2 = zeroReal* zeroReal + zeroImg * zeroImg;
- const auto [poleReal, poleImg] = getComplexPoleZ(ringingFrequency, pq, sampleRate);
- float poleCoeff1 = -2 * poleReal;
- float poleCoeff2 = poleReal * poleReal + poleImg * poleImg;
- const float norm = (1.0f + poleCoeff1 + poleCoeff2) / (1.0f + zeroCoeff1 + zeroCoeff2);
- coefficient[0] = 1.0f * norm;
- coefficient[1] = zeroCoeff1 * norm;
- coefficient[2] = zeroCoeff2 * norm;
- coefficient[3] = poleCoeff1;
- coefficient[4] = poleCoeff2;
+ BiquadFilterCoefficients coefficient = bsfCoefs(ringingFrequency, sampleRate, zq, pq);
return std::make_shared<HapticBiquadFilter>(channelCount, coefficient);
}
diff --git a/media/libeffects/hapticgenerator/Processors.h b/media/libeffects/hapticgenerator/Processors.h
index 5cf0557..452a985 100644
--- a/media/libeffects/hapticgenerator/Processors.h
+++ b/media/libeffects/hapticgenerator/Processors.h
@@ -44,19 +44,50 @@
class SlowEnvelope {
public:
SlowEnvelope(float cornerFrequency, float sampleRate,
- float normalizationPower, size_t channelCount);
+ float normalizationPower, float envOffset,
+ size_t channelCount);
void process(float *out, const float *in, size_t frameCount);
+ void setNormalizationPower(float normalizationPower);
+
void clear();
private:
const std::shared_ptr<HapticBiquadFilter> mLpf;
std::vector<float> mLpfInBuffer;
std::vector<float> mLpfOutBuffer;
- const float mNormalizationPower;
+ float mNormalizationPower;
+ const float mEnvOffset;
const float mChannelCount;
- const float mEnv;
+};
+
+
+// A class providing a process function that compressively distorts a waveforms
+class Distortion {
+public:
+ Distortion(float cornerFrequency, float sampleRate,
+ float inputGain, float cubeThreshold,
+ float outputGain, size_t channelCount);
+
+ void process(float *out, const float *in, size_t frameCount);
+
+ void setCornerFrequency(float cornerFrequency);
+ void setInputGain(float inputGain);
+ void setCubeThrehold(float cubeThreshold);
+ void setOutputGain(float outputGain);
+
+ void clear();
+
+private:
+ const std::shared_ptr<HapticBiquadFilter> mLpf;
+ std::vector<float> mLpfInBuffer;
+ float mSampleRate;
+ float mCornerFrequency;
+ float mInputGain;
+ float mCubeThreshold;
+ float mOutputGain;
+ const size_t mChannelCount;
};
// Helper functions
@@ -64,6 +95,17 @@
BiquadFilterCoefficients cascadeFirstOrderFilters(const BiquadFilterCoefficients &coefs1,
const BiquadFilterCoefficients &coefs2);
+BiquadFilterCoefficients lpfCoefs(const float cornerFrequency, const float sampleRate);
+
+BiquadFilterCoefficients bpfCoefs(const float ringingFrequency,
+ const float q,
+ const float sampleRate);
+
+BiquadFilterCoefficients bsfCoefs(const float ringingFrequency,
+ const float sampleRate,
+ const float zq,
+ const float pq);
+
std::shared_ptr<HapticBiquadFilter> createLPF(const float cornerFrequency,
const float sampleRate,
const size_t channelCount);
@@ -78,16 +120,6 @@
const float sampleRate,
const size_t channelCount);
-std::shared_ptr<HapticBiquadFilter> createAPF(const float cornerFrequency,
- const float sampleRate,
- const size_t channelCount);
-
-// Create two cascaded APF with two different corner frequency.
-std::shared_ptr<HapticBiquadFilter> createAPF2(const float cornerFrequency1,
- const float cornerFrequency2,
- const float sampleRate,
- const size_t channelCount);
-
std::shared_ptr<HapticBiquadFilter> createBPF(const float ringingFrequency,
const float q,
const float sampleRate,
diff --git a/media/libeffects/lvm/tests/reverb_test.cpp b/media/libeffects/lvm/tests/reverb_test.cpp
index cecc975..0ea401c 100644
--- a/media/libeffects/lvm/tests/reverb_test.cpp
+++ b/media/libeffects/lvm/tests/reverb_test.cpp
@@ -312,9 +312,6 @@
config.inputCfg.samplingRate = config.outputCfg.samplingRate = revConfigParams.sampleRate;
config.inputCfg.channels = config.outputCfg.channels = revConfigParams.chMask;
config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
- if (AUDIO_CHANNEL_OUT_MONO == revConfigParams.chMask) {
- config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- }
if (int status = reverbCreateEffect(&effectHandle, &config, sessionId, ioId,
revConfigParams.auxiliary);
status != 0) {
@@ -346,19 +343,11 @@
const int ioChannelCount = revConfigParams.fChannels;
const int ioFrameSize = ioChannelCount * sizeof(short);
const int maxChannelCount = std::max(channelCount, ioChannelCount);
- /*
- * Mono input will be converted to 2 channels internally in the process call
- * by copying the same data into the second channel.
- * Hence when channelCount is 1, output buffer should be allocated for
- * 2 channels. The outChannelCount takes care of allocation of sufficient
- * memory for the output buffer.
- */
- const int outChannelCount = (channelCount == 1 ? 2 : channelCount);
std::vector<short> in(frameLength * maxChannelCount);
- std::vector<short> out(frameLength * outChannelCount);
+ std::vector<short> out(frameLength * maxChannelCount);
std::vector<float> floatIn(frameLength * channelCount);
- std::vector<float> floatOut(frameLength * outChannelCount);
+ std::vector<float> floatOut(frameLength * channelCount);
int frameCounter = 0;
@@ -392,11 +381,11 @@
#else
memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
#endif
- memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * outChannelCount);
+ memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
- if (ioChannelCount != outChannelCount) {
- adjust_channels(out.data(), outChannelCount, out.data(), ioChannelCount, sizeof(short),
- frameLength * outChannelCount * sizeof(short));
+ if (ioChannelCount != channelCount) {
+ adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short),
+ frameLength * channelCount * sizeof(short));
}
(void)fwrite(out.data(), ioFrameSize, frameLength, outputFp.get());
frameCounter += frameLength;
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 4489e81..3738d62 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -33,6 +33,7 @@
#include "EffectReverb.h"
// from Reverb/lib
#include "LVREV.h"
+#include "VectorArithmetic.h"
// effect_handle_t interface implementation for reverb
extern "C" const struct effect_interface_s gReverbInterface;
@@ -332,6 +333,7 @@
//----------------------------------------------------------------------------
int process(effect_buffer_t* pIn, effect_buffer_t* pOut, int frameCount, ReverbContext* pContext) {
int channels = audio_channel_count_from_out_mask(pContext->config.inputCfg.channels);
+ int outChannels = audio_channel_count_from_out_mask(pContext->config.outputCfg.channels);
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
// Reverb only effects the stereo channels in multichannel source.
@@ -454,33 +456,49 @@
}
}
- if (channels > 2) {
+ if (outChannels > 2) {
// Accumulate if required
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
for (int i = 0; i < frameCount; i++) {
- pOut[channels * i] += pContext->OutFrames[FCC_2 * i];
- pOut[channels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
+ pOut[outChannels * i] += pContext->OutFrames[FCC_2 * i];
+ pOut[outChannels * i + 1] += pContext->OutFrames[FCC_2 * i + 1];
}
} else {
for (int i = 0; i < frameCount; i++) {
- pOut[channels * i] = pContext->OutFrames[FCC_2 * i];
- pOut[channels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
+ pOut[outChannels * i] = pContext->OutFrames[FCC_2 * i];
+ pOut[outChannels * i + 1] = pContext->OutFrames[FCC_2 * i + 1];
}
}
- for (int i = 0; i < frameCount; i++) {
- for (int j = FCC_2; j < channels; j++) {
- pOut[channels * i + j] = pIn[channels * i + j];
+ if (!pContext->auxiliary) {
+ for (int i = 0; i < frameCount; i++) {
+ // channels and outChannels are expected to be same.
+ for (int j = FCC_2; j < outChannels; j++) {
+ pOut[outChannels * i + j] = pIn[outChannels * i + j];
+ }
}
}
} else {
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
- for (int i = 0; i < frameCount * FCC_2; i++) {
- pOut[i] += pContext->OutFrames[i];
+ if (outChannels == FCC_1) {
+ for (int i = 0; i < frameCount; i++) {
+ pOut[i] +=
+ ((pContext->OutFrames[i * FCC_2] + pContext->OutFrames[i * FCC_2 + 1]) *
+ 0.5f);
+ }
+ } else {
+ for (int i = 0; i < frameCount * FCC_2; i++) {
+ pOut[i] += pContext->OutFrames[i];
+ }
}
} else {
- memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
+ if (outChannels == FCC_1) {
+ From2iToMono_Float((const process_buffer_t*)pContext->OutFrames, pOut, frameCount);
+ } else {
+ memcpy(pOut, pContext->OutFrames, frameCount * sizeof(*pOut) * FCC_2);
+ }
}
}
+
return 0;
} /* end process */
@@ -549,7 +567,7 @@
CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
((!pContext->auxiliary) && (inputChannels <= LVM_MAX_CHANNELS)));
int outputChannels = audio_channel_count_from_out_mask(pConfig->outputCfg.channels);
- CHECK_ARG(outputChannels >= FCC_2 && outputChannels <= LVM_MAX_CHANNELS);
+ CHECK_ARG(outputChannels <= LVM_MAX_CHANNELS);
CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE ||
pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
CHECK_ARG(pConfig->inputCfg.format == EFFECT_BUFFER_FORMAT);
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index e46a136..eb3ce34 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -18,7 +18,7 @@
],
}
-cc_library_shared {
+cc_library {
name: "libaudiopreprocessing",
vendor: true,
relative_install_path: "soundfx",
diff --git a/media/libeffects/preprocessing/benchmarks/Android.bp b/media/libeffects/preprocessing/benchmarks/Android.bp
index 246d14e..c1b2295 100644
--- a/media/libeffects/preprocessing/benchmarks/Android.bp
+++ b/media/libeffects/preprocessing/benchmarks/Android.bp
@@ -12,14 +12,16 @@
cc_benchmark {
name: "preprocessing_benchmark",
vendor: true,
- relative_install_path: "soundfx",
srcs: ["preprocessing_benchmark.cpp"],
shared_libs: [
- "libaudiopreprocessing",
"libaudioutils",
"liblog",
"libutils",
],
+ static_libs: [
+ "libaudiopreprocessing",
+ "webrtc_audio_processing",
+ ],
cflags: [
"-DWEBRTC_POSIX",
"-fvisibility=default",
diff --git a/media/libeffects/preprocessing/tests/Android.bp b/media/libeffects/preprocessing/tests/Android.bp
index cfa6559..8848e79 100644
--- a/media/libeffects/preprocessing/tests/Android.bp
+++ b/media/libeffects/preprocessing/tests/Android.bp
@@ -12,19 +12,17 @@
cc_test {
name: "AudioPreProcessingTest",
-
vendor: true,
-
- relative_install_path: "soundfx",
-
srcs: ["PreProcessingTest.cpp"],
-
shared_libs: [
- "libaudiopreprocessing",
"libaudioutils",
"liblog",
"libutils",
],
+ static_libs: [
+ "libaudiopreprocessing",
+ "webrtc_audio_processing",
+ ],
header_libs: [
"libaudioeffects",
"libhardware_headers",
diff --git a/media/libmedia/tests/mediaplayer/Android.bp b/media/libmedia/tests/mediaplayer/Android.bp
index 5538ea0..0fff7b4 100644
--- a/media/libmedia/tests/mediaplayer/Android.bp
+++ b/media/libmedia/tests/mediaplayer/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_media_libmedia_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_media_libmedia_license"],
+}
+
cc_test {
name: "IMediaPlayerTest",
test_suites: ["device-tests", "mts"],
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index a181b06..0f80d35 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -123,6 +123,7 @@
#define AMEDIAMETRICS_PROP_FRAMECOUNT "frameCount" // int32
#define AMEDIAMETRICS_PROP_INPUTDEVICES "inputDevices" // string value
+#define AMEDIAMETRICS_PROP_INTERNALTRACKID "internalTrackId" // int32
#define AMEDIAMETRICS_PROP_INTERVALCOUNT "intervalCount" // int32
#define AMEDIAMETRICS_PROP_LATENCYMS "latencyMs" // double value
#define AMEDIAMETRICS_PROP_LOGSESSIONID "logSessionId" // hex string, "" none
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/libmediatranscoding/tests/Android.bp
index ff5a9fa..06b9b17 100644
--- a/media/libmediatranscoding/tests/Android.bp
+++ b/media/libmediatranscoding/tests/Android.bp
@@ -1,5 +1,4 @@
// Build the unit tests for libmediatranscoding.
-
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
diff --git a/media/libnblog/ReportPerformance.cpp b/media/libnblog/ReportPerformance.cpp
index aa678ba..4c78b01 100644
--- a/media/libnblog/ReportPerformance.cpp
+++ b/media/libnblog/ReportPerformance.cpp
@@ -92,8 +92,8 @@
(*dataJson)["threadNum"] = item.first;
root.append(*dataJson);
}
- Json::StyledWriter writer;
- std::string rootStr = writer.write(root);
+ Json::StreamWriterBuilder factory;
+ std::string rootStr = Json::writeString(factory, root);
write(fd, rootStr.c_str(), rootStr.size());
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 61a6ae9..7fa870a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -118,6 +118,11 @@
static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on"; /* 0..n */
static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off"; /* 0..n */
static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame"; /* 0..n */
+static const char *kCodecChannelCount = "android.media.mediacodec.channelCount";
+static const char *kCodecSampleRate = "android.media.mediacodec.sampleRate";
+static const char *kCodecVideoEncodedBytes = "android.media.mediacodec.vencode.bytes";
+static const char *kCodecVideoEncodedFrames = "android.media.mediacodec.vencode.frames";
+static const char *kCodecVideoEncodedDurationUs = "android.media.mediacodec.vencode.durationUs";
// the kCodecRecent* fields appear only in getMetrics() results
static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max"; /* in us */
@@ -695,6 +700,10 @@
mHavePendingInputBuffers(false),
mCpuBoostRequested(false),
mLatencyUnknown(0),
+ mBytesEncoded(0),
+ mEarliestEncodedPtsUs(INT64_MAX),
+ mLatestEncodedPtsUs(INT64_MIN),
+ mFramesEncoded(0),
mNumLowLatencyEnables(0),
mNumLowLatencyDisables(0),
mIsLowLatencyModeOn(false),
@@ -802,6 +811,18 @@
mediametrics_setInt64(mMetricsHandle, kCodecLifetimeMs, lifetime);
}
+ if (mBytesEncoded) {
+ Mutex::Autolock al(mOutputStatsLock);
+
+ mediametrics_setInt64(mMetricsHandle, kCodecVideoEncodedBytes, mBytesEncoded);
+ int64_t duration = 0;
+ if (mLatestEncodedPtsUs > mEarliestEncodedPtsUs) {
+ duration = mLatestEncodedPtsUs - mEarliestEncodedPtsUs;
+ }
+ mediametrics_setInt64(mMetricsHandle, kCodecVideoEncodedDurationUs, duration);
+ mediametrics_setInt64(mMetricsHandle, kCodecVideoEncodedFrames, mFramesEncoded);
+ }
+
{
Mutex::Autolock al(mLatencyLock);
mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables);
@@ -1005,10 +1026,34 @@
}
// when we get a buffer back from the codec
-void MediaCodec::statsBufferReceived(int64_t presentationUs) {
+void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer) {
CHECK_NE(mState, UNINITIALIZED);
+ if (mIsVideo && (mFlags & kFlagIsEncoder)) {
+ int32_t flags = 0;
+ (void) buffer->meta()->findInt32("flags", &flags);
+
+ // some of these frames, we don't want to count
+ // standalone EOS.... has an invalid timestamp
+ if ((flags & (BUFFER_FLAG_CODECCONFIG|BUFFER_FLAG_EOS)) == 0) {
+ mBytesEncoded += buffer->size();
+ mFramesEncoded++;
+
+ Mutex::Autolock al(mOutputStatsLock);
+ int64_t timeUs = 0;
+ if (buffer->meta()->findInt64("timeUs", &timeUs)) {
+ if (timeUs > mLatestEncodedPtsUs) {
+ mLatestEncodedPtsUs = timeUs;
+ }
+ // can't chain as an else-if or this never triggers
+ if (timeUs < mEarliestEncodedPtsUs) {
+ mEarliestEncodedPtsUs = timeUs;
+ }
+ }
+ }
+ }
+
// mutex access to mBuffersInFlight and other stats
Mutex::Autolock al(mLatencyLock);
@@ -1064,7 +1109,7 @@
return;
}
- // nowNs start our calculations
+ // now start our calculations
const int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
int64_t latencyUs = (nowNs - startdata.startedNs + 500) / 1000;
@@ -1337,6 +1382,17 @@
ALOGE("Invalid size(s), width=%d, height=%d", mVideoWidth, mVideoHeight);
return BAD_VALUE;
}
+ } else {
+ if (mMetricsHandle != 0) {
+ int32_t channelCount;
+ if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecChannelCount, channelCount);
+ }
+ int32_t sampleRate;
+ if (format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
+ mediametrics_setInt32(mMetricsHandle, kCodecSampleRate, sampleRate);
+ }
+ }
}
updateLowLatency(format);
@@ -2183,14 +2239,15 @@
int64_t timeUs;
CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
- statsBufferReceived(timeUs);
-
response->setInt64("timeUs", timeUs);
int32_t flags;
CHECK(buffer->meta()->findInt32("flags", &flags));
response->setInt32("flags", flags);
+
+ statsBufferReceived(timeUs, buffer);
+
response->postReply(replyID);
}
@@ -3171,16 +3228,21 @@
break;
}
- // If we're flushing, stopping, configuring or starting but
+ // If we're flushing, configuring or starting but
// received a release request, post the reply for the pending call
// first, and consider it done. The reply token will be replaced
// after this, and we'll no longer be able to reply.
- if (mState == FLUSHING || mState == STOPPING
- || mState == CONFIGURING || mState == STARTING) {
+ if (mState == FLUSHING || mState == CONFIGURING || mState == STARTING) {
// mReply is always set if in these states.
postPendingRepliesAndDeferredMessages(
std::string("kWhatRelease:") + stateString(mState));
}
+ // If we're stopping but received a release request, post the reply
+ // for the pending call if necessary. Note that the reply may have been
+ // already posted due to an error.
+ if (mState == STOPPING && mReplyID) {
+ postPendingRepliesAndDeferredMessages("kWhatRelease:STOPPING");
+ }
if (mFlags & kFlagSawMediaServerDie) {
// It's dead, Jim. Don't expect initiateShutdown to yield
@@ -4332,13 +4394,13 @@
msg->setInt64("timeUs", timeUs);
- statsBufferReceived(timeUs);
-
int32_t flags;
CHECK(buffer->meta()->findInt32("flags", &flags));
msg->setInt32("flags", flags);
+ statsBufferReceived(timeUs, buffer);
+
msg->post();
}
}
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index a28d479..5f64686 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -528,6 +528,14 @@
std::deque<BufferFlightTiming_t> mBuffersInFlight;
Mutex mLatencyLock;
int64_t mLatencyUnknown; // buffers for which we couldn't calculate latency
+
+ Mutex mOutputStatsLock;
+ int64_t mBytesEncoded = 0;
+ int64_t mEarliestEncodedPtsUs = INT64_MAX;
+ int64_t mLatestEncodedPtsUs = INT64_MIN;
+ int32_t mFramesEncoded = 0;
+
+
int64_t mNumLowLatencyEnables; // how many times low latency mode is enabled
int64_t mNumLowLatencyDisables; // how many times low latency mode is disabled
bool mIsLowLatencyModeOn; // is low latency mode on currently
@@ -544,7 +552,7 @@
sp<BatteryChecker> mBatteryChecker;
void statsBufferSent(int64_t presentationUs);
- void statsBufferReceived(int64_t presentationUs);
+ void statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer);
enum {
// the default shape of our latency histogram buckets
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
index d00a50f..6facbd8 100644
--- a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -286,16 +286,18 @@
// initiateShutdown(); shutdown is being handled at the component thread.
// 2) Error occurred, but the shutdown operation is still being done.
// 3) MediaCodec looper thread handles the error.
- // 4) Component thread completes shutdown and posts onStopCompleted()
+ // 4) Client releases the codec upon the error; previous shutdown is still
+ // going on.
+ // 5) Component thread completes shutdown and posts onStopCompleted();
+ // Shutdown from release also completes.
static const AString kCodecName{"test.codec"};
static const AString kCodecOwner{"nobody"};
static const AString kMediaType{"video/x-test"};
- std::promise<void> errorOccurred;
sp<MockCodec> mockCodec;
std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
- [&mockCodec, &errorOccurred](const AString &, const char *) {
+ [&mockCodec](const AString &, const char *) {
mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
// No mock setup, as we don't expect any buffer operations
// in this scenario.
@@ -314,13 +316,14 @@
mockCodec->callback()->onStartCompleted();
});
ON_CALL(*mockCodec, initiateShutdown(true))
- .WillByDefault([mockCodec, &errorOccurred](bool) {
+ .WillByDefault([mockCodec](bool) {
mockCodec->callback()->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- // Mark that 1) and 2) are complete.
- errorOccurred.set_value();
});
ON_CALL(*mockCodec, initiateShutdown(false))
.WillByDefault([mockCodec](bool) {
+ // Previous stop finished now.
+ mockCodec->callback()->onStopCompleted();
+ // Release also finished.
mockCodec->callback()->onReleaseCompleted();
});
return mockCodec;
@@ -332,19 +335,11 @@
ASSERT_NE(nullptr, codec) << "Codec must not be null";
ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";
- std::thread([mockCodec, &errorOccurred]{
- // Simulate component thread that handles stop()
- errorOccurred.get_future().wait();
- // Error occurred but shutdown request still got processed.
- mockCodec->callback()->onStopCompleted();
- }).detach();
-
codec->configure(new AMessage, nullptr, nullptr, 0);
codec->start();
- codec->stop();
- // Sleep here to give time for the MediaCodec looper thread
- // to process the messages.
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ // stop() will fail because of the error
+ EXPECT_NE(OK, codec->stop());
+ // upon receiving the error, client tries to release the codec.
codec->release();
looper->stop();
}
diff --git a/media/mtp/tests/MtpFfsHandleTest/Android.bp b/media/mtp/tests/MtpFfsHandleTest/Android.bp
index cd6e750..ec9c7a4 100644
--- a/media/mtp/tests/MtpFfsHandleTest/Android.bp
+++ b/media/mtp/tests/MtpFfsHandleTest/Android.bp
@@ -38,4 +38,3 @@
"-Werror",
],
}
-
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index 3af9771..6e9945d 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -380,12 +380,15 @@
}
Vector<uint8_t> session;
status_t status = mObj->mDrm->openSession(DrmPlugin::kSecurityLevelMax, session);
- if (status == OK) {
- mObj->mIds.push_front(session);
- List<idvec_t>::iterator iter = mObj->mIds.begin();
- sessionId->ptr = iter->array();
- sessionId->length = iter->size();
+ if (status != OK) {
+ sessionId->ptr = NULL;
+ sessionId->length = 0;
+ return translateStatus(status);
}
+ mObj->mIds.push_front(session);
+ List<idvec_t>::iterator iter = mObj->mIds.begin();
+ sessionId->ptr = iter->array();
+ sessionId->length = iter->size();
return AMEDIA_OK;
}
@@ -489,6 +492,7 @@
} else {
keySetId->ptr = NULL;
keySetId->length = 0;
+ return translateStatus(status);
}
return AMEDIA_OK;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ae9fc64..dacb758 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -85,15 +85,6 @@
#include "TypedLogger.h"
-#define VALUE_OR_FATAL(result) \
- ({ \
- auto _tmp = (result); \
- LOG_ALWAYS_FATAL_IF(!_tmp.ok(), \
- "Failed result (%d)", \
- _tmp.error()); \
- std::move(_tmp.value()); \
- })
-
// ----------------------------------------------------------------------------
// Note: the following macro is used for extremely verbose logging message. In
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index af16448..7fb69be 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -67,7 +67,7 @@
mIntervalStartTimeNs = systemTime();
}
- void logConstructor(pid_t creatorPid, uid_t creatorUid,
+ void logConstructor(pid_t creatorPid, uid_t creatorUid, int32_t internalTrackId,
const std::string& traits = {},
audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT) const {
// Once this item is logged by the server, the client can add properties.
@@ -78,6 +78,7 @@
.set(AMEDIAMETRICS_PROP_ALLOWUID, (int32_t)creatorUid)
.set(AMEDIAMETRICS_PROP_EVENT,
AMEDIAMETRICS_PROP_PREFIX_SERVER AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
+ .set(AMEDIAMETRICS_PROP_INTERNALTRACKID, internalTrackId)
.set(AMEDIAMETRICS_PROP_TRAITS, traits);
// log streamType from the service, since client doesn't know chosen streamType.
if (streamType != AUDIO_STREAM_DEFAULT) {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 86c92ea..5454778 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -724,7 +724,7 @@
// Once this item is logged by the server, the client can add properties.
const char * const traits = sharedBuffer == 0 ? "" : "static";
- mTrackMetrics.logConstructor(creatorPid, uid, traits, streamType);
+ mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
}
AudioFlinger::PlaybackThread::Track::~Track()
@@ -2421,7 +2421,7 @@
#endif
// Once this item is logged by the server, the client can add properties.
- mTrackMetrics.logConstructor(creatorPid, uid);
+ mTrackMetrics.logConstructor(creatorPid, uid, id());
}
AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
@@ -2984,7 +2984,7 @@
mPid(pid), mSilenced(false), mSilencedNotified(false)
{
// Once this item is logged by the server, the client can add properties.
- mTrackMetrics.logConstructor(creatorPid, uid);
+ mTrackMetrics.logConstructor(creatorPid, uid, id());
}
AudioFlinger::MmapThread::MmapTrack::~MmapTrack()
diff --git a/services/audiopolicy/common/managerdefinitions/include/Serializer.h b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
index 48c4147..b70c595 100644
--- a/services/audiopolicy/common/managerdefinitions/include/Serializer.h
+++ b/services/audiopolicy/common/managerdefinitions/include/Serializer.h
@@ -21,5 +21,9 @@
namespace android {
status_t deserializeAudioPolicyFile(const char *fileName, AudioPolicyConfig *config);
+// In VTS mode all vendor extensions are ignored. This is done because
+// VTS tests are built using AOSP code and thus can not use vendor overlays
+// of system libraries.
+status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config);
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 129f6f6..562c213 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -20,8 +20,8 @@
#include <memory>
#include <string>
#include <utility>
+#include <variant>
-#include <hidl/Status.h>
#include <libxml/parser.h>
#include <libxml/xinclude.h>
#include <media/convert.h>
@@ -36,12 +36,14 @@
namespace {
-// TODO(mnaganov): Consider finding an alternative for using HIDL code.
-using hardware::Return;
-using hardware::Status;
-using hardware::Void;
using utilities::convertTo;
+static inline bool maybeVendorExtension(const std::string& s) {
+ // Only checks whether the string starts with the "vendor prefix".
+ static const std::string vendorPrefix = "VX_";
+ return s.size() > vendorPrefix.size() && s.substr(0, vendorPrefix.size()) == vendorPrefix;
+}
+
template<typename E, typename C>
struct AndroidCollectionTraits {
typedef sp<E> Element;
@@ -187,7 +189,7 @@
struct GlobalConfigTraits
{
- typedef void Element;
+ typedef std::monostate Element;
static constexpr const char *tag = "globalConfiguration";
@@ -203,7 +205,7 @@
struct SurroundSoundTraits
{
- typedef void Element;
+ typedef std::monostate Element;
static constexpr const char *tag = "surroundSound";
@@ -226,14 +228,15 @@
class PolicySerializer
{
public:
- status_t deserialize(const char *configFile, AudioPolicyConfig *config);
+ status_t deserialize(const char *configFile, AudioPolicyConfig *config,
+ bool ignoreVendorExtensions = false);
template <class Trait>
status_t deserializeCollection(const xmlNode *cur,
typename Trait::Collection *collection,
typename Trait::PtrSerializingCtx serializingContext);
template <class Trait>
- Return<typename Trait::Element> deserialize(const xmlNode *cur,
+ std::variant<status_t, typename Trait::Element> deserialize(const xmlNode *cur,
typename Trait::PtrSerializingCtx serializingContext);
private:
@@ -242,6 +245,7 @@
typedef AudioPolicyConfig Element;
+ bool mIgnoreVendorExtensions = false;
std::string mChannelMasksSeparator = ",";
std::string mSamplingRatesSeparator = ",";
std::string mFlagsSeparator = "|";
@@ -307,14 +311,17 @@
}
for (; child != NULL; child = child->next) {
if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
- auto element = deserialize<Trait>(child, serializingContext);
- if (element.isOk()) {
- status_t status = Trait::addElementToCollection(element, collection);
+ auto maybeElement = deserialize<Trait>(child, serializingContext);
+ if (maybeElement.index() == 1) {
+ status_t status = Trait::addElementToCollection(
+ std::get<1>(maybeElement), collection);
if (status != NO_ERROR) {
ALOGE("%s: could not add element to %s collection", __func__,
Trait::collectionTag);
return status;
}
+ } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) {
+ // Skip a vendor extension element.
} else {
return BAD_VALUE;
}
@@ -328,8 +335,8 @@
}
template<>
-Return<AudioGainTraits::Element> PolicySerializer::deserialize<AudioGainTraits>(const xmlNode *cur,
- AudioGainTraits::PtrSerializingCtx /*serializingContext*/)
+std::variant<status_t, AudioGainTraits::Element> PolicySerializer::deserialize<AudioGainTraits>(
+ const xmlNode *cur, AudioGainTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = AudioGainTraits::Attributes;
@@ -393,12 +400,13 @@
if (gain->getMode() != 0) {
return gain;
} else {
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
}
template<>
-Return<AudioProfileTraits::Element> PolicySerializer::deserialize<AudioProfileTraits>(
+std::variant<status_t, AudioProfileTraits::Element>
+PolicySerializer::deserialize<AudioProfileTraits>(
const xmlNode *cur, AudioProfileTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = AudioProfileTraits::Attributes;
@@ -407,6 +415,10 @@
std::string format = getXmlAttribute(cur, Attributes::format);
std::string channels = getXmlAttribute(cur, Attributes::channelMasks);
+ if (mIgnoreVendorExtensions && maybeVendorExtension(format)) {
+ ALOGI("%s: vendor extension format \"%s\" skipped", __func__, format.c_str());
+ return NO_INIT;
+ }
AudioProfileTraits::Element profile = new AudioProfile(formatFromString(format, gDynamicFormat),
channelMasksFromString(channels, mChannelMasksSeparator.c_str()),
samplingRatesFromString(samplingRates, mSamplingRatesSeparator.c_str()));
@@ -419,21 +431,21 @@
}
template<>
-Return<MixPortTraits::Element> PolicySerializer::deserialize<MixPortTraits>(const xmlNode *child,
- MixPortTraits::PtrSerializingCtx /*serializingContext*/)
+std::variant<status_t, MixPortTraits::Element> PolicySerializer::deserialize<MixPortTraits>(
+ const xmlNode *child, MixPortTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = MixPortTraits::Attributes;
std::string name = getXmlAttribute(child, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, MixPortTraits::tag, Attributes::name, name.c_str());
std::string role = getXmlAttribute(child, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: Role=%s", __func__, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ?
@@ -444,7 +456,7 @@
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(child, &profiles, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
@@ -476,7 +488,7 @@
AudioGainTraits::Collection gains;
status = deserializeCollection<AudioGainTraits>(child, &gains, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
mixPort->setGains(gains);
@@ -484,7 +496,7 @@
}
template<>
-Return<DevicePortTraits::Element> PolicySerializer::deserialize<DevicePortTraits>(
+std::variant<status_t, DevicePortTraits::Element> PolicySerializer::deserialize<DevicePortTraits>(
const xmlNode *cur, DevicePortTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = DevicePortTraits::Attributes;
@@ -493,30 +505,34 @@
std::string name = getXmlAttribute(cur, Attributes::tagName);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::tagName);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::tagName, name.c_str());
std::string typeName = getXmlAttribute(cur, Attributes::type);
if (typeName.empty()) {
ALOGE("%s: no type for %s", __func__, name.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::type, typeName.c_str());
std::string role = getXmlAttribute(cur, Attributes::role);
if (role.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::role);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::role, role.c_str());
audio_port_role_t portRole = (role == Attributes::roleSource) ?
AUDIO_PORT_ROLE_SOURCE : AUDIO_PORT_ROLE_SINK;
+ if (mIgnoreVendorExtensions && maybeVendorExtension(typeName)) {
+ ALOGI("%s: vendor extension device type \"%s\" skipped", __func__, typeName.c_str());
+ return NO_INIT;
+ }
audio_devices_t type = AUDIO_DEVICE_NONE;
if (!DeviceConverter::fromString(typeName, type) ||
(!audio_is_input_device(type) && portRole == AUDIO_PORT_ROLE_SOURCE) ||
(!audio_is_output_devices(type) && portRole == AUDIO_PORT_ROLE_SINK)) {
ALOGW("%s: bad type %08x", __func__, type);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
std::string encodedFormatsLiteral = getXmlAttribute(cur, Attributes::encodedFormats);
ALOGV("%s: %s %s=%s", __func__, tag, Attributes::encodedFormats, encodedFormatsLiteral.c_str());
@@ -531,7 +547,7 @@
AudioProfileTraits::Collection profiles;
status_t status = deserializeCollection<AudioProfileTraits>(cur, &profiles, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
if (profiles.empty()) {
profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
@@ -544,7 +560,7 @@
// Deserialize AudioGain children
status = deserializeCollection<AudioGainTraits>(cur, &deviceDesc->mGains, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
ALOGV("%s: adding device tag %s type %08x address %s", __func__,
deviceDesc->getName().c_str(), type, deviceDesc->address().c_str());
@@ -552,7 +568,7 @@
}
template<>
-Return<RouteTraits::Element> PolicySerializer::deserialize<RouteTraits>(
+std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<RouteTraits>(
const xmlNode *cur, RouteTraits::PtrSerializingCtx ctx)
{
using Attributes = RouteTraits::Attributes;
@@ -560,7 +576,7 @@
std::string type = getXmlAttribute(cur, Attributes::type);
if (type.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::type);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
audio_route_type_t routeType = (type == Attributes::typeMix) ?
AUDIO_ROUTE_MIX : AUDIO_ROUTE_MUX;
@@ -571,20 +587,24 @@
std::string sinkAttr = getXmlAttribute(cur, Attributes::sink);
if (sinkAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sink);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
// Convert Sink name to port pointer
sp<PolicyAudioPort> sink = ctx->findPortByTagName(sinkAttr);
- if (sink == NULL) {
+ if (sink == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no sink found with name=%s", __func__, sinkAttr.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ } else if (sink == NULL) {
+ ALOGW("Skipping route to sink \"%s\" as it likely has vendor extension type",
+ sinkAttr.c_str());
+ return NO_INIT;
}
route->setSink(sink);
std::string sourcesAttr = getXmlAttribute(cur, Attributes::sources);
if (sourcesAttr.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::sources);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
// Tokenize and Convert Sources name to port pointer
PolicyAudioPortVector sources;
@@ -594,11 +614,15 @@
while (devTag != NULL) {
if (strlen(devTag) != 0) {
sp<PolicyAudioPort> source = ctx->findPortByTagName(devTag);
- if (source == NULL) {
+ if (source == NULL && !mIgnoreVendorExtensions) {
ALOGE("%s: no source found with name=%s", __func__, devTag);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ } else if (source == NULL) {
+ ALOGW("Skipping route source \"%s\" as it likely has vendor extension type",
+ devTag);
+ } else {
+ sources.add(source);
}
- sources.add(source);
}
devTag = strtok(NULL, ",");
}
@@ -613,7 +637,7 @@
}
template<>
-Return<ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
+std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
{
using Attributes = ModuleTraits::Attributes;
@@ -625,7 +649,7 @@
std::string name = getXmlAttribute(cur, Attributes::name);
if (name.empty()) {
ALOGE("%s: No %s found", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
uint32_t versionMajor = 0, versionMinor = 0;
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
@@ -643,21 +667,21 @@
MixPortTraits::Collection mixPorts;
status_t status = deserializeCollection<MixPortTraits>(cur, &mixPorts, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setProfiles(mixPorts);
DevicePortTraits::Collection devicePorts;
status = deserializeCollection<DevicePortTraits>(cur, &devicePorts, NULL);
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setDeclaredDevices(devicePorts);
RouteTraits::Collection routes;
status = deserializeCollection<RouteTraits>(cur, &routes, module.get());
if (status != NO_ERROR) {
- return Status::fromStatusT(status);
+ return status;
}
module->setRoutes(routes);
@@ -677,6 +701,12 @@
sp<DeviceDescriptor> device = module->getDeclaredDevices().
getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
attachedDevice.get())));
+ if (device == nullptr && mIgnoreVendorExtensions) {
+ ALOGW("Skipped attached device \"%s\" because it likely uses a vendor"
+ "extension type",
+ reinterpret_cast<const char*>(attachedDevice.get()));
+ continue;
+ }
ctx->addDevice(device);
}
}
@@ -703,7 +733,8 @@
}
template<>
-Return<GlobalConfigTraits::Element> PolicySerializer::deserialize<GlobalConfigTraits>(
+std::variant<status_t, GlobalConfigTraits::Element>
+PolicySerializer::deserialize<GlobalConfigTraits>(
const xmlNode *root, GlobalConfigTraits::PtrSerializingCtx config)
{
using Attributes = GlobalConfigTraits::Attributes;
@@ -725,14 +756,15 @@
if (!engineLibrarySuffix.empty()) {
config->setEngineLibraryNameSuffix(engineLibrarySuffix);
}
- return Void();
+ return NO_ERROR;
}
}
- return Void();
+ return NO_ERROR;
}
template<>
-Return<SurroundSoundTraits::Element> PolicySerializer::deserialize<SurroundSoundTraits>(
+std::variant<status_t, SurroundSoundTraits::Element>
+PolicySerializer::deserialize<SurroundSoundTraits>(
const xmlNode *root, SurroundSoundTraits::PtrSerializingCtx config)
{
config->setDefaultSurroundFormats();
@@ -745,14 +777,15 @@
if (status == NO_ERROR) {
config->setSurroundFormats(formats);
}
- return Void();
+ return NO_ERROR;
}
}
- return Void();
+ return NO_ERROR;
}
template<>
-Return<SurroundSoundFormatTraits::Element> PolicySerializer::deserialize<SurroundSoundFormatTraits>(
+std::variant<status_t, SurroundSoundFormatTraits::Element>
+PolicySerializer::deserialize<SurroundSoundFormatTraits>(
const xmlNode *cur, SurroundSoundFormatTraits::PtrSerializingCtx /*serializingContext*/)
{
using Attributes = SurroundSoundFormatTraits::Attributes;
@@ -760,12 +793,16 @@
std::string formatLiteral = getXmlAttribute(cur, Attributes::name);
if (formatLiteral.empty()) {
ALOGE("%s: No %s found for a surround format", __func__, Attributes::name);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
+ }
+ if (mIgnoreVendorExtensions && maybeVendorExtension(formatLiteral)) {
+ ALOGI("%s: vendor extension format \"%s\" skipped", __func__, formatLiteral.c_str());
+ return NO_INIT;
}
audio_format_t format = formatFromString(formatLiteral);
if (format == AUDIO_FORMAT_DEFAULT) {
ALOGE("%s: Unrecognized format %s", __func__, formatLiteral.c_str());
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
SurroundSoundFormatTraits::Element pair = std::make_pair(
format, SurroundSoundFormatTraits::Collection::mapped_type{});
@@ -777,14 +814,16 @@
auto result = pair.second.insert(subformat);
if (!result.second) {
ALOGE("%s: could not add subformat %x to collection", __func__, subformat);
- return Status::fromStatusT(BAD_VALUE);
+ return BAD_VALUE;
}
}
return pair;
}
-status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config)
+status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig *config,
+ bool ignoreVendorExtensions)
{
+ mIgnoreVendorExtensions = ignoreVendorExtensions;
auto doc = make_xmlUnique(xmlParseFile(configFile));
if (doc == nullptr) {
ALOGE("%s: Could not parse %s document.", __func__, configFile);
@@ -845,4 +884,12 @@
return status;
}
+status_t deserializeAudioPolicyFileForVts(const char *fileName, AudioPolicyConfig *config)
+{
+ PolicySerializer serializer;
+ status_t status = serializer.deserialize(fileName, config, true /*ignoreVendorExtensions*/);
+ if (status != OK) config->clear();
+ return status;
+}
+
} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
index 2d57d4f..bc72484 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Car/Android.bp
@@ -32,8 +32,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
index df31bb9..11da8c7 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/CarEmu/Android.bp
@@ -33,8 +33,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
index 65ab8b6..91ffeb5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/Phone/Android.bp
@@ -32,8 +32,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
index 90154ee..cac63fc 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoInput/Android.bp
@@ -29,8 +29,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
index 5b06852..337f358 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/examples/SettingsNoOutput/Android.bp
@@ -29,8 +29,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index eb63636..ff4d568 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -4,8 +4,6 @@
// all of the 'license_kinds' from "frameworks_av_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
default_applicable_licenses: ["frameworks_av_license"],
}
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index e9f95cb..dd37135 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -143,11 +143,13 @@
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
"android.hardware.camera.provider@2.6",
+ "android.hardware.camera.provider@2.7",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
- "android.hardware.camera.device@3.6"
+ "android.hardware.camera.device@3.6",
+ "android.hardware.camera.device@3.7"
],
static_libs: [
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 1234dfd..706197e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -805,6 +805,7 @@
case CAMERA_DEVICE_API_VERSION_3_4:
case CAMERA_DEVICE_API_VERSION_3_5:
case CAMERA_DEVICE_API_VERSION_3_6:
+ case CAMERA_DEVICE_API_VERSION_3_7:
if (effectiveApiLevel == API_1) { // Camera1 API route
sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
*client = new Camera2Client(cameraService, tmp, packageName, featureId,
@@ -2271,6 +2272,7 @@
case CAMERA_DEVICE_API_VERSION_3_4:
case CAMERA_DEVICE_API_VERSION_3_5:
case CAMERA_DEVICE_API_VERSION_3_6:
+ case CAMERA_DEVICE_API_VERSION_3_7:
ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",
__FUNCTION__, id.string());
*isSupported = true;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index e062c14..8164df0 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -29,7 +29,6 @@
#include "Parameters.h"
#include "system/camera.h"
-#include "hardware/camera_common.h"
#include <android/hardware/ICamera.h>
#include <media/MediaProfiles.h>
#include <media/mediarecorder.h>
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 0701b6f..9fdc727 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -237,7 +237,7 @@
if (mInputStreamId == NO_STREAM) {
res = device->createInputStream(params.fastInfo.maxZslSize.width,
params.fastInfo.maxZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
- &mInputStreamId);
+ /*isMultiResolution*/false, &mInputStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create input stream: "
"%s (%d)", __FUNCTION__, client->getCameraId(),
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index d47014e..8cccbb1 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -584,7 +584,7 @@
ALOGE("%s: %s", __FUNCTION__, msg.string());
return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
}
- hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+ hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
bool earlyExit = false;
metadataGetter getMetadata = [this](const String8 &id) {return mDevice->infoPhysical(id);};
std::vector<std::string> physicalCameraIds;
@@ -738,6 +738,7 @@
bool isShared = outputConfiguration.isShared();
String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
+ bool isMultiResolution = outputConfiguration.isMultiResolution();
res = SessionConfigurationUtils::checkSurfaceType(numBufferProducers, deferredConsumer,
outputConfiguration.getSurfaceType());
@@ -809,7 +810,7 @@
streamInfo.height, streamInfo.format,
static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
- isShared);
+ isShared, isMultiResolution);
if (err == OK) {
mCompositeStreamMap.add(IInterface::asBinder(surfaces[0]->getIGraphicBufferProducer()),
compositeStream);
@@ -819,7 +820,7 @@
streamInfo.height, streamInfo.format, streamInfo.dataSpace,
static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds, outputConfiguration.getSurfaceSetID(),
- isShared);
+ isShared, isMultiResolution);
}
if (err != OK) {
@@ -888,7 +889,7 @@
static_cast<camera_stream_rotation_t>(outputConfiguration.getRotation()),
&streamId, physicalCameraId, &surfaceIds,
outputConfiguration.getSurfaceSetID(), isShared,
- consumerUsage);
+ outputConfiguration.isMultiResolution(), consumerUsage);
if (err != OK) {
res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -943,12 +944,13 @@
}
binder::Status CameraDeviceClient::createInputStream(
- int width, int height, int format,
+ int width, int height, int format, bool isMultiResolution,
/*out*/
int32_t* newStreamId) {
ATRACE_CALL();
- ALOGV("%s (w = %d, h = %d, f = 0x%x)", __FUNCTION__, width, height, format);
+ ALOGV("%s (w = %d, h = %d, f = 0x%x, isMultiResolution %d)", __FUNCTION__,
+ width, height, format, isMultiResolution);
binder::Status res;
if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
@@ -967,7 +969,7 @@
}
int streamId = -1;
- status_t err = mDevice->createInputStream(width, height, format, &streamId);
+ status_t err = mDevice->createInputStream(width, height, format, isMultiResolution, &streamId);
if (err == OK) {
mInputStream.configured = true;
mInputStream.width = width;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 5588285..9f7a4af 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -115,6 +115,7 @@
// Create an input stream of width, height, and format.
virtual binder::Status createInputStream(int width, int height, int format,
+ bool isMultiResolution,
/*out*/
int32_t* newStreamId = NULL) override;
diff --git a/services/camera/libcameraservice/api2/CompositeStream.cpp b/services/camera/libcameraservice/api2/CompositeStream.cpp
index 2f8ca6b..515b7f2 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/CompositeStream.cpp
@@ -47,7 +47,7 @@
status_t CompositeStream::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
camera_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
- std::vector<int> * surfaceIds, int streamSetId, bool isShared) {
+ std::vector<int> * surfaceIds, int streamSetId, bool isShared, bool isMultiResolution) {
if (hasDeferredConsumer) {
ALOGE("%s: Deferred consumers not supported in case of composite streams!",
__FUNCTION__);
@@ -66,6 +66,12 @@
return BAD_VALUE;
}
+ if (isMultiResolution) {
+ ALOGE("%s: Multi-resolution output not supported in case of composite streams!",
+ __FUNCTION__);
+ return BAD_VALUE;
+ }
+
return createInternalStreams(consumers, hasDeferredConsumer, width, height, format, rotation, id,
physicalCameraId, surfaceIds, streamSetId, isShared);
}
diff --git a/services/camera/libcameraservice/api2/CompositeStream.h b/services/camera/libcameraservice/api2/CompositeStream.h
index 2a934df..1bf137a 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.h
+++ b/services/camera/libcameraservice/api2/CompositeStream.h
@@ -44,7 +44,7 @@
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
- std::vector<int> *surfaceIds, int streamSetId, bool isShared);
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution);
status_t deleteStream();
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 1be46d6..5acbb99 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -166,7 +166,8 @@
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint64_t consumerUsage = 0) = 0;
+ bool isShared = false, bool isMultiResolution = false,
+ uint64_t consumerUsage = 0) = 0;
/**
* Create an output stream of the requested size, format, rotation and
@@ -181,7 +182,8 @@
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint64_t consumerUsage = 0) = 0;
+ bool isShared = false, bool isMultiResolution = false,
+ uint64_t consumerUsage = 0) = 0;
/**
* Create an input stream of width, height, and format.
@@ -189,7 +191,7 @@
* Return value is the stream ID if non-negative and an error if negative.
*/
virtual status_t createInputStream(uint32_t width, uint32_t height,
- int32_t format, /*out*/ int32_t *id) = 0;
+ int32_t format, bool multiResolution, /*out*/ int32_t *id) = 0;
struct StreamInfo {
uint32_t width;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index e9dcb01..dfe2409 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -20,7 +20,7 @@
#include "CameraProviderManager.h"
-#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+#include <android/hardware/camera/device/3.7/ICameraDevice.h>
#include <algorithm>
#include <chrono>
@@ -28,7 +28,6 @@
#include <dlfcn.h>
#include <future>
#include <inttypes.h>
-#include <hardware/camera_common.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/ServiceManagement.h>
#include <functional>
@@ -49,7 +48,7 @@
using namespace ::android::hardware::camera::common::V1_0;
using std::literals::chrono_literals::operator""s;
using hardware::camera2::utils::CameraIdAndSessionConfiguration;
-using hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
+using hardware::camera::provider::V2_7::CameraIdAndStreamCombination;
namespace {
const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
@@ -267,7 +266,7 @@
}
status_t CameraProviderManager::isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
auto deviceInfo = findDeviceInfoLocked(id);
@@ -1302,6 +1301,14 @@
mMinorVersion = 5;
}
}
+ } else {
+ auto cast2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ if (cast2_7.isOk()) {
+ sp<provider::V2_7::ICameraProvider> interface2_7 = cast2_7;
+ if (interface2_7 != nullptr) {
+ mMinorVersion = 7;
+ }
+ }
}
// cameraDeviceStatusChange callbacks may be called (and causing new devices added)
@@ -1973,38 +1980,67 @@
// TODO: This might be some other problem
return INVALID_OPERATION;
}
- auto castResult = provider::V2_6::ICameraProvider::castFrom(interface);
- if (castResult.isOk()) {
- sp<provider::V2_6::ICameraProvider> interface_2_6 = castResult;
- if (interface_2_6 != nullptr) {
- Status callStatus;
- auto cb =
- [&isSupported, &callStatus](Status s, bool supported) {
- callStatus = s;
- *isSupported = supported; };
+ auto castResult2_6 = provider::V2_6::ICameraProvider::castFrom(interface);
+ auto castResult2_7 = provider::V2_7::ICameraProvider::castFrom(interface);
+ Status callStatus;
+ auto cb =
+ [&isSupported, &callStatus](Status s, bool supported) {
+ callStatus = s;
+ *isSupported = supported; };
- auto ret = interface_2_6->isConcurrentStreamCombinationSupported(
- halCameraIdsAndStreamCombinations, cb);
- if (ret.isOk()) {
- switch (callStatus) {
- case Status::OK:
- // Expected case, do nothing.
- res = OK;
- break;
- case Status::METHOD_NOT_SUPPORTED:
- res = INVALID_OPERATION;
- break;
- default:
- ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
- callStatus);
- res = UNKNOWN_ERROR;
- }
- } else {
- ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
- res = UNKNOWN_ERROR;
- }
- return res;
+ ::android::hardware::Return<void> ret;
+ sp<provider::V2_7::ICameraProvider> interface_2_7;
+ sp<provider::V2_6::ICameraProvider> interface_2_6;
+ if (mMinorVersion >= 7 && castResult2_7.isOk()) {
+ interface_2_7 = castResult2_7;
+ if (interface_2_7 != nullptr) {
+ ret = interface_2_7->isConcurrentStreamCombinationSupported_2_7(
+ halCameraIdsAndStreamCombinations, cb);
}
+ } else if (mMinorVersion == 6 && castResult2_6.isOk()) {
+ interface_2_6 = castResult2_6;
+ if (interface_2_6 != nullptr) {
+ hardware::hidl_vec<provider::V2_6::CameraIdAndStreamCombination>
+ halCameraIdsAndStreamCombinations_2_6;
+ size_t numStreams = halCameraIdsAndStreamCombinations.size();
+ halCameraIdsAndStreamCombinations_2_6.resize(numStreams);
+ for (size_t i = 0; i < numStreams; i++) {
+ auto const& combination = halCameraIdsAndStreamCombinations[i];
+ halCameraIdsAndStreamCombinations_2_6[i].cameraId = combination.cameraId;
+ bool success =
+ SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ halCameraIdsAndStreamCombinations_2_6[i].streamConfiguration,
+ combination.streamConfiguration);
+ if (!success) {
+ *isSupported = false;
+ return OK;
+ }
+ }
+ ret = interface_2_6->isConcurrentStreamCombinationSupported(
+ halCameraIdsAndStreamCombinations_2_6, cb);
+ }
+ }
+
+ if (interface_2_7 != nullptr || interface_2_6 != nullptr) {
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
+ callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+ return res;
}
}
// unsupported operation
@@ -2374,7 +2410,7 @@
}
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
- const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/) {
const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
@@ -2382,19 +2418,37 @@
if (interface == nullptr) {
return DEAD_OBJECT;
}
- auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
- sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
- if (interface_3_5 == nullptr) {
- return INVALID_OPERATION;
- }
+ auto castResult_3_5 = device::V3_5::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult_3_5;
+ auto castResult_3_7 = device::V3_7::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_7::ICameraDevice> interface_3_7 = castResult_3_7;
status_t res;
Status callStatus;
- auto ret = interface_3_5->isStreamCombinationSupported(configuration,
+ ::android::hardware::Return<void> ret;
+ if (interface_3_7 != nullptr) {
+ ret = interface_3_7->isStreamCombinationSupported_3_7(configuration,
[&callStatus, &status] (Status s, bool combStatus) {
callStatus = s;
*status = combStatus;
});
+ } else if (interface_3_5 != nullptr) {
+ hardware::camera::device::V3_4::StreamConfiguration configuration_3_4;
+ bool success = SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ configuration_3_4, configuration);
+ if (!success) {
+ *status = false;
+ return OK;
+ }
+
+ ret = interface_3_5->isStreamCombinationSupported(configuration_3_4,
+ [&callStatus, &status] (Status s, bool combStatus) {
+ callStatus = s;
+ *status = combStatus;
+ });
+ } else {
+ return INVALID_OPERATION;
+ }
if (ret.isOk()) {
switch (callStatus) {
case Status::OK:
@@ -2769,7 +2823,7 @@
bool shouldExit = false;
status_t res = OK;
for (auto &cameraIdAndSessionConfig : cameraIdsAndSessionConfigs) {
- hardware::camera::device::V3_4::StreamConfiguration streamConfiguration;
+ hardware::camera::device::V3_7::StreamConfiguration streamConfiguration;
CameraMetadata deviceInfo;
res = getCameraCharacteristicsLocked(cameraIdAndSessionConfig.mCameraId, &deviceInfo);
if (res != OK) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 8727e7f..fa9cc1c 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -33,7 +33,8 @@
#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/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/provider/2.7/ICameraProvider.h>
+#include <android/hardware/camera/device/3.7/types.h>
#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <camera/VendorTagDescriptor.h>
@@ -78,6 +79,16 @@
HIDDEN_SECURE_CAMERA
};
+#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0)
+#define CAMERA_DEVICE_API_VERSION_3_0 HARDWARE_DEVICE_API_VERSION(3, 0)
+#define CAMERA_DEVICE_API_VERSION_3_1 HARDWARE_DEVICE_API_VERSION(3, 1)
+#define CAMERA_DEVICE_API_VERSION_3_2 HARDWARE_DEVICE_API_VERSION(3, 2)
+#define CAMERA_DEVICE_API_VERSION_3_3 HARDWARE_DEVICE_API_VERSION(3, 3)
+#define CAMERA_DEVICE_API_VERSION_3_4 HARDWARE_DEVICE_API_VERSION(3, 4)
+#define CAMERA_DEVICE_API_VERSION_3_5 HARDWARE_DEVICE_API_VERSION(3, 5)
+#define CAMERA_DEVICE_API_VERSION_3_6 HARDWARE_DEVICE_API_VERSION(3, 6)
+#define CAMERA_DEVICE_API_VERSION_3_7 HARDWARE_DEVICE_API_VERSION(3, 7)
+
/**
* A manager for all camera providers available on an Android device.
*
@@ -227,7 +238,7 @@
* Check for device support of specific stream combination.
*/
status_t isSessionConfigurationSupported(const std::string& id,
- const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/) const;
/**
@@ -430,7 +441,7 @@
*/
status_t isConcurrentSessionConfigurationSupported(
const hardware::hidl_vec<
- hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+ hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
&halCameraIdsAndStreamCombinations,
bool *isSupported);
@@ -470,7 +481,7 @@
}
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_4::StreamConfiguration &/*configuration*/,
+ const hardware::camera::device::V3_7::StreamConfiguration &/*configuration*/,
bool * /*status*/) {
return INVALID_OPERATION;
}
@@ -529,7 +540,7 @@
virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
CameraMetadata *characteristics) const override;
virtual status_t isSessionConfigurationSupported(
- const hardware::camera::device::V3_4::StreamConfiguration &configuration,
+ const hardware::camera::device::V3_7::StreamConfiguration &configuration,
bool *status /*out*/)
override;
@@ -684,7 +695,7 @@
status_t convertToHALStreamCombinationAndCameraIdsLocked(
const std::vector<hardware::camera2::utils::CameraIdAndSessionConfiguration>
&cameraIdsAndSessionConfigs,
- hardware::hidl_vec<hardware::camera::provider::V2_6::CameraIdAndStreamCombination>
+ hardware::hidl_vec<hardware::camera::provider::V2_7::CameraIdAndStreamCombination>
*halCameraIdsAndStreamCombinations,
bool *earlyExit);
};
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index d6bf83e..a556200 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -40,16 +40,17 @@
ATRACE_CALL();
int streamId = streamInfo.streamId;
- int streamSetId = streamInfo.streamSetId;
+ StreamSetKey streamSetKey = {streamInfo.streamSetId, streamInfo.isMultiRes};
- if (streamId == CAMERA3_STREAM_ID_INVALID || streamSetId == CAMERA3_STREAM_SET_ID_INVALID) {
+ if (streamId == CAMERA3_STREAM_ID_INVALID ||
+ streamSetKey.id == CAMERA3_STREAM_SET_ID_INVALID) {
ALOGE("%s: Stream id (%d) or stream set id (%d) is invalid",
- __FUNCTION__, streamId, streamSetId);
+ __FUNCTION__, streamId, streamSetKey.id);
return BAD_VALUE;
}
if (streamInfo.totalBufferCount > kMaxBufferCount || streamInfo.totalBufferCount == 0) {
ALOGE("%s: Stream id (%d) with stream set id (%d) total buffer count %zu is invalid",
- __FUNCTION__, streamId, streamSetId, streamInfo.totalBufferCount);
+ __FUNCTION__, streamId, streamSetKey.id, streamInfo.totalBufferCount);
return BAD_VALUE;
}
if (!streamInfo.isConfigured) {
@@ -75,7 +76,8 @@
for (size_t i = 0; i < mStreamSetMap.size(); i++) {
ssize_t streamIdx = mStreamSetMap[i].streamInfoMap.indexOfKey(streamId);
if (streamIdx != NAME_NOT_FOUND &&
- mStreamSetMap[i].streamInfoMap[streamIdx].streamSetId != streamInfo.streamSetId) {
+ mStreamSetMap[i].streamInfoMap[streamIdx].streamSetId != streamInfo.streamSetId &&
+ mStreamSetMap[i].streamInfoMap[streamIdx].isMultiRes != streamInfo.isMultiRes) {
ALOGE("%s: It is illegal to register the same stream id with different stream set",
__FUNCTION__);
return BAD_VALUE;
@@ -83,20 +85,20 @@
}
// Check if there is an existing stream set registered; if not, create one; otherwise, add this
// stream info to the existing stream set entry.
- ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetId);
+ ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetKey);
if (setIdx == NAME_NOT_FOUND) {
- ALOGV("%s: stream set %d is not registered to stream set map yet, create it.",
- __FUNCTION__, streamSetId);
+ ALOGV("%s: stream set %d(%d) is not registered to stream set map yet, create it.",
+ __FUNCTION__, streamSetKey.id, streamSetKey.isMultiRes);
// Create stream info map, then add to mStreamsetMap.
StreamSet newStreamSet;
- setIdx = mStreamSetMap.add(streamSetId, newStreamSet);
+ setIdx = mStreamSetMap.add(streamSetKey, newStreamSet);
}
// Update stream set map and water mark.
StreamSet& currentStreamSet = mStreamSetMap.editValueAt(setIdx);
ssize_t streamIdx = currentStreamSet.streamInfoMap.indexOfKey(streamId);
if (streamIdx != NAME_NOT_FOUND) {
- ALOGW("%s: stream %d was already registered with stream set %d",
- __FUNCTION__, streamId, streamSetId);
+ ALOGW("%s: stream %d was already registered with stream set %d(%d)",
+ __FUNCTION__, streamId, streamSetKey.id, streamSetKey.isMultiRes);
return OK;
}
currentStreamSet.streamInfoMap.add(streamId, streamInfo);
@@ -113,21 +115,22 @@
return OK;
}
-status_t Camera3BufferManager::unregisterStream(int streamId, int streamSetId) {
+status_t Camera3BufferManager::unregisterStream(int streamId, int streamSetId, bool isMultiRes) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
- ALOGV("%s: unregister stream %d with stream set %d", __FUNCTION__,
- streamId, streamSetId);
+ ALOGV("%s: unregister stream %d with stream set %d(%d)", __FUNCTION__,
+ streamId, streamSetId, isMultiRes);
- if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
- ALOGE("%s: stream %d with set id %d wasn't properly registered to this buffer manager!",
- __FUNCTION__, streamId, streamSetId);
+ StreamSetKey streamSetKey = {streamSetId, isMultiRes};
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetKey)){
+ ALOGE("%s: stream %d with set %d(%d) wasn't properly registered to this"
+ " buffer manager!", __FUNCTION__, streamId, streamSetId, isMultiRes);
return BAD_VALUE;
}
// De-list all the buffers associated with this stream first.
- StreamSet& currentSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSet& currentSet = mStreamSetMap.editValueFor(streamSetKey);
BufferCountMap& handOutBufferCounts = currentSet.handoutBufferCountMap;
BufferCountMap& attachedBufferCounts = currentSet.attachedBufferCountMap;
InfoMap& infoMap = currentSet.streamInfoMap;
@@ -150,26 +153,28 @@
// Remove this stream set if all its streams have been removed.
if (handOutBufferCounts.size() == 0 && infoMap.size() == 0) {
- mStreamSetMap.removeItem(streamSetId);
+ mStreamSetMap.removeItem(streamSetKey);
}
return OK;
}
-void Camera3BufferManager::notifyBufferRemoved(int streamId, int streamSetId) {
+void Camera3BufferManager::notifyBufferRemoved(int streamId, int streamSetId, bool isMultiRes) {
Mutex::Autolock l(mLock);
- StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSetKey streamSetKey = {streamSetId, isMultiRes};
+ StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetKey);
size_t& attachedBufferCount =
streamSet.attachedBufferCountMap.editValueFor(streamId);
attachedBufferCount--;
}
status_t Camera3BufferManager::checkAndFreeBufferOnOtherStreamsLocked(
- int streamId, int streamSetId) {
+ int streamId, StreamSetKey streamSetKey) {
StreamId firstOtherStreamId = CAMERA3_STREAM_ID_INVALID;
- StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetKey);
if (streamSet.streamInfoMap.size() == 1) {
- ALOGV("StreamSet %d has no other stream available to free", streamSetId);
+ ALOGV("StreamSet %d(%d) has no other stream available to free",
+ streamSetKey.id, streamSetKey.isMultiRes);
return OK;
}
@@ -190,7 +195,8 @@
firstOtherStreamId = CAMERA3_STREAM_ID_INVALID;
}
if (firstOtherStreamId == CAMERA3_STREAM_ID_INVALID || !freeBufferIsAttached) {
- ALOGV("StreamSet %d has no buffer available to free", streamSetId);
+ ALOGV("StreamSet %d(%d) has no buffer available to free",
+ streamSetKey.id, streamSetKey.isMultiRes);
return OK;
}
@@ -237,20 +243,21 @@
}
status_t Camera3BufferManager::getBufferForStream(int streamId, int streamSetId,
- sp<GraphicBuffer>* gb, int* fenceFd, bool noFreeBufferAtConsumer) {
+ bool isMultiRes, sp<GraphicBuffer>* gb, int* fenceFd, bool noFreeBufferAtConsumer) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
- ALOGV("%s: get buffer for stream %d with stream set %d", __FUNCTION__,
- streamId, streamSetId);
+ ALOGV("%s: get buffer for stream %d with stream set %d(%d)", __FUNCTION__,
+ streamId, streamSetId, isMultiRes);
- if (!checkIfStreamRegisteredLocked(streamId, streamSetId)) {
- ALOGE("%s: stream %d is not registered with stream set %d yet!!!",
- __FUNCTION__, streamId, streamSetId);
+ StreamSetKey streamSetKey = {streamSetId, isMultiRes};
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetKey)) {
+ ALOGE("%s: stream %d is not registered with stream set %d(%d) yet!!!",
+ __FUNCTION__, streamId, streamSetId, isMultiRes);
return BAD_VALUE;
}
- StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSet &streamSet = mStreamSetMap.editValueFor(streamSetKey);
BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
BufferCountMap& attachedBufferCounts = streamSet.attachedBufferCountMap;
@@ -272,7 +279,8 @@
bufferCount++;
return ALREADY_EXISTS;
}
- ALOGV("Stream %d set %d: Get buffer for stream: Allocate new", streamId, streamSetId);
+ ALOGV("Stream %d set %d(%d): Get buffer for stream: Allocate new",
+ streamId, streamSetId, isMultiRes);
if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
const StreamInfo& info = streamSet.streamInfoMap.valueFor(streamId);
@@ -313,13 +321,13 @@
// in returnBufferForStream() if we want to free buffer more quickly.
// TODO: probably should find out all the inactive stream IDs, and free the firstly found
// buffers for them.
- res = checkAndFreeBufferOnOtherStreamsLocked(streamId, streamSetId);
+ res = checkAndFreeBufferOnOtherStreamsLocked(streamId, streamSetKey);
if (res != OK) {
return res;
}
// Since we just allocated one new buffer above, try free one more buffer from other streams
// to prevent total buffer count from growing
- res = checkAndFreeBufferOnOtherStreamsLocked(streamId, streamSetId);
+ res = checkAndFreeBufferOnOtherStreamsLocked(streamId, streamSetKey);
if (res != OK) {
return res;
}
@@ -332,7 +340,7 @@
}
status_t Camera3BufferManager::onBufferReleased(
- int streamId, int streamSetId, bool* shouldFreeBuffer) {
+ int streamId, int streamSetId, bool isMultiRes, bool* shouldFreeBuffer) {
ATRACE_CALL();
if (shouldFreeBuffer == nullptr) {
@@ -341,22 +349,24 @@
}
Mutex::Autolock l(mLock);
- ALOGV("Stream %d set %d: Buffer released", streamId, streamSetId);
+ ALOGV("Stream %d set %d(%d): Buffer released", streamId, streamSetId, isMultiRes);
*shouldFreeBuffer = false;
- if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
+ StreamSetKey streamSetKey = {streamSetId, isMultiRes};
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetKey)){
ALOGV("%s: signaling buffer release for an already unregistered stream "
- "(stream %d with set id %d)", __FUNCTION__, streamId, streamSetId);
+ "(stream %d with set id %d(%d))", __FUNCTION__, streamId, streamSetId,
+ isMultiRes);
return OK;
}
if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
- StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetKey);
BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
size_t& bufferCount = handOutBufferCounts.editValueFor(streamId);
bufferCount--;
- ALOGV("%s: Stream %d set %d: Buffer count now %zu", __FUNCTION__, streamId, streamSetId,
- bufferCount);
+ ALOGV("%s: Stream %d set %d(%d): Buffer count now %zu", __FUNCTION__, streamId,
+ streamSetId, isMultiRes, bufferCount);
size_t totalAllocatedBufferCount = 0;
size_t totalHandOutBufferCount = 0;
@@ -371,8 +381,9 @@
// BufferManager got more than enough buffers, so decrease watermark
// to trigger more buffers free operation.
streamSet.allocatedBufferWaterMark = newWaterMark;
- ALOGV("%s: Stream %d set %d: watermark--; now %zu",
- __FUNCTION__, streamId, streamSetId, streamSet.allocatedBufferWaterMark);
+ ALOGV("%s: Stream %d set %d(%d): watermark--; now %zu",
+ __FUNCTION__, streamId, streamSetId, isMultiRes,
+ streamSet.allocatedBufferWaterMark);
}
size_t attachedBufferCount = streamSet.attachedBufferCountMap.valueFor(streamId);
@@ -395,20 +406,22 @@
return OK;
}
-status_t Camera3BufferManager::onBuffersRemoved(int streamId, int streamSetId, size_t count) {
+status_t Camera3BufferManager::onBuffersRemoved(int streamId, int streamSetId,
+ bool isMultiRes, size_t count) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
- ALOGV("Stream %d set %d: Buffer removed", streamId, streamSetId);
+ ALOGV("Stream %d set %d(%d): Buffer removed", streamId, streamSetId, isMultiRes);
- if (!checkIfStreamRegisteredLocked(streamId, streamSetId)){
+ StreamSetKey streamSetKey = {streamSetId, isMultiRes};
+ if (!checkIfStreamRegisteredLocked(streamId, streamSetKey)){
ALOGV("%s: signaling buffer removal for an already unregistered stream "
- "(stream %d with set id %d)", __FUNCTION__, streamId, streamSetId);
+ "(stream %d with set id %d(%d))", __FUNCTION__, streamId, streamSetId, isMultiRes);
return OK;
}
if (mGrallocVersion < HARDWARE_DEVICE_API_VERSION(1,0)) {
- StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetId);
+ StreamSet& streamSet = mStreamSetMap.editValueFor(streamSetKey);
BufferCountMap& handOutBufferCounts = streamSet.handoutBufferCountMap;
size_t& totalHandoutCount = handOutBufferCounts.editValueFor(streamId);
BufferCountMap& attachedBufferCounts = streamSet.attachedBufferCountMap;
@@ -427,8 +440,9 @@
totalHandoutCount -= count;
totalAttachedCount -= count;
- ALOGV("%s: Stream %d set %d: Buffer count now %zu, attached buffer count now %zu",
- __FUNCTION__, streamId, streamSetId, totalHandoutCount, totalAttachedCount);
+ ALOGV("%s: Stream %d set %d(%d): Buffer count now %zu, attached buffer count now %zu",
+ __FUNCTION__, streamId, streamSetId, isMultiRes, totalHandoutCount,
+ totalAttachedCount);
} else {
// TODO: implement gralloc V1 support
return BAD_VALUE;
@@ -444,7 +458,8 @@
String8 lines;
lines.appendFormat(" Total stream sets: %zu\n", mStreamSetMap.size());
for (size_t i = 0; i < mStreamSetMap.size(); i++) {
- lines.appendFormat(" Stream set %d has below streams:\n", mStreamSetMap.keyAt(i));
+ lines.appendFormat(" Stream set %d(%d) has below streams:\n",
+ mStreamSetMap.keyAt(i).id, mStreamSetMap.keyAt(i).isMultiRes);
for (size_t j = 0; j < mStreamSetMap[i].streamInfoMap.size(); j++) {
lines.appendFormat(" Stream %d\n", mStreamSetMap[i].streamInfoMap[j].streamId);
}
@@ -470,11 +485,12 @@
write(fd, lines.string(), lines.size());
}
-bool Camera3BufferManager::checkIfStreamRegisteredLocked(int streamId, int streamSetId) const {
- ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetId);
+bool Camera3BufferManager::checkIfStreamRegisteredLocked(int streamId,
+ StreamSetKey streamSetKey) const {
+ ssize_t setIdx = mStreamSetMap.indexOfKey(streamSetKey);
if (setIdx == NAME_NOT_FOUND) {
- ALOGV("%s: stream set %d is not registered to stream set map yet!",
- __FUNCTION__, streamSetId);
+ ALOGV("%s: stream set %d(%d) is not registered to stream set map yet!",
+ __FUNCTION__, streamSetKey.id, streamSetKey.isMultiRes);
return false;
}
@@ -486,9 +502,10 @@
size_t bufferWaterMark = mStreamSetMap[setIdx].maxAllowedBufferCount;
if (bufferWaterMark == 0 || bufferWaterMark > kMaxBufferCount) {
- ALOGW("%s: stream %d with stream set %d is not registered correctly to stream set map,"
+ ALOGW("%s: stream %d with stream set %d(%d) is not registered correctly to stream set map,"
" as the water mark (%zu) is wrong!",
- __FUNCTION__, streamId, streamSetId, bufferWaterMark);
+ __FUNCTION__, streamId, streamSetKey.id, streamSetKey.isMultiRes,
+ bufferWaterMark);
return false;
}
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.h b/services/camera/libcameraservice/device3/Camera3BufferManager.h
index f0de1c1..64aaa230 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.h
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.h
@@ -99,7 +99,7 @@
* combination doesn't match what was registered, or this stream wasn't registered
* to this buffer manager before.
*/
- status_t unregisterStream(int streamId, int streamSetId);
+ status_t unregisterStream(int streamId, int streamSetId, bool isMultiRes);
/**
* This method obtains a buffer for a stream from this buffer manager.
@@ -127,8 +127,8 @@
* NO_MEMORY: Unable to allocate a buffer for this stream at this time.
*/
status_t getBufferForStream(
- int streamId, int streamSetId, sp<GraphicBuffer>* gb, int* fenceFd,
- bool noFreeBufferAtConsumer = false);
+ int streamId, int streamSetId, bool isMultiRes, sp<GraphicBuffer>* gb,
+ int* fenceFd, bool noFreeBufferAtConsumer = false);
/**
* This method notifies the manager that a buffer has been released by the consumer.
@@ -153,7 +153,8 @@
* combination doesn't match what was registered, or this stream wasn't registered
* to this buffer manager before, or shouldFreeBuffer is null/
*/
- status_t onBufferReleased(int streamId, int streamSetId, /*out*/bool* shouldFreeBuffer);
+ status_t onBufferReleased(int streamId, int streamSetId, bool isMultiRes,
+ /*out*/bool* shouldFreeBuffer);
/**
* This method notifies the manager that certain buffers has been removed from the
@@ -171,13 +172,13 @@
* to this buffer manager before, or the removed buffer count is larger than
* current total handoutCount or attachedCount.
*/
- status_t onBuffersRemoved(int streamId, int streamSetId, size_t count);
+ status_t onBuffersRemoved(int streamId, int streamSetId, bool isMultiRes, size_t count);
/**
* This method notifiers the manager that a buffer is freed from the buffer queue, usually
* because onBufferReleased signals the caller to free a buffer via the shouldFreeBuffer flag.
*/
- void notifyBufferRemoved(int streamId, int streamSetId);
+ void notifyBufferRemoved(int streamId, int streamSetId, bool isMultiRes);
/**
* Dump the buffer manager statistics.
@@ -292,8 +293,20 @@
/**
* Stream set map managed by this buffer manager.
*/
- typedef int StreamSetId;
- KeyedVector<StreamSetId, StreamSet> mStreamSetMap;
+ struct StreamSetKey {
+ // The stream set ID
+ int id;
+ // Whether this stream set is for multi-resolution output streams. It's
+ // valid for 2 stream sets to have the same stream set ID if: one is for
+ // multi-resolution output stream, and the other one is not.
+ bool isMultiRes;
+
+ inline bool operator<(const StreamSetKey& other) const {
+ return (isMultiRes < other.isMultiRes) ||
+ ((isMultiRes == other.isMultiRes) && (id < other.id));
+ }
+ };
+ KeyedVector<StreamSetKey, StreamSet> mStreamSetMap;
KeyedVector<StreamId, wp<Camera3OutputStream>> mStreamMap;
// TODO: There is no easy way to query the Gralloc version in this code yet, we have different
@@ -304,13 +317,13 @@
* Check if this stream was successfully registered already. This method needs to be called with
* mLock held.
*/
- bool checkIfStreamRegisteredLocked(int streamId, int streamSetId) const;
+ bool checkIfStreamRegisteredLocked(int streamId, StreamSetKey streamSetKey) const;
/**
* Check if other streams in the stream set has extra buffer available to be freed, and
* free one if so.
*/
- status_t checkAndFreeBufferOnOtherStreamsLocked(int streamId, int streamSetId);
+ status_t checkAndFreeBufferOnOtherStreamsLocked(int streamId, StreamSetKey streamSetKey);
};
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 73a133f..18eb57e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -313,6 +313,7 @@
mFakeStreamId = NO_STREAM;
mNeedConfig = true;
mPauseStateNotify = false;
+ mIsInputStreamMultiResolution = false;
// Measure the clock domain offset between camera and video/hw_composer
camera_metadata_entry timestampSource =
@@ -481,7 +482,7 @@
return gotLock;
}
-Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
+camera3::Size Camera3Device::getMaxJpegResolution() const {
int32_t maxJpegWidth = 0, maxJpegHeight = 0;
const int STREAM_CONFIGURATION_SIZE = 4;
const int STREAM_FORMAT_OFFSET = 0;
@@ -492,7 +493,7 @@
mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
if (availableStreamConfigs.count == 0 ||
availableStreamConfigs.count % STREAM_CONFIGURATION_SIZE != 0) {
- return Size(0, 0);
+ return camera3::Size(0, 0);
}
// Get max jpeg size (area-wise).
@@ -509,7 +510,7 @@
}
}
- return Size(maxJpegWidth, maxJpegHeight);
+ return camera3::Size(maxJpegWidth, maxJpegHeight);
}
nsecs_t Camera3Device::getMonoToBoottimeOffset() {
@@ -603,7 +604,7 @@
ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
// Get max jpeg size (area-wise).
- Size maxJpegResolution = getMaxJpegResolution();
+ camera3::Size maxJpegResolution = getMaxJpegResolution();
if (maxJpegResolution.width == 0) {
ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
__FUNCTION__, mId.string());
@@ -1252,7 +1253,7 @@
}
status_t Camera3Device::createInputStream(
- uint32_t width, uint32_t height, int format, int *id) {
+ uint32_t width, uint32_t height, int format, bool isMultiResolution, int *id) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
@@ -1299,6 +1300,7 @@
newStream->setStatusTracker(mStatusTracker);
mInputStream = newStream;
+ mIsInputStreamMultiResolution = isMultiResolution;
*id = mNextStreamId++;
@@ -1323,7 +1325,8 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
- std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared,
+ bool isMultiResolution, uint64_t consumerUsage) {
ATRACE_CALL();
if (consumer == nullptr) {
@@ -1336,23 +1339,24 @@
return createStream(consumers, /*hasDeferredConsumer*/ false, width, height,
format, dataSpace, rotation, id, physicalCameraId, surfaceIds, streamSetId,
- isShared, consumerUsage);
+ isShared, isMultiResolution, consumerUsage);
}
status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
- std::vector<int> *surfaceIds, int streamSetId, bool isShared, uint64_t consumerUsage) {
+ std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
+ uint64_t consumerUsage) {
ATRACE_CALL();
Mutex::Autolock il(mInterfaceLock);
nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
Mutex::Autolock l(mLock);
ALOGV("Camera %s: Creating new stream %d: %d x %d, format %d, dataspace %d rotation %d"
- " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s", mId.string(),
- mNextStreamId, width, height, format, dataSpace, rotation, consumerUsage, isShared,
- physicalCameraId.string());
+ " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d",
+ mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
+ consumerUsage, isShared, physicalCameraId.string(), isMultiResolution);
status_t res;
bool wasActive = false;
@@ -1414,7 +1418,7 @@
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, blobBufferSize, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
} else if (format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
ssize_t rawOpaqueBufferSize = getRawOpaqueBufferSize(width, height);
if (rawOpaqueBufferSize <= 0) {
@@ -1423,20 +1427,19 @@
}
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, rawOpaqueBufferSize, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
} else if (isShared) {
newStream = new Camera3SharedOutputStream(mNextStreamId, consumers,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId,
- mUseHalBufManager);
+ mTimestampOffset, physicalCameraId, streamSetId, mUseHalBufManager);
} else if (consumers.size() == 0 && hasDeferredConsumer) {
newStream = new Camera3OutputStream(mNextStreamId,
width, height, format, consumerUsage, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
} else {
newStream = new Camera3OutputStream(mNextStreamId, consumers[0],
width, height, format, dataSpace, rotation,
- mTimestampOffset, physicalCameraId, streamSetId);
+ mTimestampOffset, physicalCameraId, streamSetId, isMultiResolution);
}
size_t consumerCount = consumers.size();
@@ -2549,8 +2552,9 @@
if (mInputStream != NULL && notifyRequestThread) {
while (true) {
camera_stream_buffer_t inputBuffer;
+ camera3::Size inputBufferSize;
status_t res = mInputStream->getInputBuffer(&inputBuffer,
- /*respectHalLimit*/ false);
+ &inputBufferSize, /*respectHalLimit*/ false);
if (res != OK) {
// Exhausted acquiring all input buffers.
break;
@@ -2587,6 +2591,7 @@
camera_stream_configuration config;
config.operation_mode = mOperatingMode;
config.num_streams = (mInputStream != NULL) + mOutputStreams.size();
+ config.input_is_multi_resolution = false;
Vector<camera3::camera_stream_t*> streams;
streams.setCapacity(config.num_streams);
@@ -2602,6 +2607,8 @@
return INVALID_OPERATION;
}
streams.add(inputStream);
+
+ config.input_is_multi_resolution = mIsInputStreamMultiResolution;
}
for (size_t i = 0; i < mOutputStreams.size(); i++) {
@@ -2999,6 +3006,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_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ mHidlSession_3_7 = castResult_3_7;
+ }
auto castResult_3_6 = device::V3_6::ICameraDeviceSession::castFrom(mHidlSession);
if (castResult_3_6.isOk()) {
mHidlSession_3_6 = castResult_3_6;
@@ -3032,6 +3043,7 @@
}
void Camera3Device::HalInterface::clear() {
+ mHidlSession_3_7.clear();
mHidlSession_3_6.clear();
mHidlSession_3_5.clear();
mHidlSession_3_4.clear();
@@ -3158,15 +3170,23 @@
if (!valid()) return INVALID_OPERATION;
status_t res = OK;
+ if (config->input_is_multi_resolution && mHidlSession_3_7 == nullptr) {
+ ALOGE("%s: Camera device doesn't support multi-resolution input stream", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
// Convert stream config to HIDL
std::set<int> activeStreams;
device::V3_2::StreamConfiguration requestedConfiguration3_2;
device::V3_4::StreamConfiguration requestedConfiguration3_4;
+ device::V3_7::StreamConfiguration requestedConfiguration3_7;
requestedConfiguration3_2.streams.resize(config->num_streams);
requestedConfiguration3_4.streams.resize(config->num_streams);
+ requestedConfiguration3_7.streams.resize(config->num_streams);
for (size_t i = 0; i < config->num_streams; i++) {
device::V3_2::Stream &dst3_2 = requestedConfiguration3_2.streams[i];
device::V3_4::Stream &dst3_4 = requestedConfiguration3_4.streams[i];
+ device::V3_7::Stream &dst3_7 = requestedConfiguration3_7.streams[i];
camera3::camera_stream_t *src = config->streams[i];
Camera3Stream* cam3stream = Camera3Stream::cast(src);
@@ -3207,6 +3227,8 @@
if (src->physical_camera_id != nullptr) {
dst3_4.physicalCameraId = src->physical_camera_id;
}
+ dst3_7.v3_4 = dst3_4;
+ dst3_7.groupId = cam3stream->getHalStreamGroupId();
activeStreams.insert(streamId);
// Create Buffer ID map if necessary
@@ -3227,6 +3249,10 @@
requestedConfiguration3_4.sessionParams.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
get_camera_metadata_size(sessionParams));
+ requestedConfiguration3_7.operationMode = operationMode;
+ requestedConfiguration3_7.sessionParams.setToExternal(
+ reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
+ get_camera_metadata_size(sessionParams));
// Invoke configureStreams
device::V3_3::HalStreamConfiguration finalConfiguration;
@@ -3273,7 +3299,17 @@
};
// See which version of HAL we have
- if (mHidlSession_3_6 != nullptr) {
+ if (mHidlSession_3_7 != nullptr) {
+ ALOGV("%s: v3.7 device found", __FUNCTION__);
+ requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
+ requestedConfiguration3_7.multiResolutionInputImage = config->input_is_multi_resolution;
+ auto err = mHidlSession_3_7->configureStreams_3_7(
+ requestedConfiguration3_7, configStream36Cb);
+ res = postprocConfigStream36(err);
+ if (res != OK) {
+ return res;
+ }
+ } else if (mHidlSession_3_6 != nullptr) {
ALOGV("%s: v3.6 device found", __FUNCTION__);
device::V3_5::StreamConfiguration requestedConfiguration3_5;
requestedConfiguration3_5.v3_4 = requestedConfiguration3_4;
@@ -3531,6 +3567,11 @@
if (!valid()) return INVALID_OPERATION;
sp<device::V3_4::ICameraDeviceSession> hidlSession_3_4;
+ sp<device::V3_7::ICameraDeviceSession> hidlSession_3_7;
+ auto castResult_3_7 = device::V3_7::ICameraDeviceSession::castFrom(mHidlSession);
+ if (castResult_3_7.isOk()) {
+ hidlSession_3_7 = castResult_3_7;
+ }
auto castResult_3_4 = device::V3_4::ICameraDeviceSession::castFrom(mHidlSession);
if (castResult_3_4.isOk()) {
hidlSession_3_4 = castResult_3_4;
@@ -3538,8 +3579,11 @@
hardware::hidl_vec<device::V3_2::CaptureRequest> captureRequests;
hardware::hidl_vec<device::V3_4::CaptureRequest> captureRequests_3_4;
+ hardware::hidl_vec<device::V3_7::CaptureRequest> captureRequests_3_7;
size_t batchSize = requests.size();
- if (hidlSession_3_4 != nullptr) {
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7.resize(batchSize);
+ } else if (hidlSession_3_4 != nullptr) {
captureRequests_3_4.resize(batchSize);
} else {
captureRequests.resize(batchSize);
@@ -3549,7 +3593,10 @@
status_t res = OK;
for (size_t i = 0; i < batchSize; i++) {
- if (hidlSession_3_4 != nullptr) {
+ if (hidlSession_3_7 != nullptr) {
+ res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_7[i].v3_4.v3_2,
+ /*out*/&handlesCreated, /*out*/&inflightBuffers);
+ } else if (hidlSession_3_4 != nullptr) {
res = wrapAsHidlRequest(requests[i], /*out*/&captureRequests_3_4[i].v3_2,
/*out*/&handlesCreated, /*out*/&inflightBuffers);
} else {
@@ -3582,7 +3629,9 @@
for (size_t i = 0; i < batchSize; i++) {
camera_capture_request_t* request = requests[i];
device::V3_2::CaptureRequest* captureRequest;
- if (hidlSession_3_4 != nullptr) {
+ if (hidlSession_3_7 != nullptr) {
+ captureRequest = &captureRequests_3_7[i].v3_4.v3_2;
+ } else if (hidlSession_3_4 != nullptr) {
captureRequest = &captureRequests_3_4[i].v3_2;
} else {
captureRequest = &captureRequests[i];
@@ -3609,33 +3658,42 @@
captureRequest->fmqSettingsSize = 0u;
}
- if (hidlSession_3_4 != nullptr) {
- captureRequests_3_4[i].physicalCameraSettings.resize(request->num_physcam_settings);
+ // hidl session 3.7 specific handling.
+ if (hidlSession_3_7 != nullptr) {
+ captureRequests_3_7[i].inputWidth = request->input_width;
+ captureRequests_3_7[i].inputHeight = request->input_height;
+ }
+
+ // hidl session 3.7 and 3.4 specific handling.
+ if (hidlSession_3_7 != nullptr || hidlSession_3_4 != nullptr) {
+ hardware::hidl_vec<device::V3_4::PhysicalCameraSetting>& physicalCameraSettings =
+ (hidlSession_3_7 != nullptr) ?
+ captureRequests_3_7[i].v3_4.physicalCameraSettings :
+ captureRequests_3_4[i].physicalCameraSettings;
+ physicalCameraSettings.resize(request->num_physcam_settings);
for (size_t j = 0; j < request->num_physcam_settings; j++) {
if (request->physcam_settings != nullptr) {
size_t settingsSize = get_camera_metadata_size(request->physcam_settings[j]);
if (mRequestMetadataQueue != nullptr && mRequestMetadataQueue->write(
reinterpret_cast<const uint8_t*>(request->physcam_settings[j]),
settingsSize)) {
- captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
- captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize =
- settingsSize;
+ physicalCameraSettings[j].settings.resize(0);
+ physicalCameraSettings[j].fmqSettingsSize = settingsSize;
} else {
if (mRequestMetadataQueue != nullptr) {
ALOGW("%s: couldn't utilize fmq, fallback to hwbinder", __FUNCTION__);
}
- captureRequests_3_4[i].physicalCameraSettings[j].settings.setToExternal(
+ physicalCameraSettings[j].settings.setToExternal(
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(
request->physcam_settings[j])),
get_camera_metadata_size(request->physcam_settings[j]));
- captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
+ physicalCameraSettings[j].fmqSettingsSize = 0u;
}
} else {
captureRequests_3_4[i].physicalCameraSettings[j].fmqSettingsSize = 0u;
captureRequests_3_4[i].physicalCameraSettings[j].settings.resize(0);
}
- captureRequests_3_4[i].physicalCameraSettings[j].physicalCameraId =
- request->physcam_id[j];
+ physicalCameraSettings[j].physicalCameraId = request->physcam_id[j];
}
}
}
@@ -3646,7 +3704,10 @@
status = s;
*numRequestProcessed = n;
};
- if (hidlSession_3_4 != nullptr) {
+ if (hidlSession_3_7 != nullptr) {
+ err = hidlSession_3_7->processCaptureRequest_3_7(captureRequests_3_7, cachesToRemove,
+ resultCallback);
+ } else if (hidlSession_3_4 != nullptr) {
err = hidlSession_3_4->processCaptureRequest_3_4(captureRequests_3_4, cachesToRemove,
resultCallback);
} else {
@@ -4055,8 +4116,9 @@
// Abort the input buffers for reprocess requests.
if ((*it)->mInputStream != NULL) {
camera_stream_buffer_t inputBuffer;
+ camera3::Size inputBufferSize;
status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer,
- /*respectHalLimit*/ false);
+ &inputBufferSize, /*respectHalLimit*/ false);
if (res != OK) {
ALOGW("%s: %d: couldn't get input buffer while clearing the request "
"list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
@@ -4262,33 +4324,34 @@
void Camera3Device::RequestThread::updateNextRequest(NextRequest& nextRequest) {
// Update the latest request sent to HAL
- if (nextRequest.halRequest.settings != NULL) { // Don't update if they were unchanged
+ camera_capture_request_t& halRequest = nextRequest.halRequest;
+ if (halRequest.settings != NULL) { // Don't update if they were unchanged
Mutex::Autolock al(mLatestRequestMutex);
- camera_metadata_t* cloned = clone_camera_metadata(nextRequest.halRequest.settings);
+ camera_metadata_t* cloned = clone_camera_metadata(halRequest.settings);
mLatestRequest.acquire(cloned);
mLatestPhysicalRequest.clear();
- for (uint32_t i = 0; i < nextRequest.halRequest.num_physcam_settings; i++) {
- cloned = clone_camera_metadata(nextRequest.halRequest.physcam_settings[i]);
- mLatestPhysicalRequest.emplace(nextRequest.halRequest.physcam_id[i],
+ for (uint32_t i = 0; i < halRequest.num_physcam_settings; i++) {
+ cloned = clone_camera_metadata(halRequest.physcam_settings[i]);
+ mLatestPhysicalRequest.emplace(halRequest.physcam_id[i],
CameraMetadata(cloned));
}
sp<Camera3Device> parent = mParent.promote();
if (parent != NULL) {
parent->monitorMetadata(TagMonitor::REQUEST,
- nextRequest.halRequest.frame_number,
+ halRequest.frame_number,
0, mLatestRequest, mLatestPhysicalRequest);
}
}
- if (nextRequest.halRequest.settings != NULL) {
+ if (halRequest.settings != NULL) {
nextRequest.captureRequest->mSettingsList.begin()->metadata.unlock(
- nextRequest.halRequest.settings);
+ halRequest.settings);
}
- cleanupPhysicalSettings(nextRequest.captureRequest, &nextRequest.halRequest);
+ cleanupPhysicalSettings(nextRequest.captureRequest, &halRequest);
}
bool Camera3Device::RequestThread::updateSessionParameters(const CameraMetadata& settings) {
@@ -4651,6 +4714,9 @@
// Fill in buffers
if (captureRequest->mInputStream != NULL) {
halRequest->input_buffer = &captureRequest->mInputBuffer;
+
+ halRequest->input_width = captureRequest->mInputBufferSize.width;
+ halRequest->input_height = captureRequest->mInputBufferSize.height;
totalNumBuffers += 1;
} else {
halRequest->input_buffer = NULL;
@@ -4754,13 +4820,7 @@
}
String8 physicalCameraId = outputStream->getPhysicalCameraId();
-
if (!physicalCameraId.isEmpty()) {
- // Physical stream isn't supported for input request.
- if (halRequest->input_buffer) {
- CLOGE("Physical stream is not supported for input request");
- return INVALID_OPERATION;
- }
requestedPhysicalCameras.insert(physicalCameraId);
}
halRequest->num_output_buffers++;
@@ -5237,7 +5297,8 @@
// Since RequestThread::clear() removes buffers from the input stream,
// get the right buffer here before unlocking mRequestLock
if (nextRequest->mInputStream != NULL) {
- res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
+ res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer,
+ &nextRequest->mInputBufferSize);
if (res != OK) {
// Can't get input buffer from gralloc queue - this could be due to
// disconnected queue or other producer misbehavior, so not a fatal
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 09fa30a..018dbe5 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -35,6 +35,7 @@
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.2/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
@@ -52,6 +53,7 @@
#include "device3/InFlightRequest.h"
#include "device3/Camera3OutputInterface.h"
#include "device3/Camera3OfflineSession.h"
+#include "device3/Camera3StreamInterface.h"
#include "utils/TagMonitor.h"
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
@@ -71,7 +73,6 @@
class Camera3Stream;
class Camera3ZslStream;
-class Camera3OutputStreamInterface;
class Camera3StreamInterface;
} // namespace camera3
@@ -133,17 +134,19 @@
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint64_t consumerUsage = 0) override;
+ bool isShared = false, bool isMultiResolution = false,
+ uint64_t consumerUsage = 0) override;
status_t createStream(const std::vector<sp<Surface>>& consumers,
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
const String8& physicalCameraId,
std::vector<int> *surfaceIds = nullptr,
int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
- bool isShared = false, uint64_t consumerUsage = 0) override;
+ bool isShared = false, bool isMultiResolution = false,
+ uint64_t consumerUsage = 0) override;
status_t createInputStream(
- uint32_t width, uint32_t height, int format,
+ uint32_t width, uint32_t height, int format, bool isMultiResolution,
int *id) override;
status_t getStreamInfo(int id, StreamInfo *streamInfo) override;
@@ -418,6 +421,8 @@
sp<hardware::camera::device::V3_5::ICameraDeviceSession> mHidlSession_3_5;
// Valid if ICameraDeviceSession is @3.6 or newer
sp<hardware::camera::device::V3_6::ICameraDeviceSession> mHidlSession_3_6;
+ // Valid if ICameraDeviceSession is @3.7 or newer
+ sp<hardware::camera::device::V3_7::ICameraDeviceSession> mHidlSession_3_7;
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
@@ -490,6 +495,7 @@
camera3::StreamSet mOutputStreams;
sp<camera3::Camera3Stream> mInputStream;
+ bool mIsInputStreamMultiResolution;
SessionStatsBuilder mSessionStatsBuilder;
int mNextStreamId;
@@ -523,6 +529,7 @@
PhysicalCameraSettingsList mSettingsList;
sp<camera3::Camera3Stream> mInputStream;
camera_stream_buffer_t mInputBuffer;
+ camera3::Size mInputBufferSize;
Vector<sp<camera3::Camera3OutputStreamInterface> >
mOutputStreams;
SurfaceMap mOutputSurfaces;
@@ -748,7 +755,7 @@
* Helper function to get the largest Jpeg resolution (in area)
* Return Size(0, 0) if static metatdata is invalid
*/
- Size getMaxJpegResolution() const;
+ camera3::Size getMaxJpegResolution() const;
/**
* Helper function to get the offset between MONOTONIC and BOOTTIME
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index f6acda8..a837900 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -32,10 +32,10 @@
Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId) :
+ const String8& physicalCameraId, int setId, bool isMultiResolution) :
Camera3Stream(id, type,
width, height, maxSize, format, dataSpace, rotation,
- physicalCameraId, setId),
+ physicalCameraId, setId, isMultiResolution),
mTotalBufferCount(0),
mHandoutTotalBufferCount(0),
mHandoutOutputBufferCount(0),
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 719fa14..2e744ee 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -36,7 +36,7 @@
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
- int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
public:
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index ad70a3a..b00a963 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -46,10 +46,14 @@
}
status_t Camera3InputStream::getInputBufferLocked(
- camera_stream_buffer *buffer) {
+ camera_stream_buffer *buffer, Size *size) {
ATRACE_CALL();
status_t res;
+ if (size == nullptr) {
+ ALOGE("%s: size must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
// FIXME: will not work in (re-)registration
if (mState == STATE_IN_CONFIG || mState == STATE_IN_RECONFIG) {
ALOGE("%s: Stream %d: Buffer registration for input streams"
@@ -77,10 +81,12 @@
return res;
}
+ size->width = bufferItem.mGraphicBuffer->getWidth();
+ size->height = bufferItem.mGraphicBuffer->getHeight();
+
anb = bufferItem.mGraphicBuffer->getNativeBuffer();
assert(anb != NULL);
fenceFd = bufferItem.mFence->dup();
-
/**
* FenceFD now owned by HAL except in case of error,
* in which case we reassign it to acquire_fence
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 03afa17..46221d1 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -70,7 +70,7 @@
* Camera3Stream interface
*/
- virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
+ virtual status_t getInputBufferLocked(camera_stream_buffer *buffer, Size *size);
virtual status_t returnInputBufferLocked(
const camera_stream_buffer &buffer);
virtual status_t getInputBufferProducerLocked(
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index c835f51..3ec3b6b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -44,10 +44,10 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
- int setId) :
+ int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, setId),
+ physicalCameraId, setId, isMultiResolution),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -70,9 +70,11 @@
sp<Surface> consumer,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- nsecs_t timestampOffset, const String8& physicalCameraId, int setId) :
+ nsecs_t timestampOffset, const String8& physicalCameraId, int setId,
+ bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height, maxSize,
- format, dataSpace, rotation, physicalCameraId, setId),
+ format, dataSpace, rotation, physicalCameraId, setId,
+ isMultiResolution),
mConsumer(consumer),
mTransform(0),
mTraceFirstBuffer(true),
@@ -102,10 +104,10 @@
uint32_t width, uint32_t height, int format,
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
- const String8& physicalCameraId, int setId) :
+ const String8& physicalCameraId, int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, width, height,
/*maxSize*/0, format, dataSpace, rotation,
- physicalCameraId, setId),
+ physicalCameraId, setId, isMultiResolution),
mConsumer(nullptr),
mTransform(0),
mTraceFirstBuffer(true),
@@ -141,11 +143,11 @@
camera_stream_rotation_t rotation,
const String8& physicalCameraId,
uint64_t consumerUsage, nsecs_t timestampOffset,
- int setId) :
+ int setId, bool isMultiResolution) :
Camera3IOStreamBase(id, type, width, height,
/*maxSize*/0,
format, dataSpace, rotation,
- physicalCameraId, setId),
+ physicalCameraId, setId, isMultiResolution),
mTransform(0),
mTraceFirstBuffer(true),
mUseMonoTimestamp(false),
@@ -570,10 +572,12 @@
!(isConsumedByHWComposer() || isConsumedByHWTexture())) {
uint64_t consumerUsage = 0;
getEndpointUsage(&consumerUsage);
+ uint32_t width = (mMaxSize == 0) ? getWidth() : mMaxSize;
+ uint32_t height = (mMaxSize == 0) ? getHeight() : 1;
StreamInfo streamInfo(
- getId(), getStreamSetId(), getWidth(), getHeight(), getFormat(), getDataSpace(),
+ getId(), getStreamSetId(), width, height, getFormat(), getDataSpace(),
mUsage | consumerUsage, mTotalBufferCount,
- /*isConfigured*/true);
+ /*isConfigured*/true, isMultiResolution());
wp<Camera3OutputStream> weakThis(this);
res = mBufferManager->registerStream(weakThis,
streamInfo);
@@ -604,7 +608,8 @@
if (mUseBufferManager) {
sp<GraphicBuffer> gb;
- res = mBufferManager->getBufferForStream(getId(), getStreamSetId(), &gb, fenceFd);
+ res = mBufferManager->getBufferForStream(getId(), getStreamSetId(),
+ isMultiResolution(), &gb, fenceFd);
if (res == OK) {
// Attach this buffer to the bufferQueue: the buffer will be in dequeue state after a
// successful return.
@@ -693,7 +698,8 @@
sp<GraphicBuffer> gb;
res = mBufferManager->getBufferForStream(
- getId(), getStreamSetId(), &gb, fenceFd, /*noFreeBuffer*/true);
+ getId(), getStreamSetId(), isMultiResolution(),
+ &gb, fenceFd, /*noFreeBuffer*/true);
if (res == OK) {
// Attach this buffer to the bufferQueue: the buffer will be in dequeue state after
@@ -740,7 +746,8 @@
onBuffersRemovedLocked(removedBuffers);
if (notifyBufferManager && mUseBufferManager && removedBuffers.size() > 0) {
- mBufferManager->onBuffersRemoved(getId(), getStreamSetId(), removedBuffers.size());
+ mBufferManager->onBuffersRemoved(getId(), getStreamSetId(), isMultiResolution(),
+ removedBuffers.size());
}
}
}
@@ -802,7 +809,7 @@
// Since device is already idle, there is no getBuffer call to buffer manager, unregister the
// stream at this point should be safe.
if (mUseBufferManager) {
- res = mBufferManager->unregisterStream(getId(), getStreamSetId());
+ res = mBufferManager->unregisterStream(getId(), getStreamSetId(), isMultiResolution());
if (res != OK) {
ALOGE("%s: Unable to unregister stream %d from buffer manager "
"(error %d %s)", __FUNCTION__, mId, res, strerror(-res));
@@ -914,7 +921,8 @@
ALOGV("Stream %d: Buffer released", stream->getId());
bool shouldFreeBuffer = false;
status_t res = stream->mBufferManager->onBufferReleased(
- stream->getId(), stream->getStreamSetId(), &shouldFreeBuffer);
+ stream->getId(), stream->getStreamSetId(), stream->isMultiResolution(),
+ &shouldFreeBuffer);
if (res != OK) {
ALOGE("%s: signaling buffer release to buffer manager failed: %s (%d).", __FUNCTION__,
strerror(-res), res);
@@ -927,7 +935,7 @@
stream->detachBufferLocked(&buffer, /*fenceFd*/ nullptr);
if (buffer.get() != nullptr) {
stream->mBufferManager->notifyBufferRemoved(
- stream->getId(), stream->getStreamSetId());
+ stream->getId(), stream->getStreamSetId(), stream->isMultiResolution());
}
}
}
@@ -945,7 +953,7 @@
stream->onBuffersRemovedLocked(buffers);
if (stream->mUseBufferManager) {
stream->mBufferManager->onBuffersRemoved(stream->getId(),
- stream->getStreamSetId(), buffers.size());
+ stream->getStreamSetId(), stream->isMultiResolution(), buffers.size());
}
ALOGV("Stream %d: %zu Buffers discarded.", stream->getId(), buffers.size());
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 366d22a..c82f2a6 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -48,6 +48,7 @@
uint64_t combinedUsage;
size_t totalBufferCount;
bool isConfigured;
+ bool isMultiRes;
explicit StreamInfo(int id = CAMERA3_STREAM_ID_INVALID,
int setId = CAMERA3_STREAM_SET_ID_INVALID,
uint32_t w = 0,
@@ -56,7 +57,8 @@
android_dataspace ds = HAL_DATASPACE_UNKNOWN,
uint64_t usage = 0,
size_t bufferCount = 0,
- bool configured = false) :
+ bool configured = false,
+ bool multiRes = false) :
streamId(id),
streamSetId(setId),
width(w),
@@ -65,7 +67,8 @@
dataSpace(ds),
combinedUsage(usage),
totalBufferCount(bufferCount),
- isConfigured(configured){}
+ isConfigured(configured),
+ isMultiRes(multiRes) {}
};
/**
@@ -84,7 +87,7 @@
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
- int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
/**
* Set up a stream for formats that have a variable buffer size for the same
@@ -96,7 +99,7 @@
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
- int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
/**
* Set up a stream with deferred consumer for formats that have 2 dimensions, such as
@@ -107,7 +110,7 @@
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
- int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
virtual ~Camera3OutputStream();
@@ -232,7 +235,7 @@
android_dataspace dataSpace, camera_stream_rotation_t rotation,
const String8& physicalCameraId,
uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
- int setId = CAMERA3_STREAM_SET_ID_INVALID);
+ int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false);
/**
* Note that we release the lock briefly in this function
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index 772fe6e..142889a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -46,6 +46,7 @@
uint32_t num_streams;
camera_stream_t **streams;
uint32_t operation_mode;
+ bool input_is_multi_resolution;
} camera_stream_configuration_t;
typedef struct camera_capture_request {
@@ -57,6 +58,8 @@
uint32_t num_physcam_settings;
const char **physcam_id;
const camera_metadata_t **physcam_settings;
+ int32_t input_width;
+ int32_t input_height;
} camera_capture_request_t;
typedef struct camera_capture_result {
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 4cb954e..c6e7002 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -49,7 +49,7 @@
camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId) :
+ const String8& physicalCameraId, int setId, bool isMultiResolution) :
camera_stream(),
mId(id),
mSetId(setId),
@@ -73,7 +73,8 @@
mDataSpaceOverridden(false),
mOriginalDataSpace(dataSpace),
mPhysicalCameraId(physicalCameraId),
- mLastTimestamp(0) {
+ mLastTimestamp(0),
+ mIsMultiResolution(isMultiResolution) {
camera_stream::stream_type = type;
camera_stream::width = width;
@@ -99,6 +100,14 @@
return mSetId;
}
+int Camera3Stream::getHalStreamGroupId() const {
+ return mIsMultiResolution ? mSetId : -1;
+}
+
+bool Camera3Stream::isMultiResolution() const {
+ return mIsMultiResolution;
+}
+
uint32_t Camera3Stream::getWidth() const {
return camera_stream::width;
}
@@ -743,11 +752,16 @@
return res;
}
-status_t Camera3Stream::getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit) {
+status_t Camera3Stream::getInputBuffer(camera_stream_buffer *buffer,
+ Size* size, bool respectHalLimit) {
ATRACE_CALL();
Mutex::Autolock l(mLock);
status_t res = OK;
+ if (size == nullptr) {
+ ALOGE("%s: size must not be null", __FUNCTION__);
+ return BAD_VALUE;
+ }
// This function should be only called when the stream is configured already.
if (mState != STATE_CONFIGURED) {
ALOGE("%s: Stream %d: Can't get input buffers if stream is not in CONFIGURED state %d",
@@ -769,7 +783,7 @@
}
}
- res = getInputBufferLocked(buffer);
+ res = getInputBufferLocked(buffer, size);
if (res == OK) {
fireBufferListenersLocked(*buffer, /*acquired*/true, /*output*/false);
if (buffer->buffer) {
@@ -918,7 +932,7 @@
ALOGE("%s: This type of stream does not support output", __FUNCTION__);
return INVALID_OPERATION;
}
-status_t Camera3Stream::getInputBufferLocked(camera_stream_buffer *) {
+status_t Camera3Stream::getInputBufferLocked(camera_stream_buffer *, Size *) {
ALOGE("%s: This type of stream does not support input", __FUNCTION__);
return INVALID_OPERATION;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 55ed2f2..45d8478 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -147,6 +147,14 @@
* Get the output stream set id.
*/
int getStreamSetId() const;
+ /**
+ * Is this stream part of a multi-resolution stream set
+ */
+ bool isMultiResolution() const;
+ /**
+ * Get the HAL stream group id for a multi-resolution stream set
+ */
+ int getHalStreamGroupId() const;
/**
* Get the stream's dimensions and format
@@ -356,10 +364,13 @@
* For bidirectional streams, this method applies to the input-side
* buffers.
*
+ * This method also returns the size of the returned input buffer.
+ *
* Normally this call will block until the handed out buffer count is less than the stream
* max buffer count; if respectHalLimit is set to false, this is ignored.
*/
- status_t getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true);
+ status_t getInputBuffer(camera_stream_buffer *buffer,
+ Size* size, bool respectHalLimit = true);
/**
* Return a buffer to the stream after use by the HAL.
@@ -487,7 +498,7 @@
Camera3Stream(int id, camera_stream_type type,
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
- const String8& physicalCameraId, int setId);
+ const String8& physicalCameraId, int setId, bool isMultiResolution);
wp<Camera3StreamBufferFreedListener> mBufferFreedListener;
@@ -509,7 +520,7 @@
virtual status_t getBuffersLocked(std::vector<OutstandingBuffer>*);
- virtual status_t getInputBufferLocked(camera_stream_buffer *buffer);
+ virtual status_t getInputBufferLocked(camera_stream_buffer *buffer, Size* size);
virtual status_t returnInputBufferLocked(
const camera_stream_buffer &buffer);
@@ -608,6 +619,7 @@
String8 mPhysicalCameraId;
nsecs_t mLastTimestamp;
+ bool mIsMultiResolution = false;
bool mSupportOfflineProcessing = false;
}; // class Camera3Stream
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index c558b07..a567cb4 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -72,6 +72,12 @@
int release_fence;
} camera_stream_buffer_t;
+struct Size {
+ uint32_t width;
+ uint32_t height;
+ explicit Size(uint32_t w = 0, uint32_t h = 0) : width(w), height(h){}
+};
+
enum {
/**
* This stream set ID indicates that the set ID is invalid, and this stream doesn't intend to
@@ -352,7 +358,8 @@
* Normally this call will block until the handed out buffer count is less than the stream
* max buffer count; if respectHalLimit is set to false, this is ignored.
*/
- virtual status_t getInputBuffer(camera_stream_buffer *buffer, bool respectHalLimit = true) = 0;
+ virtual status_t getInputBuffer(camera_stream_buffer *buffer,
+ Size *size, bool respectHalLimit = true) = 0;
/**
* Return a buffer to the stream after use by the HAL.
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index df4ef95..c7d7c4b 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -18,6 +18,17 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_av_services_camera_libcameraservice_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_av_services_camera_libcameraservice_license",
+ ],
+}
+
cc_fuzz {
name: "camera_service_fuzzer",
srcs: [
@@ -39,12 +50,14 @@
"android.hardware.camera.provider@2.4",
"android.hardware.camera.provider@2.5",
"android.hardware.camera.provider@2.6",
+ "android.hardware.camera.provider@2.7",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
"android.hardware.camera.device@3.5",
"android.hardware.camera.device@3.6",
+ "android.hardware.camera.device@3.7",
],
fuzz_config: {
cc: [
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index b530342..0b5ad79 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -33,9 +33,11 @@
android.hardware.camera.provider@2.4 \
android.hardware.camera.provider@2.5 \
android.hardware.camera.provider@2.6 \
+ android.hardware.camera.provider@2.7 \
android.hardware.camera.device@1.0 \
android.hardware.camera.device@3.2 \
android.hardware.camera.device@3.4 \
+ android.hardware.camera.device@3.7 \
android.hidl.token@1.0-utils
LOCAL_STATIC_LIBRARIES := \
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index c28f427..8f42a85 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -262,23 +262,24 @@
void SessionConfigurationUtils::mapStreamInfo(const OutputStreamInfo &streamInfo,
camera3::camera_stream_rotation_t rotation, String8 physicalId,
- hardware::camera::device::V3_4::Stream *stream /*out*/) {
+ int32_t groupId, hardware::camera::device::V3_7::Stream *stream /*out*/) {
if (stream == nullptr) {
return;
}
- stream->v3_2.streamType = hardware::camera::device::V3_2::StreamType::OUTPUT;
- stream->v3_2.width = streamInfo.width;
- stream->v3_2.height = streamInfo.height;
- stream->v3_2.format = Camera3Device::mapToPixelFormat(streamInfo.format);
+ 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);
auto u = streamInfo.consumerUsage;
camera3::Camera3OutputStream::applyZSLUsageQuirk(streamInfo.format, &u);
- stream->v3_2.usage = Camera3Device::mapToConsumerUsage(u);
- stream->v3_2.dataSpace = Camera3Device::mapToHidlDataspace(streamInfo.dataSpace);
- stream->v3_2.rotation = Camera3Device::mapToStreamRotation(rotation);
- stream->v3_2.id = -1; // Invalid stream id
- stream->physicalCameraId = std::string(physicalId.string());
- stream->bufferSize = 0;
+ 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;
}
binder::Status SessionConfigurationUtils::checkPhysicalCameraId(
@@ -358,7 +359,7 @@
const SessionConfiguration& sessionConfiguration,
const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
- hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration, bool *earlyExit) {
+ hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration, bool *earlyExit) {
auto operatingMode = sessionConfiguration.getOperatingMode();
binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
@@ -393,14 +394,16 @@
streamConfiguration.streams.resize(streamCount);
size_t streamIdx = 0;
if (isInputValid) {
- streamConfiguration.streams[streamIdx++] = {{/*streamId*/0,
+ streamConfiguration.streams[streamIdx++] = {{{/*streamId*/0,
hardware::camera::device::V3_2::StreamType::INPUT,
static_cast<uint32_t> (sessionConfiguration.getInputWidth()),
static_cast<uint32_t> (sessionConfiguration.getInputHeight()),
Camera3Device::mapToPixelFormat(sessionConfiguration.getInputFormat()),
/*usage*/ 0, HAL_DATASPACE_UNKNOWN,
hardware::camera::device::V3_2::StreamRotation::ROTATION_0},
- /*physicalId*/ nullptr, /*bufferSize*/0};
+ /*physicalId*/ nullptr, /*bufferSize*/0}, /*groupId*/-1};
+ streamConfiguration.multiResolutionInputImage =
+ sessionConfiguration.inputIsMultiResolution();
}
for (const auto &it : outputConfigs) {
@@ -410,6 +413,7 @@
String8 physicalCameraId = String8(it.getPhysicalCameraId());
size_t numBufferProducers = bufferProducers.size();
bool isStreamInfoValid = false;
+ int32_t groupId = it.isMultiResolution() ? it.getSurfaceSetID() : -1;
OutputStreamInfo streamInfo;
res = checkSurfaceType(numBufferProducers, deferredConsumer, it.getSurfaceType());
@@ -432,7 +436,7 @@
if (surfaceType == OutputConfiguration::SURFACE_TYPE_SURFACE_VIEW) {
streamInfo.consumerUsage |= GraphicBuffer::USAGE_HW_COMPOSER;
}
- mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId,
+ mapStreamInfo(streamInfo, camera3::CAMERA_STREAM_ROTATION_0, physicalCameraId, groupId,
&streamConfiguration.streams[streamIdx++]);
isStreamInfoValid = true;
@@ -488,12 +492,13 @@
for (const auto& compositeStream : compositeStreams) {
mapStreamInfo(compositeStream,
static_cast<camera_stream_rotation_t> (it.getRotation()),
- physicalCameraId, &streamConfiguration.streams[streamIdx++]);
+ physicalCameraId, groupId,
+ &streamConfiguration.streams[streamIdx++]);
}
} else {
mapStreamInfo(streamInfo,
static_cast<camera_stream_rotation_t> (it.getRotation()),
- physicalCameraId, &streamConfiguration.streams[streamIdx++]);
+ physicalCameraId, groupId, &streamConfiguration.streams[streamIdx++]);
}
isStreamInfoValid = true;
}
@@ -503,4 +508,27 @@
}
+bool SessionConfigurationUtils::convertHALStreamCombinationFromV37ToV34(
+ hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
+ const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37) {
+ if (streamConfigV37.multiResolutionInputImage) {
+ // ICameraDevice older than 3.7 doesn't support multi-resolution input image.
+ return false;
+ }
+
+ streamConfigV34.streams.resize(streamConfigV37.streams.size());
+ for (size_t i = 0; i < streamConfigV37.streams.size(); i++) {
+ if (streamConfigV37.streams[i].groupId != -1) {
+ // ICameraDevice older than 3.7 doesn't support multi-resolution output
+ // image
+ return false;
+ }
+ streamConfigV34.streams[i] = streamConfigV37.streams[i].v3_4;
+ }
+ streamConfigV34.operationMode = streamConfigV37.operationMode;
+ streamConfigV34.sessionParams = streamConfigV37.sessionParams;
+
+ return true;
+}
+
}// namespace android
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index 6ac7ab4..36e1dd7 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -21,7 +21,7 @@
#include <camera/camera2/OutputConfiguration.h>
#include <camera/camera2/SessionConfiguration.h>
#include <camera/camera2/SubmitInfo.h>
-#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.7/types.h>
#include <device3/Camera3StreamInterface.h>
@@ -53,8 +53,8 @@
const String8 &cameraId, const CameraMetadata &physicalCameraMetadata);
static void mapStreamInfo(const camera3::OutputStreamInfo &streamInfo,
- camera3::camera_stream_rotation_t rotation, String8 physicalId,
- hardware::camera::device::V3_4::Stream *stream /*out*/);
+ camera3::camera_stream_rotation_t rotation, String8 physicalId, int32_t groupId,
+ hardware::camera::device::V3_7::Stream *stream /*out*/);
// Check that the physicalCameraId passed in is spported by the camera
// device.
@@ -76,9 +76,16 @@
convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
const String8 &cameraId, const CameraMetadata &deviceInfo,
metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
- hardware::camera::device::V3_4::StreamConfiguration &streamConfiguration,
+ hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
bool *earlyExit);
+ // 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.
+ static bool convertHALStreamCombinationFromV37ToV34(
+ hardware::camera::device::V3_4::StreamConfiguration &streamConfigV34,
+ const hardware::camera::device::V3_7::StreamConfiguration &streamConfigV37);
+
static const int32_t MAX_SURFACES_PER_STREAM = 4;
static const int32_t ROUNDING_WIDTH_CAP = 1920;
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index d502b30..1c5ab77 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -186,6 +186,16 @@
metrics_proto.set_lifetime_millis(lifetimeMs);
}
+ // new for S; need to plumb through to westworld
+ // android.media.mediacodec.channelCount int32
+ // android.media.mediacodec.sampleRate int32
+
+ // new for S; need to plumb through to westworld
+ // TODO PWG may want these fuzzed up a bit to obscure some precision
+ // android.media.mediacodec.vencode.bytes int64
+ // android.media.mediacodec.vencode.frames int64
+ // android.media.mediacodec.vencode.durationUs int64
+
std::string serialized;
if (!metrics_proto.SerializeToString(&serialized)) {
ALOGE("Failed to serialize codec metrics");
diff --git a/services/mediametrics/tests/Android.bp b/services/mediametrics/tests/Android.bp
index 71193a2..3baf739 100644
--- a/services/mediametrics/tests/Android.bp
+++ b/services/mediametrics/tests/Android.bp
@@ -11,6 +11,10 @@
name: "mediametrics_tests",
test_suites: ["device-tests"],
+ // not all shared libraries are populated in the 2nd architecture in
+ // particular, libmediametricsservice we use to have a tame copy of the service
+ compile_multilib: "first",
+
cflags: [
"-Wall",
"-Werror",
diff --git a/services/mediatranscoding/Android.bp b/services/mediatranscoding/Android.bp
index 1825424..a9fd14f 100644
--- a/services/mediatranscoding/Android.bp
+++ b/services/mediatranscoding/Android.bp
@@ -1,3 +1,4 @@
+// service library
package {
default_applicable_licenses: [
"frameworks_av_services_mediatranscoding_license",
@@ -17,7 +18,6 @@
],
}
-// service library
cc_library {
name: "libmediatranscodingservice",
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 63120f8..df2b4a3 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -81,6 +81,7 @@
"android.hardware.tv.tuner@1.0",
"android.hardware.tv.tuner@1.1",
"libbase",
+ "libbinder",
"libbinder_ndk",
"libcutils",
"libfmq",
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index 9624e27..77e1c40 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "TunerService"
#include <android/binder_manager.h>
+#include <android/content/pm/IPackageManagerNative.h>
+#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include "TunerService.h"
#include "TunerFrontend.h"
@@ -50,6 +52,33 @@
namespace android {
TunerService::TunerService() {
+ sp<IServiceManager> serviceMgr = defaultServiceManager();
+ sp<content::pm::IPackageManagerNative> packageMgr;
+ if (serviceMgr.get() == nullptr) {
+ ALOGE("%s: Cannot find service manager", __func__);
+ return;
+ } else {
+ sp<IBinder> binder = serviceMgr->waitForService(String16("package_native"));
+ packageMgr = interface_cast<content::pm::IPackageManagerNative>(binder);
+ }
+
+ bool hasFeature = false;
+ if (packageMgr != nullptr) {
+ binder::Status status = packageMgr->hasSystemFeature(FEATURE_TUNER, 0, &hasFeature);
+ if (!status.isOk()) {
+ ALOGE("%s: hasSystemFeature failed: %s",
+ __func__, status.exceptionMessage().c_str());
+ return;
+ }
+ if (!hasFeature) {
+ ALOGD("Current device does not support tuner feaure.");
+ return;
+ }
+ } else {
+ ALOGD("%s: Cannot find package manager.", __func__);
+ return;
+ }
+
::ndk::SpAIBinder binder(AServiceManager_waitForService("tv_tuner_resource_mgr"));
mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
updateTunerResources();
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 0570681..f8e2ee6 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -72,6 +72,8 @@
const static int TUNER_HAL_VERSION_UNKNOWN = 0;
const static int TUNER_HAL_VERSION_1_0 = 1 << 16;
const static int TUNER_HAL_VERSION_1_1 = (1 << 16) | 1;
+// System Feature defined in PackageManager
+static const ::android::String16 FEATURE_TUNER(::android::String16("android.hardware.tv.tuner"));
typedef enum {
FRONTEND,