Merge changes from topic "aaudio_session"

* changes:
  aaudio: implement sessionId for effects
  aaudio test: test sessionID for effects
  aaudio: header for SessionId for effects
gugelfrei
Phil Burk 7 years ago committed by Android (Google) Code Review
commit 9831721434

@ -52,6 +52,9 @@ class MmapStreamInterface : public virtual RefBase
* \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 @@ class MmapStreamInterface : public virtual RefBase
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);

@ -123,7 +123,7 @@ enum {
/**
* 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 @@ enum {
* 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 @@ enum {
};
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_setContentType(AAudioStreamBuilder* builder,
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.
*/
@ -995,6 +1040,28 @@ AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream);
*/
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.

@ -20,6 +20,7 @@ LIBAAUDIO {
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 @@ LIBAAUDIO {
AAudioStream_getInputPreset; # introduced=28
AAudioStream_getFramesWritten;
AAudioStream_getFramesRead;
AAudioStream_getSessionId; # introduced=28
AAudioStream_getTimestamp;
AAudioStream_isMMapUsed;
local:

@ -56,6 +56,8 @@ status_t AAudioStreamConfiguration::writeToParcel(Parcel* parcel) const {
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_t AAudioStreamConfiguration::readFromParcel(const Parcel* parcel) {
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);

@ -133,6 +133,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
setSampleRate(configurationOutput.getSampleRate());
setSamplesPerFrame(configurationOutput.getSamplesPerFrame());
setDeviceId(configurationOutput.getDeviceId());
setSessionId(configurationOutput.getSessionId());
setSharingMode(configurationOutput.getSharingMode());
setUsage(configurationOutput.getUsage());

@ -196,12 +196,19 @@ AAUDIO_API void AAudioStreamBuilder_setInputPreset(AAudioStreamBuilder* builder,
}
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 @@ AAUDIO_API aaudio_input_preset_t AAudioStream_getInputPreset(AAudioStream* strea
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);

@ -38,6 +38,7 @@ void AAudioStreamParameters::copyFrom(const AAudioStreamParameters &other) {
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 @@ aaudio_result_t AAudioStreamParameters::validate() const {
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 @@ aaudio_result_t AAudioStreamParameters::validate() const {
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 @@ void AAudioStreamParameters::dump() const {
ALOGD("mContentType = %6d", mContentType);
ALOGD("mInputPreset = %6d", mInputPreset);
}

@ -112,6 +112,14 @@ public:
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 @@ private:
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 */

@ -108,8 +108,10 @@ aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
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",

@ -216,6 +216,10 @@ public:
return mInputPreset;
}
int32_t getSessionId() const {
return mSessionId;
}
/**
* This is only valid after setSamplesPerFrame() and setFormat() have been called.
*/
@ -455,10 +459,15 @@ protected:
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 @@ private:
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

@ -141,6 +141,13 @@ aaudio_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
// 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;
}

@ -117,6 +117,9 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
.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 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
callbackData,
notificationFrames,
false /*threadCanCallJava*/,
AUDIO_SESSION_ALLOCATE,
sessionId,
streamTransferType,
flags,
AUDIO_UID_INVALID, // DEFAULT uid
@ -189,6 +192,13 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder)
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;

@ -134,6 +134,11 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
.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 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
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 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
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.

@ -250,6 +250,13 @@ aaudio_result_t AAudioConvert_androidToAAudioResult(status_t status) {
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) {

@ -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.
*/
@ -37,6 +40,13 @@ android::status_t AAudioConvert_aaudioToAndroidStatus(aaudio_result_t result);
*/
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.
*

@ -112,6 +112,18 @@ cc_test {
],
}
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"],

@ -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);
}

@ -262,6 +262,7 @@ status_t MmapStreamInterface::openMmapStream(MmapStreamInterface::stream_directi
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 MmapStreamInterface::openMmapStream(MmapStreamInterface::stream_directi
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 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
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 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
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 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
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 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
deviceId, &portId);
} else {
ret = AudioSystem::getInputForAttr(attr, &io,
sessionId,
actualSessionId,
client.clientPid,
client.clientUid,
config,
@ -326,13 +331,14 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
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;
}

@ -271,6 +271,7 @@ public:
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);

@ -102,8 +102,8 @@ sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
}
}
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 @@ sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
}
}
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 @@ sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
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 @@ sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
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);
}

@ -47,7 +47,7 @@ public:
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

@ -64,6 +64,7 @@ std::string AAudioServiceEndpoint::dump() const {
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 @@ bool AAudioServiceEndpoint::matches(const AAudioStreamConfiguration& configurati
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;

@ -144,12 +144,16 @@ aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamReques
? 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 @@ aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamReques
}
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

@ -77,6 +77,8 @@ aaudio_result_t AAudioServiceEndpointShared::open(const aaudio::AAudioStreamRequ
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;

Loading…
Cancel
Save