Merge changes from topic "aaudio_session"
* changes:
aaudio: implement sessionId for effects
aaudio test: test sessionID for effects
aaudio: header for SessionId for effects
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/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/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;