Merge "Camera: Update listeners about permission changes"
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index 8c19e1d..b200abf 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -5688,13 +5688,17 @@
*
* <p>The ID of the active physical camera that's backing the logical camera. All camera
* streams and metadata that are not physical camera specific will be originating from this
- * physical camera. This must be one of valid physical IDs advertised in the physicalIds
- * static tag.</p>
+ * physical camera.</p>
* <p>For a logical camera made up of physical cameras where each camera's lenses have
* different characteristics, the camera device may choose to switch between the physical
* cameras when application changes FOCAL_LENGTH or SCALER_CROP_REGION.
* At the time of lens switch, this result metadata reflects the new active physical camera
* ID.</p>
+ * <p>This key will be available if the camera device advertises this key via {@link ACAMERA_REQUEST_AVAILABLE_RESULT_KEYS }.
+ * When available, this must be one of valid physical IDs backing this logical multi-camera.
+ * If this key is not available for a logical multi-camera, the camera device implementation
+ * may still switch between different active physical cameras based on use case, but the
+ * current active physical camera information won't be available to the application.</p>
*/
ACAMERA_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID = // byte
ACAMERA_LOGICAL_MULTI_CAMERA_START + 2,
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 7a444a3..fb6af93 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -99,6 +99,34 @@
*/
virtual size_t numClientBuffers() const = 0;
+ void handleImageData(const sp<Codec2Buffer> &buffer) {
+ sp<ABuffer> imageDataCandidate = buffer->getImageData();
+ if (imageDataCandidate == nullptr) {
+ return;
+ }
+ sp<ABuffer> imageData;
+ if (!mFormat->findBuffer("image-data", &imageData)
+ || imageDataCandidate->size() != imageData->size()
+ || memcmp(imageDataCandidate->data(), imageData->data(), imageData->size()) != 0) {
+ ALOGD("[%s] updating image-data", mName);
+ sp<AMessage> newFormat = dupFormat();
+ newFormat->setBuffer("image-data", imageDataCandidate);
+ MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
+ if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
+ int32_t stride = img->mPlane[0].mRowInc;
+ newFormat->setInt32(KEY_STRIDE, stride);
+ ALOGD("[%s] updating stride = %d", mName, stride);
+ if (img->mNumPlanes > 1 && stride > 0) {
+ int32_t vstride = (img->mPlane[1].mOffset - img->mPlane[0].mOffset) / stride;
+ newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
+ ALOGD("[%s] updating vstride = %d", mName, vstride);
+ }
+ }
+ setFormat(newFormat);
+ buffer->setFormat(newFormat);
+ }
+ }
+
protected:
std::string mComponentName; ///< name of component for debugging
std::string mChannelName; ///< name of channel for debugging
@@ -255,34 +283,6 @@
mSkipCutBuffer = scb;
}
- void handleImageData(const sp<Codec2Buffer> &buffer) {
- sp<ABuffer> imageDataCandidate = buffer->getImageData();
- if (imageDataCandidate == nullptr) {
- return;
- }
- sp<ABuffer> imageData;
- if (!mFormat->findBuffer("image-data", &imageData)
- || imageDataCandidate->size() != imageData->size()
- || memcmp(imageDataCandidate->data(), imageData->data(), imageData->size()) != 0) {
- ALOGD("[%s] updating image-data", mName);
- sp<AMessage> newFormat = dupFormat();
- newFormat->setBuffer("image-data", imageDataCandidate);
- MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
- if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
- int32_t stride = img->mPlane[0].mRowInc;
- newFormat->setInt32(KEY_STRIDE, stride);
- ALOGD("[%s] updating stride = %d", mName, stride);
- if (img->mNumPlanes > 1 && stride > 0) {
- int32_t vstride = (img->mPlane[1].mOffset - img->mPlane[0].mOffset) / stride;
- newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
- ALOGD("[%s] updating vstride = %d", mName, vstride);
- }
- }
- setFormat(newFormat);
- buffer->setFormat(newFormat);
- }
- }
-
protected:
sp<SkipCutBuffer> mSkipCutBuffer;
@@ -783,6 +783,7 @@
status_t err = mImpl.grabBuffer(index, &c2Buffer);
if (err == OK) {
c2Buffer->setFormat(mFormat);
+ handleImageData(c2Buffer);
*buffer = c2Buffer;
return true;
}
@@ -1053,6 +1054,7 @@
return false;
}
*index = mImpl.assignSlot(newBuffer);
+ handleImageData(newBuffer);
*buffer = newBuffer;
return true;
}
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 4200a46..7239302 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1557,6 +1557,21 @@
} else if (!strcmp("A_FLAC", codecID)) {
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
+ } else if ((!strcmp("A_MS/ACM", codecID))) {
+ if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
+ ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
+ codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
+ continue;
+ } else {
+ uint16_t ID = *(uint16_t *)codecPrivate;
+ if (ID == 0x0055) {
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
+ } else {
+ ALOGW("A_MS/ACM unsupported type , continue");
+ continue;
+ }
+ }
} else {
ALOGW("%s is not supported.", codecID);
continue;
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 1a527b3..0e31804 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -60,7 +60,7 @@
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 64 * 1024;
+ def.nBufferSize = 192 * 1024;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
@@ -78,7 +78,7 @@
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 64 * 1024;
+ def.nBufferSize = 192 * 1024;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index 82a0631..4302aee 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -423,6 +423,11 @@
CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
offset += mOtherDataLenBits / 8;
}
+
+ if (i < mNumSubFrames && offset >= buffer->size()) {
+ ALOGW("Skip subframes after %d, total %d", (int)i, (int)mNumSubFrames);
+ break;
+ }
}
if (offset < buffer->size()) {
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index f01947a..8377723 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -21,6 +21,7 @@
"libutils",
"libbinder",
"libandroidicu",
+ "android.hardware.media.omx@1.0",
],
static_libs: [
@@ -33,6 +34,9 @@
"frameworks/av/services/mediaresourcemanager",
],
+ // back to 32-bit, b/126502613
+ compile_multilib: "32",
+
init_rc: ["mediaserver.rc"],
cflags: [
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 0b274a7..f9f1acc 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -85,7 +85,6 @@
"libutils",
"libcutils",
"libnativewindow",
- "libandroid_runtime",
"libbinder",
"libhidlbase",
"libgui",
@@ -94,6 +93,12 @@
"libmediandk_utils",
],
+ required: [
+ // libmediandk may be used by Java and non-Java things. When lower-level things use it,
+ // they shouldn't have to take on the cost of loading libandroid_runtime.
+ "libandroid_runtime",
+ ],
+
export_include_dirs: ["include"],
product_variables: {
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index b010aa9..bcc7ff3 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -25,7 +25,7 @@
#include <cutils/atomic.h>
#include <utils/Log.h>
#include <android_media_Utils.h>
-#include <android_runtime/android_view_Surface.h>
+#include <ui/PublicFormat.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <grallocusage/GrallocUsageConversion.h>
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
@@ -272,8 +272,8 @@
media_status_t
AImageReader::init() {
PublicFormat publicFormat = static_cast<PublicFormat>(mFormat);
- mHalFormat = android_view_Surface_mapPublicFormatToHalFormat(publicFormat);
- mHalDataSpace = android_view_Surface_mapPublicFormatToHalDataspace(publicFormat);
+ mHalFormat = mapPublicFormatToHalFormat(publicFormat);
+ mHalDataSpace = mapPublicFormatToHalDataspace(publicFormat);
mHalUsage = AHardwareBuffer_convertToGrallocUsageBits(mUsage);
sp<IGraphicBufferProducer> gbProducer;
diff --git a/media/ndk/NdkMediaCrypto.cpp b/media/ndk/NdkMediaCrypto.cpp
index b8af5ff..ce2c660 100644
--- a/media/ndk/NdkMediaCrypto.cpp
+++ b/media/ndk/NdkMediaCrypto.cpp
@@ -29,7 +29,6 @@
#include <binder/IServiceManager.h>
#include <media/ICrypto.h>
#include <media/IMediaDrmService.h>
-#include <android_runtime/AndroidRuntime.h>
#include <android_util_Binder.h>
#include <jni.h>
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 1abee93..0891f2a 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -23,9 +23,7 @@
#include <jni.h>
#include <unistd.h>
-#include <android_runtime/AndroidRuntime.h>
-#include <android_util_Binder.h>
-#include <binder/IServiceManager.h>
+#include <binder/IBinder.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
@@ -41,8 +39,67 @@
#include "../../libstagefright/include/NuCachedSource2.h"
#include "NdkMediaDataSourceCallbacksPriv.h"
+#include <mutex> // std::call_once,once_flag
+#include <dlfcn.h> // dlopen
+
using namespace android;
+// load libandroid_runtime.so lazily.
+// A vendor process may use libmediandk but should not depend on libandroid_runtime.
+// TODO(jooyung): remove duplicate (b/125550121)
+// frameworks/native/libs/binder/ndk/ibinder_jni.cpp
+namespace {
+
+typedef JNIEnv* (*getJNIEnv_t)();
+typedef sp<IBinder> (*ibinderForJavaObject_t)(JNIEnv* env, jobject obj);
+
+getJNIEnv_t getJNIEnv_;
+ibinderForJavaObject_t ibinderForJavaObject_;
+
+std::once_flag mLoadFlag;
+
+void load() {
+ std::call_once(mLoadFlag, []() {
+ void* handle = dlopen("libandroid_runtime.so", RTLD_LAZY);
+ if (handle == nullptr) {
+ ALOGE("Could not open libandroid_runtime.");
+ return;
+ }
+
+ getJNIEnv_ = reinterpret_cast<getJNIEnv_t>(
+ dlsym(handle, "_ZN7android14AndroidRuntime9getJNIEnvEv"));
+ if (getJNIEnv_ == nullptr) {
+ ALOGE("Could not find AndroidRuntime::getJNIEnv.");
+ // no return
+ }
+
+ ibinderForJavaObject_ = reinterpret_cast<ibinderForJavaObject_t>(
+ dlsym(handle, "_ZN7android20ibinderForJavaObjectEP7_JNIEnvP8_jobject"));
+ if (ibinderForJavaObject_ == nullptr) {
+ ALOGE("Could not find ibinderForJavaObject.");
+ // no return
+ }
+ });
+}
+
+JNIEnv* getJNIEnv() {
+ load();
+ if (getJNIEnv_ == nullptr) {
+ return nullptr;
+ }
+ return (getJNIEnv_)();
+}
+
+sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
+ load();
+ if (ibinderForJavaObject_ == nullptr) {
+ return nullptr;
+ }
+ return (ibinderForJavaObject_)(env, obj);
+}
+
+} // namespace
+
struct AMediaDataSource {
void *userdata;
AMediaDataSourceReadAt readAt;
@@ -124,9 +181,14 @@
if (obj == NULL) {
return NULL;
}
+ sp<IBinder> binder;
switch (version) {
case 1:
- return interface_cast<IMediaHTTPService>(ibinderForJavaObject(env, obj));
+ binder = ibinderForJavaObject(env, obj);
+ if (binder == NULL) {
+ return NULL;
+ }
+ return interface_cast<IMediaHTTPService>(binder);
case 2:
return new JMedia2HTTPService(env, obj);
default:
@@ -179,7 +241,7 @@
switch (version) {
case 1:
- env = AndroidRuntime::getJNIEnv();
+ env = getJNIEnv();
clazz = "android/media/MediaHTTPService";
method = "createHttpServiceBinderIfNecessary";
signature = "(Ljava/lang/String;)Landroid/os/IBinder;";
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 28e4f12..c83b255 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -34,7 +34,6 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NuMediaExtractor.h>
#include <media/IMediaHTTPService.h>
-#include <android_runtime/AndroidRuntime.h>
#include <android_util_Binder.h>
#include <jni.h>
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 7cc7f16..768a7a9 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -26,7 +26,6 @@
#include <utils/StrongPointer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <android_runtime/AndroidRuntime.h>
#include <android_util_Binder.h>
#include <jni.h>
diff --git a/media/ndk/NdkMediaMuxer.cpp b/media/ndk/NdkMediaMuxer.cpp
index e79926d..d1992bf 100644
--- a/media/ndk/NdkMediaMuxer.cpp
+++ b/media/ndk/NdkMediaMuxer.cpp
@@ -30,7 +30,6 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaMuxer.h>
#include <media/IMediaHTTPService.h>
-#include <android_runtime/AndroidRuntime.h>
#include <android_util_Binder.h>
#include <jni.h>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8a45fc2..8f181a4 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -842,6 +842,12 @@
mIoJitterMs.toString().c_str());
}
+ if (mLatencyMs.getN() > 0) {
+ dprintf(fd, " Threadloop %s latency stats: %s\n",
+ isOutput() ? "write" : "read",
+ mLatencyMs.toString().c_str());
+ }
+
if (locked) {
mLock.unlock();
}
@@ -3380,6 +3386,14 @@
}
}
}
+
+ if (audio_has_proportional_frames(mFormat)) {
+ const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
+ if (latencyMs != 0.) { // note 0. means timestamp is empty.
+ mLatencyMs.add(latencyMs);
+ }
+ }
+
} // if (mType ... ) { // no indentation
#if 0
// logFormat example
@@ -5296,13 +5310,6 @@
dprintf(fd, " Master balance: %f (%s)\n", mMasterBalance.load(),
(hasFastMixer() ? std::to_string(mFastMixer->getMasterBalance())
: mBalance.toString()).c_str());
- const double latencyMs = mTimestamp.getOutputServerLatencyMs(mSampleRate);
- if (latencyMs != 0.) {
- dprintf(fd, " NormalMixer latency ms: %.2lf\n", latencyMs);
- } else {
- dprintf(fd, " NormalMixer latency ms: unavail\n");
- }
-
if (hasFastMixer()) {
dprintf(fd, " FastMixer thread %p tid=%d", mFastMixer.get(), mFastMixer->getTid());
@@ -7042,6 +7049,15 @@
mTimestampVerifier.error();
}
}
+
+ // From the timestamp, input read latency is negative output write latency.
+ const audio_input_flags_t flags = mInput != NULL ? mInput->flags : AUDIO_INPUT_FLAG_NONE;
+ const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
+ ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
+ if (latencyMs != 0.) { // note 0. means timestamp is empty.
+ mLatencyMs.add(latencyMs);
+ }
+
// Use this to track timestamp information
// ALOGD("%s", mTimestamp.toString().c_str());
@@ -7734,14 +7750,6 @@
(void)input->stream->dump(fd);
}
- const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
- ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
- if (latencyMs != 0.) {
- dprintf(fd, " NormalRecord latency ms: %.2lf\n", latencyMs);
- } else {
- dprintf(fd, " NormalRecord latency ms: unavail\n");
- }
-
dprintf(fd, " Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
dprintf(fd, " Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 4968829..1afea08 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -520,6 +520,7 @@
// This should be read under ThreadBase lock (if not on the threadLoop thread).
audio_utils::Statistics<double> mIoJitterMs{0.995 /* alpha */};
audio_utils::Statistics<double> mProcessTimeMs{0.995 /* alpha */};
+ audio_utils::Statistics<double> mLatencyMs{0.995 /* alpha */};
bool mIsMsdDevice = false;
// A condition that must be evaluated by the thread loop has changed and
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
index 996347b..4af93e1 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioGain.h
@@ -20,6 +20,7 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <system/audio.h>
+#include <vector>
namespace android {
@@ -59,12 +60,36 @@
void getDefaultConfig(struct audio_gain_config *config);
status_t checkConfig(const struct audio_gain_config *config);
+ void setUseForVolume(bool canUseForVolume) { mUseForVolume = canUseForVolume; }
+ bool canUseForVolume() const { return mUseForVolume; }
+
const struct audio_gain &getGain() const { return mGain; }
private:
int mIndex;
struct audio_gain mGain;
bool mUseInChannelMask;
+ bool mUseForVolume = false;
+};
+
+class AudioGains : public std::vector<sp<AudioGain> >
+{
+public:
+ bool canUseForVolume() const
+ {
+ for (const auto &gain: *this) {
+ if (gain->canUseForVolume()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ int32_t add(const sp<AudioGain> gain)
+ {
+ push_back(gain);
+ return 0;
+ }
};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index cf9519b..704f404 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -98,7 +98,7 @@
ActivityTracking::dump(dst, spaces);
dst->appendFormat(", Volume: %.03f, MuteCount: %02d\n", mCurVolumeDb, mMuteCount);
}
- void setVolume(float volume) { mCurVolumeDb = volume; }
+ void setVolume(float volumeDb) { mCurVolumeDb = volumeDb; }
float getVolume() const { return mCurVolumeDb; }
private:
@@ -156,7 +156,7 @@
virtual bool isDuplicated() const { return false; }
virtual uint32_t latency() { return 0; }
virtual bool isFixedVolume(audio_devices_t device);
- virtual bool setVolume(float volume,
+ virtual bool setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t delayMs,
@@ -219,10 +219,10 @@
{
return mVolumeActivities[vs].decMuteCount();
}
- void setCurVolume(VolumeSource vs, float volume)
+ void setCurVolume(VolumeSource vs, float volumeDb)
{
// Even if not activity for this group registered, need to create anyway
- mVolumeActivities[vs].setVolume(volume);
+ mVolumeActivities[vs].setVolume(volumeDb);
}
float getCurVolume(VolumeSource vs) const
{
@@ -327,7 +327,7 @@
setClientActive(client, false);
}
}
- virtual bool setVolume(float volume,
+ virtual bool setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t delayMs,
@@ -401,7 +401,7 @@
void dump(String8 *dst) const override;
- virtual bool setVolume(float volume,
+ virtual bool setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t delayMs,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 1b5a2d6..2d182bd 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -18,6 +18,7 @@
#include "AudioCollections.h"
#include "AudioProfile.h"
+#include "AudioGain.h"
#include "HandleGenerator.h"
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -29,9 +30,7 @@
namespace android {
class HwModule;
-class AudioGain;
class AudioRoute;
-typedef Vector<sp<AudioGain> > AudioGainCollection;
class AudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
{
@@ -49,8 +48,8 @@
virtual const String8 getTagName() const = 0;
- void setGains(const AudioGainCollection &gains) { mGains = gains; }
- const AudioGainCollection &getGains() const { return mGains; }
+ void setGains(const AudioGains &gains) { mGains = gains; }
+ const AudioGains &getGains() const { return mGains; }
virtual void setFlags(uint32_t flags)
{
@@ -138,7 +137,7 @@
void log(const char* indent) const;
- AudioGainCollection mGains; // gain controllers
+ AudioGains mGains; // gain controllers
private:
void pickChannelMask(audio_channel_mask_t &channelMask, const ChannelsVector &channelMasks) const;
@@ -165,6 +164,8 @@
return (other != 0) && (other->getAudioPort() != 0) && (getAudioPort() != 0) &&
(other->getAudioPort()->getModuleHandle() == getAudioPort()->getModuleHandle());
}
+ bool hasGainController(bool canUseForVolume = false) const;
+
unsigned int mSamplingRate = 0u;
audio_format_t mFormat = AUDIO_FORMAT_INVALID;
audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_NONE;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 7293bc4..fd33649 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -149,7 +149,7 @@
return false;
}
-bool AudioOutputDescriptor::setVolume(float volume,
+bool AudioOutputDescriptor::setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device __unused,
uint32_t delayMs,
@@ -158,9 +158,9 @@
// We actually change the volume if:
// - the float value returned by computeVolume() changed
// - the force flag is set
- if (volume != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
- ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volume, delayMs);
- setCurVolume(static_cast<VolumeSource>(stream), volume);
+ if (volumeDb != getCurVolume(static_cast<VolumeSource>(stream)) || force) {
+ ALOGV("setVolume() for stream %d, volume %f, delay %d", stream, volumeDb, delayMs);
+ setCurVolume(static_cast<VolumeSource>(stream), volumeDb);
return true;
}
return false;
@@ -388,15 +388,39 @@
mFlags & AUDIO_OUTPUT_FLAG_FAST ? AUDIO_LATENCY_LOW : AUDIO_LATENCY_NORMAL;
}
-bool SwAudioOutputDescriptor::setVolume(float volume,
+bool SwAudioOutputDescriptor::setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t delayMs,
bool force)
{
- if (!AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force)) {
+ if (!AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force)) {
return false;
}
+ if (!devices().isEmpty()) {
+ // Assume first device to check upon Gain Crontroller availability
+ const auto &devicePort = devices().itemAt(0);
+ ALOGV("%s: device %s hasGC %d", __FUNCTION__,
+ devicePort->toString().c_str(), devices().itemAt(0)->hasGainController(true));
+ if (devicePort->hasGainController(true)) {
+ // @todo: default stream volume to max (0) when using HW Port gain?
+ float volumeAmpl = Volume::DbToAmpl(0);
+ mClientInterface->setStreamVolume(stream, volumeAmpl, mIoHandle, delayMs);
+
+ AudioGains gains = devicePort->getGains();
+ int gainMinValueInMb = gains[0]->getMinValueInMb();
+ int gainMaxValueInMb = gains[0]->getMaxValueInMb();
+ int gainStepValueInMb = gains[0]->getStepValueInMb();
+ int gainValueMb = ((volumeDb * 100)/ gainStepValueInMb) * gainStepValueInMb;
+ gainValueMb = std::max(gainMinValueInMb, std::min(gainValueMb, gainMaxValueInMb));
+
+ audio_port_config config = {};
+ devicePort->toAudioPortConfig(&config);
+ config.config_mask = AUDIO_PORT_CONFIG_GAIN;
+ config.gain.values[0] = gainValueMb;
+ return mClientInterface->setAudioPortConfig(&config, 0) == NO_ERROR;
+ }
+ }
// Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is enabled
float volumeAmpl = Volume::DbToAmpl(getCurVolume(static_cast<VolumeSource>(stream)));
if (stream == AUDIO_STREAM_BLUETOOTH_SCO) {
@@ -591,13 +615,13 @@
}
-bool HwAudioOutputDescriptor::setVolume(float volume,
+bool HwAudioOutputDescriptor::setVolume(float volumeDb,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t delayMs,
bool force)
{
- bool changed = AudioOutputDescriptor::setVolume(volume, stream, device, delayMs, force);
+ bool changed = AudioOutputDescriptor::setVolume(volumeDb, stream, device, delayMs, force);
if (changed) {
// TODO: use gain controller on source device if any to adjust volume
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 9fcf5e7..a66c695 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -479,4 +479,14 @@
dstConfig, srcConfig, AUDIO_PORT_CONFIG_FLAGS, { AUDIO_INPUT_FLAG_NONE });
}
+bool AudioPortConfig::hasGainController(bool canUseForVolume) const
+{
+ sp<AudioPort> audioport = getAudioPort();
+ if (audioport == nullptr) {
+ return false;
+ }
+ return canUseForVolume ? audioport->getGains().canUseForVolume()
+ : audioport->getGains().size() > 0;
+}
+
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 81d3968..5f820c2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -64,7 +64,7 @@
}
};
-struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGainCollection>
+struct AudioGainTraits : public AndroidCollectionTraits<AudioGain, AudioGains>
{
static constexpr const char *tag = "gain";
static constexpr const char *collectionTag = "gains";
@@ -84,6 +84,9 @@
static constexpr const char *minRampMs = "minRampMs";
/** needed if mode AUDIO_GAIN_MODE_RAMP. */
static constexpr const char *maxRampMs = "maxRampMs";
+ /** needed to allow use setPortGain instead of setStreamVolume. */
+ static constexpr const char *useForVolume = "useForVolume";
+
};
static Return<Element> deserialize(const xmlNode *cur, PtrSerializingCtx serializingContext);
@@ -375,9 +378,14 @@
if (!maxRampMsLiteral.empty() && convertTo(maxRampMsLiteral, maxRampMs)) {
gain->setMaxRampInMs(maxRampMs);
}
- ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d", __func__,
- gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
- gain->getMaxValueInMb());
+ std::string useForVolumeLiteral = getXmlAttribute(cur, Attributes::useForVolume);
+ bool useForVolume = false;
+ if (!useForVolumeLiteral.empty() && convertTo(useForVolumeLiteral, useForVolume)) {
+ gain->setUseForVolume(useForVolume);
+ }
+ ALOGV("%s: adding new gain mode %08x channel mask %08x min mB %d max mB %d UseForVolume: %d",
+ __func__, gain->getMode(), gain->getChannelMask(), gain->getMinValueInMb(),
+ gain->getMaxValueInMb(), useForVolume);
if (gain->getMode() != 0) {
return gain;
diff --git a/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml b/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml
new file mode 100644
index 0000000..57bd4f8
--- /dev/null
+++ b/services/audiopolicy/config/a2dp_in_audio_policy_configuration.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Bluetooth Input Audio HAL Audio Policy Configuration file -->
+<module name="a2dp" halVersion="2.0">
+ <mixPorts>
+ <mixPort name="a2dp input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="a2dp input"
+ sources="BT A2DP In"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index b4cc1d3..b28381b 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -173,8 +173,8 @@
</module>
- <!-- A2dp Audio HAL -->
- <xi:include href="a2dp_audio_policy_configuration.xml"/>
+ <!-- A2dp Input Audio HAL -->
+ <xi:include href="a2dp_in_audio_policy_configuration.xml"/>
<!-- Usb Audio HAL -->
<xi:include href="usb_audio_policy_configuration.xml"/>
@@ -182,8 +182,8 @@
<!-- Remote Submix Audio HAL -->
<xi:include href="r_submix_audio_policy_configuration.xml"/>
- <!-- Hearing aid Audio HAL -->
- <xi:include href="hearing_aid_audio_policy_configuration.xml"/>
+ <!-- Bluetooth Audio HAL -->
+ <xi:include href="bluetooth_audio_policy_configuration.xml"/>
<!-- MSD Audio HAL (optional) -->
<xi:include href="msd_audio_policy_configuration.xml"/>
diff --git a/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
new file mode 100644
index 0000000..b4cc1d3
--- /dev/null
+++ b/services/audiopolicy/config/audio_policy_configuration_bluetooth_legacy_hal.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="true"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="3.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="deep_buffer" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="compressed_offload" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD|AUDIO_OUTPUT_FLAG_NON_BLOCKING">
+ <profile name="" format="AUDIO_FORMAT_MP3"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ <profile name="" format="AUDIO_FORMAT_AAC_LC"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="voice_tx" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </mixPort>
+ <mixPort name="voice_rx" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-8400"
+ maxValueMB="4000"
+ defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000,16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="Earpiece"
+ sources="primary output,deep_buffer,BT SCO Headset Mic"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,deep_buffer,compressed_offload,BT SCO Headset Mic,Telephony Rx"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
+ <route type="mix" sink="Telephony Tx"
+ sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic, voice_tx"/>
+ <route type="mix" sink="voice_rx"
+ sources="Telephony Rx"/>
+ </routes>
+
+ </module>
+
+ <!-- A2dp Audio HAL -->
+ <xi:include href="a2dp_audio_policy_configuration.xml"/>
+
+ <!-- Usb Audio HAL -->
+ <xi:include href="usb_audio_policy_configuration.xml"/>
+
+ <!-- Remote Submix Audio HAL -->
+ <xi:include href="r_submix_audio_policy_configuration.xml"/>
+
+ <!-- Hearing aid Audio HAL -->
+ <xi:include href="hearing_aid_audio_policy_configuration.xml"/>
+
+ <!-- MSD Audio HAL (optional) -->
+ <xi:include href="msd_audio_policy_configuration.xml"/>
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section:
+ IMPORTANT NOTE: Volume tables have been moved to engine configuration.
+ Keep it here for legacy.
+ Engine will fallback on these files if none are provided by engine.
+ -->
+
+ <xi:include href="audio_policy_volumes.xml"/>
+ <xi:include href="default_volume_tables.xml"/>
+
+ <!-- End of Volume section -->
+
+ <!-- Surround Sound configuration -->
+
+ <xi:include href="surround_sound_configuration_5_0.xml"/>
+
+ <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
new file mode 100644
index 0000000..ce78eb0
--- /dev/null
+++ b/services/audiopolicy/config/bluetooth_audio_policy_configuration.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Bluetooth Audio HAL Audio Policy Configuration file -->
+<module name="bluetooth" halVersion="2.0">
+ <mixPorts>
+ <!-- A2DP Audio Ports -->
+ <mixPort name="a2dp output" role="source"/>
+ <!-- Hearing AIDs Audio Ports -->
+ <mixPort name="hearing aid output" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="24000,16000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- A2DP Audio Ports -->
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100,48000,88200,96000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <!-- Hearing AIDs Audio Ports -->
+ <devicePort tagName="BT Hearing Aid Out" type="AUDIO_DEVICE_OUT_HEARING_AID" role="sink"/>
+ </devicePorts>
+ <routes>
+ <route type="mix" sink="BT A2DP Out"
+ sources="a2dp output"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="a2dp output"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="a2dp output"/>
+ <route type="mix" sink="BT Hearing Aid Out"
+ sources="hearing aid output"/>
+ </routes>
+</module>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c39899c..c969af3 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -33,8 +33,8 @@
#define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
#define AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME \
"audio_policy_configuration_a2dp_offload_disabled.xml"
-#define AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME \
- "audio_policy_configuration_bluetooth_hal_enabled.xml"
+#define AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME \
+ "audio_policy_configuration_bluetooth_legacy_hal.xml"
#include <inttypes.h>
#include <math.h>
@@ -479,36 +479,16 @@
std::vector<audio_format_t> *formats)
{
ALOGV("getHwOffloadEncodingFormatsSupportedForA2DP()");
- char *tok = NULL, *saveptr;
status_t status = NO_ERROR;
- char encoding_formats_list[PROPERTY_VALUE_MAX];
- audio_format_t format = AUDIO_FORMAT_DEFAULT;
- // FIXME This list should not come from a property but the supported encoded
- // formats of declared A2DP devices in primary module
- property_get("persist.bluetooth.a2dp_offload.cap", encoding_formats_list, "");
- tok = strtok_r(encoding_formats_list, "-", &saveptr);
- for (;tok != NULL; tok = strtok_r(NULL, "-", &saveptr)) {
- if (strcmp(tok, "sbc") == 0) {
- ALOGV("%s: SBC offload supported\n",__func__);
- format = AUDIO_FORMAT_SBC;
- } else if (strcmp(tok, "aptx") == 0) {
- ALOGV("%s: APTX offload supported\n",__func__);
- format = AUDIO_FORMAT_APTX;
- } else if (strcmp(tok, "aptxhd") == 0) {
- ALOGV("%s: APTX HD offload supported\n",__func__);
- format = AUDIO_FORMAT_APTX_HD;
- } else if (strcmp(tok, "ldac") == 0) {
- ALOGV("%s: LDAC offload supported\n",__func__);
- format = AUDIO_FORMAT_LDAC;
- } else if (strcmp(tok, "aac") == 0) {
- ALOGV("%s: AAC offload supported\n",__func__);
- format = AUDIO_FORMAT_AAC;
- } else {
- ALOGE("%s: undefined token - %s\n",__func__, tok);
- continue;
- }
- formats->push_back(format);
+ std::unordered_set<audio_format_t> formatSet;
+ sp<HwModule> primaryModule =
+ mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
+ DeviceVector declaredDevices = primaryModule->getDeclaredDevices().getDevicesFromTypeMask(
+ AUDIO_DEVICE_OUT_ALL_A2DP);
+ for (const auto& device : declaredDevices) {
+ formatSet.insert(device->encodedFormats().begin(), device->encodedFormats().end());
}
+ formats->assign(formatSet.begin(), formatSet.end());
return status;
}
@@ -4182,17 +4162,17 @@
status_t ret;
if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) {
- if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+ if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) &&
+ property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+ // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offlaod) are disabled, and uses
+ // the legacy hardware module for A2DP and hearing aid.
+ fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
+ } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
+ // A2DP offload supported but disabled: try to use special XML file
fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
- } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.enabled", false)) {
- // This property persist.bluetooth.bluetooth_audio_hal.enabled is temporary only.
- // xml files AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME, although having
- // the same name, must be different in offload and non offload cases in device
- // specific configuration file.
- fileNames.push_back(AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME);
}
- } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.enabled", false)) {
- fileNames.push_back(AUDIO_POLICY_BLUETOOTH_HAL_ENABLED_XML_CONFIG_FILE_NAME);
+ } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) {
+ fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
}
fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);
@@ -5159,7 +5139,7 @@
if ((hasVoiceStream(streams) &&
(isInCall() || mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc))) ||
- (hasStream(streams, AUDIO_STREAM_ALARM) &&
+ ((hasStream(streams, AUDIO_STREAM_ALARM) || hasStream(streams, AUDIO_STREAM_ENFORCED_AUDIBLE)) &&
mOutputs.isStrategyActiveOnSameModule(productStrategy, outputDesc)) ||
outputDesc->isStrategyActive(productStrategy)) {
// Retrieval of devices for voice DL is done on primary output profile, cannot
@@ -5632,7 +5612,7 @@
audio_devices_t device)
{
auto &curves = getVolumeCurves(stream);
- float volumeDB = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
+ float volumeDb = curves.volIndexToDb(Volume::getDeviceCategory(device), index);
// handle the case of accessibility active while a ringtone is playing: if the ringtone is much
// louder than the accessibility prompt, the prompt cannot be heard, thus masking the touch
@@ -5642,7 +5622,7 @@
&& (AUDIO_MODE_RINGTONE == mEngine->getPhoneState())
&& isStreamActive(AUDIO_STREAM_RING, 0)) {
const float ringVolumeDB = computeVolume(AUDIO_STREAM_RING, index, device);
- return ringVolumeDB - 4 > volumeDB ? ringVolumeDB - 4 : volumeDB;
+ return ringVolumeDB - 4 > volumeDb ? ringVolumeDB - 4 : volumeDb;
}
// in-call: always cap volume by voice volume + some low headroom
@@ -5661,10 +5641,10 @@
const float maxVoiceVolDb =
computeVolume(AUDIO_STREAM_VOICE_CALL, voiceVolumeIndex, device)
+ IN_CALL_EARPIECE_HEADROOM_DB;
- if (volumeDB > maxVoiceVolDb) {
+ if (volumeDb > maxVoiceVolDb) {
ALOGV("computeVolume() stream %d at vol=%f overriden by stream %d at vol=%f",
- stream, volumeDB, AUDIO_STREAM_VOICE_CALL, maxVoiceVolDb);
- volumeDB = maxVoiceVolDb;
+ stream, volumeDb, AUDIO_STREAM_VOICE_CALL, maxVoiceVolDb);
+ volumeDb = maxVoiceVolDb;
}
} break;
default:
@@ -5697,7 +5677,7 @@
// just stopped
if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) ||
mLimitRingtoneVolume) {
- volumeDB += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
+ volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
audio_devices_t musicDevice =
mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA),
nullptr, true /*fromCache*/).types();
@@ -5706,29 +5686,29 @@
musicDevice);
float minVolDB = (musicVolDB > SONIFICATION_HEADSET_VOLUME_MIN_DB) ?
musicVolDB : SONIFICATION_HEADSET_VOLUME_MIN_DB;
- if (volumeDB > minVolDB) {
- volumeDB = minVolDB;
+ if (volumeDb > minVolDB) {
+ volumeDb = minVolDB;
ALOGV("computeVolume limiting volume to %f musicVol %f", minVolDB, musicVolDB);
}
if (device & (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP |
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES)) {
// on A2DP, also ensure notification volume is not too low compared to media when
// intended to be played
- if ((volumeDB > -96.0f) &&
- (musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDB)) {
+ if ((volumeDb > -96.0f) &&
+ (musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB > volumeDb)) {
ALOGV("computeVolume increasing volume for stream=%d device=0x%X from %f to %f",
stream, device,
- volumeDB, musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
- volumeDB = musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
+ volumeDb, musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB);
+ volumeDb = musicVolDB - SONIFICATION_A2DP_MAX_MEDIA_DIFF_DB;
}
}
} else if ((Volume::getDeviceForVolume(device) != AUDIO_DEVICE_OUT_SPEAKER) ||
(stream != AUDIO_STREAM_ALARM && stream != AUDIO_STREAM_RING)) {
- volumeDB += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
+ volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB;
}
}
- return volumeDB;
+ return volumeDb;
}
int AudioPolicyManager::rescaleVolumeIndex(int srcIndex,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index d9514f6..8cbf3af 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -450,7 +450,7 @@
for (size_t i =0; i < mAudioRecordClients.size(); i++) {
sp<AudioRecordClient> current = mAudioRecordClients[i];
if (!current->active) continue;
- if (isPrivacySensitive(current->attributes.source)) {
+ if (isPrivacySensitiveSource(current->attributes.source)) {
if (current->startTimeNs > latestSensitiveStartNs) {
latestSensitiveActive = current;
latestSensitiveStartNs = current->startTimeNs;
@@ -489,7 +489,10 @@
bool isLatest = current == latestActive;
bool isLatestSensitive = current == latestSensitiveActive;
bool forceIdle = true;
- if (mUidPolicy->isAssistantUid(current->uid)) {
+
+ if (isVirtualSource(source)) {
+ forceIdle = false;
+ } else if (mUidPolicy->isAssistantUid(current->uid)) {
if (isA11yOnTop) {
if (source == AUDIO_SOURCE_HOTWORD || source == AUDIO_SOURCE_VOICE_RECOGNITION) {
forceIdle = false;
@@ -505,10 +508,6 @@
(source == AUDIO_SOURCE_VOICE_RECOGNITION || source == AUDIO_SOURCE_HOTWORD)) {
forceIdle = false;
}
- } else if (source == AUDIO_SOURCE_VOICE_DOWNLINK ||
- source == AUDIO_SOURCE_VOICE_CALL ||
- (source == AUDIO_SOURCE_VOICE_UPLINK)) {
- forceIdle = false;
} else {
if (!isAssistantOnTop && (isOnTop || isLatest) &&
(!isSensitiveActive || isLatestSensitive)) {
@@ -542,14 +541,27 @@
}
/* static */
-bool AudioPolicyService::isPrivacySensitive(audio_source_t source)
+bool AudioPolicyService::isPrivacySensitiveSource(audio_source_t source)
+{
+ switch (source) {
+ case AUDIO_SOURCE_CAMCORDER:
+ case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+/* static */
+bool AudioPolicyService::isVirtualSource(audio_source_t source)
{
switch (source) {
case AUDIO_SOURCE_VOICE_UPLINK:
case AUDIO_SOURCE_VOICE_DOWNLINK:
case AUDIO_SOURCE_VOICE_CALL:
- case AUDIO_SOURCE_CAMCORDER:
- case AUDIO_SOURCE_VOICE_COMMUNICATION:
+ case AUDIO_SOURCE_REMOTE_SUBMIX:
+ case AUDIO_SOURCE_FM_TUNER:
return true;
default:
break;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index aaace0c..a2e75cd 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -327,7 +327,8 @@
void silenceAllRecordings_l();
- static bool isPrivacySensitive(audio_source_t source);
+ static bool isPrivacySensitiveSource(audio_source_t source);
+ static bool isVirtualSource(audio_source_t source);
// If recording we need to make sure the UID is allowed to do that. If the UID is idle
// then it cannot record and gets buffers with zeros - silence. As soon as the UID
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 923d17a..2794324 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -58,6 +58,8 @@
#include "CameraService.h"
#include "utils/CameraThreadState.h"
+#include <tuple>
+
using namespace android::camera3;
using namespace android::hardware::camera;
using namespace android::hardware::camera::device::V3_2;
@@ -1094,7 +1096,7 @@
hBuf.acquireFence.setTo(acquireFence, /*shouldOwn*/true);
hBuf.releaseFence = nullptr;
- res = mInterface->pushInflightRequestBuffer(bufferId, buffer);
+ res = mInterface->pushInflightRequestBuffer(bufferId, buffer, streamId);
if (res != OK) {
ALOGE("%s: Can't get register request buffers for stream %d: %s (%d)",
__FUNCTION__, streamId, strerror(-res), res);
@@ -2847,12 +2849,19 @@
}
streams.add(outputStream);
- if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
- outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+ if (outputStream->format == HAL_PIXEL_FORMAT_BLOB) {
size_t k = i + ((mInputStream != nullptr) ? 1 : 0); // Input stream if present should
// always occupy the initial entry.
- bufferSizes[k] = static_cast<uint32_t>(
- getJpegBufferSize(outputStream->width, outputStream->height));
+ if (outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+ bufferSizes[k] = static_cast<uint32_t>(
+ getJpegBufferSize(outputStream->width, outputStream->height));
+ } else if (outputStream->data_space ==
+ static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
+ bufferSizes[k] = outputStream->width * outputStream->height;
+ } else {
+ ALOGW("%s: Blob dataSpace %d not supported",
+ __FUNCTION__, outputStream->data_space);
+ }
}
}
@@ -3270,7 +3279,15 @@
std::vector<std::pair<int32_t, int32_t>> inflightKeys;
mInterface->getInflightBufferKeys(&inflightKeys);
- int32_t inputStreamId = (mInputStream != nullptr) ? mInputStream->getId() : -1;
+ // Inflight buffers for HAL buffer manager
+ std::vector<uint64_t> inflightRequestBufferKeys;
+ mInterface->getInflightRequestBufferKeys(&inflightRequestBufferKeys);
+
+ // (streamId, frameNumber, buffer_handle_t*) tuple for all inflight buffers.
+ // frameNumber will be -1 for buffers from HAL buffer manager
+ std::vector<std::tuple<int32_t, int32_t, buffer_handle_t*>> inflightBuffers;
+ inflightBuffers.reserve(inflightKeys.size() + inflightRequestBufferKeys.size());
+
for (auto& pair : inflightKeys) {
int32_t frameNumber = pair.first;
int32_t streamId = pair.second;
@@ -3281,6 +3298,26 @@
__FUNCTION__, frameNumber, streamId);
continue;
}
+ inflightBuffers.push_back(std::make_tuple(streamId, frameNumber, buffer));
+ }
+
+ for (auto& bufferId : inflightRequestBufferKeys) {
+ int32_t streamId = -1;
+ buffer_handle_t* buffer = nullptr;
+ status_t res = mInterface->popInflightRequestBuffer(bufferId, &buffer, &streamId);
+ if (res != OK) {
+ ALOGE("%s: cannot find in-flight buffer %" PRIu64, __FUNCTION__, bufferId);
+ continue;
+ }
+ inflightBuffers.push_back(std::make_tuple(streamId, /*frameNumber*/-1, buffer));
+ }
+
+ int32_t inputStreamId = (mInputStream != nullptr) ? mInputStream->getId() : -1;
+ for (auto& tuple : inflightBuffers) {
+ status_t res = OK;
+ int32_t streamId = std::get<0>(tuple);
+ int32_t frameNumber = std::get<1>(tuple);
+ buffer_handle_t* buffer = std::get<2>(tuple);
camera3_stream_buffer_t streamBuffer;
streamBuffer.buffer = buffer;
@@ -4583,6 +4620,17 @@
return;
}
+void Camera3Device::HalInterface::getInflightRequestBufferKeys(
+ std::vector<uint64_t>* out) {
+ std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
+ out->clear();
+ out->reserve(mRequestedBuffers.size());
+ for (auto& pair : mRequestedBuffers) {
+ out->push_back(pair.first);
+ }
+ return;
+}
+
status_t Camera3Device::HalInterface::pushInflightBufferLocked(
int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer, int acquireFence) {
uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
@@ -4610,9 +4658,9 @@
}
status_t Camera3Device::HalInterface::pushInflightRequestBuffer(
- uint64_t bufferId, buffer_handle_t* buf) {
+ uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
- auto pair = mRequestedBuffers.insert({bufferId, buf});
+ auto pair = mRequestedBuffers.insert({bufferId, {streamId, buf}});
if (!pair.second) {
ALOGE("%s: bufId %" PRIu64 " is already inflight!",
__FUNCTION__, bufferId);
@@ -4623,7 +4671,13 @@
// Find and pop a buffer_handle_t based on bufferId
status_t Camera3Device::HalInterface::popInflightRequestBuffer(
- uint64_t bufferId, /*out*/ buffer_handle_t **buffer) {
+ uint64_t bufferId,
+ /*out*/ buffer_handle_t** buffer,
+ /*optional out*/ int32_t* streamId) {
+ if (buffer == nullptr) {
+ ALOGE("%s: buffer (%p) must not be null", __FUNCTION__, buffer);
+ return BAD_VALUE;
+ }
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
auto it = mRequestedBuffers.find(bufferId);
if (it == mRequestedBuffers.end()) {
@@ -4631,7 +4685,10 @@
__FUNCTION__, bufferId);
return BAD_VALUE;
}
- *buffer = it->second;
+ *buffer = it->second.second;
+ if (streamId != nullptr) {
+ *streamId = it->second.first;
+ }
mRequestedBuffers.erase(it);
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b25d89d..d3bb212 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -320,16 +320,22 @@
status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer);
- // Register a bufId/buffer_handle_t to inflight request buffer
- status_t pushInflightRequestBuffer(uint64_t bufferId, buffer_handle_t* buf);
+ // Register a bufId (streamId, buffer_handle_t) to inflight request buffer
+ status_t pushInflightRequestBuffer(
+ uint64_t bufferId, buffer_handle_t* buf, int32_t streamId);
// Find a buffer_handle_t based on bufferId
- status_t popInflightRequestBuffer(uint64_t bufferId, /*out*/ buffer_handle_t **buffer);
+ status_t popInflightRequestBuffer(uint64_t bufferId,
+ /*out*/ buffer_handle_t** buffer,
+ /*optional out*/ int32_t* streamId = nullptr);
// Get a vector of (frameNumber, streamId) pair of currently inflight
// buffers
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
+ // Get a vector of bufferId of currently inflight buffers
+ void getInflightRequestBufferKeys(std::vector<uint64_t>* out);
+
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
private:
// Always valid
@@ -398,7 +404,7 @@
// Buffers given to HAL through requestStreamBuffer API
std::mutex mRequestedBuffersLock;
- std::unordered_map<uint64_t, buffer_handle_t*> mRequestedBuffers;
+ std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> mRequestedBuffers;
uint32_t mNextStreamConfigCounter = 1;