Merge "soundtrigger: Add support for HAL V2.1"
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index d689e25..0196a0c 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -52,6 +52,9 @@
* \param[in,out] deviceId audio device the stream should preferably be routed to/from
* Requested as input,
* Actual as output
+ * \param[in,out] sessionId audio sessionId for the stream
+ * Requested as input, may be AUDIO_SESSION_ALLOCATE
+ * Actual as output
* \param[in] callback the MmapStreamCallback interface used by AudioFlinger to notify
* condition changes affecting the stream operation
* \param[out] interface the MmapStreamInterface interface controlling the created stream
@@ -66,6 +69,7 @@
audio_config_base_t *config,
const AudioClient& client,
audio_port_handle_t *deviceId,
+ audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
audio_port_handle_t *handle);
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index b3e069d..5da8114 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -123,7 +123,7 @@
/**
* No particular performance needs. Default.
*/
- AAUDIO_PERFORMANCE_MODE_NONE = 10,
+ AAUDIO_PERFORMANCE_MODE_NONE = 10,
/**
* Extending battery life is most important.
@@ -131,12 +131,12 @@
* This mode is not supported in input streams.
* Mode NONE will be used if this is requested.
*/
- AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
+ AAUDIO_PERFORMANCE_MODE_POWER_SAVING,
/**
* Reducing latency is most important.
*/
- AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
+ AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
};
typedef int32_t aaudio_performance_mode_t;
@@ -283,6 +283,25 @@
};
typedef int32_t aaudio_input_preset_t;
+enum {
+ /**
+ * Do not allocate a session ID.
+ * Effects cannot be used with this stream.
+ * Default.
+ */
+ AAUDIO_SESSION_ID_NONE = -1,
+
+ /**
+ * Allocate a session ID that can be used to attach and control
+ * effects using the Java AudioEffects API.
+ * Note that the use of this flag may result in higher latency.
+ *
+ * Note that this matches the value of AudioManager.AUDIO_SESSION_ID_GENERATE.
+ */
+ AAUDIO_SESSION_ID_ALLOCATE = 0,
+};
+typedef int32_t aaudio_session_id_t;
+
typedef struct AAudioStreamStruct AAudioStream;
typedef struct AAudioStreamBuilderStruct AAudioStreamBuilder;
@@ -499,6 +518,32 @@
AAUDIO_API void AAudioStreamBuilder_setInputPreset(AAudioStreamBuilder* builder,
aaudio_input_preset_t inputPreset);
+/** Set the requested session ID.
+ *
+ * The session ID can be used to associate a stream with effects processors.
+ * The effects are controlled using the Android AudioEffect Java API.
+ *
+ * The default, if you do not call this function, is AAUDIO_SESSION_ID_NONE.
+ *
+ * If set to AAUDIO_SESSION_ID_ALLOCATE then a session ID will be allocated
+ * when the stream is opened.
+ *
+ * The allocated session ID can be obtained by calling AAudioStream_getSessionId()
+ * and then used with this function when opening another stream.
+ * This allows effects to be shared between streams.
+ *
+ * Session IDs from AAudio can be used the Android Java APIs and vice versa.
+ * So a session ID from an AAudio stream can be passed to Java
+ * and effects applied using the Java AudioEffect API.
+ *
+ * Allocated session IDs will always be positive and nonzero.
+ *
+ * @param builder reference provided by AAudio_createStreamBuilder()
+ * @param sessionId an allocated sessionID or AAUDIO_SESSION_ID_ALLOCATE
+ */
+AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
+ aaudio_session_id_t sessionId);
+
/**
* Return one of these values from the data callback function.
*/
@@ -996,6 +1041,28 @@
AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream);
/**
+ * Passes back the session ID associated with this stream.
+ *
+ * The session ID can be used to associate a stream with effects processors.
+ * The effects are controlled using the Android AudioEffect Java API.
+ *
+ * If AAudioStreamBuilder_setSessionId() was called with AAUDIO_SESSION_ID_ALLOCATE
+ * then a new session ID should be allocated once when the stream is opened.
+ *
+ * If AAudioStreamBuilder_setSessionId() was called with a previously allocated
+ * session ID then that value should be returned.
+ *
+ * If AAudioStreamBuilder_setSessionId() was not called then this function should
+ * return AAUDIO_SESSION_ID_NONE.
+ *
+ * The sessionID for a stream should not change once the stream has been opened.
+ *
+ * @param stream reference provided by AAudioStreamBuilder_openStream()
+ * @return session ID or AAUDIO_SESSION_ID_NONE
+ */
+AAUDIO_API aaudio_session_id_t AAudioStream_getSessionId(AAudioStream* stream);
+
+/**
* Passes back the time at which a particular frame was presented.
* This can be used to synchronize audio with video or MIDI.
* It can also be used to align a recorded stream with a playback stream.
diff --git a/media/libaaudio/libaaudio.map.txt b/media/libaaudio/libaaudio.map.txt
index 98fbb6f..cbf5921 100644
--- a/media/libaaudio/libaaudio.map.txt
+++ b/media/libaaudio/libaaudio.map.txt
@@ -20,6 +20,7 @@
AAudioStreamBuilder_setUsage; # introduced=28
AAudioStreamBuilder_setContentType; # introduced=28
AAudioStreamBuilder_setInputPreset; # introduced=28
+ AAudioStreamBuilder_setSessionId; # introduced=28
AAudioStreamBuilder_openStream;
AAudioStreamBuilder_delete;
AAudioStream_close;
@@ -50,6 +51,7 @@
AAudioStream_getInputPreset; # introduced=28
AAudioStream_getFramesWritten;
AAudioStream_getFramesRead;
+ AAudioStream_getSessionId; # introduced=28
AAudioStream_getTimestamp;
AAudioStream_isMMapUsed;
local:
diff --git a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
index 97672a0..959db61 100644
--- a/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamConfiguration.cpp
@@ -56,6 +56,8 @@
if (status != NO_ERROR) goto error;
status = parcel->writeInt32((int32_t) getInputPreset());
if (status != NO_ERROR) goto error;
+ status = parcel->writeInt32(getSessionId());
+ if (status != NO_ERROR) goto error;
return NO_ERROR;
error:
ALOGE("AAudioStreamConfiguration.writeToParcel(): write failed = %d", status);
@@ -94,6 +96,9 @@
status = parcel->readInt32(&value);
if (status != NO_ERROR) goto error;
setInputPreset((aaudio_input_preset_t) value);
+ status = parcel->readInt32(&value);
+ if (status != NO_ERROR) goto error;
+ setSessionId(value);
return NO_ERROR;
error:
ALOGE("AAudioStreamConfiguration.readFromParcel(): read failed = %d", status);
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 5856ec3..4980e97 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -133,6 +133,7 @@
setSampleRate(configurationOutput.getSampleRate());
setSamplesPerFrame(configurationOutput.getSamplesPerFrame());
setDeviceId(configurationOutput.getDeviceId());
+ setSessionId(configurationOutput.getSessionId());
setSharingMode(configurationOutput.getSharingMode());
setUsage(configurationOutput.getUsage());
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 9e5ca8e..df0db79 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -196,12 +196,19 @@
}
AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder,
- int32_t frames)
+ int32_t frames)
{
AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
streamBuilder->setBufferCapacity(frames);
}
+AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
+ aaudio_session_id_t sessionId)
+{
+ AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+ streamBuilder->setSessionId(sessionId);
+}
+
AAUDIO_API void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder,
AAudioStream_dataCallback callback,
void *userData)
@@ -483,6 +490,12 @@
return audioStream->getInputPreset();
}
+AAUDIO_API int32_t AAudioStream_getSessionId(AAudioStream* stream)
+{
+ AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
+ return audioStream->getSessionId();
+}
+
AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 23c4eb8..9645ea8 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -38,6 +38,7 @@
mSamplesPerFrame = other.mSamplesPerFrame;
mSampleRate = other.mSampleRate;
mDeviceId = other.mDeviceId;
+ mSessionId = other.mSessionId;
mSharingMode = other.mSharingMode;
mAudioFormat = other.mAudioFormat;
mDirection = other.mDirection;
@@ -59,6 +60,15 @@
return AAUDIO_ERROR_OUT_OF_RANGE;
}
+ // All Session ID values are legal.
+ switch (mSessionId) {
+ case AAUDIO_SESSION_ID_NONE:
+ case AAUDIO_SESSION_ID_ALLOCATE:
+ break;
+ default:
+ break;
+ }
+
switch (mSharingMode) {
case AAUDIO_SHARING_MODE_EXCLUSIVE:
case AAUDIO_SHARING_MODE_SHARED:
@@ -154,6 +164,7 @@
void AAudioStreamParameters::dump() const {
ALOGD("mDeviceId = %6d", mDeviceId);
+ ALOGD("mSessionId = %6d", mSessionId);
ALOGD("mSampleRate = %6d", mSampleRate);
ALOGD("mSamplesPerFrame = %6d", mSamplesPerFrame);
ALOGD("mSharingMode = %6d", (int)mSharingMode);
@@ -164,4 +175,3 @@
ALOGD("mContentType = %6d", mContentType);
ALOGD("mInputPreset = %6d", mInputPreset);
}
-
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.h b/media/libaaudio/src/core/AAudioStreamParameters.h
index 0c173f5..ce5dacd 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.h
+++ b/media/libaaudio/src/core/AAudioStreamParameters.h
@@ -112,6 +112,14 @@
mInputPreset = inputPreset;
}
+ aaudio_session_id_t getSessionId() const {
+ return mSessionId;
+ }
+
+ void setSessionId(aaudio_session_id_t sessionId) {
+ mSessionId = sessionId;
+ }
+
int32_t calculateBytesPerFrame() const {
return getSamplesPerFrame() * AAudioConvert_formatToSizeInBytes(getFormat());
}
@@ -137,6 +145,7 @@
aaudio_content_type_t mContentType = AAUDIO_UNSPECIFIED;
aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
+ aaudio_session_id_t mSessionId = AAUDIO_SESSION_ID_NONE;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 1b2ca39..82c0667 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -108,8 +108,10 @@
mSampleRate, mSamplesPerFrame, mFormat,
AudioStream_convertSharingModeToShortText(mSharingMode),
(getDirection() == AAUDIO_DIRECTION_OUTPUT) ? "OUTPUT" : "INPUT");
- ALOGI("open() device = %d, perfMode = %d, callback: %s with frames = %d",
- mDeviceId, mPerformanceMode,
+ ALOGI("open() device = %d, sessionId = %d, perfMode = %d, callback: %s with frames = %d",
+ mDeviceId,
+ mSessionId,
+ mPerformanceMode,
(isDataCallbackSet() ? "ON" : "OFF"),
mFramesPerDataCallback);
ALOGI("open() usage = %d, contentType = %d, inputPreset = %d",
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 21fa595..42b585f 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -216,6 +216,10 @@
return mInputPreset;
}
+ int32_t getSessionId() const {
+ return mSessionId;
+ }
+
/**
* This is only valid after setSamplesPerFrame() and setFormat() have been called.
*/
@@ -455,10 +459,15 @@
mDeviceId = deviceId;
}
+ void setSessionId(int32_t sessionId) {
+ mSessionId = sessionId;
+ }
+
std::atomic<bool> mCallbackEnabled{false};
float mDuckAndMuteVolume = 1.0f;
+
protected:
void setPeriodNanoseconds(int64_t periodNanoseconds) {
@@ -505,10 +514,13 @@
aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
+
aaudio_usage_t mUsage = AAUDIO_USAGE_MEDIA;
aaudio_content_type_t mContentType = AAUDIO_CONTENT_TYPE_MUSIC;
aaudio_input_preset_t mInputPreset = AAUDIO_INPUT_PRESET_GENERIC;
+ int32_t mSessionId = AAUDIO_UNSPECIFIED;
+
// callback ----------------------------------
AAudioStream_dataCallback mDataCallbackProc = nullptr; // external callback functions
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index f7cb8d6..293a6a8 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -141,6 +141,13 @@
// TODO Support other performance settings in MMAP mode.
// Disable MMAP if low latency not requested.
if (getPerformanceMode() != AAUDIO_PERFORMANCE_MODE_LOW_LATENCY) {
+ ALOGD("build() MMAP not available because AAUDIO_PERFORMANCE_MODE_LOW_LATENCY not used.");
+ allowMMap = false;
+ }
+
+ // SessionID and Effects are only supported in Legacy mode.
+ if (getSessionId() != AAUDIO_SESSION_ID_NONE) {
+ ALOGD("build() MMAP not available because sessionId used.");
allowMMap = false;
}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 5f4ab9b..61a0f8a 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -117,6 +117,9 @@
.tags = ""
};
+ aaudio_session_id_t requestedSessionId = builder.getSessionId();
+ audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
+
mAudioRecord = new AudioRecord(
mOpPackageName // const String16& opPackageName TODO does not compile
);
@@ -130,7 +133,7 @@
callbackData,
notificationFrames,
false /*threadCanCallJava*/,
- AUDIO_SESSION_ALLOCATE,
+ sessionId,
streamTransferType,
flags,
AUDIO_UID_INVALID, // DEFAULT uid
@@ -189,6 +192,13 @@
setState(AAUDIO_STREAM_STATE_OPEN);
setDeviceId(mAudioRecord->getRoutedDeviceId());
+
+ aaudio_session_id_t actualSessionId =
+ (requestedSessionId == AAUDIO_SESSION_ID_NONE)
+ ? AAUDIO_SESSION_ID_NONE
+ : (aaudio_session_id_t) mAudioRecord->getSessionId();
+ setSessionId(actualSessionId);
+
mAudioRecord->addAudioDeviceCallback(mDeviceCallback);
return AAUDIO_OK;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 17a8d52..52c7822 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -134,6 +134,11 @@
.tags = ""
};
+ static_assert(AAUDIO_UNSPECIFIED == AUDIO_SESSION_ALLOCATE, "Session IDs should match");
+
+ aaudio_session_id_t requestedSessionId = builder.getSessionId();
+ audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
+
mAudioTrack = new AudioTrack();
mAudioTrack->set(
AUDIO_STREAM_DEFAULT, // ignored because we pass attributes below
@@ -147,7 +152,7 @@
notificationFrames,
0, // DEFAULT sharedBuffer*/,
false, // DEFAULT threadCanCallJava
- AUDIO_SESSION_ALLOCATE,
+ sessionId,
streamTransferType,
NULL, // DEFAULT audio_offload_info_t
AUDIO_UID_INVALID, // DEFAULT uid
@@ -193,6 +198,13 @@
setState(AAUDIO_STREAM_STATE_OPEN);
setDeviceId(mAudioTrack->getRoutedDeviceId());
+
+ aaudio_session_id_t actualSessionId =
+ (requestedSessionId == AAUDIO_SESSION_ID_NONE)
+ ? AAUDIO_SESSION_ID_NONE
+ : (aaudio_session_id_t) mAudioTrack->getSessionId();
+ setSessionId(actualSessionId);
+
mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
// Update performance mode based on the actual stream flags.
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index c6adf33..2bee6e3 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -250,6 +250,13 @@
return result;
}
+audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId) {
+ // If not a valid sessionId then convert to a safe value of AUDIO_SESSION_ALLOCATE.
+ return (sessionId < AAUDIO_SESSION_ID_MIN)
+ ? AUDIO_SESSION_ALLOCATE
+ : (audio_session_t) sessionId;
+}
+
audio_format_t AAudioConvert_aaudioToAndroidDataFormat(aaudio_format_t aaudioFormat) {
audio_format_t androidFormat;
switch (aaudioFormat) {
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index f2347f5..0c59f6d 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -27,6 +27,9 @@
#include "aaudio/AAudio.h"
+
+constexpr aaudio_session_id_t AAUDIO_SESSION_ID_MIN = 1; // must be positive
+
/**
* Convert an AAudio result into the closest matching Android status.
*/
@@ -38,6 +41,13 @@
aaudio_result_t AAudioConvert_androidToAAudioResult(android::status_t status);
/**
+ * Convert an aaudio_session_id_t to a value that is safe to pass to AudioFlinger.
+ * @param sessionId
+ * @return safe value
+ */
+audio_session_t AAudioConvert_aaudioToAndroidSessionId(aaudio_session_id_t sessionId);
+
+/**
* Convert an array of floats to an array of int16_t.
*
* @param source
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 33718fc..45d417f 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -113,6 +113,18 @@
}
cc_test {
+ name: "test_session_id",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_session_id.cpp"],
+ shared_libs: [
+ "libaaudio",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
+
+cc_test {
name: "test_aaudio_monkey",
defaults: ["libaaudio_tests_defaults"],
srcs: ["test_aaudio_monkey.cpp"],
diff --git a/media/libaaudio/tests/test_session_id.cpp b/media/libaaudio/tests/test_session_id.cpp
new file mode 100644
index 0000000..d9072af
--- /dev/null
+++ b/media/libaaudio/tests/test_session_id.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// Test AAudio SessionId, which is used to associate Effects with a stream
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+#include <gtest/gtest.h>
+
+constexpr int64_t kNanosPerSecond = 1000000000;
+constexpr int kNumFrames = 256;
+constexpr int kChannelCount = 2;
+
+// Test AAUDIO_SESSION_ID_NONE default
+static void checkSessionIdNone(aaudio_performance_mode_t perfMode) {
+
+ float *buffer = new float[kNumFrames * kChannelCount];
+
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+
+ AAudioStream *aaudioStream1 = nullptr;
+ int32_t sessionId1 = 0;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream1));
+
+ // Since we did not request or specify a SessionID, we should get NONE
+ sessionId1 = AAudioStream_getSessionId(aaudioStream1);
+ ASSERT_EQ(AAUDIO_SESSION_ID_NONE, sessionId1);
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
+
+ ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1, buffer, kNumFrames, kNanosPerSecond));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
+ delete[] buffer;
+ AAudioStreamBuilder_delete(aaudioBuilder);
+}
+
+TEST(test_session_id, aaudio_session_id_none_perfnone) {
+ checkSessionIdNone(AAUDIO_PERFORMANCE_MODE_NONE);
+}
+
+TEST(test_session_id, aaudio_session_id_none_lowlat) {
+ checkSessionIdNone(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+}
+
+// Test AAUDIO_SESSION_ID_ALLOCATE
+static void checkSessionIdAllocate(aaudio_performance_mode_t perfMode,
+ aaudio_direction_t direction) {
+
+ float *buffer = new float[kNumFrames * kChannelCount];
+
+ AAudioStreamBuilder *aaudioBuilder = nullptr;
+
+ AAudioStream *aaudioStream1 = nullptr;
+ int32_t sessionId1 = 0;
+ AAudioStream *aaudioStream2 = nullptr;
+ int32_t sessionId2 = 0;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ ASSERT_EQ(AAUDIO_OK, AAudio_createStreamBuilder(&aaudioBuilder));
+
+ // Request stream properties.
+ AAudioStreamBuilder_setPerformanceMode(aaudioBuilder, perfMode);
+ // This stream could be input or output.
+ AAudioStreamBuilder_setDirection(aaudioBuilder, direction);
+
+ // Ask AAudio to allocate a Session ID.
+ AAudioStreamBuilder_setSessionId(aaudioBuilder, AAUDIO_SESSION_ID_ALLOCATE);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream1));
+
+ // Get the allocated ID from the stream.
+ sessionId1 = AAudioStream_getSessionId(aaudioStream1);
+ ASSERT_LT(0, sessionId1); // Must be positive.
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
+
+ if (direction == AAUDIO_DIRECTION_INPUT) {
+ ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream1,
+ buffer, kNumFrames, kNanosPerSecond));
+ } else {
+ ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1,
+ buffer, kNumFrames, kNanosPerSecond));
+ }
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
+
+ // Now open a second stream using the same session ID. ==================
+ AAudioStreamBuilder_setSessionId(aaudioBuilder, sessionId1);
+
+ // Reverse direction for second stream.
+ aaudio_direction_t otherDirection = (direction == AAUDIO_DIRECTION_OUTPUT)
+ ? AAUDIO_DIRECTION_INPUT
+ : AAUDIO_DIRECTION_OUTPUT;
+ AAudioStreamBuilder_setDirection(aaudioBuilder, otherDirection);
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream2));
+
+ // Get the allocated ID from the stream.
+ // It should match the ID that we set it to in the builder.
+ sessionId2 = AAudioStream_getSessionId(aaudioStream2);
+ ASSERT_EQ(sessionId1, sessionId2);
+
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream2));
+
+ if (otherDirection == AAUDIO_DIRECTION_INPUT) {
+ ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream2,
+ buffer, kNumFrames, kNanosPerSecond));
+ } else {
+ ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream2,
+ buffer, kNumFrames, kNanosPerSecond));
+ }
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream2));
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream2));
+
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
+ delete[] buffer;
+ AAudioStreamBuilder_delete(aaudioBuilder);
+}
+
+TEST(test_session_id, aaudio_session_id_alloc_perfnone_in) {
+ checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_DIRECTION_INPUT);
+}
+TEST(test_session_id, aaudio_session_id_alloc_perfnone_out) {
+ checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_NONE, AAUDIO_DIRECTION_OUTPUT);
+}
+
+TEST(test_session_id, aaudio_session_id_alloc_lowlat_in) {
+ checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_DIRECTION_INPUT);
+}
+TEST(test_session_id, aaudio_session_id_alloc_lowlat_out) {
+ checkSessionIdAllocate(AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, AAUDIO_DIRECTION_OUTPUT);
+}
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index a777663..bbf87f0 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -146,9 +146,14 @@
MediaExtractor::ExtractorDef def;
void *libHandle;
String8 libPath;
+ String8 uuidString;
ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path)
- : def(definition), libHandle(handle), libPath(path) { }
+ : def(definition), libHandle(handle), libPath(path) {
+ for (size_t i = 0; i < sizeof MediaExtractor::ExtractorDef::extractor_uuid; i++) {
+ uuidString.appendFormat("%02x", def.extractor_uuid.b[i]);
+ }
+ }
~ExtractorPlugin() {
if (libHandle != nullptr) {
ALOGV("closing handle for %s %d", libPath.c_str(), def.extractor_version);
@@ -307,4 +312,20 @@
gPluginsRegistered = true;
}
+status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
+ Mutex::Autolock autoLock(gPluginMutex);
+ String8 out;
+ out.append("Available extractors:\n");
+ for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
+ out.appendFormat(" %25s: uuid(%s), version(%u), path(%s)\n",
+ (*it)->def.extractor_name,
+ (*it)->uuidString.c_str(),
+ (*it)->def.extractor_version,
+ (*it)->libPath.c_str());
+ }
+ write(fd, out.string(), out.size());
+ return OK;
+}
+
+
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 7fddf80..55654f1 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -41,6 +41,7 @@
static sp<IMediaExtractor> CreateFromService(
const sp<DataSource> &source, const char *mime = NULL);
static void LoadPlugins(const ::std::string& apkPath);
+ static status_t dump(int fd, const Vector<String16>& args);
private:
static Mutex gPluginMutex;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 4d5e094..2a2f6fc 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -262,6 +262,7 @@
audio_config_base_t *config,
const AudioClient& client,
audio_port_handle_t *deviceId,
+ audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
audio_port_handle_t *handle)
@@ -274,7 +275,8 @@
status_t ret = NO_INIT;
if (af != 0) {
ret = af->openMmapStream(
- direction, attr, config, client, deviceId, callback, interface, handle);
+ direction, attr, config, client, deviceId,
+ sessionId, callback, interface, handle);
}
return ret;
}
@@ -284,6 +286,7 @@
audio_config_base_t *config,
const AudioClient& client,
audio_port_handle_t *deviceId,
+ audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
audio_port_handle_t *handle)
@@ -292,8 +295,10 @@
if (ret != NO_ERROR) {
return ret;
}
-
- audio_session_t sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ audio_session_t actualSessionId = *sessionId;
+ if (actualSessionId == AUDIO_SESSION_ALLOCATE) {
+ actualSessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ }
audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT;
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
@@ -303,7 +308,7 @@
fullConfig.channel_mask = config->channel_mask;
fullConfig.format = config->format;
ret = AudioSystem::getOutputForAttr(attr, &io,
- sessionId,
+ actualSessionId,
&streamType, client.clientUid,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
@@ -311,7 +316,7 @@
deviceId, &portId);
} else {
ret = AudioSystem::getInputForAttr(attr, &io,
- sessionId,
+ actualSessionId,
client.clientPid,
client.clientUid,
config,
@@ -326,13 +331,14 @@
sp<MmapThread> thread = mMmapThreads.valueFor(io);
if (thread != 0) {
interface = new MmapThreadHandle(thread);
- thread->configure(attr, streamType, sessionId, callback, *deviceId, portId);
+ thread->configure(attr, streamType, actualSessionId, callback, *deviceId, portId);
*handle = portId;
+ *sessionId = actualSessionId;
} else {
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
- AudioSystem::releaseOutput(io, streamType, sessionId);
+ AudioSystem::releaseOutput(io, streamType, actualSessionId);
} else {
- AudioSystem::releaseInput(io, sessionId);
+ AudioSystem::releaseInput(io, actualSessionId);
}
ret = NO_INIT;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index bc73ffd..5a64f0b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -271,6 +271,7 @@
audio_config_base_t *config,
const AudioClient& client,
audio_port_handle_t *deviceId,
+ audio_session_t *sessionId,
const sp<MmapStreamCallback>& callback,
sp<MmapStreamInterface>& interface,
audio_port_handle_t *handle);
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index 6e0f2b6..ede8e3f 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -47,6 +47,9 @@
#ifdef FLOAT_EFFECT_CHAIN
// define FLOAT_AUX to process aux effect buffers in float (FLOAT_EFFECT_CHAIN must be defined)
#define FLOAT_AUX
+
+// define MULTICHANNEL_EFFECT_CHAIN to allow multichannel effects (FLOAT_EFFECT_CHAIN defined)
+#define MULTICHANNEL_EFFECT_CHAIN
#endif
#endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index b4ff0d6..b13e551 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -26,6 +26,7 @@
#include <system/audio_effects/effect_aec.h>
#include <system/audio_effects/effect_ns.h>
#include <system/audio_effects/effect_visualizer.h>
+#include <audio_utils/channels.h>
#include <audio_utils/primitives.h>
#include <media/AudioEffect.h>
#include <media/audiohal/EffectHalInterface.h>
@@ -292,7 +293,6 @@
return;
}
- // TODO: Implement multichannel effects; here outChannelCount == FCC_2 == 2
const uint32_t inChannelCount =
audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
const uint32_t outChannelCount =
@@ -342,6 +342,7 @@
if (isProcessImplemented()) {
if (auxType) {
// We overwrite the aux input buffer here and clear after processing.
+ // aux input is always mono.
#ifdef FLOAT_EFFECT_CHAIN
if (mSupportsFloat) {
#ifndef FLOAT_AUX
@@ -371,6 +372,28 @@
}
}
#ifdef FLOAT_EFFECT_CHAIN
+ sp<EffectBufferHalInterface> inBuffer = mInBuffer;
+ sp<EffectBufferHalInterface> outBuffer = mOutBuffer;
+
+ if (!auxType && mInChannelCountRequested != inChannelCount) {
+ adjust_channels(
+ inBuffer->audioBuffer()->f32, mInChannelCountRequested,
+ mInConversionBuffer->audioBuffer()->f32, inChannelCount,
+ sizeof(float),
+ sizeof(float)
+ * mInChannelCountRequested * mConfig.inputCfg.buffer.frameCount);
+ inBuffer = mInConversionBuffer;
+ }
+ if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE
+ && mOutChannelCountRequested != outChannelCount) {
+ adjust_selected_channels(
+ outBuffer->audioBuffer()->f32, mOutChannelCountRequested,
+ mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
+ sizeof(float),
+ sizeof(float)
+ * mOutChannelCountRequested * mConfig.outputCfg.buffer.frameCount);
+ outBuffer = mOutConversionBuffer;
+ }
if (!mSupportsFloat) { // convert input to int16_t as effect doesn't support float.
if (!auxType) {
if (mInConversionBuffer.get() == nullptr) {
@@ -379,8 +402,9 @@
}
memcpy_to_i16_from_float(
mInConversionBuffer->audioBuffer()->s16,
- mInBuffer->audioBuffer()->f32,
+ inBuffer->audioBuffer()->f32,
inChannelCount * mConfig.inputCfg.buffer.frameCount);
+ inBuffer = mInConversionBuffer;
}
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
if (mOutConversionBuffer.get() == nullptr) {
@@ -389,21 +413,30 @@
}
memcpy_to_i16_from_float(
mOutConversionBuffer->audioBuffer()->s16,
- mOutBuffer->audioBuffer()->f32,
+ outBuffer->audioBuffer()->f32,
outChannelCount * mConfig.outputCfg.buffer.frameCount);
+ outBuffer = mOutConversionBuffer;
}
}
#endif
-
ret = mEffectInterface->process();
-
#ifdef FLOAT_EFFECT_CHAIN
if (!mSupportsFloat) { // convert output int16_t back to float.
+ sp<EffectBufferHalInterface> target =
+ mOutChannelCountRequested != outChannelCount
+ ? mOutConversionBuffer : mOutBuffer;
+
memcpy_to_float_from_i16(
- mOutBuffer->audioBuffer()->f32,
+ target->audioBuffer()->f32,
mOutConversionBuffer->audioBuffer()->s16,
outChannelCount * mConfig.outputCfg.buffer.frameCount);
}
+ if (mOutChannelCountRequested != outChannelCount) {
+ adjust_selected_channels(mOutConversionBuffer->audioBuffer()->f32, outChannelCount,
+ mOutBuffer->audioBuffer()->f32, mOutChannelCountRequested,
+ sizeof(float),
+ sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
+ }
#endif
} else {
#ifdef FLOAT_EFFECT_CHAIN
@@ -476,15 +509,28 @@
}
// TODO: handle configuration of effects replacing track process
+ // TODO: handle configuration of input (record) SW effects above the HAL,
+ // similar to output EFFECT_FLAG_TYPE_INSERT/REPLACE,
+ // in which case input channel masks should be used here.
channelMask = thread->channelMask();
+ mConfig.inputCfg.channels = channelMask;
mConfig.outputCfg.channels = channelMask;
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
- mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- ALOGV("Overriding auxiliary effect input as MONO and output as STEREO");
+ if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_MONO) {
+ mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
+ ALOGV("Overriding auxiliary effect input channels %#x as MONO",
+ mConfig.inputCfg.channels);
+ }
+#ifndef MULTICHANNEL_EFFECT_CHAIN
+ if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
+ mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ ALOGV("Overriding auxiliary effect output channels %#x as STEREO",
+ mConfig.outputCfg.channels);
+ }
+#endif
} else {
- mConfig.inputCfg.channels = channelMask;
+#ifndef MULTICHANNEL_EFFECT_CHAIN
// TODO: Update this logic when multichannel effects are implemented.
// For offloaded tracks consider mono output as stereo for proper effect initialization
if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
@@ -492,7 +538,12 @@
mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
ALOGV("Overriding effect input and output as STEREO");
}
+#endif
}
+ mInChannelCountRequested =
+ audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
+ mOutChannelCountRequested =
+ audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
@@ -530,28 +581,58 @@
status_t cmdStatus;
size = sizeof(int);
status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
- sizeof(effect_config_t),
+ sizeof(mConfig),
&mConfig,
&size,
&cmdStatus);
if (status == NO_ERROR) {
status = cmdStatus;
-#ifdef FLOAT_EFFECT_CHAIN
- mSupportsFloat = true;
-#endif
}
-#ifdef FLOAT_EFFECT_CHAIN
- else {
- ALOGV("EFFECT_CMD_SET_CONFIG failed with float format, retry with int16_t.");
- mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
- mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+
+#ifdef MULTICHANNEL_EFFECT_CHAIN
+ if (status != NO_ERROR &&
+ (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
+ || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
+ // Older effects may require exact STEREO position mask.
+ if (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
+ ALOGV("Overriding effect input channels %#x as STEREO", mConfig.inputCfg.channels);
+ mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+ if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
+ ALOGV("Overriding effect output channels %#x as STEREO", mConfig.outputCfg.channels);
+ mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+ size = sizeof(int);
status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
- sizeof(effect_config_t),
+ sizeof(mConfig),
&mConfig,
&size,
&cmdStatus);
if (status == NO_ERROR) {
status = cmdStatus;
+ }
+ }
+#endif
+
+#ifdef FLOAT_EFFECT_CHAIN
+ if (status == NO_ERROR) {
+ mSupportsFloat = true;
+ }
+
+ if (status != NO_ERROR) {
+ ALOGV("EFFECT_CMD_SET_CONFIG failed with float format, retry with int16_t.");
+ mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ size = sizeof(int);
+ status = mEffectInterface->command(EFFECT_CMD_SET_CONFIG,
+ sizeof(mConfig),
+ &mConfig,
+ &size,
+ &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ }
+ if (status == NO_ERROR) {
mSupportsFloat = false;
ALOGVV("config worked with 16 bit");
} else {
@@ -929,11 +1010,15 @@
// the original buffer) when the output buffer is identical to the input buffer,
// but we don't optimize for it here.
const bool auxType = (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY;
- if (!auxType && !mSupportsFloat && mInBuffer.get() != nullptr) {
+ const uint32_t inChannelCount =
+ audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
+ const bool formatMismatch = !mSupportsFloat || mInChannelCountRequested != inChannelCount;
+ if (!auxType && formatMismatch && mInBuffer.get() != nullptr) {
// we need to translate - create hidl shared buffer and intercept
const size_t inFrameCount = mConfig.inputCfg.buffer.frameCount;
- const int inChannels = audio_channel_count_from_out_mask(mConfig.inputCfg.channels);
- const size_t size = inChannels * inFrameCount * sizeof(int16_t);
+ // Use FCC_2 in case mInChannelCountRequested is mono and the effect is stereo.
+ const uint32_t inChannels = std::max((uint32_t)FCC_2, mInChannelCountRequested);
+ const size_t size = inChannels * inFrameCount * std::max(sizeof(int16_t), sizeof(float));
ALOGV("%s: setInBuffer updating for inChannels:%d inFrameCount:%zu total size:%zu",
__func__, inChannels, inFrameCount, size);
@@ -970,10 +1055,14 @@
#ifdef FLOAT_EFFECT_CHAIN
// Note: Any effect that does not accumulate does not need mOutConversionBuffer and
// can do in-place conversion from int16_t to float. We don't optimize here.
- if (!mSupportsFloat && mOutBuffer.get() != nullptr) {
+ const uint32_t outChannelCount =
+ audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
+ const bool formatMismatch = !mSupportsFloat || mOutChannelCountRequested != outChannelCount;
+ if (formatMismatch && mOutBuffer.get() != nullptr) {
const size_t outFrameCount = mConfig.outputCfg.buffer.frameCount;
- const int outChannels = audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
- const size_t size = outChannels * outFrameCount * sizeof(int16_t);
+ // Use FCC_2 in case mOutChannelCountRequested is mono and the effect is stereo.
+ const uint32_t outChannels = std::max((uint32_t)FCC_2, mOutChannelCountRequested);
+ const size_t size = outChannels * outFrameCount * std::max(sizeof(int16_t), sizeof(float));
ALOGV("%s: setOutBuffer updating for outChannels:%d outFrameCount:%zu total size:%zu",
__func__, outChannels, outFrameCount, size);
@@ -1813,14 +1902,8 @@
if (mInBuffer == NULL) {
return;
}
- // TODO: This will change in the future, depending on multichannel
- // and sample format changes for effects.
- // Currently effects processing is only available for stereo, AUDIO_FORMAT_PCM_16_BIT
- // (4 bytes frame size)
-
const size_t frameSize =
- audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
- * std::min((uint32_t)FCC_2, thread->channelCount());
+ audio_bytes_per_sample(EFFECT_BUFFER_FORMAT) * thread->channelCount();
memset(mInBuffer->audioBuffer()->raw, 0, thread->frameCount() * frameSize);
mInBuffer->commit();
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index eea3208..2327bb9 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -173,6 +173,8 @@
bool mSupportsFloat; // effect supports float processing
sp<EffectBufferHalInterface> mInConversionBuffer; // Buffers for HAL conversion if needed.
sp<EffectBufferHalInterface> mOutConversionBuffer;
+ uint32_t mInChannelCountRequested;
+ uint32_t mOutChannelCountRequested;
#endif
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d5def48..3a41ac8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1176,6 +1176,7 @@
switch (mType) {
case MIXER: {
+#ifndef MULTICHANNEL_EFFECT_CHAIN
// Reject any effect on mixer multichannel sinks.
// TODO: fix both format and multichannel issues with effects.
if (mChannelCount != FCC_2) {
@@ -1183,6 +1184,7 @@
" thread %s", desc->name, mChannelCount, mThreadName);
return BAD_VALUE;
}
+#endif
audio_output_flags_t flags = mOutput->flags;
if (hasFastMixer() || (flags & AUDIO_OUTPUT_FLAG_FAST)) {
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
@@ -1229,6 +1231,7 @@
desc->name, mThreadName);
return BAD_VALUE;
case DUPLICATING:
+#ifndef MULTICHANNEL_EFFECT_CHAIN
// Reject any effect on mixer multichannel sinks.
// TODO: fix both format and multichannel issues with effects.
if (mChannelCount != FCC_2) {
@@ -1236,6 +1239,7 @@
" on DUPLICATING thread %s", desc->name, mChannelCount, mThreadName);
return BAD_VALUE;
}
+#endif
if ((sessionId == AUDIO_SESSION_OUTPUT_STAGE) || (sessionId == AUDIO_SESSION_OUTPUT_MIX)) {
ALOGW("checkEffectCompatibility_l(): global effect %s on DUPLICATING"
" thread %s", desc->name, mThreadName);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 68730a5..33f31e0 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2123,7 +2123,10 @@
audio_devices_t device)
{
- if ((index < mVolumeCurves->getVolumeIndexMin(stream)) ||
+ // VOICE_CALL stream has minVolumeIndex > 0 but can be muted directly by an
+ // app that has MODIFY_PHONE_STATE permission.
+ if (((index < mVolumeCurves->getVolumeIndexMin(stream)) &&
+ !(stream == AUDIO_STREAM_VOICE_CALL && index == 0)) ||
(index > mVolumeCurves->getVolumeIndexMax(stream))) {
return BAD_VALUE;
}
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index 0dc1fce..f0f44f5 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -56,7 +56,7 @@
}
status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
- return dumpExtractors(fd, args);
+ return MediaExtractorFactory::dump(fd, args) || dumpExtractors(fd, args);
}
status_t MediaExtractorService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index b0c3771..7b8d817 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -102,8 +102,8 @@
}
}
- ALOGV("findExclusiveEndpoint_l(), found %p for device = %d",
- endpoint.get(), configuration.getDeviceId());
+ ALOGV("findExclusiveEndpoint_l(), found %p for device = %d, sessionId = %d",
+ endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
return endpoint;
}
@@ -118,8 +118,8 @@
}
}
- ALOGV("findSharedEndpoint_l(), found %p for device = %d",
- endpoint.get(), configuration.getDeviceId());
+ ALOGV("findSharedEndpoint_l(), found %p for device = %d, sessionId = %d",
+ endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
return endpoint;
}
@@ -151,19 +151,17 @@
return nullptr;
} else {
sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP();
- ALOGD("openEndpoint(),created MMAP %p", endpointMMap.get());
+ ALOGD("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("openEndpoint(), open failed");
+ ALOGE("openExclusiveEndpoint(), open failed");
endpoint.clear();
} else {
mExclusiveStreams.push_back(endpointMMap);
}
-
- ALOGD("openEndpoint(), created %p for device = %d",
- endpoint.get(), configuration.getDeviceId());
}
if (endpoint.get() != nullptr) {
@@ -209,7 +207,7 @@
mSharedStreams.push_back(endpoint);
}
}
- ALOGD("openSharedEndpoint(), created %p for device = %d, dir = %d",
+ ALOGD("openSharedEndpoint(), created %p, requested device = %d, dir = %d",
endpoint.get(), configuration.getDeviceId(), (int)direction);
IPCThreadState::self()->restoreCallingIdentity(token);
}
diff --git a/services/oboeservice/AAudioEndpointManager.h b/services/oboeservice/AAudioEndpointManager.h
index 32c8454..f6aeb5a 100644
--- a/services/oboeservice/AAudioEndpointManager.h
+++ b/services/oboeservice/AAudioEndpointManager.h
@@ -47,7 +47,7 @@
std::string dump() const;
/**
- * Find a service endpoint for the given deviceId and direction.
+ * Find a service endpoint for the given deviceId, sessionId and direction.
* If an endpoint does not already exist then try to create one.
*
* @param audioService
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 01e9c6f..33439fc 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -64,6 +64,7 @@
result << " ContentType: " << getContentType() << "\n";
result << " InputPreset: " << getInputPreset() << "\n";
result << " Reference Count: " << mOpenCount << "\n";
+ result << " Session Id: " << getSessionId() << "\n";
result << " Connected: " << mConnected.load() << "\n";
result << " Registered Streams:" << "\n";
result << AAudioServiceStreamShared::dumpHeader() << "\n";
@@ -113,6 +114,10 @@
configuration.getDeviceId() != getDeviceId()) {
return false;
}
+ if (configuration.getSessionId() != AAUDIO_SESSION_ID_ALLOCATE &&
+ configuration.getSessionId() != getSessionId()) {
+ return false;
+ }
if (configuration.getSampleRate() != AAUDIO_UNSPECIFIED &&
configuration.getSampleRate() != getSampleRate()) {
return false;
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 541be20..db01c88 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -144,12 +144,16 @@
? MmapStreamInterface::DIRECTION_OUTPUT
: MmapStreamInterface::DIRECTION_INPUT;
+ aaudio_session_id_t requestedSessionId = getSessionId();
+ audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
+
// Open HAL stream. Set mMmapStream
status_t status = MmapStreamInterface::openMmapStream(streamDirection,
&attributes,
&config,
mMmapClient,
&deviceId,
+ &sessionId,
this, // callback
mMmapStream,
&mPortHandle);
@@ -165,6 +169,17 @@
}
setDeviceId(deviceId);
+ if (sessionId == AUDIO_SESSION_ALLOCATE) {
+ ALOGW("open() - openMmapStream() failed to set sessionId");
+ }
+
+ aaudio_session_id_t actualSessionId =
+ (requestedSessionId == AAUDIO_SESSION_ID_NONE)
+ ? AAUDIO_SESSION_ID_NONE
+ : (aaudio_session_id_t) sessionId;
+ setSessionId(actualSessionId);
+ ALOGD("open() deviceId = %d, sessionId = %d", getDeviceId(), getSessionId());
+
// Create MMAP/NOIRQ buffer.
int32_t minSizeFrames = getBufferCapacity();
if (minSizeFrames <= 0) { // zero will get rejected
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 2de537a..584efe5 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -77,6 +77,8 @@
setSampleRate(mStreamInternal->getSampleRate());
setSamplesPerFrame(mStreamInternal->getSamplesPerFrame());
setDeviceId(mStreamInternal->getDeviceId());
+ setSessionId(mStreamInternal->getSessionId());
+ ALOGD("open() deviceId = %d, sessionId = %d", getDeviceId(), getSessionId());
mFramesPerBurst = mStreamInternal->getFramesPerBurst();
return result;