Merge change 22897 into eclair
* changes: Fix issue 2045911: Camera Shutter tone does not play correctly while listening to music.
This commit is contained in:
@@ -451,6 +451,7 @@ public:
|
|||||||
status_t get(const String8& key, String8& value);
|
status_t get(const String8& key, String8& value);
|
||||||
status_t getInt(const String8& key, int& value);
|
status_t getInt(const String8& key, int& value);
|
||||||
status_t getFloat(const String8& key, float& value);
|
status_t getFloat(const String8& key, float& value);
|
||||||
|
status_t getAt(size_t index, String8& key, String8& value);
|
||||||
|
|
||||||
size_t size() { return mParameters.size(); }
|
size_t size() { return mParameters.size(); }
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,13 @@
|
|||||||
|
|
||||||
#define LOG_TAG "AudioPolicyService"
|
#define LOG_TAG "AudioPolicyService"
|
||||||
//#define LOG_NDEBUG 0
|
//#define LOG_NDEBUG 0
|
||||||
|
|
||||||
|
#undef __STRICT_ANSI__
|
||||||
|
#define __STDINT_LIMITS
|
||||||
|
#define __STDC_LIMIT_MACROS
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
#include <binder/IServiceManager.h>
|
#include <binder/IServiceManager.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
@@ -54,7 +61,7 @@ AudioPolicyService::AudioPolicyService()
|
|||||||
char value[PROPERTY_VALUE_MAX];
|
char value[PROPERTY_VALUE_MAX];
|
||||||
|
|
||||||
// start tone playback thread
|
// start tone playback thread
|
||||||
mTonePlaybacThread = new AudioCommandThread();
|
mTonePlaybackThread = new AudioCommandThread();
|
||||||
// start audio commands thread
|
// start audio commands thread
|
||||||
mAudioCommandThread = new AudioCommandThread();
|
mAudioCommandThread = new AudioCommandThread();
|
||||||
|
|
||||||
@@ -80,8 +87,8 @@ AudioPolicyService::AudioPolicyService()
|
|||||||
|
|
||||||
AudioPolicyService::~AudioPolicyService()
|
AudioPolicyService::~AudioPolicyService()
|
||||||
{
|
{
|
||||||
mTonePlaybacThread->exit();
|
mTonePlaybackThread->exit();
|
||||||
mTonePlaybacThread.clear();
|
mTonePlaybackThread.clear();
|
||||||
mAudioCommandThread->exit();
|
mAudioCommandThread->exit();
|
||||||
mAudioCommandThread.clear();
|
mAudioCommandThread.clear();
|
||||||
|
|
||||||
@@ -451,9 +458,9 @@ status_t AudioPolicyService::closeInput(audio_io_handle_t input)
|
|||||||
return af->closeInput(input);
|
return af->closeInput(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output)
|
status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
|
||||||
{
|
{
|
||||||
return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output);
|
return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
|
status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
|
||||||
@@ -465,9 +472,9 @@ status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, au
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
|
void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
|
||||||
{
|
{
|
||||||
mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs);
|
mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
|
String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
|
||||||
@@ -478,13 +485,13 @@ String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const Stri
|
|||||||
|
|
||||||
status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
|
status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
|
||||||
{
|
{
|
||||||
mTonePlaybacThread->startToneCommand(tone, stream);
|
mTonePlaybackThread->startToneCommand(tone, stream);
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::stopTone()
|
status_t AudioPolicyService::stopTone()
|
||||||
{
|
{
|
||||||
mTonePlaybacThread->stopToneCommand();
|
mTonePlaybackThread->stopToneCommand();
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,58 +523,72 @@ void AudioPolicyService::AudioCommandThread::onFirstRef()
|
|||||||
|
|
||||||
bool AudioPolicyService::AudioCommandThread::threadLoop()
|
bool AudioPolicyService::AudioCommandThread::threadLoop()
|
||||||
{
|
{
|
||||||
|
nsecs_t waitTime = INT64_MAX;
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
while(!mAudioCommands.isEmpty()) {
|
while(!mAudioCommands.isEmpty()) {
|
||||||
AudioCommand *command = mAudioCommands[0];
|
nsecs_t curTime = systemTime();
|
||||||
mAudioCommands.removeAt(0);
|
// commands are sorted by increasing time stamp: execute them from index 0 and up
|
||||||
switch (command->mCommand) {
|
if (mAudioCommands[0]->mTime <= curTime) {
|
||||||
case START_TONE: {
|
AudioCommand *command = mAudioCommands[0];
|
||||||
mLock.unlock();
|
mAudioCommands.removeAt(0);
|
||||||
ToneData *data = (ToneData *)command->mParam;
|
switch (command->mCommand) {
|
||||||
LOGV("AudioCommandThread() processing start tone %d on stream %d",
|
case START_TONE: {
|
||||||
data->mType, data->mStream);
|
mLock.unlock();
|
||||||
if (mpToneGenerator != NULL)
|
ToneData *data = (ToneData *)command->mParam;
|
||||||
delete mpToneGenerator;
|
LOGV("AudioCommandThread() processing start tone %d on stream %d",
|
||||||
mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
|
data->mType, data->mStream);
|
||||||
mpToneGenerator->startTone(data->mType);
|
if (mpToneGenerator != NULL)
|
||||||
delete data;
|
delete mpToneGenerator;
|
||||||
mLock.lock();
|
mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
|
||||||
}break;
|
mpToneGenerator->startTone(data->mType);
|
||||||
case STOP_TONE: {
|
delete data;
|
||||||
mLock.unlock();
|
mLock.lock();
|
||||||
LOGV("AudioCommandThread() processing stop tone");
|
}break;
|
||||||
if (mpToneGenerator != NULL) {
|
case STOP_TONE: {
|
||||||
mpToneGenerator->stopTone();
|
mLock.unlock();
|
||||||
delete mpToneGenerator;
|
LOGV("AudioCommandThread() processing stop tone");
|
||||||
mpToneGenerator = NULL;
|
if (mpToneGenerator != NULL) {
|
||||||
|
mpToneGenerator->stopTone();
|
||||||
|
delete mpToneGenerator;
|
||||||
|
mpToneGenerator = NULL;
|
||||||
|
}
|
||||||
|
mLock.lock();
|
||||||
|
}break;
|
||||||
|
case SET_VOLUME: {
|
||||||
|
VolumeData *data = (VolumeData *)command->mParam;
|
||||||
|
LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
|
||||||
|
command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
|
||||||
|
if (command->mWaitStatus) {
|
||||||
|
command->mCond.signal();
|
||||||
|
mWaitWorkCV.wait(mLock);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
}break;
|
||||||
|
case SET_PARAMETERS: {
|
||||||
|
ParametersData *data = (ParametersData *)command->mParam;
|
||||||
|
LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
|
||||||
|
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
|
||||||
|
if (command->mWaitStatus) {
|
||||||
|
command->mCond.signal();
|
||||||
|
mWaitWorkCV.wait(mLock);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
}break;
|
||||||
|
default:
|
||||||
|
LOGW("AudioCommandThread() unknown command %d", command->mCommand);
|
||||||
}
|
}
|
||||||
mLock.lock();
|
delete command;
|
||||||
}break;
|
waitTime = INT64_MAX;
|
||||||
case SET_VOLUME: {
|
} else {
|
||||||
VolumeData *data = (VolumeData *)command->mParam;
|
waitTime = mAudioCommands[0]->mTime - curTime;
|
||||||
LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
|
break;
|
||||||
mCommandStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
|
|
||||||
mCommandCond.signal();
|
|
||||||
mWaitWorkCV.wait(mLock);
|
|
||||||
delete data;
|
|
||||||
}break;
|
|
||||||
case SET_PARAMETERS: {
|
|
||||||
ParametersData *data = (ParametersData *)command->mParam;
|
|
||||||
LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
|
|
||||||
mCommandStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
|
|
||||||
mCommandCond.signal();
|
|
||||||
mWaitWorkCV.wait(mLock);
|
|
||||||
delete data;
|
|
||||||
}break;
|
|
||||||
default:
|
|
||||||
LOGW("AudioCommandThread() unknown command %d", command->mCommand);
|
|
||||||
}
|
}
|
||||||
delete command;
|
|
||||||
}
|
}
|
||||||
LOGV("AudioCommandThread() going to sleep");
|
LOGV("AudioCommandThread() going to sleep");
|
||||||
mWaitWorkCV.wait(mLock);
|
mWaitWorkCV.waitRelative(mLock, waitTime);
|
||||||
LOGV("AudioCommandThread() waking up");
|
LOGV("AudioCommandThread() waking up");
|
||||||
}
|
}
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
@@ -583,7 +604,8 @@ void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stre
|
|||||||
data->mType = type;
|
data->mType = type;
|
||||||
data->mStream = stream;
|
data->mStream = stream;
|
||||||
command->mParam = (void *)data;
|
command->mParam = (void *)data;
|
||||||
mAudioCommands.add(command);
|
command->mWaitStatus = false;
|
||||||
|
insertCommand_l(command);
|
||||||
LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
|
LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
|
||||||
mWaitWorkCV.signal();
|
mWaitWorkCV.signal();
|
||||||
}
|
}
|
||||||
@@ -594,13 +616,16 @@ void AudioPolicyService::AudioCommandThread::stopToneCommand()
|
|||||||
AudioCommand *command = new AudioCommand();
|
AudioCommand *command = new AudioCommand();
|
||||||
command->mCommand = STOP_TONE;
|
command->mCommand = STOP_TONE;
|
||||||
command->mParam = NULL;
|
command->mParam = NULL;
|
||||||
mAudioCommands.add(command);
|
command->mWaitStatus = false;
|
||||||
|
insertCommand_l(command);
|
||||||
LOGV("AudioCommandThread() adding tone stop");
|
LOGV("AudioCommandThread() adding tone stop");
|
||||||
mWaitWorkCV.signal();
|
mWaitWorkCV.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output)
|
status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
|
||||||
{
|
{
|
||||||
|
status_t status = NO_ERROR;
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
AudioCommand *command = new AudioCommand();
|
AudioCommand *command = new AudioCommand();
|
||||||
command->mCommand = SET_VOLUME;
|
command->mCommand = SET_VOLUME;
|
||||||
@@ -609,17 +634,26 @@ status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float
|
|||||||
data->mVolume = volume;
|
data->mVolume = volume;
|
||||||
data->mIO = output;
|
data->mIO = output;
|
||||||
command->mParam = data;
|
command->mParam = data;
|
||||||
mAudioCommands.add(command);
|
if (delayMs == 0) {
|
||||||
|
command->mWaitStatus = true;
|
||||||
|
} else {
|
||||||
|
command->mWaitStatus = false;
|
||||||
|
}
|
||||||
|
insertCommand_l(command, delayMs);
|
||||||
LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
|
LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
|
||||||
mWaitWorkCV.signal();
|
mWaitWorkCV.signal();
|
||||||
mCommandCond.wait(mLock);
|
if (command->mWaitStatus) {
|
||||||
status_t status = mCommandStatus;
|
command->mCond.wait(mLock);
|
||||||
mWaitWorkCV.signal();
|
status = command->mStatus;
|
||||||
|
mWaitWorkCV.signal();
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs)
|
status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
|
||||||
{
|
{
|
||||||
|
status_t status = NO_ERROR;
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
AudioCommand *command = new AudioCommand();
|
AudioCommand *command = new AudioCommand();
|
||||||
command->mCommand = SET_PARAMETERS;
|
command->mCommand = SET_PARAMETERS;
|
||||||
@@ -627,15 +661,102 @@ status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
|
|||||||
data->mIO = ioHandle;
|
data->mIO = ioHandle;
|
||||||
data->mKeyValuePairs = keyValuePairs;
|
data->mKeyValuePairs = keyValuePairs;
|
||||||
command->mParam = data;
|
command->mParam = data;
|
||||||
mAudioCommands.add(command);
|
if (delayMs == 0) {
|
||||||
LOGV("AudioCommandThread() adding set parameter string %s, io %d", keyValuePairs.string(), ioHandle);
|
command->mWaitStatus = true;
|
||||||
mWaitWorkCV.signal();
|
} else {
|
||||||
mCommandCond.wait(mLock);
|
command->mWaitStatus = false;
|
||||||
status_t status = mCommandStatus;
|
}
|
||||||
|
insertCommand_l(command, delayMs);
|
||||||
|
LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
|
||||||
mWaitWorkCV.signal();
|
mWaitWorkCV.signal();
|
||||||
|
if (command->mWaitStatus) {
|
||||||
|
command->mCond.wait(mLock);
|
||||||
|
status = command->mStatus;
|
||||||
|
mWaitWorkCV.signal();
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insertCommand_l() must be called with mLock held
|
||||||
|
void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
|
||||||
|
{
|
||||||
|
ssize_t i;
|
||||||
|
Vector <AudioCommand *> removedCommands;
|
||||||
|
|
||||||
|
command->mTime = systemTime() + milliseconds(delayMs);
|
||||||
|
|
||||||
|
// check same pending commands with later time stamps and eliminate them
|
||||||
|
for (i = mAudioCommands.size()-1; i >= 0; i--) {
|
||||||
|
AudioCommand *command2 = mAudioCommands[i];
|
||||||
|
// commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
|
||||||
|
if (command2->mTime <= command->mTime) break;
|
||||||
|
if (command2->mCommand != command->mCommand) continue;
|
||||||
|
|
||||||
|
switch (command->mCommand) {
|
||||||
|
case SET_PARAMETERS: {
|
||||||
|
ParametersData *data = (ParametersData *)command->mParam;
|
||||||
|
ParametersData *data2 = (ParametersData *)command2->mParam;
|
||||||
|
if (data->mIO != data2->mIO) break;
|
||||||
|
LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
|
||||||
|
AudioParameter param = AudioParameter(data->mKeyValuePairs);
|
||||||
|
AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
|
||||||
|
for (size_t j = 0; j < param.size(); j++) {
|
||||||
|
String8 key;
|
||||||
|
String8 value;
|
||||||
|
param.getAt(j, key, value);
|
||||||
|
for (size_t k = 0; k < param2.size(); k++) {
|
||||||
|
String8 key2;
|
||||||
|
String8 value2;
|
||||||
|
param2.getAt(k, key2, value2);
|
||||||
|
if (key2 == key) {
|
||||||
|
param2.remove(key2);
|
||||||
|
LOGV("Filtering out parameter %s", key2.string());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if all keys have been filtered out, remove the command.
|
||||||
|
// otherwise, update the key value pairs
|
||||||
|
if (param2.size() == 0) {
|
||||||
|
removedCommands.add(command2);
|
||||||
|
} else {
|
||||||
|
data2->mKeyValuePairs = param2.toString();
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case SET_VOLUME: {
|
||||||
|
VolumeData *data = (VolumeData *)command->mParam;
|
||||||
|
VolumeData *data2 = (VolumeData *)command2->mParam;
|
||||||
|
if (data->mIO != data2->mIO) break;
|
||||||
|
if (data->mStream != data2->mStream) break;
|
||||||
|
LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
|
||||||
|
removedCommands.add(command2);
|
||||||
|
} break;
|
||||||
|
case START_TONE:
|
||||||
|
case STOP_TONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove filtered commands
|
||||||
|
for (size_t j = 0; j < removedCommands.size(); j++) {
|
||||||
|
// removed commands always have time stamps greater than current command
|
||||||
|
for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
|
||||||
|
if (mAudioCommands[k] == removedCommands[j]) {
|
||||||
|
LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
|
||||||
|
mAudioCommands.removeAt(k);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removedCommands.clear();
|
||||||
|
|
||||||
|
// insert command at the right place according to its time stamp
|
||||||
|
LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
|
||||||
|
mAudioCommands.insertAt(command, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPolicyService::AudioCommandThread::exit()
|
void AudioPolicyService::AudioCommandThread::exit()
|
||||||
{
|
{
|
||||||
LOGV("AudioCommandThread::exit");
|
LOGV("AudioCommandThread::exit");
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <media/IAudioPolicyService.h>
|
#include <media/IAudioPolicyService.h>
|
||||||
#include <hardware_legacy/AudioPolicyInterface.h>
|
#include <hardware_legacy/AudioPolicyInterface.h>
|
||||||
#include <media/ToneGenerator.h>
|
#include <media/ToneGenerator.h>
|
||||||
|
#include <utils/Vector.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -98,9 +99,9 @@ public:
|
|||||||
uint32_t *pChannels,
|
uint32_t *pChannels,
|
||||||
uint32_t acoustics);
|
uint32_t acoustics);
|
||||||
virtual status_t closeInput(audio_io_handle_t input);
|
virtual status_t closeInput(audio_io_handle_t input);
|
||||||
virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output);
|
virtual status_t setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs = 0);
|
||||||
virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
|
virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
|
||||||
virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
|
virtual void setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs = 0);
|
||||||
virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
|
virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
|
||||||
virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
|
virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
|
||||||
virtual status_t stopTone();
|
virtual status_t stopTone();
|
||||||
@@ -116,6 +117,7 @@ private:
|
|||||||
// For audio config commands, it is necessary because audio flinger requires that the calling process (user)
|
// For audio config commands, it is necessary because audio flinger requires that the calling process (user)
|
||||||
// has permission to modify audio settings.
|
// has permission to modify audio settings.
|
||||||
class AudioCommandThread : public Thread {
|
class AudioCommandThread : public Thread {
|
||||||
|
class AudioCommand;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// commands for tone AudioCommand
|
// commands for tone AudioCommand
|
||||||
@@ -136,15 +138,20 @@ private:
|
|||||||
void exit();
|
void exit();
|
||||||
void startToneCommand(int type = 0, int stream = 0);
|
void startToneCommand(int type = 0, int stream = 0);
|
||||||
void stopToneCommand();
|
void stopToneCommand();
|
||||||
status_t volumeCommand(int stream, float volume, int output);
|
status_t volumeCommand(int stream, float volume, int output, int delayMs = 0);
|
||||||
status_t parametersCommand(int ioHandle, const String8& keyValuePairs);
|
status_t parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
|
||||||
|
void insertCommand_l(AudioCommand *command, int delayMs = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// descriptor for requested tone playback event
|
// descriptor for requested tone playback event
|
||||||
class AudioCommand {
|
class AudioCommand {
|
||||||
public:
|
public:
|
||||||
int mCommand; // START_TONE, STOP_TONE ...
|
int mCommand; // START_TONE, STOP_TONE ...
|
||||||
void *mParam;
|
nsecs_t mTime; // time stamp
|
||||||
|
Condition mCond; // condition for status return
|
||||||
|
status_t mStatus; // command status
|
||||||
|
bool mWaitStatus; // true if caller is waiting for status
|
||||||
|
void *mParam; // command parameter (ToneData, VolumeData, ParametersData)
|
||||||
};
|
};
|
||||||
|
|
||||||
class ToneData {
|
class ToneData {
|
||||||
@@ -168,9 +175,7 @@ private:
|
|||||||
|
|
||||||
Mutex mLock;
|
Mutex mLock;
|
||||||
Condition mWaitWorkCV;
|
Condition mWaitWorkCV;
|
||||||
Vector<AudioCommand *> mAudioCommands; // list of pending tone events
|
Vector <AudioCommand *> mAudioCommands; // list of pending commands
|
||||||
Condition mCommandCond;
|
|
||||||
status_t mCommandStatus;
|
|
||||||
ToneGenerator *mpToneGenerator; // the tone generator
|
ToneGenerator *mpToneGenerator; // the tone generator
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -182,7 +187,7 @@ private:
|
|||||||
// connection stated our routing
|
// connection stated our routing
|
||||||
AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
|
AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
|
||||||
sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
|
sp <AudioCommandThread> mAudioCommandThread; // audio commands thread
|
||||||
sp <AudioCommandThread> mTonePlaybacThread; // tone playback thread
|
sp <AudioCommandThread> mTonePlaybackThread; // tone playback thread
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|||||||
@@ -883,5 +883,15 @@ status_t AudioParameter::getFloat(const String8& key, float& value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
|
||||||
|
{
|
||||||
|
if (mParameters.size() > index) {
|
||||||
|
key = mParameters.keyAt(index);
|
||||||
|
value = mParameters.valueAt(index);
|
||||||
|
return NO_ERROR;
|
||||||
|
} else {
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user