• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "AudioPolicyService"
18 //#define LOG_NDEBUG 0
19 
20 #undef __STRICT_ANSI__
21 #define __STDINT_LIMITS
22 #define __STDC_LIMIT_MACROS
23 #include <stdint.h>
24 
25 #include <sys/time.h>
26 #include <binder/IServiceManager.h>
27 #include <utils/Log.h>
28 #include <cutils/properties.h>
29 #include <binder/IPCThreadState.h>
30 #include <utils/String16.h>
31 #include <utils/threads.h>
32 #include "AudioPolicyService.h"
33 #include "AudioPolicyManagerGeneric.h"
34 #include <cutils/properties.h>
35 #include <dlfcn.h>
36 
37 // ----------------------------------------------------------------------------
38 // the sim build doesn't have gettid
39 
40 #ifndef HAVE_GETTID
41 # define gettid getpid
42 #endif
43 
44 namespace android {
45 
46 static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
47 static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
48 
49 static const int kDumpLockRetries = 50;
50 static const int kDumpLockSleep = 20000;
51 
checkPermission()52 static bool checkPermission() {
53 #ifndef HAVE_ANDROID_OS
54     return true;
55 #endif
56     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
57     bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
58     if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
59     return ok;
60 }
61 
62 // ----------------------------------------------------------------------------
63 
AudioPolicyService()64 AudioPolicyService::AudioPolicyService()
65     : BnAudioPolicyService() , mpPolicyManager(NULL)
66 {
67     char value[PROPERTY_VALUE_MAX];
68 
69     // start tone playback thread
70     mTonePlaybackThread = new AudioCommandThread();
71     // start audio commands thread
72     mAudioCommandThread = new AudioCommandThread();
73 
74 #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
75     mpPolicyManager = new AudioPolicyManagerGeneric(this);
76     LOGV("build for GENERIC_AUDIO - using generic audio policy");
77 #else
78     // if running in emulation - use the emulator driver
79     if (property_get("ro.kernel.qemu", value, 0)) {
80         LOGV("Running in emulation - using generic audio policy");
81         mpPolicyManager = new AudioPolicyManagerGeneric(this);
82     }
83     else {
84         LOGV("Using hardware specific audio policy");
85         mpPolicyManager = createAudioPolicyManager(this);
86     }
87 #endif
88 
89     // load properties
90     property_get("ro.camera.sound.forced", value, "0");
91     mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
92 }
93 
~AudioPolicyService()94 AudioPolicyService::~AudioPolicyService()
95 {
96     mTonePlaybackThread->exit();
97     mTonePlaybackThread.clear();
98     mAudioCommandThread->exit();
99     mAudioCommandThread.clear();
100 
101     if (mpPolicyManager) {
102         delete mpPolicyManager;
103     }
104 }
105 
106 
setDeviceConnectionState(AudioSystem::audio_devices device,AudioSystem::device_connection_state state,const char * device_address)107 status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
108                                                   AudioSystem::device_connection_state state,
109                                                   const char *device_address)
110 {
111     if (mpPolicyManager == NULL) {
112         return NO_INIT;
113     }
114     if (!checkPermission()) {
115         return PERMISSION_DENIED;
116     }
117     if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
118         return BAD_VALUE;
119     }
120     if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
121         return BAD_VALUE;
122     }
123 
124     LOGV("setDeviceConnectionState() tid %d", gettid());
125     Mutex::Autolock _l(mLock);
126     return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
127 }
128 
getDeviceConnectionState(AudioSystem::audio_devices device,const char * device_address)129 AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
130                                                   const char *device_address)
131 {
132     if (mpPolicyManager == NULL) {
133         return AudioSystem::DEVICE_STATE_UNAVAILABLE;
134     }
135     if (!checkPermission()) {
136         return AudioSystem::DEVICE_STATE_UNAVAILABLE;
137     }
138     return mpPolicyManager->getDeviceConnectionState(device, device_address);
139 }
140 
setPhoneState(int state)141 status_t AudioPolicyService::setPhoneState(int state)
142 {
143     if (mpPolicyManager == NULL) {
144         return NO_INIT;
145     }
146     if (!checkPermission()) {
147         return PERMISSION_DENIED;
148     }
149     if (state < 0 || state >= AudioSystem::NUM_MODES) {
150         return BAD_VALUE;
151     }
152 
153     LOGV("setPhoneState() tid %d", gettid());
154 
155     // TODO: check if it is more appropriate to do it in platform specific policy manager
156     AudioSystem::setMode(state);
157 
158     Mutex::Autolock _l(mLock);
159     mpPolicyManager->setPhoneState(state);
160     return NO_ERROR;
161 }
162 
setRingerMode(uint32_t mode,uint32_t mask)163 status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
164 {
165     if (mpPolicyManager == NULL) {
166         return NO_INIT;
167     }
168     if (!checkPermission()) {
169         return PERMISSION_DENIED;
170     }
171 
172     mpPolicyManager->setRingerMode(mode, mask);
173     return NO_ERROR;
174 }
175 
setForceUse(AudioSystem::force_use usage,AudioSystem::forced_config config)176 status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
177 {
178     if (mpPolicyManager == NULL) {
179         return NO_INIT;
180     }
181     if (!checkPermission()) {
182         return PERMISSION_DENIED;
183     }
184     if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
185         return BAD_VALUE;
186     }
187     if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
188         return BAD_VALUE;
189     }
190     LOGV("setForceUse() tid %d", gettid());
191     Mutex::Autolock _l(mLock);
192     mpPolicyManager->setForceUse(usage, config);
193     return NO_ERROR;
194 }
195 
getForceUse(AudioSystem::force_use usage)196 AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
197 {
198     if (mpPolicyManager == NULL) {
199         return AudioSystem::FORCE_NONE;
200     }
201     if (!checkPermission()) {
202         return AudioSystem::FORCE_NONE;
203     }
204     if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
205         return AudioSystem::FORCE_NONE;
206     }
207     return mpPolicyManager->getForceUse(usage);
208 }
209 
getOutput(AudioSystem::stream_type stream,uint32_t samplingRate,uint32_t format,uint32_t channels,AudioSystem::output_flags flags)210 audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
211                                     uint32_t samplingRate,
212                                     uint32_t format,
213                                     uint32_t channels,
214                                     AudioSystem::output_flags flags)
215 {
216     if (mpPolicyManager == NULL) {
217         return 0;
218     }
219     LOGV("getOutput() tid %d", gettid());
220     Mutex::Autolock _l(mLock);
221     return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
222 }
223 
startOutput(audio_io_handle_t output,AudioSystem::stream_type stream)224 status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
225 {
226     if (mpPolicyManager == NULL) {
227         return NO_INIT;
228     }
229     LOGV("startOutput() tid %d", gettid());
230     Mutex::Autolock _l(mLock);
231     return mpPolicyManager->startOutput(output, stream);
232 }
233 
stopOutput(audio_io_handle_t output,AudioSystem::stream_type stream)234 status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
235 {
236     if (mpPolicyManager == NULL) {
237         return NO_INIT;
238     }
239     LOGV("stopOutput() tid %d", gettid());
240     Mutex::Autolock _l(mLock);
241     return mpPolicyManager->stopOutput(output, stream);
242 }
243 
releaseOutput(audio_io_handle_t output)244 void AudioPolicyService::releaseOutput(audio_io_handle_t output)
245 {
246     if (mpPolicyManager == NULL) {
247         return;
248     }
249     LOGV("releaseOutput() tid %d", gettid());
250     Mutex::Autolock _l(mLock);
251     mpPolicyManager->releaseOutput(output);
252 }
253 
getInput(int inputSource,uint32_t samplingRate,uint32_t format,uint32_t channels,AudioSystem::audio_in_acoustics acoustics)254 audio_io_handle_t AudioPolicyService::getInput(int inputSource,
255                                     uint32_t samplingRate,
256                                     uint32_t format,
257                                     uint32_t channels,
258                                     AudioSystem::audio_in_acoustics acoustics)
259 {
260     if (mpPolicyManager == NULL) {
261         return 0;
262     }
263     Mutex::Autolock _l(mLock);
264     return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
265 }
266 
startInput(audio_io_handle_t input)267 status_t AudioPolicyService::startInput(audio_io_handle_t input)
268 {
269     if (mpPolicyManager == NULL) {
270         return NO_INIT;
271     }
272     Mutex::Autolock _l(mLock);
273     return mpPolicyManager->startInput(input);
274 }
275 
stopInput(audio_io_handle_t input)276 status_t AudioPolicyService::stopInput(audio_io_handle_t input)
277 {
278     if (mpPolicyManager == NULL) {
279         return NO_INIT;
280     }
281     Mutex::Autolock _l(mLock);
282     return mpPolicyManager->stopInput(input);
283 }
284 
releaseInput(audio_io_handle_t input)285 void AudioPolicyService::releaseInput(audio_io_handle_t input)
286 {
287     if (mpPolicyManager == NULL) {
288         return;
289     }
290     Mutex::Autolock _l(mLock);
291     mpPolicyManager->releaseInput(input);
292 }
293 
initStreamVolume(AudioSystem::stream_type stream,int indexMin,int indexMax)294 status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
295                                             int indexMin,
296                                             int indexMax)
297 {
298     if (mpPolicyManager == NULL) {
299         return NO_INIT;
300     }
301     if (!checkPermission()) {
302         return PERMISSION_DENIED;
303     }
304     if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
305         return BAD_VALUE;
306     }
307     mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
308     return NO_ERROR;
309 }
310 
setStreamVolumeIndex(AudioSystem::stream_type stream,int index)311 status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
312 {
313     if (mpPolicyManager == NULL) {
314         return NO_INIT;
315     }
316     if (!checkPermission()) {
317         return PERMISSION_DENIED;
318     }
319     if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
320         return BAD_VALUE;
321     }
322 
323     return mpPolicyManager->setStreamVolumeIndex(stream, index);
324 }
325 
getStreamVolumeIndex(AudioSystem::stream_type stream,int * index)326 status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
327 {
328     if (mpPolicyManager == NULL) {
329         return NO_INIT;
330     }
331     if (!checkPermission()) {
332         return PERMISSION_DENIED;
333     }
334     if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
335         return BAD_VALUE;
336     }
337     return mpPolicyManager->getStreamVolumeIndex(stream, index);
338 }
339 
binderDied(const wp<IBinder> & who)340 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
341     LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
342 }
343 
tryLock(Mutex & mutex)344 static bool tryLock(Mutex& mutex)
345 {
346     bool locked = false;
347     for (int i = 0; i < kDumpLockRetries; ++i) {
348         if (mutex.tryLock() == NO_ERROR) {
349             locked = true;
350             break;
351         }
352         usleep(kDumpLockSleep);
353     }
354     return locked;
355 }
356 
dumpInternals(int fd)357 status_t AudioPolicyService::dumpInternals(int fd)
358 {
359     const size_t SIZE = 256;
360     char buffer[SIZE];
361     String8 result;
362 
363     snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
364     result.append(buffer);
365     snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
366     result.append(buffer);
367     snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
368     result.append(buffer);
369 
370     write(fd, result.string(), result.size());
371     return NO_ERROR;
372 }
373 
dump(int fd,const Vector<String16> & args)374 status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
375 {
376     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
377         dumpPermissionDenial(fd);
378     } else {
379         bool locked = tryLock(mLock);
380         if (!locked) {
381             String8 result(kDeadlockedString);
382             write(fd, result.string(), result.size());
383         }
384 
385         dumpInternals(fd);
386         if (mAudioCommandThread != NULL) {
387             mAudioCommandThread->dump(fd);
388         }
389         if (mTonePlaybackThread != NULL) {
390             mTonePlaybackThread->dump(fd);
391         }
392 
393         if (mpPolicyManager) {
394             mpPolicyManager->dump(fd);
395         }
396 
397         if (locked) mLock.unlock();
398     }
399     return NO_ERROR;
400 }
401 
dumpPermissionDenial(int fd)402 status_t AudioPolicyService::dumpPermissionDenial(int fd)
403 {
404     const size_t SIZE = 256;
405     char buffer[SIZE];
406     String8 result;
407     snprintf(buffer, SIZE, "Permission Denial: "
408             "can't dump AudioPolicyService from pid=%d, uid=%d\n",
409             IPCThreadState::self()->getCallingPid(),
410             IPCThreadState::self()->getCallingUid());
411     result.append(buffer);
412     write(fd, result.string(), result.size());
413     return NO_ERROR;
414 }
415 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)416 status_t AudioPolicyService::onTransact(
417         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
418 {
419     return BnAudioPolicyService::onTransact(code, data, reply, flags);
420 }
421 
422 
423 // ----------------------------------------------------------------------------
instantiate()424 void AudioPolicyService::instantiate() {
425     defaultServiceManager()->addService(
426             String16("media.audio_policy"), new AudioPolicyService());
427 }
428 
429 
430 // ----------------------------------------------------------------------------
431 // AudioPolicyClientInterface implementation
432 // ----------------------------------------------------------------------------
433 
434 
openOutput(uint32_t * pDevices,uint32_t * pSamplingRate,uint32_t * pFormat,uint32_t * pChannels,uint32_t * pLatencyMs,AudioSystem::output_flags flags)435 audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
436                                 uint32_t *pSamplingRate,
437                                 uint32_t *pFormat,
438                                 uint32_t *pChannels,
439                                 uint32_t *pLatencyMs,
440                                 AudioSystem::output_flags flags)
441 {
442     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
443     if (af == 0) {
444         LOGW("openOutput() could not get AudioFlinger");
445         return 0;
446     }
447 
448     return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
449 }
450 
openDuplicateOutput(audio_io_handle_t output1,audio_io_handle_t output2)451 audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
452 {
453     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
454     if (af == 0) {
455         LOGW("openDuplicateOutput() could not get AudioFlinger");
456         return 0;
457     }
458     return af->openDuplicateOutput(output1, output2);
459 }
460 
closeOutput(audio_io_handle_t output)461 status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
462 {
463     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
464     if (af == 0) return PERMISSION_DENIED;
465 
466     return af->closeOutput(output);
467 }
468 
469 
suspendOutput(audio_io_handle_t output)470 status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
471 {
472     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
473     if (af == 0) {
474         LOGW("suspendOutput() could not get AudioFlinger");
475         return PERMISSION_DENIED;
476     }
477 
478     return af->suspendOutput(output);
479 }
480 
restoreOutput(audio_io_handle_t output)481 status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
482 {
483     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
484     if (af == 0) {
485         LOGW("restoreOutput() could not get AudioFlinger");
486         return PERMISSION_DENIED;
487     }
488 
489     return af->restoreOutput(output);
490 }
491 
openInput(uint32_t * pDevices,uint32_t * pSamplingRate,uint32_t * pFormat,uint32_t * pChannels,uint32_t acoustics)492 audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
493                                 uint32_t *pSamplingRate,
494                                 uint32_t *pFormat,
495                                 uint32_t *pChannels,
496                                 uint32_t acoustics)
497 {
498     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
499     if (af == 0) {
500         LOGW("openInput() could not get AudioFlinger");
501         return 0;
502     }
503 
504     return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
505 }
506 
closeInput(audio_io_handle_t input)507 status_t AudioPolicyService::closeInput(audio_io_handle_t input)
508 {
509     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
510     if (af == 0) return PERMISSION_DENIED;
511 
512     return af->closeInput(input);
513 }
514 
setStreamVolume(AudioSystem::stream_type stream,float volume,audio_io_handle_t output,int delayMs)515 status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
516 {
517     return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
518 }
519 
setStreamOutput(AudioSystem::stream_type stream,audio_io_handle_t output)520 status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
521 {
522     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
523     if (af == 0) return PERMISSION_DENIED;
524 
525     return af->setStreamOutput(stream, output);
526 }
527 
528 
setParameters(audio_io_handle_t ioHandle,const String8 & keyValuePairs,int delayMs)529 void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
530 {
531     mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
532 }
533 
getParameters(audio_io_handle_t ioHandle,const String8 & keys)534 String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
535 {
536     String8 result = AudioSystem::getParameters(ioHandle, keys);
537     return result;
538 }
539 
startTone(ToneGenerator::tone_type tone,AudioSystem::stream_type stream)540 status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
541 {
542     mTonePlaybackThread->startToneCommand(tone, stream);
543     return NO_ERROR;
544 }
545 
stopTone()546 status_t AudioPolicyService::stopTone()
547 {
548     mTonePlaybackThread->stopToneCommand();
549     return NO_ERROR;
550 }
551 
setVoiceVolume(float volume,int delayMs)552 status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
553 {
554     return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
555 }
556 
557 // -----------  AudioPolicyService::AudioCommandThread implementation ----------
558 
AudioCommandThread()559 AudioPolicyService::AudioCommandThread::AudioCommandThread()
560     :   Thread(false)
561 {
562     mpToneGenerator = NULL;
563 }
564 
565 
~AudioCommandThread()566 AudioPolicyService::AudioCommandThread::~AudioCommandThread()
567 {
568     mAudioCommands.clear();
569     if (mpToneGenerator != NULL) delete mpToneGenerator;
570 }
571 
onFirstRef()572 void AudioPolicyService::AudioCommandThread::onFirstRef()
573 {
574     const size_t SIZE = 256;
575     char buffer[SIZE];
576 
577     snprintf(buffer, SIZE, "AudioCommandThread");
578 
579     run(buffer, ANDROID_PRIORITY_AUDIO);
580 }
581 
threadLoop()582 bool AudioPolicyService::AudioCommandThread::threadLoop()
583 {
584     nsecs_t waitTime = INT64_MAX;
585 
586     mLock.lock();
587     while (!exitPending())
588     {
589         while(!mAudioCommands.isEmpty()) {
590             nsecs_t curTime = systemTime();
591             // commands are sorted by increasing time stamp: execute them from index 0 and up
592             if (mAudioCommands[0]->mTime <= curTime) {
593                 AudioCommand *command = mAudioCommands[0];
594                 mAudioCommands.removeAt(0);
595                 mLastCommand = *command;
596 
597                 switch (command->mCommand) {
598                 case START_TONE: {
599                     mLock.unlock();
600                     ToneData *data = (ToneData *)command->mParam;
601                     LOGV("AudioCommandThread() processing start tone %d on stream %d",
602                             data->mType, data->mStream);
603                     if (mpToneGenerator != NULL)
604                         delete mpToneGenerator;
605                     mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
606                     mpToneGenerator->startTone(data->mType);
607                     delete data;
608                     mLock.lock();
609                     }break;
610                 case STOP_TONE: {
611                     mLock.unlock();
612                     LOGV("AudioCommandThread() processing stop tone");
613                     if (mpToneGenerator != NULL) {
614                         mpToneGenerator->stopTone();
615                         delete mpToneGenerator;
616                         mpToneGenerator = NULL;
617                     }
618                     mLock.lock();
619                     }break;
620                 case SET_VOLUME: {
621                     VolumeData *data = (VolumeData *)command->mParam;
622                     LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
623                     command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
624                     if (command->mWaitStatus) {
625                         command->mCond.signal();
626                         mWaitWorkCV.wait(mLock);
627                     }
628                     delete data;
629                     }break;
630                 case SET_PARAMETERS: {
631                      ParametersData *data = (ParametersData *)command->mParam;
632                      LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
633                      command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
634                      if (command->mWaitStatus) {
635                          command->mCond.signal();
636                          mWaitWorkCV.wait(mLock);
637                      }
638                      delete data;
639                      }break;
640                 case SET_VOICE_VOLUME: {
641                     VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
642                     LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
643                     command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
644                     if (command->mWaitStatus) {
645                         command->mCond.signal();
646                         mWaitWorkCV.wait(mLock);
647                     }
648                     delete data;
649                     }break;
650                 default:
651                     LOGW("AudioCommandThread() unknown command %d", command->mCommand);
652                 }
653                 delete command;
654                 waitTime = INT64_MAX;
655             } else {
656                 waitTime = mAudioCommands[0]->mTime - curTime;
657                 break;
658             }
659         }
660         LOGV("AudioCommandThread() going to sleep");
661         mWaitWorkCV.waitRelative(mLock, waitTime);
662         LOGV("AudioCommandThread() waking up");
663     }
664     mLock.unlock();
665     return false;
666 }
667 
dump(int fd)668 status_t AudioPolicyService::AudioCommandThread::dump(int fd)
669 {
670     const size_t SIZE = 256;
671     char buffer[SIZE];
672     String8 result;
673 
674     snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
675     result.append(buffer);
676     write(fd, result.string(), result.size());
677 
678     bool locked = tryLock(mLock);
679     if (!locked) {
680         String8 result2(kCmdDeadlockedString);
681         write(fd, result2.string(), result2.size());
682     }
683 
684     snprintf(buffer, SIZE, "- Commands:\n");
685     result = String8(buffer);
686     result.append("   Command Time        Wait pParam\n");
687     for (int i = 0; i < (int)mAudioCommands.size(); i++) {
688         mAudioCommands[i]->dump(buffer, SIZE);
689         result.append(buffer);
690     }
691     result.append("  Last Command\n");
692     mLastCommand.dump(buffer, SIZE);
693     result.append(buffer);
694 
695     write(fd, result.string(), result.size());
696 
697     if (locked) mLock.unlock();
698 
699     return NO_ERROR;
700 }
701 
startToneCommand(int type,int stream)702 void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
703 {
704     AudioCommand *command = new AudioCommand();
705     command->mCommand = START_TONE;
706     ToneData *data = new ToneData();
707     data->mType = type;
708     data->mStream = stream;
709     command->mParam = (void *)data;
710     command->mWaitStatus = false;
711     Mutex::Autolock _l(mLock);
712     insertCommand_l(command);
713     LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
714     mWaitWorkCV.signal();
715 }
716 
stopToneCommand()717 void AudioPolicyService::AudioCommandThread::stopToneCommand()
718 {
719     AudioCommand *command = new AudioCommand();
720     command->mCommand = STOP_TONE;
721     command->mParam = NULL;
722     command->mWaitStatus = false;
723     Mutex::Autolock _l(mLock);
724     insertCommand_l(command);
725     LOGV("AudioCommandThread() adding tone stop");
726     mWaitWorkCV.signal();
727 }
728 
volumeCommand(int stream,float volume,int output,int delayMs)729 status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
730 {
731     status_t status = NO_ERROR;
732 
733     AudioCommand *command = new AudioCommand();
734     command->mCommand = SET_VOLUME;
735     VolumeData *data = new VolumeData();
736     data->mStream = stream;
737     data->mVolume = volume;
738     data->mIO = output;
739     command->mParam = data;
740     if (delayMs == 0) {
741         command->mWaitStatus = true;
742     } else {
743         command->mWaitStatus = false;
744     }
745     Mutex::Autolock _l(mLock);
746     insertCommand_l(command, delayMs);
747     LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
748     mWaitWorkCV.signal();
749     if (command->mWaitStatus) {
750         command->mCond.wait(mLock);
751         status =  command->mStatus;
752         mWaitWorkCV.signal();
753     }
754     return status;
755 }
756 
parametersCommand(int ioHandle,const String8 & keyValuePairs,int delayMs)757 status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
758 {
759     status_t status = NO_ERROR;
760 
761     AudioCommand *command = new AudioCommand();
762     command->mCommand = SET_PARAMETERS;
763     ParametersData *data = new ParametersData();
764     data->mIO = ioHandle;
765     data->mKeyValuePairs = keyValuePairs;
766     command->mParam = data;
767     if (delayMs == 0) {
768         command->mWaitStatus = true;
769     } else {
770         command->mWaitStatus = false;
771     }
772     Mutex::Autolock _l(mLock);
773     insertCommand_l(command, delayMs);
774     LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
775     mWaitWorkCV.signal();
776     if (command->mWaitStatus) {
777         command->mCond.wait(mLock);
778         status =  command->mStatus;
779         mWaitWorkCV.signal();
780     }
781     return status;
782 }
783 
voiceVolumeCommand(float volume,int delayMs)784 status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
785 {
786     status_t status = NO_ERROR;
787 
788     AudioCommand *command = new AudioCommand();
789     command->mCommand = SET_VOICE_VOLUME;
790     VoiceVolumeData *data = new VoiceVolumeData();
791     data->mVolume = volume;
792     command->mParam = data;
793     if (delayMs == 0) {
794         command->mWaitStatus = true;
795     } else {
796         command->mWaitStatus = false;
797     }
798     Mutex::Autolock _l(mLock);
799     insertCommand_l(command, delayMs);
800     LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
801     mWaitWorkCV.signal();
802     if (command->mWaitStatus) {
803         command->mCond.wait(mLock);
804         status =  command->mStatus;
805         mWaitWorkCV.signal();
806     }
807     return status;
808 }
809 
810 // insertCommand_l() must be called with mLock held
insertCommand_l(AudioCommand * command,int delayMs)811 void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
812 {
813     ssize_t i;
814     Vector <AudioCommand *> removedCommands;
815 
816     command->mTime = systemTime() + milliseconds(delayMs);
817 
818     // check same pending commands with later time stamps and eliminate them
819     for (i = mAudioCommands.size()-1; i >= 0; i--) {
820         AudioCommand *command2 = mAudioCommands[i];
821         // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
822         if (command2->mTime <= command->mTime) break;
823         if (command2->mCommand != command->mCommand) continue;
824 
825         switch (command->mCommand) {
826         case SET_PARAMETERS: {
827             ParametersData *data = (ParametersData *)command->mParam;
828             ParametersData *data2 = (ParametersData *)command2->mParam;
829             if (data->mIO != data2->mIO) break;
830             LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
831             AudioParameter param = AudioParameter(data->mKeyValuePairs);
832             AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
833             for (size_t j = 0; j < param.size(); j++) {
834                String8 key;
835                String8 value;
836                param.getAt(j, key, value);
837                for (size_t k = 0; k < param2.size(); k++) {
838                   String8 key2;
839                   String8 value2;
840                   param2.getAt(k, key2, value2);
841                   if (key2 == key) {
842                       param2.remove(key2);
843                       LOGV("Filtering out parameter %s", key2.string());
844                       break;
845                   }
846                }
847             }
848             // if all keys have been filtered out, remove the command.
849             // otherwise, update the key value pairs
850             if (param2.size() == 0) {
851                 removedCommands.add(command2);
852             } else {
853                 data2->mKeyValuePairs = param2.toString();
854             }
855         } break;
856 
857         case SET_VOLUME: {
858             VolumeData *data = (VolumeData *)command->mParam;
859             VolumeData *data2 = (VolumeData *)command2->mParam;
860             if (data->mIO != data2->mIO) break;
861             if (data->mStream != data2->mStream) break;
862             LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
863             removedCommands.add(command2);
864         } break;
865         case START_TONE:
866         case STOP_TONE:
867         default:
868             break;
869         }
870     }
871 
872     // remove filtered commands
873     for (size_t j = 0; j < removedCommands.size(); j++) {
874         // removed commands always have time stamps greater than current command
875         for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
876             if (mAudioCommands[k] == removedCommands[j]) {
877                 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
878                 mAudioCommands.removeAt(k);
879                 break;
880             }
881         }
882     }
883     removedCommands.clear();
884 
885     // insert command at the right place according to its time stamp
886     LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
887     mAudioCommands.insertAt(command, i + 1);
888 }
889 
exit()890 void AudioPolicyService::AudioCommandThread::exit()
891 {
892     LOGV("AudioCommandThread::exit");
893     {
894         AutoMutex _l(mLock);
895         requestExit();
896         mWaitWorkCV.signal();
897     }
898     requestExitAndWait();
899 }
900 
dump(char * buffer,size_t size)901 void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
902 {
903     snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
904             mCommand,
905             (int)ns2s(mTime),
906             (int)ns2ms(mTime)%1000,
907             mWaitStatus,
908             mParam);
909 }
910 
911 }; // namespace android
912