Merge "Request cpuset change for 1080p HDR using soft decoder" into pi-dev
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index c7d2545..ee3e98e 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7100,7 +7100,7 @@
/**
* <p>The camera device is a monochrome camera that doesn't contain a color filter array,
- * and the pixel values on U and Y planes are all 128.</p>
+ * and the pixel values on U and V planes are all 128.</p>
*/
ACAMERA_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12,
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 92575f2..5f05b42 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -9,12 +9,12 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
- "libutils",
],
static_libs: [
+ "libstagefright_foundation",
"libstagefright_metadatautils",
+ "libutils",
],
name: "libaacextractor",
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index bd8a00c..d962b93 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -9,6 +9,9 @@
shared_libs: [
"liblog",
"libmediaextractor",
+ ],
+
+ static_libs: [
"libstagefright_foundation",
],
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 0160ca4..6282793 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -10,11 +10,11 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
],
static_libs: [
"libFLAC",
+ "libstagefright_foundation",
],
name: "libflacextractor",
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 5412e99..fde09df18 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -9,12 +9,12 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation"
],
static_libs: [
"libmedia_midiiowrapper",
"libsonivox",
+ "libstagefright_foundation"
],
name: "libmidiextractor",
relative_install_path: "extractors",
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index c6cd753..681fd35 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -12,14 +12,14 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
- "libutils",
],
static_libs: [
"libstagefright_flacdec",
+ "libstagefright_foundation",
"libstagefright_metadatautils",
"libwebm",
+ "libutils",
],
name: "libmkvextractor",
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index d93562c..a3aeaca 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -14,10 +14,10 @@
"liblog",
"libmediaextractor",
"libstagefright_foundation",
- "libutils",
],
static_libs: [
+ "libutils",
"libstagefright_id3",
],
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 3fe2336..fa739e8 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -15,13 +15,13 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
- "libutils",
],
static_libs: [
"libstagefright_esds",
+ "libstagefright_foundation",
"libstagefright_id3",
+ "libutils",
],
cflags: [
diff --git a/media/extractors/mpeg2/Android.bp b/media/extractors/mpeg2/Android.bp
index b012b5d..5e4a592 100644
--- a/media/extractors/mpeg2/Android.bp
+++ b/media/extractors/mpeg2/Android.bp
@@ -23,11 +23,11 @@
"liblog",
"libmediaextractor",
"libstagefright_foundation",
- "libutils",
],
static_libs: [
"libstagefright_mpeg2support",
+ "libutils",
],
name: "libmpeg2extractor",
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 2c09a5f..7c6fc75 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -10,11 +10,11 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
- "libutils",
],
static_libs: [
+ "libstagefright_foundation",
+ "libutils",
"libvorbisidec",
],
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 17836bb..067933e 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -9,11 +9,11 @@
shared_libs: [
"liblog",
"libmediaextractor",
- "libstagefright_foundation",
],
static_libs: [
"libfifo",
+ "libstagefright_foundation",
],
name: "libwavextractor",
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 0bdfeac..9204824 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -392,19 +392,25 @@
}
aaudio_result_t AudioStreamInternal::startClient(const android::AudioClient& client,
- audio_port_handle_t *clientHandle) {
+ audio_port_handle_t *portHandle) {
+ ALOGV("%s() called", __func__);
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
return AAUDIO_ERROR_INVALID_STATE;
}
-
- return mServiceInterface.startClient(mServiceStreamHandle, client, clientHandle);
+ aaudio_result_t result = mServiceInterface.startClient(mServiceStreamHandle,
+ client, portHandle);
+ ALOGV("%s(%d) returning %d", __func__, *portHandle, result);
+ return result;
}
-aaudio_result_t AudioStreamInternal::stopClient(audio_port_handle_t clientHandle) {
+aaudio_result_t AudioStreamInternal::stopClient(audio_port_handle_t portHandle) {
+ ALOGV("%s(%d) called", __func__, portHandle);
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return mServiceInterface.stopClient(mServiceStreamHandle, clientHandle);
+ aaudio_result_t result = mServiceInterface.stopClient(mServiceStreamHandle, portHandle);
+ ALOGV("%s(%d) returning %d", __func__, portHandle, result);
+ return result;
}
aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 21d3fa6..a8369c2 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -1231,6 +1231,14 @@
ALOGW("dead IAudioRecord, creating a new one from %s()", from);
++mSequence;
+ const int INITIAL_RETRIES = 3;
+ int retries = INITIAL_RETRIES;
+retry:
+ if (retries < INITIAL_RETRIES) {
+ // refresh the audio configuration cache in this process to make sure we get new
+ // input parameters and new IAudioRecord in createRecord_l()
+ AudioSystem::clearAudioConfigCache();
+ }
mFlags = mOrigFlags;
// if the new IAudioRecord is created, createRecord_l() will modify the
@@ -1239,7 +1247,11 @@
Modulo<uint32_t> position(mProxy->getPosition());
mNewPosition = position + mUpdatePeriod;
status_t result = createRecord_l(position, mOpPackageName);
- if (result == NO_ERROR) {
+
+ if (result != NO_ERROR) {
+ ALOGW("%s(): createRecord_l failed, do not retry", __func__);
+ retries = 0;
+ } else {
if (mActive) {
// callback thread or sync event hasn't changed
// FIXME this fails if we have a new AudioFlinger instance
@@ -1248,6 +1260,14 @@
}
mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
}
+
+ if (result != NO_ERROR) {
+ ALOGW("%s() failed status %d, retries %d", __func__, result, retries);
+ if (--retries > 0) {
+ goto retry;
+ }
+ }
+
if (result != NO_ERROR) {
ALOGW("restoreRecord_l() failed status %d", result);
mActive = false;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 77cfe4d..8c9d3c1 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -24,6 +24,7 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
+#include <cutils/multiuser.h>
#include <media/TimeCheck.h>
#include <private/android_filesystem_config.h>
@@ -904,8 +905,7 @@
case SET_MIC_MUTE:
case SET_LOW_RAM_DEVICE:
case SYSTEM_READY: {
- uid_t multiUserClientUid = IPCThreadState::self()->getCallingUid() % AID_USER_OFFSET;
- if (multiUserClientUid >= AID_APP_START) {
+ if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index a051693..35f9727 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -24,7 +24,7 @@
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
-
+#include <cutils/multiuser.h>
#include <media/AudioEffect.h>
#include <media/IAudioPolicyService.h>
#include <media/TimeCheck.h>
@@ -872,9 +872,10 @@
case INIT_STREAM_VOLUME:
case SET_STREAM_VOLUME:
case REGISTER_POLICY_MIXES:
- case SET_MASTER_MONO: {
- uid_t multiUserClientUid = IPCThreadState::self()->getCallingUid() % AID_USER_OFFSET;
- if (multiUserClientUid >= AID_APP_START) {
+ case SET_MASTER_MONO:
+ case START_AUDIO_SOURCE:
+ case STOP_AUDIO_SOURCE: {
+ if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
IPCThreadState::self()->getCallingUid());
diff --git a/media/libstagefright/id3/Android.bp b/media/libstagefright/id3/Android.bp
index 30008d9..37f9d50 100644
--- a/media/libstagefright/id3/Android.bp
+++ b/media/libstagefright/id3/Android.bp
@@ -16,8 +16,6 @@
cfi: true,
},
},
-
- shared_libs: ["libmedia"],
}
//###############################################################################
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 7f4d819..ff58eb6 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -131,34 +131,22 @@
static_cast<void*>(mHidlMemory->getPointer())) : nullptr;
}
- void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header, OMXNodeInstance::SecureBufferType type) {
+ void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
if (!mCopyFromOmx) {
return;
}
- if (type != OMXNodeInstance::kSecureBufferTypeUnknown) {
- ALOGE("b/77486542");
- android_errorWriteLog(0x534e4554, "77486542");
- return;
- }
-
// check component returns proper range
sp<ABuffer> codec = getBuffer(header, true /* limit */);
memcpy(getPointer() + header->nOffset, codec->data(), codec->size());
}
- void CopyToOMX(const OMX_BUFFERHEADERTYPE *header, OMXNodeInstance::SecureBufferType type) {
+ void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
if (!mCopyToOmx) {
return;
}
- if (type != OMXNodeInstance::kSecureBufferTypeUnknown) {
- ALOGE("b/77486542");
- android_errorWriteLog(0x534e4554, "77486542");
- return;
- }
-
memcpy(header->pBuffer + header->nOffset,
getPointer() + header->nOffset,
header->nFilledLen);
@@ -1705,7 +1693,7 @@
header->nFilledLen = rangeLength;
header->nOffset = rangeOffset;
- buffer_meta->CopyToOMX(header, mSecureBufferType[kPortIndexInput]);
+ buffer_meta->CopyToOMX(header);
}
return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer, fenceFd);
@@ -1993,7 +1981,7 @@
CLOG_ERROR(onFillBufferDone, OMX_ErrorBadParameter,
FULL_BUFFER(NULL, buffer, msg.fenceFd));
}
- buffer_meta->CopyFromOMX(buffer, mSecureBufferType[kPortIndexOutput]);
+ buffer_meta->CopyFromOMX(buffer);
// fix up the buffer info (especially timestamp) if needed
codecBufferFilled(msg);
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
index 2d022ad..c436121 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/OMXNodeInstance.h
@@ -117,12 +117,6 @@
static OMX_CALLBACKTYPE kCallbacks;
- enum SecureBufferType {
- kSecureBufferTypeUnknown,
- kSecureBufferTypeOpaque,
- kSecureBufferTypeNativeHandle,
- };
-
private:
struct CallbackDispatcherThread;
struct CallbackDispatcher;
@@ -161,6 +155,11 @@
IOMX::PortMode mPortMode[2];
// metadata and secure buffer types and graphic buffer mode tracking
MetadataBufferType mMetadataType[2];
+ enum SecureBufferType {
+ kSecureBufferTypeUnknown,
+ kSecureBufferTypeOpaque,
+ kSecureBufferTypeNativeHandle,
+ };
SecureBufferType mSecureBufferType[2];
bool mGraphicBufferEnabled[2];
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 54121cd..949b570 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -28,6 +28,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <cutils/multiuser.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include <binder/Parcel.h>
@@ -1178,16 +1179,59 @@
}
}
+// Filter reserved keys from setParameters() before forwarding to audio HAL or acting upon.
+// Some keys are used for audio routing and audio path configuration and should be reserved for use
+// by audio policy and audio flinger for functional, privacy and security reasons.
+void AudioFlinger::filterReservedParameters(String8& keyValuePairs, uid_t callingUid)
+{
+ static const String8 kReservedParameters[] = {
+ String8(AudioParameter::keyRouting),
+ String8(AudioParameter::keySamplingRate),
+ String8(AudioParameter::keyFormat),
+ String8(AudioParameter::keyChannels),
+ String8(AudioParameter::keyFrameCount),
+ String8(AudioParameter::keyInputSource),
+ String8(AudioParameter::keyMonoOutput),
+ String8(AudioParameter::keyStreamConnect),
+ String8(AudioParameter::keyStreamDisconnect),
+ String8(AudioParameter::keyStreamSupportedFormats),
+ String8(AudioParameter::keyStreamSupportedChannels),
+ String8(AudioParameter::keyStreamSupportedSamplingRates),
+ };
+
+ // multiuser friendly app ID check for requests coming from audioserver
+ if (multiuser_get_app_id(callingUid) == AID_AUDIOSERVER) {
+ return;
+ }
+
+ AudioParameter param = AudioParameter(keyValuePairs);
+ String8 value;
+ for (auto& key : kReservedParameters) {
+ if (param.get(key, value) == NO_ERROR) {
+ ALOGW("%s: filtering key %s value %s from uid %d",
+ __func__, key.string(), value.string(), callingUid);
+ param.remove(key);
+ }
+ }
+ keyValuePairs = param.toString();
+}
+
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
- ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d",
- ioHandle, keyValuePairs.string(), IPCThreadState::self()->getCallingPid());
+ ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
+ ioHandle, keyValuePairs.string(),
+ IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
// check calling permissions
if (!settingsAllowed()) {
return PERMISSION_DENIED;
}
+ String8 filteredKeyValuePairs = keyValuePairs;
+ filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
+
+ ALOGV("%s: filtered keyvalue %s", __func__, filteredKeyValuePairs.string());
+
// AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Mutex::Autolock _l(mLock);
@@ -1198,7 +1242,7 @@
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->setParameters(keyValuePairs);
+ status_t result = dev->setParameters(filteredKeyValuePairs);
// return success if at least one audio device accepts the parameters as not all
// HALs are requested to support all parameters. If no audio device supports the
// requested parameters, the last error is reported.
@@ -1209,7 +1253,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
// disable AEC and NS if the device is a BT SCO headset supporting those pre processings
- AudioParameter param = AudioParameter(keyValuePairs);
+ AudioParameter param = AudioParameter(filteredKeyValuePairs);
String8 value;
if (param.get(String8(AudioParameter::keyBtNrec), value) == NO_ERROR) {
bool btNrecIsOff = (value == AudioParameter::valueOff);
@@ -1242,16 +1286,16 @@
}
} else if (thread == primaryPlaybackThread_l()) {
// indicate output device change to all input threads for pre processing
- AudioParameter param = AudioParameter(keyValuePairs);
+ AudioParameter param = AudioParameter(filteredKeyValuePairs);
int value;
if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
(value != 0)) {
- broacastParametersToRecordThreads_l(keyValuePairs);
+ broacastParametersToRecordThreads_l(filteredKeyValuePairs);
}
}
}
if (thread != 0) {
- return thread->setParameters(keyValuePairs);
+ return thread->setParameters(filteredKeyValuePairs);
}
return BAD_VALUE;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 3302868..963a87d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -798,6 +798,8 @@
status_t checkStreamType(audio_stream_type_t stream) const;
+ void filterReservedParameters(String8& keyValuePairs, uid_t callingUid);
+
#ifdef TEE_SINK
// all record threads serially share a common tee sink, which is re-created on format change
sp<NBAIO_Sink> mRecordTeeSink;
diff --git a/services/audioflinger/BufLog.cpp b/services/audioflinger/BufLog.cpp
index 2780290..ae96036 100644
--- a/services/audioflinger/BufLog.cpp
+++ b/services/audioflinger/BufLog.cpp
@@ -24,6 +24,7 @@
#include <pthread.h>
#include <stdio.h>
#include <string.h>
+#include <audio_utils/string.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -117,7 +118,7 @@
mByteCount = 0l;
mPaused = false;
if (tag != NULL) {
- strncpy(mTag, tag, BUFLOGSTREAM_MAX_TAGSIZE);
+ (void)audio_utils_strlcpy(mTag, tag);
} else {
mTag[0] = 0;
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1517d11..1fa9e37 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8381,7 +8381,9 @@
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
+ mLock.unlock();
callback->onRoutingChanged(deviceId);
+ mLock.lock();
}
mDeviceId = deviceId;
}
@@ -8390,7 +8392,9 @@
sendIoConfigEvent_l(AUDIO_INPUT_CONFIG_CHANGED);
sp<MmapStreamCallback> callback = mCallback.promote();
if (mDeviceId != deviceId && callback != 0) {
+ mLock.unlock();
callback->onRoutingChanged(deviceId);
+ mLock.lock();
}
mDeviceId = deviceId;
}
@@ -8556,7 +8560,9 @@
if (track->isInvalid()) {
sp<MmapStreamCallback> callback = mCallback.promote();
if (callback != 0) {
+ mLock.unlock();
callback->onTearDown(track->portId());
+ mLock.lock();
} else if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
ALOGW("Could not notify MMAP stream tear down: no onTearDown callback!");
mNoCallbackWarningCount++;
@@ -8751,9 +8757,11 @@
for (int i = 0; i < channelCount; i++) {
values.add(volume);
}
- callback->onVolumeChanged(mChannelMask, values);
mHalVolFloat = volume; // SW volume control worked, so update value.
mNoCallbackWarningCount = 0;
+ mLock.unlock();
+ callback->onVolumeChanged(mChannelMask, values);
+ mLock.lock();
} else {
if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
ALOGW("Could not set MMAP stream volume: no volume callback!");
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index e263c0c..e69e687 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -36,6 +36,7 @@
frameworks/av/services/audiopolicy/common/include \
frameworks/av/services/audiopolicy \
frameworks/av/services/audiopolicy/utilities \
+ system/media/audio_utils/include \
ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index caf3c02..09a86dd 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -52,7 +52,7 @@
void setGains(const AudioGainCollection &gains) { mGains = gains; }
const AudioGainCollection &getGains() const { return mGains; }
- void setFlags(uint32_t flags)
+ virtual void setFlags(uint32_t flags)
{
//force direct flag if offload flag is set: offloading implies a direct output stream
// and all common behaviors are driven by checking only the direct flag
diff --git a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
index 24fe7cb..67ac9bc 100644
--- a/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
+++ b/services/audiopolicy/common/managerdefinitions/include/IOProfile.h
@@ -43,6 +43,20 @@
// For a Profile aka MixPort, tag name and name are equivalent.
virtual const String8 getTagName() const { return getName(); }
+ // FIXME: this is needed because shared MMAP stream clients use the same audio session.
+ // Once capture clients are tracked individually and not per session this can be removed
+ // MMAP no IRQ input streams do not have the default limitation of one active client
+ // max as they can be used in shared mode by the same application.
+ // NOTE: this works for explicit values set in audio_policy_configuration.xml because
+ // flags are parsed before maxActiveCount by the serializer.
+ void setFlags(uint32_t flags) override
+ {
+ AudioPort::setFlags(flags);
+ if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
+ maxActiveCount = 0;
+ }
+ }
+
// This method is used for input and direct output, and is not used for other output.
// If parameter updatedSamplingRate is non-NULL, it is assigned the actual sample rate.
// For input, flags is interpreted as audio_input_flags_t.
@@ -55,7 +69,9 @@
audio_format_t *updatedFormat,
audio_channel_mask_t channelMask,
audio_channel_mask_t *updatedChannelMask,
- uint32_t flags) const;
+ // FIXME parameter type
+ uint32_t flags,
+ bool exactMatchRequiredForInputFlags = false) const;
void dump(int fd);
void log();
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index 3b1e751..19c2062 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "APM::Devices"
//#define LOG_NDEBUG 0
+#include <audio_utils/string.h>
#include "DeviceDescriptor.h"
#include "TypeConverter.h"
#include "AudioGain.h"
@@ -247,7 +248,7 @@
// ALOG_ASSERT(mModule != NULL);
dstConfig->ext.device.hw_module =
mModule != 0 ? mModule->getHandle() : AUDIO_MODULE_HANDLE_NONE;
- strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ (void)audio_utils_strlcpy_zerofill(dstConfig->ext.device.address, mAddress.string());
}
void DeviceDescriptor::toAudioPort(struct audio_port *port) const
@@ -258,7 +259,7 @@
toAudioPortConfig(&port->active_config);
port->ext.device.type = mDeviceType;
port->ext.device.hw_module = mModule->getHandle();
- strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ (void)audio_utils_strlcpy_zerofill(port->ext.device.address, mAddress.string());
}
void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 69dd06b..fbc2384 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -35,7 +35,9 @@
audio_format_t *updatedFormat,
audio_channel_mask_t channelMask,
audio_channel_mask_t *updatedChannelMask,
- uint32_t flags) const
+ // FIXME type punning here
+ uint32_t flags,
+ bool exactMatchRequiredForInputFlags) const
{
const bool isPlaybackThread =
getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
@@ -90,7 +92,7 @@
// An existing normal stream is compatible with a fast track request,
// but the fast request will be denied by AudioFlinger and converted to normal track.
if (isRecordThread && ((getFlags() ^ flags) &
- ~AUDIO_INPUT_FLAG_FAST)) {
+ ~(exactMatchRequiredForInputFlags ? AUDIO_INPUT_FLAG_NONE : AUDIO_INPUT_FLAG_FAST))) {
return false;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0d36266..a54a71f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1602,10 +1602,11 @@
// sampling rate and flags may be updated by getInputProfile
uint32_t profileSamplingRate = (config->sample_rate == 0) ?
SAMPLE_RATE_HZ_DEFAULT : config->sample_rate;
- audio_format_t profileFormat = config->format;
+ audio_format_t profileFormat;
audio_channel_mask_t profileChannelMask = config->channel_mask;
audio_input_flags_t profileFlags = flags;
for (;;) {
+ profileFormat = config->format; // reset each time through loop, in case it is updated
profile = getInputProfile(device, address,
profileSamplingRate, profileFormat, profileChannelMask,
profileFlags);
@@ -5057,21 +5058,46 @@
// TODO: perhaps isCompatibleProfile should return a "matching" score so we can return
// the best matching profile, not the first one.
+ sp<IOProfile> firstInexact;
+ uint32_t updatedSamplingRate = 0;
+ audio_format_t updatedFormat = AUDIO_FORMAT_INVALID;
+ audio_channel_mask_t updatedChannelMask = AUDIO_CHANNEL_INVALID;
for (const auto& hwModule : mHwModules) {
for (const auto& profile : hwModule->getInputProfiles()) {
// profile->log();
+ //updatedFormat = format;
if (profile->isCompatibleProfile(device, address, samplingRate,
- &samplingRate /*updatedSamplingRate*/,
+ &samplingRate /*updatedSamplingRate*/,
format,
- &format /*updatedFormat*/,
+ &format, /*updatedFormat*/
channelMask,
- &channelMask /*updatedChannelMask*/,
- (audio_output_flags_t) flags)) {
-
+ &channelMask /*updatedChannelMask*/,
+ // FIXME ugly cast
+ (audio_output_flags_t) flags,
+ true /*exactMatchRequiredForInputFlags*/)) {
return profile;
}
+ if (firstInexact == nullptr && profile->isCompatibleProfile(device, address,
+ samplingRate,
+ &updatedSamplingRate,
+ format,
+ &updatedFormat,
+ channelMask,
+ &updatedChannelMask,
+ // FIXME ugly cast
+ (audio_output_flags_t) flags,
+ false /*exactMatchRequiredForInputFlags*/)) {
+ firstInexact = profile;
+ }
+
}
}
+ if (firstInexact != nullptr) {
+ samplingRate = updatedSamplingRate;
+ format = updatedFormat;
+ channelMask = updatedChannelMask;
+ return firstInexact;
+ }
return NULL;
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 8f0c846..cf24c13 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -44,6 +44,7 @@
ALOGV("setDeviceConnectionState()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setDeviceConnectionState(device, state,
device_address, device_name);
}
@@ -55,6 +56,7 @@
if (mAudioPolicyManager == NULL) {
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getDeviceConnectionState(device,
device_address);
}
@@ -72,6 +74,7 @@
ALOGV("handleDeviceConfigChange()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->handleDeviceConfigChange(device, device_address,
device_name);
}
@@ -94,10 +97,10 @@
// operation from policy manager standpoint (no other operation (e.g track start or stop)
// can be interleaved).
Mutex::Autolock _l(mLock);
-
// TODO: check if it is more appropriate to do it in platform specific policy manager
AudioSystem::setMode(state);
+ AutoCallerClear acc;
mAudioPolicyManager->setPhoneState(state);
mPhoneState = state;
return NO_ERROR;
@@ -126,6 +129,7 @@
}
ALOGV("setForceUse()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->setForceUse(usage, config);
return NO_ERROR;
}
@@ -138,6 +142,7 @@
if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
return AUDIO_POLICY_FORCE_NONE;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getForceUse(usage);
}
@@ -151,6 +156,7 @@
}
ALOGV("getOutput()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getOutput(stream);
}
@@ -178,6 +184,7 @@
uid = callingUid;
}
audio_output_flags_t originalFlags = flags;
+ AutoCallerClear acc;
status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
&flags, selectedDeviceId, portId);
@@ -223,6 +230,7 @@
}
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->startOutput(output, stream, session);
}
@@ -259,6 +267,7 @@
}
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->stopOutput(output, stream, session);
}
@@ -279,6 +288,7 @@
{
ALOGV("doReleaseOutput from tid %d", gettid());
Mutex::Autolock _l(mLock);
+ // called from internal thread: no need to clear caller identity
mAudioPolicyManager->releaseOutput(output, stream, session);
}
@@ -337,11 +347,14 @@
AudioPolicyInterface::input_type_t inputType;
Mutex::Autolock _l(mLock);
- // the audio_in_acoustics_t parameter is ignored by get_input()
- status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
- config,
- flags, selectedDeviceId,
- &inputType, portId);
+ {
+ AutoCallerClear acc;
+ // the audio_in_acoustics_t parameter is ignored by get_input()
+ status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
+ config,
+ flags, selectedDeviceId,
+ &inputType, portId);
+ }
audioPolicyEffects = mAudioPolicyEffects;
if (status == NO_ERROR) {
@@ -372,6 +385,7 @@
if (status != NO_ERROR) {
if (status == PERMISSION_DENIED) {
+ AutoCallerClear acc;
mAudioPolicyManager->releaseInput(*input, session);
}
return status;
@@ -425,8 +439,12 @@
AudioPolicyInterface::concurrency_type__mask_t concurrency =
AudioPolicyInterface::API_INPUT_CONCURRENCY_NONE;
- status_t status = mAudioPolicyManager->startInput(
- client->input, client->session, *silenced, &concurrency);
+ status_t status;
+ {
+ AutoCallerClear acc;
+ status = mAudioPolicyManager->startInput(
+ client->input, client->session, *silenced, &concurrency);
+ }
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(concurrency & ~AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL,
@@ -461,7 +479,7 @@
// finish the recording app op
finishRecording(client->opPackageName, client->uid);
-
+ AutoCallerClear acc;
return mAudioPolicyManager->stopInput(client->input, client->session);
}
@@ -494,6 +512,7 @@
}
{
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->releaseInput(client->input, client->session);
}
}
@@ -512,6 +531,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax);
return NO_ERROR;
}
@@ -530,6 +550,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setStreamVolumeIndex(stream,
index,
device);
@@ -546,6 +567,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getStreamVolumeIndex(stream,
index,
device);
@@ -559,6 +581,7 @@
if (mAudioPolicyManager == NULL) {
return 0;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getStrategyForStream(stream);
}
@@ -573,6 +596,7 @@
return AUDIO_DEVICE_NONE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getDevicesForStream(stream);
}
@@ -583,6 +607,7 @@
return 0;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getOutputForEffect(desc);
}
@@ -596,6 +621,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
}
@@ -605,6 +631,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->unregisterEffect(id);
}
@@ -614,6 +641,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setEffectEnabled(id, enabled);
}
@@ -626,6 +654,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isStreamActive(stream, inPastMs);
}
@@ -638,6 +667,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs);
}
@@ -647,6 +677,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isSourceActive(source);
}
@@ -680,6 +711,7 @@
Mutex::Autolock _l(mLock);
Mutex::Autolock _le(mEffectsLock); // isOffloadSupported queries for
// non-offloadable effects
+ AutoCallerClear acc;
return mAudioPolicyManager->isOffloadSupported(info);
}
@@ -693,7 +725,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
}
@@ -703,7 +735,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->getAudioPort(port);
}
@@ -717,6 +749,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->createAudioPatch(patch, handle,
IPCThreadState::self()->getCallingUid());
}
@@ -730,7 +763,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->releaseAudioPatch(handle,
IPCThreadState::self()->getCallingUid());
}
@@ -743,7 +776,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation);
}
@@ -756,7 +789,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->setAudioPortConfig(config);
}
@@ -768,7 +801,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
}
@@ -778,7 +811,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->releaseSoundTriggerSession(session);
}
@@ -791,6 +824,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
+ AutoCallerClear acc;
if (registration) {
return mAudioPolicyManager->registerPolicyMixes(mixes);
} else {
@@ -806,7 +840,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->startAudioSource(source, attributes, handle,
IPCThreadState::self()->getCallingUid());
}
@@ -817,7 +851,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->stopAudioSource(handle);
}
@@ -830,6 +864,7 @@
return PERMISSION_DENIED;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setMasterMono(mono);
}
@@ -839,6 +874,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getMasterMono(mono);
}
@@ -850,6 +886,7 @@
return NAN;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getStreamVolumeDB(stream, index, device);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 082923a..f3cddc3 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -26,6 +26,7 @@
#include <sys/time.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
+#include <cutils/multiuser.h>
#include <cutils/properties.h>
#include <binder/IPCThreadState.h>
#include <binder/ActivityManager.h>
@@ -151,6 +152,7 @@
{
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager) {
+ // called from binder death notification: no need to clear caller identity
mAudioPolicyManager->releaseResourcesForUid(uid);
}
}
@@ -273,7 +275,7 @@
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
const String8& regId, int32_t state)
{
- if (mAudioPolicyServiceClient != 0 && (mUid % AID_USER_OFFSET) < AID_APP_START) {
+ if (mAudioPolicyServiceClient != 0 && multiuser_get_app_id(mUid) < AID_APP_START) {
mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state);
}
}
@@ -283,7 +285,7 @@
const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
audio_patch_handle_t patchHandle)
{
- if (mAudioPolicyServiceClient != 0 && (mUid % AID_USER_OFFSET) < AID_APP_START) {
+ if (mAudioPolicyServiceClient != 0 && multiuser_get_app_id(mUid) < AID_APP_START) {
mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, clientInfo,
clientConfig, deviceConfig, patchHandle);
}
@@ -335,6 +337,7 @@
{
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager) {
+ AutoCallerClear acc;
mAudioPolicyManager->setRecordSilenced(uid, silenced);
}
}
@@ -575,7 +578,7 @@
}
bool AudioPolicyService::UidPolicy::isServiceUid(uid_t uid) const {
- return uid % AID_USER_OFFSET < AID_APP_START;
+ return multiuser_get_app_id(uid) < AID_APP_START;
}
void AudioPolicyService::UidPolicy::notifyService(uid_t uid, bool active) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index b3bc12b..d8dd797 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -640,6 +640,22 @@
bool isVirtualDevice; // uses vitual device: updated by APM::getInputForAttr()
};
+ // A class automatically clearing and restoring binder caller identity inside
+ // a code block (scoped variable)
+ // Declare one systematically before calling AudioPolicyManager methods so that they are
+ // executed with the same level of privilege as audioserver process.
+ class AutoCallerClear {
+ public:
+ AutoCallerClear() :
+ mToken(IPCThreadState::self()->clearCallingIdentity()) {}
+ ~AutoCallerClear() {
+ IPCThreadState::self()->restoreCallingIdentity(mToken);
+ }
+
+ private:
+ const int64_t mToken;
+ };
+
// Internal dump utilities.
status_t dumpPermissionDenial(int fd);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 714d50f..c87b5eb 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -243,6 +243,7 @@
}
if (mFlashlight->hasFlashUnit(id)) {
+ Mutex::Autolock al(mTorchStatusMutex);
mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
}
@@ -253,6 +254,7 @@
void CameraService::removeStates(const String8 id) {
updateCameraNumAndIds();
if (mFlashlight->hasFlashUnit(id)) {
+ Mutex::Autolock al(mTorchStatusMutex);
mTorchStatusMap.removeItem(id);
}
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index ab8f4ed..04fee13 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -150,7 +150,7 @@
}
sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
- AAudioService &aaudioService __unused,
+ AAudioService &aaudioService,
const aaudio::AAudioStreamRequest &request) {
std::lock_guard<std::mutex> lock(mExclusiveLock);
@@ -166,13 +166,14 @@
// Already open so do not allow a second stream.
return nullptr;
} else {
- sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP();
+ sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP(aaudioService);
ALOGV("openExclusiveEndpoint(), no match so try to open MMAP %p for dev %d",
endpointMMap.get(), configuration.getDeviceId());
endpoint = endpointMMap;
aaudio_result_t result = endpoint->open(request);
if (result != AAUDIO_OK) {
+ ALOGE("openExclusiveEndpoint(), open failed");
endpoint.clear();
} else {
mExclusiveStreams.push_back(endpointMMap);
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index ad5bb3a..5675b0b 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -288,11 +288,11 @@
aaudio_result_t result = AAUDIO_OK;
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("unregisterAudioThread(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
if (serviceStream->getRegisteredThread() != clientThreadId) {
- ALOGE("AAudioService::unregisterAudioThread(), wrong thread");
+ ALOGE("%s(), wrong thread", __func__);
result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
} else {
serviceStream->setRegisteredThread(0);
@@ -305,7 +305,7 @@
audio_port_handle_t *clientHandle) {
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("startClient(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
aaudio_result_t result = serviceStream->startClient(client, clientHandle);
@@ -313,12 +313,28 @@
}
aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
- audio_port_handle_t clientHandle) {
+ audio_port_handle_t portHandle) {
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
if (serviceStream.get() == nullptr) {
- ALOGE("stopClient(), illegal stream handle = 0x%0x", streamHandle);
+ ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
- aaudio_result_t result = serviceStream->stopClient(clientHandle);
+ aaudio_result_t result = serviceStream->stopClient(portHandle);
+ return checkForPendingClose(serviceStream, result);
+}
+
+// This is only called internally when AudioFlinger wants to tear down a stream.
+// So we do not have to check permissions.
+aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
+ ALOGD("%s(%d) called", __func__, portHandle);
+ sp<AAudioServiceStreamBase> serviceStream =
+ mStreamTracker.findStreamByPortHandle(portHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
+ }
+ serviceStream->incrementServiceReferenceCount();
+ aaudio_result_t result = serviceStream->stop();
+ serviceStream->disconnect();
return checkForPendingClose(serviceStream, result);
}
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index bdd9e0b..d21b1cd 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -83,6 +83,8 @@
aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
audio_port_handle_t clientHandle) override;
+ aaudio_result_t disconnectStreamByPortHandle(audio_port_handle_t portHandle);
+
private:
/**
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 96e621a..0349034 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -78,6 +78,17 @@
return result.str();
}
+// @return true if stream found
+bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
+ std::lock_guard<std::mutex> lock(mLockStreams);
+ for (const auto stream : mRegisteredStreams) {
+ if (stream->getPortHandle() == portHandle) {
+ return true;
+ }
+ }
+ return false;
+}
+
void AAudioServiceEndpoint::disconnectRegisteredStreams() {
std::lock_guard<std::mutex> lock(mLockStreams);
mConnected.store(false);
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 6312c51..6015b28 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -102,6 +102,13 @@
}
protected:
+
+ /**
+ * @param portHandle
+ * @return return true if a stream with the given portHandle is registered
+ */
+ bool isStreamRegistered(audio_port_handle_t portHandle);
+
void disconnectRegisteredStreams();
mutable std::mutex mLockStreams;
@@ -116,7 +123,6 @@
int32_t mRequestedDeviceId = 0;
std::atomic<bool> mConnected{true};
-
};
} /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 5f1de76..f9e21fb 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -48,8 +48,10 @@
using namespace android; // TODO just import names needed
using namespace aaudio; // TODO just import names needed
-AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP()
- : mMmapStream(nullptr) {}
+
+AAudioServiceEndpointMMAP::AAudioServiceEndpointMMAP(AAudioService &audioService)
+ : mMmapStream(nullptr)
+ , mAAudioService(audioService) {}
AAudioServiceEndpointMMAP::~AAudioServiceEndpointMMAP() {}
@@ -277,14 +279,21 @@
}
aaudio_result_t AAudioServiceEndpointMMAP::startStream(sp<AAudioServiceStreamBase> stream,
- audio_port_handle_t *clientHandle) {
+ audio_port_handle_t *clientHandle __unused) {
// Start the client on behalf of the AAudio service.
// Use the port handle that was provided by openMmapStream().
- return startClient(mMmapClient, &mPortHandle);
+ audio_port_handle_t tempHandle = mPortHandle;
+ aaudio_result_t result = startClient(mMmapClient, &tempHandle);
+ // When AudioFlinger is passed a valid port handle then it should not change it.
+ LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
+ "%s() port handle not expected to change from %d to %d",
+ __func__, mPortHandle, tempHandle);
+ ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+ return result;
}
aaudio_result_t AAudioServiceEndpointMMAP::stopStream(sp<AAudioServiceStreamBase> stream,
- audio_port_handle_t clientHandle) {
+ audio_port_handle_t clientHandle __unused) {
mFramesTransferred.reset32();
// Round 64-bit counter up to a multiple of the buffer capacity.
@@ -293,24 +302,27 @@
// when the stream is stopped.
mFramesTransferred.roundUp64(getBufferCapacity());
+ // Use the port handle that was provided by openMmapStream().
+ ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
return stopClient(mPortHandle);
}
aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
- ALOGV("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
+ ALOGD("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
audio_port_handle_t originalHandle = *clientHandle;
status_t status = mMmapStream->start(client, clientHandle);
aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
- ALOGV("%s() , %d => %d returns %d", __func__, originalHandle, *clientHandle, result);
+ ALOGD("%s() , portHandle %d => %d, returns %d", __func__, originalHandle, *clientHandle, result);
return result;
}
aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
+ ALOGD("%s(portHandle = %d), called", __func__, clientHandle);
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
- ALOGV("%s(%d) returns %d", __func__, clientHandle, result);
+ ALOGD("%s(portHandle = %d), returns %d", __func__, clientHandle, result);
return result;
}
@@ -343,11 +355,19 @@
return 0; // TODO
}
-
-void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t handle __unused) {
- ALOGD("%s(%p) called", __func__, this);
- //TODO: disconnect only stream corresponding to handle received
- disconnectRegisteredStreams();
+// This is called by AudioFlinger when it wants to destroy a stream.
+void AAudioServiceEndpointMMAP::onTearDown(audio_port_handle_t portHandle) {
+ ALOGD("%s(portHandle = %d) called", __func__, portHandle);
+ // Are we tearing down the EXCLUSIVE MMAP stream?
+ if (isStreamRegistered(portHandle)) {
+ ALOGD("%s(%d) tearing down this entire MMAP endpoint", __func__, portHandle);
+ disconnectRegisteredStreams();
+ } else {
+ // Must be a SHARED stream?
+ ALOGD("%s(%d) disconnect a specific stream", __func__, portHandle);
+ aaudio_result_t result = mAAudioService.disconnectStreamByPortHandle(portHandle);
+ ALOGD("%s(%d) disconnectStreamByPortHandle returned %d", __func__, portHandle, result);
+ }
};
void AAudioServiceEndpointMMAP::onVolumeChanged(audio_channel_mask_t channels,
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index c4c943d..5e815e0 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -42,7 +42,7 @@
, public android::MmapStreamCallback {
public:
- AAudioServiceEndpointMMAP();
+ explicit AAudioServiceEndpointMMAP(android::AAudioService &audioService);
virtual ~AAudioServiceEndpointMMAP();
@@ -88,8 +88,12 @@
// Interface to the AudioFlinger MMAP support.
android::sp<android::MmapStreamInterface> mMmapStream;
struct audio_mmap_buffer_info mMmapBufferinfo;
+
+ // There is only one port associated with an MMAP endpoint.
audio_port_handle_t mPortHandle = AUDIO_PORT_HANDLE_NONE;
+ android::AAudioService &mAAudioService;
+
android::base::unique_fd mAudioDataFileDescriptor;
int64_t mHardwareTimeOffsetNanos = 0; // TODO get from HAL
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index 227250c..d671710 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -30,7 +30,7 @@
namespace aaudio {
/**
- * This manages an internal stream that is shared by multiple Client streams.
+ * This manages an AudioStreamInternal that is shared by multiple Client streams.
*/
class AAudioServiceEndpointShared : public AAudioServiceEndpoint {
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 18f14ee..c943008 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -61,7 +61,7 @@
}
std::string AAudioServiceStreamBase::dumpHeader() {
- return std::string(" T Handle UId Run State Format Burst Chan Capacity");
+ return std::string(" T Handle UId Port Run State Format Burst Chan Capacity");
}
std::string AAudioServiceStreamBase::dump() const {
@@ -70,6 +70,7 @@
result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << mHandle
<< std::dec << std::setfill(' ') ;
result << std::setw(6) << mMmapClient.clientUid;
+ result << std::setw(7) << mClientHandle;
result << std::setw(4) << (isRunning() ? "yes" : " no");
result << std::setw(6) << getState();
result << std::setw(7) << getFormat();
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 3720596..d8102be 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -180,6 +180,10 @@
mHandle = handle;
}
+ audio_port_handle_t getPortHandle() const {
+ return mClientHandle;
+ }
+
aaudio_stream_state_t getState() const {
return mState;
}
@@ -269,6 +273,7 @@
int32_t mFramesPerBurst = 0;
android::AudioClient mMmapClient; // set in open, used in MMAP start()
+ // TODO rename mClientHandle to mPortHandle to be more consistent with AudioFlinger.
audio_port_handle_t mClientHandle = AUDIO_PORT_HANDLE_NONE;
SimpleDoubleBuffer<Timestamp> mAtomicTimestamp;
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
index ef88b34..9d5d8fc 100644
--- a/services/oboeservice/AAudioStreamTracker.cpp
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -53,6 +53,26 @@
return serviceStream;
}
+
+// The port handle is only available when the stream is started.
+// So we have to iterate over all the streams.
+// Luckily this rarely happens.
+sp<AAudioServiceStreamBase> AAudioStreamTracker::findStreamByPortHandle(
+ audio_port_handle_t portHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.begin();
+ while (it != mStreamsByHandle.end()) {
+ auto candidate = it->second;
+ if (candidate->getPortHandle() == portHandle) {
+ serviceStream = candidate;
+ break;
+ }
+ it++;
+ }
+ return serviceStream;
+}
+
// advance to next legal handle value
__attribute__((no_sanitize("integer")))
aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) {
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
index 70d440d..54e46ca 100644
--- a/services/oboeservice/AAudioStreamTracker.h
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -46,6 +46,14 @@
android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
/**
+ * Look up a stream based on the AudioPolicy portHandle.
+ * @param portHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<aaudio::AAudioServiceStreamBase> findStreamByPortHandle(
+ audio_port_handle_t portHandle);
+
+ /**
* Store a strong pointer to the stream and return a unique handle for future reference.
* The handle is guaranteed not to collide with an existing stream.
* @param serviceStream