Merge "CameraService: Clean up ICameraServiceProxy; send it more info" into oc-dr1-dev
diff --git a/include/media/AudioClient.h b/include/media/AudioClient.h
new file mode 120000
index 0000000..a0530e4
--- /dev/null
+++ b/include/media/AudioClient.h
@@ -0,0 +1 @@
+../../media/libaudioclient/include/media/AudioClient.h
\ No newline at end of file
diff --git a/include/media/MmapStreamInterface.h b/include/media/MmapStreamInterface.h
index 7dbc19e..d689e25 100644
--- a/include/media/MmapStreamInterface.h
+++ b/include/media/MmapStreamInterface.h
@@ -18,6 +18,7 @@
#define ANDROID_AUDIO_MMAP_STREAM_INTERFACE_H
#include <system/audio.h>
+#include <media/AudioClient.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -37,12 +38,6 @@
DIRECTION_INPUT, /**< open a capture mmap stream */
} stream_direction_t;
- class Client {
- public:
- uid_t clientUid;
- pid_t clientPid;
- String16 packageName;
- };
/**
* Open a playback or capture stream in MMAP mode at the audio HAL.
*
@@ -53,13 +48,14 @@
* \param[in,out] config audio parameters (sampling rate, format ...) for the stream.
* Requested parameters as input,
* Actual parameters as output
- * \param[in] client a Client struct describing the first client using this stream.
+ * \param[in] client a AudioClient struct describing the first client using this stream.
* \param[in,out] deviceId audio device the stream should preferably be routed to/from
* Requested as input,
* 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
+ * \param[out] same unique handle as the one used for the first client stream started.
* \return OK if the stream was successfully created.
* NO_INIT if AudioFlinger is not properly initialized
* BAD_VALUE if the stream cannot be opened because of invalid arguments
@@ -68,10 +64,11 @@
static status_t openMmapStream(stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
- const Client& client,
+ const AudioClient& client,
audio_port_handle_t *deviceId,
const sp<MmapStreamCallback>& callback,
- sp<MmapStreamInterface>& interface);
+ sp<MmapStreamInterface>& interface,
+ audio_port_handle_t *handle);
/**
* Retrieve information on the mmap buffer used for audio samples transfer.
@@ -105,13 +102,13 @@
* Start a stream operating in mmap mode.
* createMmapBuffer() must be called before calling start()
*
- * \param[in] client a Client struct describing the client starting on this stream.
+ * \param[in] client a AudioClient struct describing the client starting on this stream.
* \param[out] handle unique handle for this instance. Used with stop().
* \return OK in case of success.
* NO_INIT in case of initialization error
* INVALID_OPERATION if called out of sequence
*/
- virtual status_t start(const Client& client, audio_port_handle_t *handle) = 0;
+ virtual status_t start(const AudioClient& client, audio_port_handle_t *handle) = 0;
/**
* Stop a stream operating in mmap mode.
diff --git a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
index f1593fe..910b10c 100644
--- a/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
+++ b/media/libaaudio/examples/input_monitor/src/input_monitor.cpp
@@ -26,30 +26,18 @@
#include "AAudioExampleUtils.h"
#include "AAudioSimpleRecorder.h"
-#define SAMPLE_RATE 48000
-
-#define NUM_SECONDS 10
-
+// TODO support FLOAT
+#define REQUIRED_FORMAT AAUDIO_FORMAT_PCM_I16
#define MIN_FRAMES_TO_READ 48 /* arbitrary, 1 msec at 48000 Hz */
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
- (void)argc; // unused
-
+ AAudioArgsParser argParser;
aaudio_result_t result;
AAudioSimpleRecorder recorder;
int actualSamplesPerFrame;
int actualSampleRate;
- const aaudio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
- aaudio_format_t actualDataFormat;
-
- const int requestedInputChannelCount = 2; // Can affect whether we get a FAST path.
-
- //aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
- const aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
- //aaudio_performance_mode_t requestedPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
- //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
- const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+ aaudio_format_t actualDataFormat;
aaudio_sharing_mode_t actualSharingMode;
AAudioStream *aaudioStream = nullptr;
@@ -70,18 +58,18 @@
printf("%s - Monitor input level using AAudio\n", argv[0]);
- AAudio_setMMapPolicy(AAUDIO_POLICY_ALWAYS);
+ argParser.setFormat(REQUIRED_FORMAT);
+ if (argParser.parseArgs(argc, argv)) {
+ return EXIT_FAILURE;
+ }
- recorder.setPerformanceMode(requestedPerformanceMode);
- recorder.setSharingMode(requestedSharingMode);
-
- result = recorder.open(requestedInputChannelCount, 48000, requestedDataFormat,
- nullptr, nullptr, nullptr);
+ result = recorder.open(argParser);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - recorder.open() returned %d\n", result);
goto finish;
}
aaudioStream = recorder.getStream();
+ argParser.compareWithStream(aaudioStream);
deviceId = AAudioStream_getDeviceId(aaudioStream);
printf("deviceId = %d\n", deviceId);
@@ -91,11 +79,6 @@
actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
printf("SamplesPerFrame = %d\n", actualSampleRate);
- actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
- printf("SharingMode: requested = %s, actual = %s\n",
- getSharingModeText(requestedSharingMode),
- getSharingModeText(actualSharingMode));
-
// This is the number of frames that are written in one chunk by a DMA controller
// or a DSP.
framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
@@ -110,14 +93,12 @@
printf("DataFormat: framesPerRead = %d\n",framesPerRead);
actualDataFormat = AAudioStream_getFormat(aaudioStream);
- printf("DataFormat: requested = %d, actual = %d\n", requestedDataFormat, actualDataFormat);
+ printf("DataFormat: requested = %d, actual = %d\n",
+ REQUIRED_FORMAT, actualDataFormat);
// TODO handle other data formats
- assert(actualDataFormat == AAUDIO_FORMAT_PCM_I16);
+ assert(actualDataFormat == REQUIRED_FORMAT);
- printf("PerformanceMode: requested = %d, actual = %d\n", requestedPerformanceMode,
- AAudioStream_getPerformanceMode(aaudioStream));
-
- // Allocate a buffer for the audio data.
+ // Allocate a buffer for the PCM_16 audio data.
data = new(std::nothrow) int16_t[framesPerRead * actualSamplesPerFrame];
if (data == nullptr) {
fprintf(stderr, "ERROR - could not allocate data buffer\n");
@@ -136,7 +117,7 @@
printf("after start, state = %s\n", AAudio_convertStreamStateToText(state));
// Record for a while.
- framesToRecord = actualSampleRate * NUM_SECONDS;
+ framesToRecord = actualSampleRate * argParser.getDurationSeconds();
framesLeft = framesToRecord;
while (framesLeft > 0) {
// Read audio data from the stream.
@@ -176,6 +157,8 @@
goto finish;
}
+ argParser.compareWithStream(aaudioStream);
+
finish:
recorder.close();
delete[] data;
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 9f06ee7..45a3beb 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -20,7 +20,6 @@
#include <assert.h>
#include <cctype>
#include <math.h>
-#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
new file mode 100644
index 0000000..54217a5
--- /dev/null
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef AAUDIO_EXAMPLE_ARGS_PARSER_H
+#define AAUDIO_EXAMPLE_ARGS_PARSER_H
+
+#include <cctype>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <aaudio/AAudio.h>
+#include <aaudio/AAudioTesting.h>
+#include <AAudioExampleUtils.h>
+
+// TODO use this as a base class within AAudio
+class AAudioParameters {
+public:
+
+ /**
+ * This is also known as samplesPerFrame.
+ */
+ int32_t getChannelCount() const {
+ return mChannelCount;
+ }
+
+ void setChannelCount(int32_t channelCount) {
+ mChannelCount = channelCount;
+ }
+
+ int32_t getSampleRate() const {
+ return mSampleRate;
+ }
+
+ void setSampleRate(int32_t sampleRate) {
+ mSampleRate = sampleRate;
+ }
+
+ aaudio_format_t getFormat() const {
+ return mFormat;
+ }
+
+ void setFormat(aaudio_format_t format) {
+ mFormat = format;
+ }
+
+ aaudio_sharing_mode_t getSharingMode() const {
+ return mSharingMode;
+ }
+
+ void setSharingMode(aaudio_sharing_mode_t sharingMode) {
+ mSharingMode = sharingMode;
+ }
+
+ int32_t getBufferCapacity() const {
+ return mBufferCapacity;
+ }
+
+ void setBufferCapacity(int32_t frames) {
+ mBufferCapacity = frames;
+ }
+
+ int32_t getPerformanceMode() const {
+ return mPerformanceMode;
+ }
+
+ void setPerformanceMode(aaudio_performance_mode_t performanceMode) {
+ mPerformanceMode = performanceMode;
+ }
+
+ int32_t getDeviceId() const {
+ return mDeviceId;
+ }
+
+ void setDeviceId(int32_t deviceId) {
+ mDeviceId = deviceId;
+ }
+
+ int32_t getNumberOfBursts() const {
+ return mNumberOfBursts;
+ }
+
+ void setNumberOfBursts(int32_t numBursts) {
+ mNumberOfBursts = numBursts;
+ }
+
+ /**
+ * Apply these parameters to a stream builder.
+ * @param builder
+ */
+ void applyParameters(AAudioStreamBuilder *builder) const {
+ AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
+ AAudioStreamBuilder_setFormat(builder, mFormat);
+ AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
+ AAudioStreamBuilder_setBufferCapacityInFrames(builder, mBufferCapacity);
+ AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
+ AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
+ AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
+ }
+
+private:
+ int32_t mChannelCount = AAUDIO_UNSPECIFIED;
+ aaudio_format_t mFormat = AAUDIO_FORMAT_UNSPECIFIED;
+ int32_t mSampleRate = AAUDIO_UNSPECIFIED;
+
+ int32_t mBufferCapacity = AAUDIO_UNSPECIFIED;
+ int32_t mDeviceId = AAUDIO_UNSPECIFIED;
+ aaudio_sharing_mode_t mSharingMode = AAUDIO_SHARING_MODE_SHARED;
+ aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
+
+ int32_t mNumberOfBursts = AAUDIO_UNSPECIFIED;
+};
+
+class AAudioArgsParser : public AAudioParameters {
+public:
+ AAudioArgsParser() = default;
+ ~AAudioArgsParser() = default;
+
+ enum {
+ DEFAULT_DURATION_SECONDS = 5
+ };
+
+ /**
+ * @param arg
+ * @return true if the argument was not handled
+ */
+ bool parseArg(const char *arg) {
+ bool unrecognized = false;
+ if (arg[0] == '-') {
+ char option = arg[1];
+ switch (option) {
+ case 'b':
+ setBufferCapacity(atoi(&arg[2]));
+ break;
+ case 'c':
+ setChannelCount(atoi(&arg[2]));
+ break;
+ case 'd':
+ mDurationSeconds = atoi(&arg[2]);
+ break;
+ case 'm':
+ AAudio_setMMapPolicy(AAUDIO_POLICY_AUTO);
+ break;
+ case 'n':
+ setNumberOfBursts(atoi(&arg[2]));
+ break;
+ case 'p':
+ setPerformanceMode(parsePerformanceMode(arg[2]));
+ break;
+ case 'r':
+ setSampleRate(atoi(&arg[2]));
+ break;
+ case 'x':
+ setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
+ break;
+ default:
+ unrecognized = true;
+ break;
+ }
+ }
+ return unrecognized;
+ }
+
+ /**
+ *
+ * @param argc
+ * @param argv
+ * @return true if an unrecognized argument was passed
+ */
+ bool parseArgs(int argc, const char **argv) {
+ for (int i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (parseArg(arg)) {
+ usage();
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ static void usage() {
+ printf("-c{channels} -d{duration} -m -n{burstsPerBuffer} -p{perfMode} -r{rate} -x\n");
+ printf(" Default values are UNSPECIFIED unless otherwise stated.\n");
+ printf(" -b{bufferCapacity} frames\n");
+ printf(" -c{channels} for example 2 for stereo\n");
+ printf(" -d{duration} in seconds, default is %d\n", DEFAULT_DURATION_SECONDS);
+ printf(" -m enable MMAP\n");
+ printf(" -n{numberOfBursts} for setBufferSize\n");
+ printf(" -p{performanceMode} set output AAUDIO_PERFORMANCE_MODE*, default NONE\n");
+ printf(" n for _NONE\n");
+ printf(" l for _LATENCY\n");
+ printf(" p for _POWER_SAVING;\n");
+ printf(" -r{sampleRate} for example 44100\n");
+ printf(" -x to use EXCLUSIVE mode\n");
+ }
+
+ static aaudio_performance_mode_t parsePerformanceMode(char c) {
+ aaudio_performance_mode_t mode = AAUDIO_PERFORMANCE_MODE_NONE;
+ switch (c) {
+ case 'n':
+ mode = AAUDIO_PERFORMANCE_MODE_NONE;
+ break;
+ case 'l':
+ mode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
+ break;
+ case 'p':
+ mode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
+ break;
+ default:
+ printf("ERROR invalid performance mode %c\n", c);
+ break;
+ }
+ return mode;
+ }
+
+ /**
+ * Print stream parameters in comparison with requested values.
+ * @param stream
+ */
+ void compareWithStream(AAudioStream *stream) {
+
+ printf(" DeviceId: requested = %d, actual = %d\n",
+ getDeviceId(), AAudioStream_getDeviceId(stream));
+
+ aaudio_stream_state_t state = AAudioStream_getState(stream);
+ printf(" State: %s\n", AAudio_convertStreamStateToText(state));
+
+ // Check to see what kind of stream we actually got.
+ printf(" SampleRate: requested = %d, actual = %d\n",
+ getSampleRate(), AAudioStream_getSampleRate(stream));
+
+ printf(" ChannelCount: requested = %d, actual = %d\n",
+ getChannelCount(), AAudioStream_getChannelCount(stream));
+
+ printf(" DataFormat: requested = %d, actual = %d\n",
+ getFormat(), AAudioStream_getFormat(stream));
+
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(stream);
+ int32_t sizeFrames = AAudioStream_getBufferSizeInFrames(stream);
+ printf(" Buffer: burst = %d\n", framesPerBurst);
+ if (framesPerBurst > 0) {
+ printf(" Buffer: size = %d = (%d * %d) + %d\n",
+ sizeFrames,
+ (sizeFrames / framesPerBurst),
+ framesPerBurst,
+ (sizeFrames % framesPerBurst));
+ }
+ printf(" Capacity: requested = %d, actual = %d\n", getBufferCapacity(),
+ AAudioStream_getBufferCapacityInFrames(stream));
+
+ printf(" SharingMode: requested = %s, actual = %s\n",
+ getSharingModeText(getSharingMode()),
+ getSharingModeText(AAudioStream_getSharingMode(stream)));
+
+ printf(" PerformanceMode: requested = %d, actual = %d\n",
+ getPerformanceMode(), AAudioStream_getPerformanceMode(stream));
+ printf(" Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
+ ? "yes" : "no");
+
+ }
+
+ int32_t getDurationSeconds() const {
+ return mDurationSeconds;
+ }
+
+ void setDurationSeconds(int32_t seconds) {
+ mDurationSeconds = seconds;
+ }
+
+private:
+ int32_t mDurationSeconds = DEFAULT_DURATION_SECONDS;
+};
+
+#endif // AAUDIO_EXAMPLE_ARGS_PARSER_H
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
index aaeb25f..19f8aff 100644
--- a/media/libaaudio/examples/utils/AAudioSimplePlayer.h
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -23,6 +23,7 @@
#include <sched.h>
#include <aaudio/AAudio.h>
+#include "AAudioArgsParser.h"
#include "SineGenerator.h"
//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
@@ -55,15 +56,23 @@
mRequestedPerformanceMode = requestedPerformanceMode;
}
+ // TODO Extract a common base class for record and playback.
/**
* Also known as "sample rate"
* Only call this after open() has been called.
*/
- int32_t getFramesPerSecond() {
+ int32_t getFramesPerSecond() const {
+ return getSampleRate(); // alias
+ }
+
+ /**
+ * Only call this after open() has been called.
+ */
+ int32_t getSampleRate() const {
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getSampleRate(mStream);;
+ return AAudioStream_getSampleRate(mStream);
}
/**
@@ -73,57 +82,83 @@
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getChannelCount(mStream);;
+ return AAudioStream_getChannelCount(mStream);
}
/**
* Open a stream
*/
+ aaudio_result_t open(const AAudioParameters ¶meters,
+ AAudioStream_dataCallback dataCallback = nullptr,
+ AAudioStream_errorCallback errorCallback = nullptr,
+ void *userContext = nullptr) {
+ aaudio_result_t result = AAUDIO_OK;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ AAudioStreamBuilder *builder = nullptr;
+ result = AAudio_createStreamBuilder(&builder);
+ if (result != AAUDIO_OK) return result;
+
+ parameters.applyParameters(builder); // apply args
+
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
+
+ if (dataCallback != nullptr) {
+ AAudioStreamBuilder_setDataCallback(builder, dataCallback, userContext);
+ }
+ if (errorCallback != nullptr) {
+ AAudioStreamBuilder_setErrorCallback(builder, errorCallback, userContext);
+ }
+ //AAudioStreamBuilder_setFramesPerDataCallback(builder, CALLBACK_SIZE_FRAMES);
+ //AAudioStreamBuilder_setBufferCapacityInFrames(builder, 48 * 8);
+
+ // Open an AAudioStream using the Builder.
+ result = AAudioStreamBuilder_openStream(builder, &mStream);
+
+ if (result == AAUDIO_OK) {
+ int32_t sizeInBursts = parameters.getNumberOfBursts();
+ if (sizeInBursts > 0) {
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
+ AAudioStream_setBufferSizeInFrames(mStream, sizeInBursts * framesPerBurst);
+ }
+ }
+
+ AAudioStreamBuilder_delete(builder);
+ return result;
+ }
+
aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
- AAudioStream_dataCallback dataProc, AAudioStream_errorCallback errorProc,
+ AAudioStream_dataCallback dataProc,
+ AAudioStream_errorCallback errorProc,
void *userContext) {
aaudio_result_t result = AAUDIO_OK;
// Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&mBuilder);
+ AAudioStreamBuilder *builder = nullptr;
+ result = AAudio_createStreamBuilder(&builder);
if (result != AAUDIO_OK) return result;
- //AAudioStreamBuilder_setSampleRate(mBuilder, 44100);
- AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequestedPerformanceMode);
- AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
+ AAudioStreamBuilder_setPerformanceMode(builder, mRequestedPerformanceMode);
+ AAudioStreamBuilder_setSharingMode(builder, mRequestedSharingMode);
+
+ AAudioStreamBuilder_setChannelCount(builder, channelCount);
+ AAudioStreamBuilder_setSampleRate(builder, sampSampleRate);
+ AAudioStreamBuilder_setFormat(builder, format);
+
if (dataProc != nullptr) {
- AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext);
+ AAudioStreamBuilder_setDataCallback(builder, dataProc, userContext);
}
if (errorProc != nullptr) {
- AAudioStreamBuilder_setErrorCallback(mBuilder, errorProc, userContext);
+ AAudioStreamBuilder_setErrorCallback(builder, errorProc, userContext);
}
- AAudioStreamBuilder_setChannelCount(mBuilder, channelCount);
- AAudioStreamBuilder_setSampleRate(mBuilder, sampSampleRate);
- AAudioStreamBuilder_setFormat(mBuilder, format);
- //AAudioStreamBuilder_setFramesPerDataCallback(mBuilder, CALLBACK_SIZE_FRAMES);
- AAudioStreamBuilder_setBufferCapacityInFrames(mBuilder, 48 * 8);
-
- //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
- aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
- //aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
- AAudioStreamBuilder_setPerformanceMode(mBuilder, perfMode);
+ //AAudioStreamBuilder_setFramesPerDataCallback(builder, CALLBACK_SIZE_FRAMES);
+ //AAudioStreamBuilder_setBufferCapacityInFrames(builder, 48 * 8);
// Open an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
- if (result != AAUDIO_OK) goto finish1;
+ result = AAudioStreamBuilder_openStream(builder, &mStream);
- printf("AAudioStream_getFramesPerBurst() = %d\n",
- AAudioStream_getFramesPerBurst(mStream));
- printf("AAudioStream_getBufferSizeInFrames() = %d\n",
- AAudioStream_getBufferSizeInFrames(mStream));
- printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
- AAudioStream_getBufferCapacityInFrames(mStream));
- printf("AAudioStream_getPerformanceMode() = %d, requested %d\n",
- AAudioStream_getPerformanceMode(mStream), perfMode);
-
- finish1:
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
+ AAudioStreamBuilder_delete(builder);
return result;
}
@@ -132,8 +167,6 @@
printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
AAudioStream_close(mStream);
mStream = nullptr;
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
}
return AAUDIO_OK;
}
@@ -178,7 +211,6 @@
}
private:
- AAudioStreamBuilder *mBuilder = nullptr;
AAudioStream *mStream = nullptr;
aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
diff --git a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
index 9e7c463..cb12fda 100644
--- a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
+++ b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
@@ -20,10 +20,12 @@
#define AAUDIO_SIMPLE_RECORDER_H
#include <aaudio/AAudio.h>
+#include "AAudioArgsParser.h"
//#define SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
#define SHARING_MODE AAUDIO_SHARING_MODE_SHARED
#define PERFORMANCE_MODE AAUDIO_PERFORMANCE_MODE_NONE
+
/**
* Simple wrapper for AAudio that opens an input stream either in callback or blocking read mode.
*/
@@ -54,11 +56,18 @@
* Also known as "sample rate"
* Only call this after open() has been called.
*/
- int32_t getFramesPerSecond() {
+ int32_t getFramesPerSecond() const {
+ return getSampleRate(); // alias
+ }
+
+ /**
+ * Only call this after open() has been called.
+ */
+ int32_t getSampleRate() const {
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getSampleRate(mStream);;
+ return AAudioStream_getSampleRate(mStream);
}
/**
@@ -68,7 +77,7 @@
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getSamplesPerFrame(mStream);;
+ return AAudioStream_getChannelCount(mStream);
}
/**
* Only call this after open() has been called.
@@ -77,53 +86,85 @@
if (mStream == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- return AAudioStream_getFramesRead(mStream);;
+ return AAudioStream_getFramesRead(mStream);
+ }
+
+ aaudio_result_t open(const AAudioParameters ¶meters,
+ AAudioStream_dataCallback dataCallback = nullptr,
+ AAudioStream_errorCallback errorCallback = nullptr,
+ void *userContext = nullptr) {
+ aaudio_result_t result = AAUDIO_OK;
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ AAudioStreamBuilder *builder = nullptr;
+ result = AAudio_createStreamBuilder(&builder);
+ if (result != AAUDIO_OK) return result;
+
+ parameters.applyParameters(builder); // apply args
+
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
+
+ if (dataCallback != nullptr) {
+ AAudioStreamBuilder_setDataCallback(builder, dataCallback, userContext);
+ }
+ if (errorCallback != nullptr) {
+ AAudioStreamBuilder_setErrorCallback(builder, errorCallback, userContext);
+ }
+
+ // Open an AAudioStream using the Builder.
+ result = AAudioStreamBuilder_openStream(builder, &mStream);
+ if (result != AAUDIO_OK) {
+ fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
+ result, AAudio_convertResultToText(result));
+ }
+
+ if (result == AAUDIO_OK) {
+ int32_t sizeInBursts = parameters.getNumberOfBursts();
+ if (sizeInBursts > 0) {
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(mStream);
+ AAudioStream_setBufferSizeInFrames(mStream, sizeInBursts * framesPerBurst);
+ }
+ }
+
+ AAudioStreamBuilder_delete(builder);
+ return result;
}
/**
* Open a stream
*/
aaudio_result_t open(int channelCount, int sampSampleRate, aaudio_format_t format,
- AAudioStream_dataCallback dataProc, AAudioStream_errorCallback errorProc,
+ AAudioStream_dataCallback dataProc,
+ AAudioStream_errorCallback errorProc,
void *userContext) {
aaudio_result_t result = AAUDIO_OK;
// Use an AAudioStreamBuilder to contain requested parameters.
- result = AAudio_createStreamBuilder(&mBuilder);
+ AAudioStreamBuilder *builder = nullptr;
+ result = AAudio_createStreamBuilder(&builder);
if (result != AAUDIO_OK) return result;
- AAudioStreamBuilder_setDirection(mBuilder, AAUDIO_DIRECTION_INPUT);
- AAudioStreamBuilder_setPerformanceMode(mBuilder, mRequestedPerformanceMode);
- AAudioStreamBuilder_setSharingMode(mBuilder, mRequestedSharingMode);
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
+ AAudioStreamBuilder_setPerformanceMode(builder, mRequestedPerformanceMode);
+ AAudioStreamBuilder_setSharingMode(builder, mRequestedSharingMode);
if (dataProc != nullptr) {
- AAudioStreamBuilder_setDataCallback(mBuilder, dataProc, userContext);
+ AAudioStreamBuilder_setDataCallback(builder, dataProc, userContext);
}
if (errorProc != nullptr) {
- AAudioStreamBuilder_setErrorCallback(mBuilder, errorProc, userContext);
+ AAudioStreamBuilder_setErrorCallback(builder, errorProc, userContext);
}
- AAudioStreamBuilder_setChannelCount(mBuilder, channelCount);
- AAudioStreamBuilder_setSampleRate(mBuilder, sampSampleRate);
- AAudioStreamBuilder_setFormat(mBuilder, format);
+ AAudioStreamBuilder_setChannelCount(builder, channelCount);
+ AAudioStreamBuilder_setSampleRate(builder, sampSampleRate);
+ AAudioStreamBuilder_setFormat(builder, format);
// Open an AAudioStream using the Builder.
- result = AAudioStreamBuilder_openStream(mBuilder, &mStream);
+ result = AAudioStreamBuilder_openStream(builder, &mStream);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - AAudioStreamBuilder_openStream() returned %d %s\n",
result, AAudio_convertResultToText(result));
- goto finish1;
}
- printf("AAudioStream_getFramesPerBurst() = %d\n",
- AAudioStream_getFramesPerBurst(mStream));
- printf("AAudioStream_getBufferSizeInFrames() = %d\n",
- AAudioStream_getBufferSizeInFrames(mStream));
- printf("AAudioStream_getBufferCapacityInFrames() = %d\n",
- AAudioStream_getBufferCapacityInFrames(mStream));
- return result;
-
- finish1:
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
+ AAudioStreamBuilder_delete(builder);
return result;
}
@@ -132,8 +173,6 @@
printf("call AAudioStream_close(%p)\n", mStream); fflush(stdout);
AAudioStream_close(mStream);
mStream = nullptr;
- AAudioStreamBuilder_delete(mBuilder);
- mBuilder = nullptr;
}
return AAUDIO_OK;
}
@@ -186,7 +225,6 @@
}
private:
- AAudioStreamBuilder *mBuilder = nullptr;
AAudioStream *mStream = nullptr;
aaudio_sharing_mode_t mRequestedSharingMode = SHARING_MODE;
aaudio_performance_mode_t mRequestedPerformanceMode = PERFORMANCE_MODE;
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index b9269e6..0125c0f 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -23,39 +23,22 @@
#include <aaudio/AAudioTesting.h>
#include "AAudioExampleUtils.h"
#include "AAudioSimplePlayer.h"
+#include "AAudioArgsParser.h"
-#define SAMPLE_RATE 48000
#define NUM_SECONDS 4
-//#define MMAP_POLICY AAUDIO_UNSPECIFIED
-//#define MMAP_POLICY AAUDIO_POLICY_NEVER
-//#define MMAP_POLICY AAUDIO_POLICY_AUTO
-#define MMAP_POLICY AAUDIO_POLICY_ALWAYS
-
-#define REQUESTED_FORMAT AAUDIO_FORMAT_PCM_I16
-
-//#define REQUESTED_SHARING_MODE AAUDIO_SHARING_MODE_SHARED
-#define REQUESTED_SHARING_MODE AAUDIO_SHARING_MODE_EXCLUSIVE
-
-
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
- (void)argc; // unused
-
+ AAudioArgsParser argParser;
AAudioSimplePlayer player;
SineThreadedData_t myData;
- aaudio_result_t result = AAUDIO_OK;
+ aaudio_result_t result = AAUDIO_OK;
- const int requestedChannelCount = 2;
- int actualChannelCount = 0;
- const int requestedSampleRate = SAMPLE_RATE;
- int actualSampleRate = 0;
- aaudio_format_t requestedDataFormat = REQUESTED_FORMAT;
+ int32_t actualChannelCount = 0;
+ int32_t actualSampleRate = 0;
aaudio_format_t actualDataFormat = AAUDIO_FORMAT_UNSPECIFIED;
- aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
AAudioStream *aaudioStream = nullptr;
- aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
int32_t framesPerBurst = 0;
int32_t framesPerWrite = 0;
int32_t bufferCapacity = 0;
@@ -64,61 +47,37 @@
int32_t xRunCount = 0;
float *floatData = nullptr;
int16_t *shortData = nullptr;
- int32_t deviceId;
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("%s - Play a sine wave using AAudio\n", argv[0]);
+ printf("%s - Play a sine wave using AAudio V0.1.1\n", argv[0]);
- AAudio_setMMapPolicy(MMAP_POLICY);
- printf("requested MMapPolicy = %d\n", AAudio_getMMapPolicy());
+ if (argParser.parseArgs(argc, argv)) {
+ return EXIT_FAILURE;
+ }
- player.setSharingMode(REQUESTED_SHARING_MODE);
-
- result = player.open(requestedChannelCount, requestedSampleRate, requestedDataFormat,
- nullptr, nullptr, &myData);
+ result = player.open(argParser);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - player.open() returned %d\n", result);
goto finish;
}
aaudioStream = player.getStream();
- // Request stream properties.
- deviceId = AAudioStream_getDeviceId(aaudioStream);
- printf("deviceId = %d\n", deviceId);
+ argParser.compareWithStream(aaudioStream);
- state = AAudioStream_getState(aaudioStream);
- printf("after open, state = %s\n", AAudio_convertStreamStateToText(state));
-
- // Check to see what kind of stream we actually got.
+ actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
- printf("SampleRate: requested = %d, actual = %d\n", requestedSampleRate, actualSampleRate);
+ actualDataFormat = AAudioStream_getFormat(aaudioStream);
myData.sineOsc1.setup(440.0, actualSampleRate);
myData.sineOsc2.setup(660.0, actualSampleRate);
- actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
- printf("ChannelCount: requested = %d, actual = %d\n",
- requestedChannelCount, actualChannelCount);
-
- actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
- printf("SharingMode: requested = %s, actual = %s\n",
- getSharingModeText(REQUESTED_SHARING_MODE),
- getSharingModeText(actualSharingMode));
-
- // This is the number of frames that are read in one chunk by a DMA controller
- // or a DSP or a mixer.
- framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
- printf("Buffer: bufferSize = %d\n", AAudioStream_getBufferSizeInFrames(aaudioStream));
- bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
- printf("Buffer: bufferCapacity = %d, remainder = %d\n",
- bufferCapacity, bufferCapacity % framesPerBurst);
-
// Some DMA might use very short bursts of 16 frames. We don't need to write such small
// buffers. But it helps to use a multiple of the burst size for predictable scheduling.
+ framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
framesPerWrite = framesPerBurst;
while (framesPerWrite < 48) {
framesPerWrite *= 2;
@@ -126,13 +85,6 @@
printf("Buffer: framesPerBurst = %d\n",framesPerBurst);
printf("Buffer: framesPerWrite = %d\n",framesPerWrite);
- printf("PerformanceMode = %d\n", AAudioStream_getPerformanceMode(aaudioStream));
- printf("is MMAP used? = %s\n", AAudioStream_isMMapUsed(aaudioStream) ? "yes" : "no");
-
- actualDataFormat = AAudioStream_getFormat(aaudioStream);
- printf("DataFormat: requested = %d, actual = %d\n", REQUESTED_FORMAT, actualDataFormat);
- // TODO handle other data formats
-
// Allocate a buffer for the audio data.
if (actualDataFormat == AAUDIO_FORMAT_PCM_FLOAT) {
floatData = new float[framesPerWrite * actualChannelCount];
@@ -151,11 +103,11 @@
goto finish;
}
- state = AAudioStream_getState(aaudioStream);
- printf("after start, state = %s\n", AAudio_convertStreamStateToText(state));
+ printf("after start, state = %s\n",
+ AAudio_convertStreamStateToText(AAudioStream_getState(aaudioStream)));
// Play for a while.
- framesToPlay = actualSampleRate * NUM_SECONDS;
+ framesToPlay = actualSampleRate * argParser.getDurationSeconds();
framesLeft = framesToPlay;
while (framesLeft > 0) {
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index 69145aa..2211b72 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -27,36 +27,42 @@
#include "AAudioExampleUtils.h"
#include "AAudioSimplePlayer.h"
-#define NUM_SECONDS 5
-
// Application data that gets passed to the callback.
#define MAX_FRAME_COUNT_RECORDS 256
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
- (void)argc; // unused
+ AAudioArgsParser argParser;
AAudioSimplePlayer player;
SineThreadedData_t myData;
aaudio_result_t result;
+ int32_t actualSampleRate;
// Make printf print immediately so that debug info is not stuck
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("%s - Play a sine sweep using an AAudio callback\n", argv[0]);
+
+ printf("%s - Play a sine sweep using an AAudio callback V0.1.1\n", argv[0]);
myData.schedulerChecked = false;
- result = player.open(2, 44100, AAUDIO_FORMAT_PCM_FLOAT,
+ if (argParser.parseArgs(argc, argv)) {
+ return EXIT_FAILURE;
+ }
+
+ result = player.open(argParser,
SimplePlayerDataCallbackProc, SimplePlayerErrorCallbackProc, &myData);
if (result != AAUDIO_OK) {
fprintf(stderr, "ERROR - player.open() returned %d\n", result);
goto error;
}
- printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond());
- printf("player.getChannelCount() = %d\n", player.getChannelCount());
- myData.sineOsc1.setup(440.0, 48000);
+
+ argParser.compareWithStream(player.getStream());
+
+ actualSampleRate = player.getSampleRate();
+ myData.sineOsc1.setup(440.0, actualSampleRate);
myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
- myData.sineOsc2.setup(660.0, 48000);
+ myData.sineOsc2.setup(660.0, actualSampleRate);
myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
#if 0
@@ -73,8 +79,9 @@
goto error;
}
- printf("Sleep for %d seconds while audio plays in a callback thread.\n", NUM_SECONDS);
- for (int second = 0; second < NUM_SECONDS; second++)
+ printf("Sleep for %d seconds while audio plays in a callback thread.\n",
+ argParser.getDurationSeconds());
+ for (int second = 0; second < argParser.getDurationSeconds(); second++)
{
const struct timespec request = { .tv_sec = 1, .tv_nsec = 0 };
(void) clock_nanosleep(CLOCK_MONOTONIC, 0 /*flags*/, &request, NULL /*remain*/);
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index 469f0a8..89ae85c 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -97,6 +97,17 @@
aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) override;
+ aaudio_result_t startClient(aaudio_handle_t streamHandle __unused,
+ const android::AudioClient& client __unused,
+ audio_port_handle_t *clientHandle) override {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
+ aaudio_result_t stopClient(aaudio_handle_t streamHandle __unused,
+ audio_port_handle_t clientHandle __unused) override {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {
// TODO This is just a stub so we can have a client Binder to pass to the service.
// TODO Implemented in a later CL.
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index 7368062..a64405b 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -18,6 +18,7 @@
#define ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
#include <utils/StrongPointer.h>
+#include <media/AudioClient.h>
#include "binding/AAudioServiceDefinitions.h"
#include "binding/AAudioStreamRequest.h"
@@ -86,6 +87,13 @@
virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) = 0;
+
+ virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
+ const android::AudioClient& client,
+ audio_port_handle_t *clientHandle) = 0;
+
+ virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
+ audio_port_handle_t clientHandle) = 0;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.cpp b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
index 8a765ad..abdcf5b 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
@@ -52,8 +52,12 @@
status = parcel->writeBool(mSharingModeMatchRequired);
if (status != NO_ERROR) goto error;
+ status = parcel->writeBool(mInService);
+ if (status != NO_ERROR) goto error;
+
status = mConfiguration.writeToParcel(parcel);
if (status != NO_ERROR) goto error;
+
return NO_ERROR;
error:
@@ -74,8 +78,12 @@
status = parcel->readBool(&mSharingModeMatchRequired);
if (status != NO_ERROR) goto error;
+ status = parcel->readBool(&mInService);
+ if (status != NO_ERROR) goto error;
+
status = mConfiguration.readFromParcel(parcel);
if (status != NO_ERROR) goto error;
+
return NO_ERROR;
error:
@@ -91,5 +99,7 @@
ALOGD("AAudioStreamRequest mUserId = %d", mUserId);
ALOGD("AAudioStreamRequest mProcessId = %d", mProcessId);
ALOGD("AAudioStreamRequest mDirection = %d", mDirection);
+ ALOGD("AAudioStreamRequest mSharingModeMatchRequired = %d", mSharingModeMatchRequired);
+ ALOGD("AAudioStreamRequest mInService = %d", mInService);
mConfiguration.dump();
}
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.h b/media/libaaudio/src/binding/AAudioStreamRequest.h
index 462246b..b0fa96a 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.h
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.h
@@ -76,6 +76,14 @@
return mConfiguration;
}
+ bool isInService() const {
+ return mInService;
+ }
+
+ void setInService(bool inService) {
+ mInService = inService;
+ }
+
virtual status_t writeToParcel(Parcel* parcel) const override;
virtual status_t readFromParcel(const Parcel* parcel) override;
@@ -90,6 +98,7 @@
pid_t mProcessId;
aaudio_direction_t mDirection;
bool mSharingModeMatchRequired = false;
+ bool mInService = false; // Stream opened by AAudioservice
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index ff13fc2..7b01e44 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -16,7 +16,7 @@
// This file is used in both client and server processes.
// This is needed to make sense of the logs more easily.
-#define LOG_TAG (mInService ? "AAudioService" : "AAudio")
+#define LOG_TAG (mInService ? "AudioStreamInternal_Service" : "AudioStreamInternal_Client")
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -93,6 +93,7 @@
request.setProcessId(getpid());
request.setDirection(getDirection());
request.setSharingModeMatchRequired(isSharingModeMatchRequired());
+ request.setInService(mInService);
request.getConfiguration().setDeviceId(getDeviceId());
request.getConfiguration().setSampleRate(getSampleRate());
@@ -326,6 +327,21 @@
return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
}
+aaudio_result_t AudioStreamInternal::startClient(const android::AudioClient& client,
+ audio_port_handle_t *clientHandle) {
+ if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return mServiceInterface.startClient(mServiceStreamHandle, client, clientHandle);
+}
+
+aaudio_result_t AudioStreamInternal::stopClient(audio_port_handle_t clientHandle) {
+ if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
+ return AAUDIO_ERROR_INVALID_STATE;
+ }
+ return mServiceInterface.stopClient(mServiceStreamHandle, clientHandle);
+}
+
aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds) {
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 257a702..109e425 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -87,6 +87,11 @@
//PlayerBase virtuals
virtual void destroy();
+ aaudio_result_t startClient(const android::AudioClient& client,
+ audio_port_handle_t *clientHandle);
+
+ aaudio_result_t stopClient(audio_port_handle_t clientHandle);
+
protected:
aaudio_result_t processData(void *buffer,
@@ -170,7 +175,6 @@
AudioEndpointParcelable mEndPointParcelable; // description of the buffers filled by service
EndpointDescriptor mEndpointDescriptor; // buffer description with resolved addresses
-
};
} /* namespace aaudio */
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index d320320..ceba211 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -323,6 +323,7 @@
return BAD_VALUE;
}
data.write(attr, sizeof(audio_attributes_t));
+ data.writeInt32(*input);
data.writeInt32(session);
data.writeInt32(pid);
data.writeInt32(uid);
@@ -1024,6 +1025,7 @@
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_attributes_t attr;
data.read(&attr, sizeof(audio_attributes_t));
+ audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
audio_session_t session = (audio_session_t)data.readInt32();
pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
@@ -1033,7 +1035,6 @@
audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32();
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
- audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
status_t status = getInputForAttr(&attr, &input, session, pid, uid,
&config,
flags, &selectedDeviceId, &portId);
diff --git a/media/libaudioclient/include/media/AudioClient.h b/media/libaudioclient/include/media/AudioClient.h
new file mode 100644
index 0000000..9efd76d
--- /dev/null
+++ b/media/libaudioclient/include/media/AudioClient.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+
+#ifndef ANDROID_AUDIO_CLIENT_H
+#define ANDROID_AUDIO_CLIENT_H
+
+#include <system/audio.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class AudioClient {
+ public:
+ AudioClient() :
+ clientUid(-1), clientPid(-1), packageName("") {}
+
+ uid_t clientUid;
+ pid_t clientPid;
+ String16 packageName;
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_CLIENT_H
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index bdeecb0..1f98e8d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -960,7 +960,9 @@
return NO_MEMORY;
}
hidlMem = mapMemory(hidlMemToken);
-
+ if (hidlMem == nullptr) {
+ return NO_MEMORY;
+ }
err = mOMXNode->useBuffer(
portIndex, hidlMemToken, &info.mBufferID);
} else {
@@ -1008,6 +1010,9 @@
return NO_MEMORY;
}
hidlMem = mapMemory(hidlMemToken);
+ if (hidlMem == nullptr) {
+ return NO_MEMORY;
+ }
info.mData = new SharedMemoryBuffer(format, hidlMem);
info.mMemRef = hidlMem;
} else {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 61a2b5f..6ed0d0e 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -972,6 +972,14 @@
}
if (handle != nullptr) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = frame->getMemory(&offset, &size);
+ if (heap->getHeapID() != mMemoryHeapBase->getHeapID()) {
+ ALOGE("%s: Mismatched heap ID, ignoring release (got %x, expected %x)",
+ __FUNCTION__, heap->getHeapID(), mMemoryHeapBase->getHeapID());
+ return;
+ }
uint32_t batchSize = 0;
{
Mutex::Autolock autoLock(mBatchLock);
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index db99ef2..22d7d27 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -1043,6 +1043,10 @@
case OMXBuffer::kBufferTypeHidlMemory: {
sp<IHidlMemory> hidlMemory = mapMemory(omxBuffer.mHidlMemory);
+ if (hidlMemory == nullptr) {
+ ALOGE("OMXNodeInstance useBuffer() failed to map memory");
+ return NO_MEMORY;
+ }
return useBuffer_l(portIndex, NULL, hidlMemory, buffer);
}
default:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d850aa9..38c9687 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -260,10 +260,11 @@
status_t MmapStreamInterface::openMmapStream(MmapStreamInterface::stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
- const MmapStreamInterface::Client& client,
+ const AudioClient& client,
audio_port_handle_t *deviceId,
const sp<MmapStreamCallback>& callback,
- sp<MmapStreamInterface>& interface)
+ sp<MmapStreamInterface>& interface,
+ audio_port_handle_t *handle)
{
sp<AudioFlinger> af;
{
@@ -273,7 +274,7 @@
status_t ret = NO_INIT;
if (af != 0) {
ret = af->openMmapStream(
- direction, attr, config, client, deviceId, callback, interface);
+ direction, attr, config, client, deviceId, callback, interface, handle);
}
return ret;
}
@@ -281,10 +282,11 @@
status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
- const MmapStreamInterface::Client& client,
+ const AudioClient& client,
audio_port_handle_t *deviceId,
const sp<MmapStreamCallback>& callback,
- sp<MmapStreamInterface>& interface)
+ sp<MmapStreamInterface>& interface,
+ audio_port_handle_t *handle)
{
status_t ret = initCheck();
if (ret != NO_ERROR) {
@@ -293,7 +295,7 @@
audio_session_t sessionId = (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_t io = AUDIO_IO_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
audio_config_t fullConfig = AUDIO_CONFIG_INITIALIZER;
@@ -325,6 +327,7 @@
if (thread != 0) {
interface = new MmapThreadHandle(thread);
thread->configure(attr, streamType, sessionId, callback, portId);
+ *handle = portId;
} else {
ret = NO_INIT;
}
@@ -1279,7 +1282,7 @@
if (thread == NULL) {
thread = (ThreadBase *)checkMmapThread_l(ioHandle);
if (thread == NULL) {
- String8("");
+ return String8("");
}
}
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2e0bc66..8a96c1d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -294,10 +294,11 @@
status_t openMmapStream(MmapStreamInterface::stream_direction_t direction,
const audio_attributes_t *attr,
audio_config_base_t *config,
- const MmapStreamInterface::Client& client,
+ const AudioClient& client,
audio_port_handle_t *deviceId,
const sp<MmapStreamCallback>& callback,
- sp<MmapStreamInterface>& interface);
+ sp<MmapStreamInterface>& interface,
+ audio_port_handle_t *handle);
private:
// FIXME The 400 is temporarily too high until a leak of writers in media.log is fixed.
static const size_t kLogMemorySize = 400 * 1024;
@@ -596,7 +597,7 @@
virtual status_t createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info);
virtual status_t getMmapPosition(struct audio_mmap_position *position);
- virtual status_t start(const MmapStreamInterface::Client& client,
+ virtual status_t start(const AudioClient& client,
audio_port_handle_t *handle);
virtual status_t stop(audio_port_handle_t handle);
virtual status_t standby();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 085be00..d932483 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7523,7 +7523,7 @@
return mThread->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThreadHandle::start(const MmapStreamInterface::Client& client,
+status_t AudioFlinger::MmapThreadHandle::start(const AudioClient& client,
audio_port_handle_t *handle)
{
@@ -7616,77 +7616,75 @@
return mHalStream->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThread::start(const MmapStreamInterface::Client& client,
+status_t AudioFlinger::MmapThread::start(const AudioClient& client,
audio_port_handle_t *handle)
{
- ALOGV("%s clientUid %d mStandby %d", __FUNCTION__, client.clientUid, mStandby);
+ ALOGV("%s clientUid %d mStandby %d mPortId %d *handle %d", __FUNCTION__,
+ client.clientUid, mStandby, mPortId, *handle);
if (mHalStream == 0) {
return NO_INIT;
}
status_t ret;
- audio_session_t sessionId;
- audio_port_handle_t portId;
- if (mActiveTracks.size() == 0) {
+ if (*handle == mPortId) {
// for the first track, reuse portId and session allocated when the stream was opened
ret = mHalStream->start();
if (ret != NO_ERROR) {
ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
return ret;
}
- portId = mPortId;
- sessionId = mSessionId;
mStandby = false;
+ return NO_ERROR;
+ }
+
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+
+ audio_io_handle_t io = mId;
+ if (isOutput()) {
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+ config.sample_rate = mSampleRate;
+ config.channel_mask = mChannelMask;
+ config.format = mFormat;
+ audio_stream_type_t stream = streamType();
+ audio_output_flags_t flags =
+ (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
+ audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+ ret = AudioSystem::getOutputForAttr(&mAttr, &io,
+ mSessionId,
+ &stream,
+ client.clientUid,
+ &config,
+ flags,
+ &deviceId,
+ &portId);
} else {
- // for other tracks than first one, get a new port ID from APM.
- sessionId = (audio_session_t)mAudioFlinger->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- audio_io_handle_t io;
- if (isOutput()) {
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
- config.sample_rate = mSampleRate;
- config.channel_mask = mChannelMask;
- config.format = mFormat;
- audio_stream_type_t stream = streamType();
- audio_output_flags_t flags =
- (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
- audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
- ret = AudioSystem::getOutputForAttr(&mAttr, &io,
- sessionId,
- &stream,
- client.clientUid,
- &config,
- flags,
- &deviceId,
- &portId);
- } else {
- audio_config_base_t config;
- config.sample_rate = mSampleRate;
- config.channel_mask = mChannelMask;
- config.format = mFormat;
- audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
- ret = AudioSystem::getInputForAttr(&mAttr, &io,
- sessionId,
- client.clientPid,
- client.clientUid,
- &config,
- AUDIO_INPUT_FLAG_MMAP_NOIRQ,
- &deviceId,
- &portId);
- }
- // APM should not chose a different input or output stream for the same set of attributes
- // and audo configuration
- if (ret != NO_ERROR || io != mId) {
- ALOGE("%s: error getting output or input from APM (error %d, io %d expected io %d)",
- __FUNCTION__, ret, io, mId);
- return BAD_VALUE;
- }
+ audio_config_base_t config;
+ config.sample_rate = mSampleRate;
+ config.channel_mask = mChannelMask;
+ config.format = mFormat;
+ audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
+ ret = AudioSystem::getInputForAttr(&mAttr, &io,
+ mSessionId,
+ client.clientPid,
+ client.clientUid,
+ &config,
+ AUDIO_INPUT_FLAG_MMAP_NOIRQ,
+ &deviceId,
+ &portId);
+ }
+ // APM should not chose a different input or output stream for the same set of attributes
+ // and audo configuration
+ if (ret != NO_ERROR || io != mId) {
+ ALOGE("%s: error getting output or input from APM (error %d, io %d expected io %d)",
+ __FUNCTION__, ret, io, mId);
+ return BAD_VALUE;
}
if (isOutput()) {
- ret = AudioSystem::startOutput(mId, streamType(), sessionId);
+ ret = AudioSystem::startOutput(mId, streamType(), mSessionId);
} else {
- ret = AudioSystem::startInput(mId, sessionId);
+ ret = AudioSystem::startInput(mId, mSessionId);
}
// abort if start is rejected by audio policy manager
@@ -7694,9 +7692,9 @@
ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret);
if (mActiveTracks.size() != 0) {
if (isOutput()) {
- AudioSystem::releaseOutput(mId, streamType(), sessionId);
+ AudioSystem::releaseOutput(mId, streamType(), mSessionId);
} else {
- AudioSystem::releaseInput(mId, sessionId);
+ AudioSystem::releaseInput(mId, mSessionId);
}
} else {
mHalStream->stop();
@@ -7704,11 +7702,11 @@
return PERMISSION_DENIED;
}
- sp<MmapTrack> track = new MmapTrack(this, mSampleRate, mFormat, mChannelMask, sessionId,
+ sp<MmapTrack> track = new MmapTrack(this, mSampleRate, mFormat, mChannelMask, mSessionId,
client.clientUid, portId);
mActiveTracks.add(track);
- sp<EffectChain> chain = getEffectChain_l(sessionId);
+ sp<EffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
chain->setStrategy(AudioSystem::getStrategyForStream(streamType()));
chain->incTrackCnt();
@@ -7716,10 +7714,9 @@
}
*handle = portId;
-
broadcast_l();
- ALOGV("%s DONE handle %d stream %p", __FUNCTION__, portId, mHalStream.get());
+ ALOGV("%s DONE handle %d stream %p", __FUNCTION__, *handle, mHalStream.get());
return NO_ERROR;
}
@@ -7732,6 +7729,11 @@
return NO_INIT;
}
+ if (handle == mPortId) {
+ mHalStream->stop();
+ return NO_ERROR;
+ }
+
sp<MmapTrack> track;
for (const sp<MmapTrack> &t : mActiveTracks) {
if (handle == t->portId()) {
@@ -7747,14 +7749,10 @@
if (isOutput()) {
AudioSystem::stopOutput(mId, streamType(), track->sessionId());
- if (mActiveTracks.size() != 0) {
- AudioSystem::releaseOutput(mId, streamType(), track->sessionId());
- }
+ AudioSystem::releaseOutput(mId, streamType(), track->sessionId());
} else {
AudioSystem::stopInput(mId, track->sessionId());
- if (mActiveTracks.size() != 0) {
- AudioSystem::releaseInput(mId, track->sessionId());
- }
+ AudioSystem::releaseInput(mId, track->sessionId());
}
sp<EffectChain> chain = getEffectChain_l(track->sessionId());
@@ -7765,9 +7763,6 @@
broadcast_l();
- if (mActiveTracks.size() == 0) {
- mHalStream->stop();
- }
return NO_ERROR;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 9db19d6..65266b0 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1478,7 +1478,7 @@
status_t createMmapBuffer(int32_t minSizeFrames,
struct audio_mmap_buffer_info *info);
status_t getMmapPosition(struct audio_mmap_position *position);
- status_t start(const MmapStreamInterface::Client& client, audio_port_handle_t *handle);
+ status_t start(const AudioClient& client, audio_port_handle_t *handle);
status_t stop(audio_port_handle_t handle);
status_t standby();
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index ded2285..4f79ed2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -71,7 +71,7 @@
virtual void toAudioPort(struct audio_port *port) const;
- virtual void importAudioPort(const sp<AudioPort>& port);
+ virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
void addAudioProfile(const sp<AudioProfile> &profile) { mProfiles.add(profile); }
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index 18fba25..ca070cf 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -51,6 +51,7 @@
audio_channel_mask_t channelMask() const { return mConfig.channel_mask; }
audio_input_flags_t flags() const { return mFlags; }
uid_t uid() const { return mUid; }
+ void setUid(uid_t uid) { mUid = uid; }
bool matches(const sp<AudioSession> &other) const;
bool isSoundTrigger() const { return mIsSoundTrigger; }
uint32_t openCount() const { return mOpenCount; } ;
@@ -68,7 +69,7 @@
const audio_source_t mInputSource;
const struct audio_config_base mConfig;
const audio_input_flags_t mFlags;
- const uid_t mUid;
+ uid_t mUid;
bool mIsSoundTrigger;
uint32_t mOpenCount;
uint32_t mActiveCount;
diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
index 9a52d22..1a644d7 100644
--- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h
@@ -48,7 +48,7 @@
// AudioPort
virtual void attach(const sp<HwModule>& module);
virtual void toAudioPort(struct audio_port *port) const;
- virtual void importAudioPort(const sp<AudioPort>& port);
+ virtual void importAudioPort(const sp<AudioPort>& port, bool force = false);
audio_port_handle_t getId() const;
status_t dump(int fd, int spaces, int index, bool verbose = true) const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 6ed2cb7..fcf9070 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -128,7 +128,7 @@
port->num_gains = i;
}
-void AudioPort::importAudioPort(const sp<AudioPort>& port)
+void AudioPort::importAudioPort(const sp<AudioPort>& port, bool force __unused)
{
size_t indexToImport;
for (indexToImport = 0; indexToImport < port->mProfiles.size(); indexToImport++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
index f0e48b6..a2c1165 100644
--- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp
@@ -263,7 +263,10 @@
strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
-void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port) {
+void DeviceDescriptor::importAudioPort(const sp<AudioPort>& port, bool force) {
+ if (!force && !port->hasDynamicAudioProfile()) {
+ return;
+ }
AudioPort::importAudioPort(port);
port->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 77b0182..55c364f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1495,6 +1495,43 @@
"session %d, flags %#x",
attr->source, config->sample_rate, config->format, config->channel_mask, session, flags);
+ // special case for mmap capture: if an input IO handle is specified, we reuse this input if
+ // possible
+ if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) == AUDIO_INPUT_FLAG_MMAP_NOIRQ &&
+ *input != AUDIO_IO_HANDLE_NONE) {
+ ssize_t index = mInputs.indexOfKey(*input);
+ if (index < 0) {
+ ALOGW("getInputForAttr() unknown MMAP input %d", *input);
+ return BAD_VALUE;
+ }
+ sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(index);
+ sp<AudioSession> audioSession = inputDesc->getAudioSession(session);
+ if (audioSession == 0) {
+ ALOGW("getInputForAttr() unknown session %d on input %d", session, *input);
+ return BAD_VALUE;
+ }
+ // For MMAP mode, the first call to getInputForAttr() is made on behalf of audioflinger.
+ // The second call is for the first active client and sets the UID. Any further call
+ // corresponds to a new client and is only permitted from the same UId.
+ if (audioSession->openCount() == 1) {
+ audioSession->setUid(uid);
+ } else if (audioSession->uid() != uid) {
+ ALOGW("getInputForAttr() bad uid %d for session %d uid %d",
+ uid, session, audioSession->uid());
+ return INVALID_OPERATION;
+ }
+ audioSession->changeOpenCount(1);
+ *inputType = API_INPUT_LEGACY;
+ if (*portId == AUDIO_PORT_HANDLE_NONE) {
+ *portId = AudioPort::getNextUniqueId();
+ }
+ DeviceVector inputDevices = mAvailableInputDevices.getDevicesFromType(inputDesc->mDevice);
+ *selectedDeviceId = inputDevices.size() > 0 ? inputDevices.itemAt(0)->getId()
+ : AUDIO_PORT_HANDLE_NONE;
+ ALOGI("%s reusing MMAP input %d for session %d", __FUNCTION__, *input, session);
+ return NO_ERROR;
+ }
+
*input = AUDIO_IO_HANDLE_NONE;
*inputType = API_INPUT_INVALID;
@@ -1898,6 +1935,11 @@
continue;
}
+ if ((audioSession->flags() & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0 &&
+ activeDesc->getId() == inputDesc->getId()) {
+ continue;
+ }
+
audio_source_t activeSource = activeDesc->inputSource(true);
if (audioSession->inputSource() == AUDIO_SOURCE_HOTWORD) {
if (activeSource == AUDIO_SOURCE_HOTWORD) {
@@ -3724,7 +3766,7 @@
sp<DeviceDescriptor> devDesc = mAvailableInputDevices[index];
if (!devDesc->isAttached()) {
devDesc->attach(mHwModules[i]);
- devDesc->importAudioPort(inProfile);
+ devDesc->importAudioPort(inProfile, true);
}
}
}
@@ -4087,8 +4129,8 @@
continue;
}
- ALOGV("opening output for device %08x with params %s profile %p",
- device, address.string(), profile.get());
+ ALOGV("opening output for device %08x with params %s profile %p name %s",
+ device, address.string(), profile.get(), profile->getName().string());
desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
desc->mDevice = device;
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -4337,6 +4379,10 @@
config.channel_mask = desc->mChannelMask;
config.format = desc->mFormat;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+
+ ALOGV("opening inputput for device %08x with params %s profile %p name %s",
+ desc->mDevice, address.string(), profile.get(), profile->getName().string());
+
status_t status = mpClientInterface->openInput(profile->getModuleHandle(),
&input,
&config,
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index 02d4a19..ec2f5b9 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioEndpointManager"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -104,6 +104,8 @@
// If we can't find an existing one then open a new one.
if (endpoint == nullptr) {
+ // we must call openStream with audioserver identity
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
switch(direction) {
case AAUDIO_DIRECTION_INPUT:
capture = new AAudioServiceEndpointCapture(audioService);
@@ -138,6 +140,7 @@
}
ALOGD("AAudioEndpointManager::openEndpoint(), created %p for device = %d, dir = %d",
endpoint, configuration.getDeviceId(), (int)direction);
+ IPCThreadState::self()->restoreCallingIdentity(token);
}
if (endpoint != nullptr) {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 669bb54..3992719 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -50,8 +50,9 @@
android::AAudioService::AAudioService()
: BnAAudioService() {
- mCachedProcessId = getpid();
- mCachedUserId = getuid(); // TODO consider using geteuid()
+ mAudioClient.clientUid = getuid(); // TODO consider using geteuid()
+ mAudioClient.clientPid = getpid();
+ mAudioClient.packageName = String16("");
AAudioClientTracker::getInstance().setAAudioService(this);
}
@@ -92,7 +93,7 @@
// Enforce limit on client processes.
pid_t pid = request.getProcessId();
- if (pid != mCachedProcessId) {
+ if (pid != mAudioClient.clientPid) {
int32_t count = AAudioClientTracker::getInstance().getStreamCount(pid);
if (count >= MAX_STREAMS_PER_PROCESS) {
ALOGE("AAudioService::openStream(): exceeded max streams per process %d >= %d",
@@ -107,7 +108,13 @@
}
if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
- serviceStream = new AAudioServiceStreamMMAP(mCachedUserId);
+ // only trust audioserver for in service indication
+ bool inService = false;
+ if (mAudioClient.clientPid == IPCThreadState::self()->getCallingPid() &&
+ mAudioClient.clientUid == IPCThreadState::self()->getCallingUid()) {
+ inService = request.isInService();
+ }
+ serviceStream = new AAudioServiceStreamMMAP(mAudioClient, inService);
result = serviceStream->open(request, configurationOutput);
if (result != AAUDIO_OK) {
// fall back to using a shared stream
@@ -132,8 +139,6 @@
result, AAudio_convertResultToText(result));
return result;
} else {
- const uid_t ownerUserId = request.getUserId(); // only set by service, not by client
- serviceStream->setOwnerUserId(ownerUserId);
aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream.get());
if (handle < 0) {
ALOGE("AAudioService::openStream(): handle table full");
@@ -143,7 +148,6 @@
ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
serviceStream->setHandle(handle);
pid_t pid = request.getProcessId();
- serviceStream->setOwnerProcessId(pid);
AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
}
return handle;
@@ -181,8 +185,8 @@
const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
const uid_t ownerUserId = serviceStream->getOwnerUserId();
bool callerOwnsIt = callingUserId == ownerUserId;
- bool serverCalling = callingUserId == mCachedUserId;
- bool serverOwnsIt = ownerUserId == mCachedUserId;
+ bool serverCalling = callingUserId == mAudioClient.clientUid;
+ bool serverOwnsIt = ownerUserId == mAudioClient.clientUid;
bool allowed = callerOwnsIt || serverCalling || serverOwnsIt;
if (!allowed) {
ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
@@ -212,6 +216,7 @@
ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
+
aaudio_result_t result = serviceStream->start();
return result;
}
@@ -286,3 +291,26 @@
serviceStream->setRegisteredThread(0);
return AAUDIO_OK;
}
+
+aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
+ const android::AudioClient& client,
+ audio_port_handle_t *clientHandle) {
+ AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream == nullptr) {
+ ALOGE("AAudioService::startClient(), illegal stream handle = 0x%0x",
+ streamHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
+ }
+ return serviceStream->startClient(client, clientHandle);
+}
+
+aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
+ audio_port_handle_t clientHandle) {
+ AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream == nullptr) {
+ ALOGE("AAudioService::stopClient(), illegal stream handle = 0x%0x",
+ streamHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
+ }
+ return serviceStream->stopClient(clientHandle);
+}
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index f84ac4c..8421efc 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -21,6 +21,7 @@
#include <pthread.h>
#include <binder/BinderService.h>
+#include <media/AudioClient.h>
#include <aaudio/AAudio.h>
#include "utility/HandleTracker.h"
@@ -72,14 +73,20 @@
virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t tid);
+ virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
+ const android::AudioClient& client,
+ audio_port_handle_t *clientHandle);
+
+ virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
+ audio_port_handle_t clientHandle);
+
private:
aaudio::AAudioServiceStreamBase *convertHandleToServiceStream(aaudio_handle_t streamHandle) const;
HandleTracker mHandleTracker;
- uid_t mCachedUserId = -1;
- pid_t mCachedProcessId = -1;
+ android::AudioClient mAudioClient;
enum constants {
DEFAULT_AUDIO_PRIORITY = 2
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index b519829..5895974 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioServiceEndpoint"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -94,7 +94,7 @@
}
aaudio_result_t AAudioServiceEndpoint::close() {
- return getStreamInternal()->close();
+ return getStreamInternal()->close();
}
// TODO, maybe use an interface to reduce exposure
@@ -113,26 +113,25 @@
aaudio_result_t AAudioServiceEndpoint::startStream(sp<AAudioServiceStreamShared> sharedStream) {
// TODO use real-time technique to avoid mutex, eg. atomic command FIFO
+ aaudio_result_t result = AAUDIO_OK;
std::lock_guard<std::mutex> lock(mLockStreams);
- mRunningStreams.push_back(sharedStream);
- if (mRunningStreams.size() == 1) {
+ if (++mRunningStreams == 1) {
+ result = getStreamInternal()->requestStart();
startSharingThread_l();
}
- return AAUDIO_OK;
+ return result;
}
aaudio_result_t AAudioServiceEndpoint::stopStream(sp<AAudioServiceStreamShared> sharedStream) {
int numRunningStreams = 0;
{
std::lock_guard<std::mutex> lock(mLockStreams);
- mRunningStreams.erase(
- std::remove(mRunningStreams.begin(), mRunningStreams.end(), sharedStream),
- mRunningStreams.end());
- numRunningStreams = mRunningStreams.size();
+ numRunningStreams = --mRunningStreams;
}
if (numRunningStreams == 0) {
// Don't call this under a lock because the callbackLoop also uses the lock.
stopSharingThread();
+ getStreamInternal()->requestStop();
}
return AAUDIO_OK;
}
@@ -163,11 +162,8 @@
void AAudioServiceEndpoint::disconnectRegisteredStreams() {
std::lock_guard<std::mutex> lock(mLockStreams);
- for(auto baseStream : mRunningStreams) {
- baseStream->onStop();
- }
- mRunningStreams.clear();
for(auto sharedStream : mRegisteredStreams) {
+ sharedStream->stop();
sharedStream->disconnect();
}
mRegisteredStreams.clear();
@@ -189,3 +185,4 @@
return true;
}
+
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index a78d3fa..ed995e5 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -79,7 +79,7 @@
std::vector<android::sp<AAudioServiceStreamShared>> mRegisteredStreams;
- std::vector<android::sp<AAudioServiceStreamShared>> mRunningStreams;
+ size_t mRunningStreams = 0;
private:
aaudio_result_t startSharingThread_l();
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index a144c54..6a37330 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -57,9 +57,7 @@
void *AAudioServiceEndpointCapture::callbackLoop() {
ALOGD("AAudioServiceEndpointCapture(): callbackLoop() entering");
int32_t underflowCount = 0;
-
- aaudio_result_t result = getStreamInternal()->requestStart();
-
+ aaudio_result_t result = AAUDIO_OK;
int64_t timeoutNanos = getStreamInternal()->calculateReasonableTimeout();
// result might be a frame count
@@ -78,21 +76,21 @@
// Distribute data to each active stream.
{ // use lock guard
std::lock_guard <std::mutex> lock(mLockStreams);
- for (sp<AAudioServiceStreamShared> sharedStream : mRunningStreams) {
- FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
- if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
- getFramesPerBurst()) {
- underflowCount++;
- } else {
- fifo->write(mDistributionBuffer, getFramesPerBurst());
+ for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
+ if (sharedStream->isRunning()) {
+ FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
+ if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
+ getFramesPerBurst()) {
+ underflowCount++;
+ } else {
+ fifo->write(mDistributionBuffer, getFramesPerBurst());
+ }
+ sharedStream->markTransferTime(AudioClock::getNanoseconds());
}
- sharedStream->markTransferTime(AudioClock::getNanoseconds());
}
}
}
- result = getStreamInternal()->requestStop();
-
ALOGD("AAudioServiceEndpointCapture(): callbackLoop() exiting, %d underflows", underflowCount);
return NULL; // TODO review
}
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 1afcc1e..86ccde0 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -68,9 +68,7 @@
void *AAudioServiceEndpointPlay::callbackLoop() {
ALOGD("AAudioServiceEndpointPlay(): callbackLoop() entering");
int32_t underflowCount = 0;
-
- aaudio_result_t result = getStreamInternal()->requestStart();
-
+ aaudio_result_t result = AAUDIO_OK;
int64_t timeoutNanos = getStreamInternal()->calculateReasonableTimeout();
// result might be a frame count
@@ -79,13 +77,15 @@
mMixer.clear();
{ // use lock guard
std::lock_guard <std::mutex> lock(mLockStreams);
- for (sp<AAudioServiceStreamShared> sharedStream : mRunningStreams) {
- FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
- float volume = 1.0; // to match legacy volume
- bool underflowed = mMixer.mix(fifo, volume);
- underflowCount += underflowed ? 1 : 0;
- // TODO log underflows in each stream
- sharedStream->markTransferTime(AudioClock::getNanoseconds());
+ for (sp<AAudioServiceStreamShared> sharedStream : mRegisteredStreams) {
+ if (sharedStream->isRunning()) {
+ FifoBuffer *fifo = sharedStream->getDataFifoBuffer();
+ float volume = 1.0; // to match legacy volume
+ bool underflowed = mMixer.mix(fifo, volume);
+ underflowCount += underflowed ? 1 : 0;
+ // TODO log underflows in each stream
+ sharedStream->markTransferTime(AudioClock::getNanoseconds());
+ }
}
}
@@ -102,8 +102,6 @@
}
}
- result = getStreamInternal()->requestStop();
-
ALOGD("AAudioServiceEndpointPlay(): callbackLoop() exiting, %d underflows", underflowCount);
return NULL; // TODO review
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index 52b1801..e0f6ad4 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioServiceStreamBase"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -38,6 +38,9 @@
AAudioServiceStreamBase::AAudioServiceStreamBase()
: mUpMessageQueue(nullptr)
, mAAudioThread() {
+ mMmapClient.clientUid = -1;
+ mMmapClient.clientPid = -1;
+ mMmapClient.packageName = String16("");
}
AAudioServiceStreamBase::~AAudioServiceStreamBase() {
@@ -45,7 +48,8 @@
// If the stream is deleted when OPEN or in use then audio resources will leak.
// This would indicate an internal error. So we want to find this ASAP.
LOG_ALWAYS_FATAL_IF(!(mState == AAUDIO_STREAM_STATE_CLOSED
- || mState == AAUDIO_STREAM_STATE_UNINITIALIZED),
+ || mState == AAUDIO_STREAM_STATE_UNINITIALIZED
+ || mState == AAUDIO_STREAM_STATE_DISCONNECTED),
"service stream still open, state = %d", mState);
}
@@ -58,13 +62,18 @@
result << " framesPerBurst = " << mFramesPerBurst << "\n";
result << " channelCount = " << mSamplesPerFrame << "\n";
result << " capacityFrames = " << mCapacityInFrames << "\n";
- result << " owner uid = " << mOwnerUserId << "\n";
+ result << " owner uid = " << mMmapClient.clientUid << "\n";
return result.str();
}
aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest &request,
aaudio::AAudioStreamConfiguration &configurationOutput) {
+
+ mMmapClient.clientUid = request.getUserId();
+ mMmapClient.clientPid = request.getProcessId();
+ mMmapClient.packageName.setTo(String16("")); // FIXME what should we do here?
+
std::lock_guard<std::mutex> lock(mLockUpMessageQueue);
if (mUpMessageQueue != nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
@@ -86,6 +95,9 @@
}
aaudio_result_t AAudioServiceStreamBase::start() {
+ if (isRunning()) {
+ return AAUDIO_OK;
+ }
sendServiceEvent(AAUDIO_SERVICE_EVENT_STARTED);
mState = AAUDIO_STREAM_STATE_STARTED;
mThreadEnabled.store(true);
@@ -94,32 +106,34 @@
aaudio_result_t AAudioServiceStreamBase::pause() {
aaudio_result_t result = AAUDIO_OK;
- if (isRunning()) {
- sendCurrentTimestamp();
- mThreadEnabled.store(false);
- result = mAAudioThread.stop();
- if (result != AAUDIO_OK) {
- disconnect();
- return result;
- }
- sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
+ if (!isRunning()) {
+ return result;
}
+ sendCurrentTimestamp();
+ mThreadEnabled.store(false);
+ result = mAAudioThread.stop();
+ if (result != AAUDIO_OK) {
+ disconnect();
+ return result;
+ }
+ sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
mState = AAUDIO_STREAM_STATE_PAUSED;
return result;
}
aaudio_result_t AAudioServiceStreamBase::stop() {
aaudio_result_t result = AAUDIO_OK;
- if (isRunning()) {
- // TODO wait for data to be played out
- sendCurrentTimestamp(); // warning - this calls a virtual function
- result = stopTimestampThread();
- if (result != AAUDIO_OK) {
- disconnect();
- return result;
- }
- sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
+ if (!isRunning()) {
+ return result;
}
+ // TODO wait for data to be played out
+ sendCurrentTimestamp(); // warning - this calls a virtual function
+ result = stopTimestampThread();
+ if (result != AAUDIO_OK) {
+ disconnect();
+ return result;
+ }
+ sendServiceEvent(AAUDIO_SERVICE_EVENT_STOPPED);
mState = AAUDIO_STREAM_STATE_STOPPED;
return result;
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index c7df6f3..93a522e 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -27,6 +27,7 @@
#include "binding/AudioEndpointParcelable.h"
#include "binding/AAudioServiceMessage.h"
#include "utility/AAudioUtilities.h"
+#include <media/AudioClient.h>
#include "SharedRingBuffer.h"
#include "AAudioThread.h"
@@ -85,9 +86,19 @@
*/
virtual aaudio_result_t flush();
+ virtual aaudio_result_t startClient(const android::AudioClient& client __unused,
+ audio_port_handle_t *clientHandle __unused) {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
+ virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle __unused) {
+ return AAUDIO_ERROR_UNAVAILABLE;
+ }
+
bool isRunning() const {
return mState == AAUDIO_STREAM_STATE_STARTED;
}
+
// -------------------------------------------------------------------
/**
@@ -124,17 +135,11 @@
void disconnect();
uid_t getOwnerUserId() const {
- return mOwnerUserId;
- }
- void setOwnerUserId(uid_t uid) {
- mOwnerUserId = uid;
+ return mMmapClient.clientUid;
}
pid_t getOwnerProcessId() const {
- return mOwnerProcessId;
- }
- void setOwnerProcessId(pid_t pid) {
- mOwnerProcessId = pid;
+ return mMmapClient.clientPid;
}
aaudio_handle_t getHandle() const {
@@ -164,24 +169,25 @@
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
- pid_t mRegisteredClientThread = ILLEGAL_THREAD_ID;
+ pid_t mRegisteredClientThread = ILLEGAL_THREAD_ID;
- SharedRingBuffer* mUpMessageQueue;
- std::mutex mLockUpMessageQueue;
+ SharedRingBuffer* mUpMessageQueue;
+ std::mutex mLockUpMessageQueue;
- AAudioThread mAAudioThread;
+ AAudioThread mAAudioThread;
// This is used by one thread to tell another thread to exit. So it must be atomic.
- std::atomic<bool> mThreadEnabled;
+ std::atomic<bool> mThreadEnabled;
- aaudio_format_t mAudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
- int32_t mFramesPerBurst = 0;
- int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
- int32_t mSampleRate = AAUDIO_UNSPECIFIED;
- int32_t mCapacityInFrames = AAUDIO_UNSPECIFIED;
- uid_t mOwnerUserId = -1;
- pid_t mOwnerProcessId = -1;
+ aaudio_format_t mAudioFormat = AAUDIO_FORMAT_UNSPECIFIED;
+ int32_t mFramesPerBurst = 0;
+ int32_t mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+ int32_t mSampleRate = AAUDIO_UNSPECIFIED;
+ int32_t mCapacityInFrames = AAUDIO_UNSPECIFIED;
+ android::AudioClient mMmapClient;
+ audio_port_handle_t mClientHandle = AUDIO_PORT_HANDLE_NONE;
+
private:
- aaudio_handle_t mHandle = -1;
+ aaudio_handle_t mHandle = -1;
};
} /* namespace aaudio */
diff --git a/services/oboeservice/AAudioServiceStreamExclusive.h b/services/oboeservice/AAudioServiceStreamExclusive.h
deleted file mode 100644
index db382a3..0000000
--- a/services/oboeservice/AAudioServiceStreamExclusive.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef AAUDIO_AAUDIO_SERVICE_STREAM_EXCLUSIVE_H
-#define AAUDIO_AAUDIO_SERVICE_STREAM_EXCLUSIVE_H
-
-#include "AAudioServiceStreamMMAP.h"
-
-namespace aaudio {
-
-/**
- * Exclusive mode stream in the AAudio service.
- *
- * This is currently a stub.
- * We may move code from AAudioServiceStreamMMAP into this class.
- * If not, then it will be removed.
- */
-class AAudioServiceStreamExclusive : public AAudioServiceStreamMMAP {
-
-public:
- AAudioServiceStreamExclusive() {};
- virtual ~AAudioServiceStreamExclusive() = default;
-};
-
-} /* namespace aaudio */
-
-#endif //AAUDIO_AAUDIO_SERVICE_STREAM_EXCLUSIVE_H
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 1b80486..68be3c3 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioServiceStreamMMAP"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -41,19 +41,21 @@
* Service Stream that uses an MMAP buffer.
*/
-AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(uid_t serviceUid)
+AAudioServiceStreamMMAP::AAudioServiceStreamMMAP(const android::AudioClient& serviceClient,
+ bool inService)
: AAudioServiceStreamBase()
, mMmapStreamCallback(new MyMmapStreamCallback(*this))
, mPreviousFrameCounter(0)
, mMmapStream(nullptr)
- , mCachedUserId(serviceUid) {
+ , mServiceClient(serviceClient)
+ , mInService(inService) {
}
aaudio_result_t AAudioServiceStreamMMAP::close() {
if (mState == AAUDIO_STREAM_STATE_CLOSED) {
return AAUDIO_OK;
}
-
+ stop();
if (mMmapStream != 0) {
mMmapStream.clear(); // TODO review. Is that all we have to do?
// Apparently the above close is asynchronous. An attempt to open a new device
@@ -90,9 +92,6 @@
const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
audio_port_handle_t deviceId = configurationInput.getDeviceId();
-
- mMmapClient.clientUid = request.getUserId();
- mMmapClient.clientPid = request.getProcessId();
aaudio_direction_t direction = request.getDirection();
// Fill in config
@@ -123,8 +122,6 @@
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
}
- mMmapClient.packageName.setTo(String16("aaudio_service")); // FIXME what should we do here?
-
MmapStreamInterface::stream_direction_t streamDirection = (direction == AAUDIO_DIRECTION_OUTPUT)
? MmapStreamInterface::DIRECTION_OUTPUT : MmapStreamInterface::DIRECTION_INPUT;
@@ -135,7 +132,8 @@
mMmapClient,
&deviceId,
mMmapStreamCallback,
- mMmapStream);
+ mMmapStream,
+ &mPortHandle);
if (status != OK) {
ALOGE("openMmapStream returned status %d", status);
return AAUDIO_ERROR_UNAVAILABLE;
@@ -172,7 +170,7 @@
mCapacityInFrames = -mCapacityInFrames;
} else {
// exclusive mode is only possible if the final fd destination is inside audioserver
- if ((mMmapClient.clientUid != mCachedUserId) &&
+ if ((mMmapClient.clientUid != mServiceClient.clientUid) &&
configurationInput.getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
// Fallback is handled by caller but indicate what is possible in case
// this is used in the future
@@ -223,15 +221,21 @@
* Start the flow of data.
*/
aaudio_result_t AAudioServiceStreamMMAP::start() {
+ if (isRunning()) {
+ return AAUDIO_OK;
+ }
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
aaudio_result_t result;
- status_t status = mMmapStream->start(mMmapClient, &mPortHandle);
+ status_t status = mMmapStream->start(mServiceClient, &mPortHandle);
if (status != OK) {
ALOGE("AAudioServiceStreamMMAP::start() mMmapStream->start() returned %d", status);
disconnect();
result = AAudioConvert_androidToAAudioResult(status);
} else {
result = AAudioServiceStreamBase::start();
+ if (!mInService && result == AAUDIO_OK) {
+ startClient(mMmapClient, &mClientHandle);
+ }
}
return result;
}
@@ -240,18 +244,28 @@
* Stop the flow of data such that start() can resume with loss of data.
*/
aaudio_result_t AAudioServiceStreamMMAP::pause() {
+ if (!isRunning()) {
+ return AAUDIO_OK;
+ }
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-
aaudio_result_t result1 = AAudioServiceStreamBase::pause();
+ if (!mInService) {
+ stopClient(mClientHandle);
+ }
status_t status = mMmapStream->stop(mPortHandle);
mFramesRead.reset32();
return (result1 != AAUDIO_OK) ? result1 : AAudioConvert_androidToAAudioResult(status);
}
aaudio_result_t AAudioServiceStreamMMAP::stop() {
+ if (!isRunning()) {
+ return AAUDIO_OK;
+ }
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
-
aaudio_result_t result1 = AAudioServiceStreamBase::stop();
+ if (!mInService) {
+ stopClient(mClientHandle);
+ }
aaudio_result_t status = mMmapStream->stop(mPortHandle);
mFramesRead.reset32();
return (result1 != AAUDIO_OK) ? result1 : AAudioConvert_androidToAAudioResult(status);
@@ -266,6 +280,15 @@
return AAudioServiceStreamBase::flush();;
}
+aaudio_result_t AAudioServiceStreamMMAP::startClient(const android::AudioClient& client,
+ audio_port_handle_t *clientHandle) {
+ return AAudioConvert_androidToAAudioResult(mMmapStream->start(client, clientHandle));
+}
+
+aaudio_result_t AAudioServiceStreamMMAP::stopClient(audio_port_handle_t clientHandle) {
+ return AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
+}
+
aaudio_result_t AAudioServiceStreamMMAP::getFreeRunningPosition(int64_t *positionFrames,
int64_t *timeNanos) {
struct audio_mmap_position position;
@@ -301,11 +324,11 @@
void AAudioServiceStreamMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
ALOGD("AAudioServiceStreamMMAP::onRoutingChanged() called with %d, old = %d",
- deviceId, mPortHandle);
- if (mPortHandle > 0 && mPortHandle != deviceId) {
+ deviceId, mDeviceId);
+ if (mDeviceId != AUDIO_PORT_HANDLE_NONE && mDeviceId != deviceId) {
disconnect();
}
- mPortHandle = deviceId;
+ mDeviceId = deviceId;
};
/**
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 257bea9..533e5a8 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -43,7 +43,7 @@
, public android::MmapStreamCallback {
public:
- AAudioServiceStreamMMAP(uid_t serviceUid);
+ AAudioServiceStreamMMAP(const android::AudioClient& serviceClient, bool inService);
virtual ~AAudioServiceStreamMMAP() = default;
aaudio_result_t open(const aaudio::AAudioStreamRequest &request,
@@ -77,6 +77,11 @@
aaudio_result_t close() override;
+ virtual aaudio_result_t startClient(const android::AudioClient& client,
+ audio_port_handle_t *clientHandle);
+
+ virtual aaudio_result_t stopClient(audio_port_handle_t clientHandle);
+
/**
* Send a MMAP/NOIRQ buffer timestamp to the client.
*/
@@ -131,9 +136,10 @@
// Interface to the AudioFlinger MMAP support.
android::sp<android::MmapStreamInterface> mMmapStream;
struct audio_mmap_buffer_info mMmapBufferinfo;
- android::MmapStreamInterface::Client mMmapClient;
- audio_port_handle_t mPortHandle = -1; // TODO review best default
- uid_t mCachedUserId = -1;
+ audio_port_handle_t mPortHandle = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+ android::AudioClient mServiceClient;
+ bool mInService = false;
};
} // namespace aaudio
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 8bb34d1..fe488cb 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "AAudioService"
+#define LOG_TAG "AAudioServiceStreamShared"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
@@ -191,6 +191,9 @@
* An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
*/
aaudio_result_t AAudioServiceStreamShared::start() {
+ if (isRunning()) {
+ return AAUDIO_OK;
+ }
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
@@ -201,7 +204,10 @@
ALOGE("AAudioServiceStreamShared::start() mServiceEndpoint returned %d", result);
disconnect();
} else {
- result = AAudioServiceStreamBase::start();
+ result = endpoint->getStreamInternal()->startClient(mMmapClient, &mClientHandle);
+ if (result == AAUDIO_OK) {
+ result = AAudioServiceStreamBase::start();
+ }
}
return result;
}
@@ -212,10 +218,14 @@
* An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
*/
aaudio_result_t AAudioServiceStreamShared::pause() {
+ if (!isRunning()) {
+ return AAUDIO_OK;
+ }
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
+ endpoint->getStreamInternal()->stopClient(mClientHandle);
aaudio_result_t result = endpoint->stopStream(this);
if (result != AAUDIO_OK) {
ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
@@ -225,10 +235,14 @@
}
aaudio_result_t AAudioServiceStreamShared::stop() {
+ if (!isRunning()) {
+ return AAUDIO_OK;
+ }
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
+ endpoint->getStreamInternal()->stopClient(mClientHandle);
aaudio_result_t result = endpoint->stopStream(this);
if (result != AAUDIO_OK) {
ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result);
@@ -248,7 +262,7 @@
return AAUDIO_ERROR_INVALID_STATE;
}
if (mState != AAUDIO_STREAM_STATE_PAUSED) {
- ALOGE("AAudioServiceStreamShared::flush() stream not paused, state = %s",
+ ALOGE("AAudioServiceStreamShared::flush() stream not paused, state = %s",
AAudio_convertStreamStateToText(mState));
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -261,11 +275,12 @@
return AAUDIO_OK;
}
+ stop();
+
AAudioServiceEndpoint *endpoint = mServiceEndpoint;
if (endpoint == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
- endpoint->stopStream(this);
endpoint->unregisterStream(this);
@@ -277,7 +292,6 @@
delete mAudioDataQueue;
mAudioDataQueue = nullptr;
}
-
return AAudioServiceStreamBase::close();
}
@@ -293,9 +307,6 @@
return AAUDIO_OK;
}
-void AAudioServiceStreamShared::onStop() {
-}
-
void AAudioServiceStreamShared::markTransferTime(int64_t nanoseconds) {
mMarkedPosition = mAudioDataQueue->getFifoBuffer()->getReadCounter();
mMarkedTime = nanoseconds;
diff --git a/services/oboeservice/AAudioServiceStreamShared.h b/services/oboeservice/AAudioServiceStreamShared.h
index 742c5af..6b67337 100644
--- a/services/oboeservice/AAudioServiceStreamShared.h
+++ b/services/oboeservice/AAudioServiceStreamShared.h
@@ -87,8 +87,6 @@
*/
void markTransferTime(int64_t nanoseconds);
- void onStop();
-
protected:
aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;