Merge "Check if the tuner feature is supported before waiting for the TRM service" 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/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index f8f2bc6..a84fd92 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -345,10 +345,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 +364,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("Failed to make drm plugin: %d", status);
return;
}
plugin = hPlugin;
@@ -372,7 +372,7 @@
);
if (!hResult.isOk()) {
- ALOGE("createPlugin remote call failed");
+ DrmUtils::LOG2BE("createPlugin remote call failed");
}
return plugin;
@@ -566,7 +566,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;
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index 82eadd9..f7e6717 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("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("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..7fe3501 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -27,7 +27,14 @@
#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 <iterator>
+#include <mutex>
#include <vector>
@@ -42,6 +49,53 @@
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});
+ }
+}
+
+#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 +173,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 +188,36 @@
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", T::descriptor);
+ }
+
+ auto allLogs(gLogBuf.getLogs());
+ 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..66a2b6a 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) {
@@ -833,12 +828,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 +1140,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 +1158,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 +1217,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/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..00ed3b8 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -114,6 +114,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 +954,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 +1576,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..d2f714a 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -218,6 +218,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 +3269,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/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/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/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 61a6ae9..3e5f9ea 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -3171,16 +3171,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
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/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/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/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index df4ef95..d06b2c5 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: [
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",