Merge "codec2: libgav1 integration part 1"
diff --git a/apex/manifest.json b/apex/manifest.json
index 03b9dd0..3011ee8 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media",
- "version": 220000000
+ "version": 290000000
}
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 58ce868..83a5178 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media.swcodec",
- "version": 220000000
+ "version": 290000000
}
diff --git a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
index 529c167..a43d707 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraDevice.cpp
@@ -31,6 +31,17 @@
#include "ACameraCaptureSession.inc"
+#define CHECK_TRANSACTION_AND_RET(remoteRet, status, callName) \
+ if (!remoteRet.isOk()) { \
+ ALOGE("%s: Transaction error during %s call %s", __FUNCTION__, callName, \
+ remoteRet.description().c_str()); \
+ return ACAMERA_ERROR_UNKNOWN; \
+ } \
+ if (status != Status::NO_ERROR) { \
+ ALOGE("%s: %s call failed", __FUNCTION__, callName); \
+ return utils::convertFromHidl(status); \
+ }
+
using namespace android;
namespace android {
@@ -151,7 +162,7 @@
return ACAMERA_ERROR_CAMERA_DISCONNECTED;
}
CameraMetadata rawRequest;
- Status status = Status::NO_ERROR;
+ Status status = Status::UNKNOWN_ERROR;
auto remoteRet = mRemote->createDefaultRequest(
utils::convertToHidl(templateId),
[&status, &rawRequest](auto s, const hidl_vec<uint8_t> &metadata) {
@@ -161,14 +172,7 @@
ALOGE("%s: Couldn't create default request", __FUNCTION__);
}
});
- if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction error while trying to create default request %s", __FUNCTION__,
- remoteRet.description().c_str());
- return ACAMERA_ERROR_UNKNOWN;
- }
- if (status != Status::NO_ERROR) {
- return utils::convertFromHidl(status);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "createDefaultRequest()")
ACaptureRequest* outReq = new ACaptureRequest();
outReq->settings = new ACameraMetadata(rawRequest.release(), ACameraMetadata::ACM_REQUEST);
if (physicalCameraIdList != nullptr) {
@@ -243,20 +247,15 @@
}
bool configSupported = false;
- Status status = Status::NO_ERROR;
+ Status status = Status::UNKNOWN_ERROR;
auto remoteRet = mRemote->isSessionConfigurationSupported(sessionConfig,
[&status, &configSupported](auto s, auto supported) {
status = s;
configSupported = supported;
});
- if (status == Status::INVALID_OPERATION) {
- return ACAMERA_ERROR_UNSUPPORTED_OPERATION;
- } else if (!remoteRet.isOk()) {
- return ACAMERA_ERROR_UNKNOWN;
- } else {
- return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "isSessionConfigurationSupported()");
+ return configSupported ? ACAMERA_OK : ACAMERA_ERROR_STREAM_CONFIGURE_FAIL;
}
static void addMetadataToPhysicalCameraSettings(const CameraMetadata *metadata,
@@ -525,16 +524,13 @@
mRepeatingSequenceId = REQUEST_ID_NONE;
int64_t lastFrameNumber;
- Status status = Status::NO_ERROR;
+ Status status = Status::UNKNOWN_ERROR;
auto remoteRet = mRemote->cancelRepeatingRequest(
[&status, &lastFrameNumber](Status s, auto frameNumber) {
status = s;
lastFrameNumber = frameNumber;
});
- if (!remoteRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("%s: Unable to cancel active repeating request", __FUNCTION__);
- return utils::convertFromHidl(status);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "cancelRepeatingRequest()");
checkRepeatingSequenceCompleteLocked(repeatingSequenceId, lastFrameNumber);
}
return ACAMERA_OK;
@@ -582,15 +578,12 @@
}
int64_t lastFrameNumber;
- Status status;
+ Status status = Status::UNKNOWN_ERROR;
auto remoteRet = mRemote->flush([&status, &lastFrameNumber](auto s, auto frameNumber) {
status = s;
lastFrameNumber = frameNumber;
});
- if (!remoteRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("%s: Abort captures failed", __FUNCTION__);
- return utils::convertFromHidl(status);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, status, "flush()")
if (mRepeatingSequenceId != REQUEST_ID_NONE) {
checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
}
@@ -611,10 +604,7 @@
}
auto remoteRet = mRemote->waitUntilIdle();
- if (!remoteRet.isOk()) {
- ALOGE("%s: Transaction waitUntilIdle failed", __FUNCTION__);
- return utils::convertFromHidl(remoteRet);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "waitUntilIdle()")
return ACAMERA_OK;
}
@@ -689,34 +679,25 @@
mIdle = true;
auto remoteRet = mRemote->beginConfigure();
- if (!remoteRet.isOk()|| remoteRet != Status::NO_ERROR) {
- ALOGE("Camera device %s begin configure failed", getId());
- return utils::convertFromHidl(remoteRet);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "beginConfigure()")
// delete to-be-deleted streams
for (auto streamId : deleteList) {
remoteRet = mRemote->deleteStream(streamId);
- if (!remoteRet.isOk() || remoteRet != Status::NO_ERROR) {
- ALOGE("Camera device %s failed to remove stream %d", getId(), streamId);
- return utils::convertFromHidl(remoteRet);
- }
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "deleteStream()")
mConfiguredOutputs.erase(streamId);
}
// add new streams
for (auto outputPair : addSet) {
int streamId;
- Status status;
+ Status status = Status::UNKNOWN_ERROR;
auto ret = mRemote->createStream(outputPair.second,
[&status, &streamId](Status s, auto stream_id) {
status = s;
streamId = stream_id;
});
- if (!remoteRet.isOk() || status != Status::NO_ERROR) {
- ALOGE("Camera device %s failed to create stream", getId());
- return utils::convertFromHidl(status);
- }
+ CHECK_TRANSACTION_AND_RET(ret, status, "createStream()")
mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
}
@@ -729,11 +710,8 @@
params.unlock(params_metadata);
}
remoteRet = mRemote->endConfigure(StreamConfigurationMode::NORMAL_MODE, hidlParams);
- if (!remoteRet.isOk()) {
- ALOGE("Transaction error: endConfigure failed %s", remoteRet.description().c_str());
- }
-
- return utils::convertFromHidl(remoteRet);
+ CHECK_TRANSACTION_AND_RET(remoteRet, remoteRet, "endConfigure()")
+ return ACAMERA_OK;
}
void
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 37de30a..7ab0124 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -24,6 +24,7 @@
#include <algorithm>
#include <mutex>
#include <string>
+#include <variant>
#include <vector>
#include <stdio.h>
#include <stdio.h>
@@ -49,6 +50,7 @@
static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using ConfiguredWindows = std::set<native_handle_t *>;
class CameraHelper {
public:
@@ -60,9 +62,12 @@
const char* physicalCameraId;
native_handle_t* anw;
};
- int initCamera(native_handle_t* imgReaderAnw,
+
+ // Retaining the error code in case the caller needs to analyze it.
+ std::variant<int, ConfiguredWindows> initCamera(native_handle_t* imgReaderAnw,
const std::vector<PhysicalImgReaderInfo>& physicalImgReaders,
bool usePhysicalSettings) {
+ ConfiguredWindows configuredWindows;
if (imgReaderAnw == nullptr) {
ALOGE("Cannot initialize camera before image reader get initialized.");
return -1;
@@ -78,7 +83,7 @@
ret = ACameraManager_openCamera(mCameraManager, mCameraId, &mDeviceCb, &mDevice);
if (ret != AMEDIA_OK || mDevice == nullptr) {
ALOGE("Failed to open camera, ret=%d, mDevice=%p.", ret, mDevice);
- return -1;
+ return ret;
}
// Create capture session
@@ -97,8 +102,9 @@
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret;
}
-
+ configuredWindows.insert(mImgReaderAnw);
std::vector<const char*> idPointerList;
+ std::set<const native_handle_t*> physicalStreamMap;
for (auto& physicalStream : physicalImgReaders) {
ACaptureSessionOutput* sessionOutput = nullptr;
ret = ACaptureSessionPhysicalOutput_create(physicalStream.anw,
@@ -112,21 +118,25 @@
ALOGE("ACaptureSessionOutputContainer_add failed, ret=%d", ret);
return ret;
}
- mExtraOutputs.push_back(sessionOutput);
+ ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
+ if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
+ ALOGW("ACameraDevice_isSessionConfigurationSupported failed, ret=%d camera id %s",
+ ret, mCameraId);
+ ACaptureSessionOutputContainer_remove(mOutputs, sessionOutput);
+ ACaptureSessionOutput_free(sessionOutput);
+ continue;
+ }
+ configuredWindows.insert(physicalStream.anw);
// Assume that at most one physical stream per physical camera.
mPhysicalCameraIds.push_back(physicalStream.physicalCameraId);
idPointerList.push_back(physicalStream.physicalCameraId);
+ physicalStreamMap.insert(physicalStream.anw);
+ mSessionPhysicalOutputs.push_back(sessionOutput);
}
ACameraIdList cameraIdList;
cameraIdList.numCameras = idPointerList.size();
cameraIdList.cameraIds = idPointerList.data();
- ret = ACameraDevice_isSessionConfigurationSupported(mDevice, mOutputs);
- if (ret != ACAMERA_OK && ret != ACAMERA_ERROR_UNSUPPORTED_OPERATION) {
- ALOGE("ACameraDevice_isSessionConfigurationSupported failed, ret=%d", ret);
- return ret;
- }
-
ret = ACameraDevice_createCaptureSession(mDevice, mOutputs, &mSessionCb, &mSession);
if (ret != AMEDIA_OK) {
ALOGE("ACameraDevice_createCaptureSession failed, ret=%d", ret);
@@ -157,6 +167,10 @@
}
for (auto& physicalStream : physicalImgReaders) {
+ if (physicalStreamMap.find(physicalStream.anw) == physicalStreamMap.end()) {
+ ALOGI("Skipping physicalStream anw=%p", physicalStream.anw);
+ continue;
+ }
ACameraOutputTarget* outputTarget = nullptr;
ret = ACameraOutputTarget_create(physicalStream.anw, &outputTarget);
if (ret != AMEDIA_OK) {
@@ -168,11 +182,11 @@
ALOGE("ACaptureRequest_addTarget failed, ret=%d", ret);
return ret;
}
- mReqExtraOutputs.push_back(outputTarget);
+ mReqPhysicalOutputs.push_back(outputTarget);
}
mIsCameraReady = true;
- return 0;
+ return configuredWindows;
}
@@ -184,10 +198,10 @@
ACameraOutputTarget_free(mReqImgReaderOutput);
mReqImgReaderOutput = nullptr;
}
- for (auto& outputTarget : mReqExtraOutputs) {
+ for (auto& outputTarget : mReqPhysicalOutputs) {
ACameraOutputTarget_free(outputTarget);
}
- mReqExtraOutputs.clear();
+ mReqPhysicalOutputs.clear();
if (mStillRequest) {
ACaptureRequest_free(mStillRequest);
mStillRequest = nullptr;
@@ -201,10 +215,10 @@
ACaptureSessionOutput_free(mImgReaderOutput);
mImgReaderOutput = nullptr;
}
- for (auto& extraOutput : mExtraOutputs) {
+ for (auto& extraOutput : mSessionPhysicalOutputs) {
ACaptureSessionOutput_free(extraOutput);
}
- mExtraOutputs.clear();
+ mSessionPhysicalOutputs.clear();
if (mOutputs) {
ACaptureSessionOutputContainer_free(mOutputs);
mOutputs = nullptr;
@@ -262,13 +276,13 @@
// Capture session
ACaptureSessionOutputContainer* mOutputs = nullptr;
ACaptureSessionOutput* mImgReaderOutput = nullptr;
- std::vector<ACaptureSessionOutput*> mExtraOutputs;
+ std::vector<ACaptureSessionOutput*> mSessionPhysicalOutputs;
ACameraCaptureSession* mSession = nullptr;
// Capture request
ACaptureRequest* mStillRequest = nullptr;
ACameraOutputTarget* mReqImgReaderOutput = nullptr;
- std::vector<ACameraOutputTarget*> mReqExtraOutputs;
+ std::vector<ACameraOutputTarget*> mReqPhysicalOutputs;
bool mIsCameraReady = false;
const char* mCameraId;
@@ -581,9 +595,11 @@
}
CameraHelper cameraHelper(id, mCameraManager);
- ret = cameraHelper.initCamera(testCase.getNativeWindow(),
- {}/*physicalImageReaders*/, false/*usePhysicalSettings*/);
- if (ret < 0) {
+ std::variant<int, ConfiguredWindows> retInit =
+ cameraHelper.initCamera(testCase.getNativeWindow(), {}/*physicalImageReaders*/,
+ false/*usePhysicalSettings*/);
+ int *retp = std::get_if<int>(&retInit);
+ if (retp) {
ALOGE("Unable to initialize camera helper");
return false;
}
@@ -751,10 +767,15 @@
physicalImgReaderInfo.push_back({physicalCameraIds[0], testCases[1]->getNativeWindow()});
physicalImgReaderInfo.push_back({physicalCameraIds[1], testCases[2]->getNativeWindow()});
- int ret = cameraHelper.initCamera(testCases[0]->getNativeWindow(),
- physicalImgReaderInfo, usePhysicalSettings);
- ASSERT_EQ(ret, 0);
-
+ std::variant<int, ConfiguredWindows> retInit =
+ cameraHelper.initCamera(testCases[0]->getNativeWindow(), physicalImgReaderInfo,
+ usePhysicalSettings);
+ int *retp = std::get_if<int>(&retInit);
+ ASSERT_EQ(retp, nullptr);
+ ConfiguredWindows *configuredWindowsp = std::get_if<ConfiguredWindows>(&retInit);
+ ASSERT_NE(configuredWindowsp, nullptr);
+ ASSERT_LE(configuredWindowsp->size(), testCases.size());
+ int ret = 0;
if (!cameraHelper.isCameraReady()) {
ALOGW("Camera is not ready after successful initialization. It's either due to camera "
"on board lacks BACKWARDS_COMPATIBLE capability or the device does not have "
@@ -776,9 +797,15 @@
break;
}
}
- ASSERT_EQ(testCases[0]->getAcquiredImageCount(), pictureCount);
- ASSERT_EQ(testCases[1]->getAcquiredImageCount(), pictureCount);
- ASSERT_EQ(testCases[2]->getAcquiredImageCount(), pictureCount);
+ for(auto &testCase : testCases) {
+ auto it = configuredWindowsp->find(testCase->getNativeWindow());
+ if (it == configuredWindowsp->end()) {
+ continue;
+ }
+ ALOGI("Testing window %p", testCase->getNativeWindow());
+ ASSERT_EQ(testCase->getAcquiredImageCount(), pictureCount);
+ }
+
ASSERT_TRUE(cameraHelper.checkCallbacks(pictureCount));
ACameraMetadata_free(staticMetadata);
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 077a91f..1cfdc19 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -508,7 +508,7 @@
.limitTo(D::ENCODER & D::VIDEO));
// convert to timestamp base
add(ConfigMapper(KEY_I_FRAME_INTERVAL, C2_PARAMKEY_SYNC_FRAME_INTERVAL, "value")
- .withMapper([](C2Value v) -> C2Value {
+ .withMappers([](C2Value v) -> C2Value {
// convert from i32 to float
int32_t i32Value;
float fpValue;
@@ -518,6 +518,12 @@
return int64_t(c2_min(1000000 * fpValue + 0.5, (double)INT64_MAX));
}
return C2Value();
+ }, [](C2Value v) -> C2Value {
+ int64_t i64;
+ if (v.get(&i64)) {
+ return float(i64) / 1000000;
+ }
+ return C2Value();
}));
// remove when codecs switch to proper coding.gop (add support for calculating gop)
deprecated(ConfigMapper("i-frame-period", "coding.gop", "intra-period")
@@ -711,7 +717,7 @@
// convert to dBFS and add default
add(ConfigMapper(KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, C2_PARAMKEY_DRC_TARGET_REFERENCE_LEVEL, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
@@ -722,7 +728,7 @@
// convert to 0-1 (%) and add default
add(ConfigMapper(KEY_AAC_DRC_ATTENUATION_FACTOR, C2_PARAMKEY_DRC_ATTENUATION_FACTOR, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
@@ -733,7 +739,7 @@
// convert to 0-1 (%) and add default
add(ConfigMapper(KEY_AAC_DRC_BOOST_FACTOR, C2_PARAMKEY_DRC_BOOST_FACTOR, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
@@ -744,7 +750,7 @@
// convert to compression type and add default
add(ConfigMapper(KEY_AAC_DRC_HEAVY_COMPRESSION, C2_PARAMKEY_DRC_COMPRESSION_MODE, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
@@ -755,7 +761,7 @@
// convert to dBFS and add default
add(ConfigMapper(KEY_AAC_ENCODED_TARGET_LEVEL, C2_PARAMKEY_DRC_ENCODED_TARGET_LEVEL, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < 0) {
@@ -766,7 +772,7 @@
// convert to effect type (these map to SDK values) and add default
add(ConfigMapper(KEY_AAC_DRC_EFFECT_TYPE, C2_PARAMKEY_DRC_EFFECT_TYPE, "value")
- .limitTo(D::AUDIO & D::DECODER)
+ .limitTo(D::AUDIO & D::DECODER & D::CONFIG)
.withMapper([](C2Value v) -> C2Value {
int32_t value;
if (!v.get(&value) || value < -1 || value > 8) {
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 1e7f9fa..02dc516 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1512,6 +1512,13 @@
return aps->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
+status_t AudioSystem::setRttEnabled(bool enabled)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setRttEnabled(enabled);
+}
+
// ---------------------------------------------------------------------------
int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index c548457..64f0aca 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -104,6 +104,7 @@
GET_VOLUME_GROUP_FOR_ATTRIBUTES,
SET_ALLOWED_CAPTURE_POLICY,
MOVE_EFFECTS_TO_IO,
+ SET_RTT_ENABLED
};
#define MAX_ITEMS_PER_LIST 1024
@@ -1271,6 +1272,18 @@
volumeGroup = static_cast<volume_group_t>(reply.readInt32());
return NO_ERROR;
}
+
+ virtual status_t setRttEnabled(bool enabled)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(enabled));
+ status_t status = remote()->transact(SET_RTT_ENABLED, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1332,7 +1345,8 @@
case REMOVE_UID_DEVICE_AFFINITY:
case GET_OFFLOAD_FORMATS_A2DP:
case LIST_AUDIO_VOLUME_GROUPS:
- case GET_VOLUME_GROUP_FOR_ATTRIBUTES: {
+ case GET_VOLUME_GROUP_FOR_ATTRIBUTES:
+ case SET_RTT_ENABLED: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -2347,6 +2361,14 @@
return NO_ERROR;
}
+ case SET_RTT_ENABLED: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ bool enabled = static_cast<bool>(data.readInt32());
+ status_t status = setRttEnabled(enabled);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 56c69f6..09e80b2 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -394,6 +394,8 @@
static status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup);
+ static status_t setRttEnabled(bool enabled);
+
// ----------------------------------------------------------------------------
class AudioVolumeGroupCallback : public RefBase
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 33ab1f9..32275cf 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -220,6 +220,8 @@
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup) = 0;
+
+ virtual status_t setRttEnabled(bool enabled) = 0;
};
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index b25f82e..b07f21d 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -322,6 +322,14 @@
const struct audio_port_config *sinks,
audio_patch_handle_t *patch) {
if (mDevice == 0) return NO_INIT;
+ if (patch == nullptr) return BAD_VALUE;
+
+ if (*patch != AUDIO_PATCH_HANDLE_NONE) {
+ status_t status = releaseAudioPatch(*patch);
+ ALOGW_IF(status != NO_ERROR, "%s error %d releasing patch handle %d",
+ __func__, status, *patch);
+ }
+
hidl_vec<AudioPortConfig> hidlSources, hidlSinks;
HidlUtils::audioPortConfigsFromHal(num_sources, sources, &hidlSources);
HidlUtils::audioPortConfigsFromHal(num_sinks, sinks, &hidlSinks);
diff --git a/media/libmedia/include/media/omx/1.0/Conversion.h b/media/libmedia/include/media/omx/1.0/Conversion.h
index 80e8f3a..6dc46b7 100644
--- a/media/libmedia/include/media/omx/1.0/Conversion.h
+++ b/media/libmedia/include/media/omx/1.0/Conversion.h
@@ -625,8 +625,18 @@
// convert: AnwBuffer -> GraphicBuffer
// Ref: frameworks/native/libs/ui/GraphicBuffer.cpp: GraphicBuffer::flatten
inline bool convertTo(GraphicBuffer* l, AnwBuffer const& t) {
- native_handle_t* handle = t.nativeHandle == nullptr ?
- nullptr : native_handle_clone(t.nativeHandle);
+ native_handle_t* handle = nullptr;
+
+ if (t.nativeHandle != nullptr) {
+ handle = native_handle_clone(t.nativeHandle);
+ if (handle == nullptr) {
+ ALOGE("Failed to clone handle: numFds=%d, data[0]=%d, data[1]=%d",
+ t.nativeHandle->numFds,
+ (t.nativeHandle->numFds > 0) ? t.nativeHandle->data[0] : -1,
+ (t.nativeHandle->numFds > 1) ? t.nativeHandle->data[1] : -1);
+ return false;
+ }
+ }
size_t const numInts = 12 + (handle ? handle->numInts : 0);
int32_t* ints = new int32_t[numInts];
@@ -756,7 +766,12 @@
return true;
}
AnwBuffer anwBuffer;
- anwBuffer.nativeHandle = t.nativeHandle;
+ // Explicitly get the native_handle_t* (in stead of assigning t.nativeHandle)
+ // so that we don't do an extra native_handle_clone() in this step, as the
+ // convertion to GraphicBuffer below will do a clone regardless.
+ // If we encounter an invalid handle, the convertTo() below would fail (while
+ // the assigning of hidl_handle would abort and cause a crash).
+ anwBuffer.nativeHandle = t.nativeHandle.getNativeHandle();
anwBuffer.attr = t.attr.anwBuffer;
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
if (!convertTo(graphicBuffer.get(), anwBuffer)) {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 5a58aa0..0f72c0d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -90,8 +90,11 @@
ALOGV("resetDataSource");
mHTTPService.clear();
- mHttpSource.clear();
- mDisconnected = false;
+ {
+ Mutex::Autolock _l_d(mDisconnectLock);
+ mHttpSource.clear();
+ mDisconnected = false;
+ }
mUri.clear();
mUriHeaders.clear();
mSources.clear();
@@ -152,7 +155,10 @@
ALOGV("setDataSource (source: %p)", source.get());
resetDataSource();
- mDataSource = source;
+ {
+ Mutex::Autolock _l_d(mDisconnectLock);
+ mDataSource = source;
+ }
return OK;
}
@@ -163,8 +169,12 @@
status_t NuPlayer::GenericSource::initFromDataSource() {
sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL);
- sp<DataSource> dataSource = mDataSource;
+ sp<DataSource> dataSource;
+ {
+ Mutex::Autolock _l_d(mDisconnectLock);
+ dataSource = mDataSource;
+ }
+ CHECK(dataSource != NULL);
mLock.unlock();
// This might take long time if data source is not reliable.
@@ -359,6 +369,7 @@
}
void NuPlayer::GenericSource::onPrepareAsync() {
+ mDisconnectLock.lock();
ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
// delayed data source creation
@@ -372,20 +383,29 @@
String8 contentType;
if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
- mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
- if (mHttpSource == NULL) {
+ sp<DataSource> httpSource;
+ mDisconnectLock.unlock();
+ httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
+ if (httpSource == NULL) {
ALOGE("Failed to create http source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
+ mDisconnectLock.lock();
+
+ if (!mDisconnected) {
+ mHttpSource = httpSource;
+ }
}
mLock.unlock();
+ mDisconnectLock.unlock();
// This might take long time if connection has some issue.
sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
mHTTPService, uri, &mUriHeaders, &contentType,
static_cast<HTTPBase *>(mHttpSource.get()));
mLock.lock();
+ mDisconnectLock.lock();
if (!mDisconnected) {
mDataSource = dataSource;
}
@@ -428,6 +448,7 @@
if (mDataSource == NULL) {
ALOGE("Failed to create data source!");
+ mDisconnectLock.unlock();
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
@@ -437,6 +458,8 @@
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
+ mDisconnectLock.unlock();
+
// For cached streaming cases, we need to wait for enough
// buffering before reporting prepared.
mIsStreaming = (mCachedSource != NULL);
@@ -503,9 +526,13 @@
void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
if (err != OK) {
- mDataSource.clear();
+ {
+ Mutex::Autolock _l_d(mDisconnectLock);
+ mDataSource.clear();
+ mHttpSource.clear();
+ }
+
mCachedSource.clear();
- mHttpSource.clear();
mBitrate = -1;
mPrevBufferPercentage = -1;
@@ -547,7 +574,7 @@
void NuPlayer::GenericSource::disconnect() {
sp<DataSource> dataSource, httpSource;
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l_d(mDisconnectLock);
dataSource = mDataSource;
httpSource = mHttpSource;
mDisconnected = true;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 065cac1..4d1905d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -170,6 +170,7 @@
sp<ABuffer> mGlobalTimedText;
mutable Mutex mLock;
+ mutable Mutex mDisconnectLock; // Protects mDataSource, mHttpSource and mDisconnected
sp<ALooper> mLooper;
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index cb87b55..b738fef 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -52,6 +52,7 @@
OggWriter::OggWriter(int fd)
: mFd(dup(fd)),
+ mHaveAllCodecSpecificData(false),
mInitCheck(mFd < 0 ? NO_INIT : OK) {
// empty
}
@@ -115,17 +116,26 @@
mSampleRate = sampleRate;
uint32_t type;
- const void *header_data;
- size_t packet_size;
+ const void *header_data = NULL;
+ size_t packet_size = 0;
+
if (!source->getFormat()->findData(kKeyOpusHeader, &type, &header_data, &packet_size)) {
- ALOGE("opus header not found");
- return UNKNOWN_ERROR;
+ ALOGV("opus header not found in format");
+ } else if (header_data && packet_size) {
+ writeOggHeaderPackets((unsigned char *)header_data, packet_size);
+ } else {
+ ALOGD("ignoring incomplete opus header data in format");
}
+ mSource = source;
+ return OK;
+}
+
+status_t OggWriter::writeOggHeaderPackets(unsigned char *buf, size_t size) {
ogg_packet op;
ogg_page og;
- op.packet = (unsigned char *)header_data;
- op.bytes = packet_size;
+ op.packet = buf;
+ op.bytes = size;
op.b_o_s = 1;
op.e_o_s = 0;
op.granulepos = 0;
@@ -169,8 +179,8 @@
write(mFd, og.body, og.body_len);
}
- mSource = source;
free(comments);
+ mHaveAllCodecSpecificData = true;
return OK;
}
@@ -301,12 +311,35 @@
&& isCodecSpecific)
|| IsOpusHeader((uint8_t*)buffer->data() + buffer->range_offset(),
buffer->range_length())) {
- ALOGV("Drop codec specific info buffer");
+ if (mHaveAllCodecSpecificData == false) {
+ size_t opusHeadSize = 0;
+ size_t codecDelayBufSize = 0;
+ size_t seekPreRollBufSize = 0;
+ void *opusHeadBuf = NULL;
+ void *codecDelayBuf = NULL;
+ void *seekPreRollBuf = NULL;
+ GetOpusHeaderBuffers((uint8_t*)buffer->data() + buffer->range_offset(),
+ buffer->range_length(), &opusHeadBuf,
+ &opusHeadSize, &codecDelayBuf,
+ &codecDelayBufSize, &seekPreRollBuf,
+ &seekPreRollBufSize);
+ writeOggHeaderPackets((unsigned char *)opusHeadBuf, opusHeadSize);
+ } else {
+ ALOGV("ignoring later copy of CSD contained in info buffer");
+ }
buffer->release();
buffer = nullptr;
continue;
}
+ if (mHaveAllCodecSpecificData == false) {
+ ALOGE("Did not get valid opus header before first sample data");
+ buffer->release();
+ buffer = nullptr;
+ err = ERROR_MALFORMED;
+ break;
+ }
+
int64_t timestampUs;
CHECK(buffer->meta_data().findInt64(kKeyTime, ×tampUs));
if (timestampUs > mEstimatedDurationUs) {
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 76a400c..8d0ea3a 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -572,16 +572,17 @@
}
void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
- if (portIndex == 0 && mState != NULL) {
- // Make sure that the next buffer output does not still
- // depend on fragments from the last one decoded.
-
+ if (portIndex == 0) {
mInputBufferCount = 0;
mNumFramesOutput = 0;
mSawInputEos = false;
mSignalledOutputEos = false;
mNumFramesLeftOnPage = -1;
- vorbis_dsp_restart(mState);
+ if (mState != NULL) {
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ vorbis_dsp_restart(mState);
+ }
}
}
@@ -603,6 +604,7 @@
mSawInputEos = false;
mSignalledOutputEos = false;
mSignalledError = false;
+ mNumFramesLeftOnPage = -1;
mOutputPortSettingsChange = NONE;
}
diff --git a/media/libstagefright/include/media/stagefright/OggWriter.h b/media/libstagefright/include/media/stagefright/OggWriter.h
index e3837cd..1a0a1d2 100644
--- a/media/libstagefright/include/media/stagefright/OggWriter.h
+++ b/media/libstagefright/include/media/stagefright/OggWriter.h
@@ -43,6 +43,7 @@
private:
int mFd;
+ bool mHaveAllCodecSpecificData;
status_t mInitCheck;
sp<MediaSource> mSource;
bool mStarted = false;
@@ -66,6 +67,8 @@
OggWriter(const OggWriter&);
OggWriter& operator=(const OggWriter&);
+
+ status_t writeOggHeaderPackets(unsigned char *buf, size_t size);
};
} // namespace android
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 16fdeaf..b824212 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -128,7 +128,7 @@
if (isAudioServerOrRootUid(uid)) return true;
static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
bool ok = PermissionCache::checkPermission(sCaptureAudioOutput, pid, uid);
- if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
+ if (!ok) ALOGV("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
return ok;
}
@@ -149,7 +149,7 @@
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
ok = PermissionCache::checkPermission(sCaptureHotwordAllowed, pid, uid);
}
- if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
+ if (!ok) ALOGV("android.permission.CAPTURE_AUDIO_HOTWORD");
return ok;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index dca84c0..c42923a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -120,8 +120,9 @@
ALOGV("getAudioPolicyMix() for dev=0x%x addr=%s", deviceType, address.string());
for (ssize_t i = 0; i < size(); i++) {
- if (itemAt(i)->mDeviceType == deviceType
- && itemAt(i)->mDeviceAddress.compare(address) == 0) {
+ // Workaround: when an in audio policy is registered, it opens an output
+ // that tries to find the audio policy, thus the device must be ignored.
+ if (itemAt(i)->mDeviceAddress.compare(address) == 0) {
policyMix = itemAt(i);
ALOGV("getAudioPolicyMix: found mix %zu match (devType=0x%x addr=%s)",
i, deviceType, address.string());
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index b0a8541..fa8da89 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -193,7 +193,8 @@
if (!mPackageManager.allowPlaybackCapture(uid)) {
attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
}
- if (!bypassInterruptionPolicyAllowed(pid, uid)) {
+ if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
+ && !bypassInterruptionPolicyAllowed(pid, uid)) {
attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
}
audio_output_flags_t originalFlags = flags;
@@ -1316,4 +1317,12 @@
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getVolumeGroupFromAudioAttributes(aa, volumeGroup);
}
+
+status_t AudioPolicyService::setRttEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mLock);
+ mUidPolicy->setRttEnabled(enabled);
+ return NO_ERROR;
+}
+
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index e3c72ae..77f7997 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -409,7 +409,7 @@
// following cases:
// Another client in the same UID has already been allowed to capture
// OR The client is the assistant
-// AND an accessibility service is on TOP
+// AND an accessibility service is on TOP or a RTT call is active
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR uses VOICE_RECOGNITION AND is on TOP
// OR uses HOTWORD
@@ -436,6 +436,9 @@
bool isAssistantOnTop = false;
bool isSensitiveActive = false;
bool isInCall = mPhoneState == AUDIO_MODE_IN_CALL;
+ bool rttCallActive =
+ (mPhoneState == AUDIO_MODE_IN_CALL || mPhoneState == AUDIO_MODE_IN_COMMUNICATION)
+ && mUidPolicy->isRttEnabled();
// if Sensor Privacy is enabled then all recordings should be silenced.
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -518,13 +521,13 @@
allowCapture = true;
} else if (mUidPolicy->isAssistantUid(current->uid)) {
// For assistant allow capture if:
- // An accessibility service is on TOP
+ // An accessibility service is on TOP or a RTT call is active
// AND the source is VOICE_RECOGNITION or HOTWORD
// OR is on TOP AND uses VOICE_RECOGNITION
// OR uses HOTWORD
// AND there is no active privacy sensitive capture or call
// OR client has CAPTURE_AUDIO_OUTPUT privileged permission
- if (isA11yOnTop) {
+ if (isA11yOnTop || rttCallActive) {
if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
allowCapture = true;
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 8db63a5..e467f70 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -256,6 +256,8 @@
virtual status_t getVolumeGroupFromAudioAttributes(const AudioAttributes &aa,
volume_group_t &volumeGroup);
+ virtual status_t setRttEnabled(bool enabled);
+
status_t doStopOutput(audio_port_handle_t portId);
void doReleaseOutput(audio_port_handle_t portId);
@@ -345,7 +347,8 @@
class UidPolicy : public BnUidObserver, public virtual IBinder::DeathRecipient {
public:
explicit UidPolicy(wp<AudioPolicyService> service)
- : mService(service), mObserverRegistered(false), mAssistantUid(0) {}
+ : mService(service), mObserverRegistered(false),
+ mAssistantUid(0), mRttEnabled(false) {}
void registerSelf();
void unregisterSelf();
@@ -360,6 +363,8 @@
void setA11yUids(const std::vector<uid_t>& uids) { mA11yUids.clear(); mA11yUids = uids; }
bool isA11yUid(uid_t uid);
bool isA11yOnTop();
+ void setRttEnabled(bool enabled) { mRttEnabled = enabled; }
+ bool isRttEnabled() { return mRttEnabled; }
// BnUidObserver implementation
void onUidActive(uid_t uid) override;
@@ -387,6 +392,7 @@
std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
uid_t mAssistantUid;
std::vector<uid_t> mA11yUids;
+ bool mRttEnabled;
};
// If sensor privacy is enabled then all apps, including those that are active, should be
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 00f0d86..9771f9e 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2876,7 +2876,8 @@
config.streams = streams.editArray();
// Do the HAL configuration; will potentially touch stream
- // max_buffers, usage, priv fields.
+ // max_buffers, usage, and priv fields, as well as data_space and format
+ // fields for IMPLEMENTATION_DEFINED formats.
const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
res = mInterface->configureStreams(sessionBuffer, &config, bufferSizes);
@@ -4202,10 +4203,19 @@
dst3_2.streamType = streamType;
dst3_2.width = src->width;
dst3_2.height = src->height;
- dst3_2.format = mapToPixelFormat(src->format);
dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
- dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
+ // For HidlSession version 3.5 or newer, the format and dataSpace sent
+ // to HAL are original, not the overriden ones.
+ if (mHidlSession_3_5 != nullptr) {
+ dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden() ?
+ cam3stream->getOriginalFormat() : src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(cam3stream->isDataSpaceOverridden() ?
+ cam3stream->getOriginalDataSpace() : src->data_space);
+ } else {
+ dst3_2.format = mapToPixelFormat(src->format);
+ dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
+ }
dst3_4.v3_2 = dst3_2;
dst3_4.bufferSize = bufferSizes[i];
if (src->physical_camera_id != nullptr) {
@@ -4266,7 +4276,7 @@
return OK;
};
- // See if we have v3.4 or v3.3 HAL
+ // See which version of HAL we have
if (mHidlSession_3_5 != nullptr) {
ALOGV("%s: v3.5 device found", __FUNCTION__);
device::V3_5::StreamConfiguration requestedConfiguration3_5;
@@ -4281,7 +4291,6 @@
} else if (mHidlSession_3_4 != nullptr) {
// We do; use v3.4 for the call
ALOGV("%s: v3.4 device found", __FUNCTION__);
- device::V3_4::HalStreamConfiguration finalConfiguration3_4;
auto err = mHidlSession_3_4->configureStreams_3_4(
requestedConfiguration3_4, configStream34Cb);
res = postprocConfigStream34(err);
@@ -4352,12 +4361,12 @@
device::V3_3::HalStream &src = finalConfiguration.streams[realIdx];
Camera3Stream* dstStream = Camera3Stream::cast(dst);
- dstStream->setFormatOverride(false);
- dstStream->setDataSpaceOverride(false);
int overrideFormat = mapToFrameworkFormat(src.v3_2.overrideFormat);
android_dataspace overrideDataSpace = mapToFrameworkDataspace(src.overrideDataSpace);
if (dst->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ dstStream->setFormatOverride(false);
+ dstStream->setDataSpaceOverride(false);
if (dst->format != overrideFormat) {
ALOGE("%s: Stream %d: Format override not allowed for format 0x%x", __FUNCTION__,
streamId, dst->format);
@@ -4367,10 +4376,13 @@
streamId, dst->format);
}
} else {
- dstStream->setFormatOverride((dst->format != overrideFormat) ? true : false);
- dstStream->setDataSpaceOverride((dst->data_space != overrideDataSpace) ? true : false);
-
+ bool needFormatOverride =
+ requestedConfiguration3_2.streams[i].format != src.v3_2.overrideFormat;
+ bool needDataspaceOverride =
+ requestedConfiguration3_2.streams[i].dataSpace != src.overrideDataSpace;
// Override allowed with IMPLEMENTATION_DEFINED
+ dstStream->setFormatOverride(needFormatOverride);
+ dstStream->setDataSpaceOverride(needDataspaceOverride);
dst->format = overrideFormat;
dst->data_space = overrideDataSpace;
}
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index e3b74d7..86b45cb 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -55,7 +55,7 @@
mStreamSplitter = new Camera3StreamSplitter(mUseHalBufManager);
- uint64_t usage;
+ uint64_t usage = 0;
getEndpointUsage(&usage);
std::unordered_map<size_t, sp<Surface>> initialSurfaces;
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index d73a2f9..2df084b 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -60,6 +60,8 @@
mUsage(0),
mOldUsage(0),
mOldMaxBuffers(0),
+ mOldFormat(-1),
+ mOldDataSpace(HAL_DATASPACE_UNKNOWN),
mPrepared(false),
mPrepareBlockRequest(true),
mPreparedBufferIdx(0),
@@ -67,6 +69,8 @@
mBufferLimitLatency(kBufferLimitLatencyBinSize),
mFormatOverridden(false),
mOriginalFormat(-1),
+ mDataSpaceOverridden(false),
+ mOriginalDataSpace(HAL_DATASPACE_UNKNOWN),
mPhysicalCameraId(physicalCameraId),
mLastTimestamp(0) {
@@ -121,7 +125,9 @@
void Camera3Stream::setFormatOverride(bool formatOverridden) {
mFormatOverridden = formatOverridden;
- if (formatOverridden) mOriginalFormat = camera3_stream::format;
+ if (formatOverridden && mOriginalFormat == -1) {
+ mOriginalFormat = camera3_stream::format;
+ }
}
bool Camera3Stream::isFormatOverridden() const {
@@ -134,7 +140,9 @@
void Camera3Stream::setDataSpaceOverride(bool dataSpaceOverridden) {
mDataSpaceOverridden = dataSpaceOverridden;
- if (dataSpaceOverridden) mOriginalDataSpace = camera3_stream::data_space;
+ if (dataSpaceOverridden && mOriginalDataSpace == HAL_DATASPACE_UNKNOWN) {
+ mOriginalDataSpace = camera3_stream::data_space;
+ }
}
bool Camera3Stream::isDataSpaceOverridden() const {
@@ -250,6 +258,8 @@
mOldUsage = mUsage;
mOldMaxBuffers = camera3_stream::max_buffers;
+ mOldFormat = camera3_stream::format;
+ mOldDataSpace = camera3_stream::data_space;
res = getEndpointUsage(&mUsage);
if (res != OK) {
@@ -324,7 +334,9 @@
// so. As documented in hardware/camera3.h:configure_streams().
if (mState == STATE_IN_RECONFIG &&
mOldUsage == mUsage &&
- mOldMaxBuffers == camera3_stream::max_buffers && !mDataSpaceOverridden) {
+ mOldMaxBuffers == camera3_stream::max_buffers &&
+ mOldDataSpace == camera3_stream::data_space &&
+ mOldFormat == camera3_stream::format) {
mState = STATE_CONFIGURED;
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index c916fe8..533318f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -540,8 +540,12 @@
uint64_t mUsage;
private:
+ // Previously configured stream properties (post HAL override)
uint64_t mOldUsage;
uint32_t mOldMaxBuffers;
+ int mOldFormat;
+ android_dataspace mOldDataSpace;
+
Condition mOutputBufferReturnedSignal;
Condition mInputBufferReturnedSignal;
static const nsecs_t kWaitForBufferDuration = 3000000000LL; // 3000 ms