| /** |
| * Copyright (C) 2020 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. |
| */ |
| |
| #include <binder/IServiceManager.h> |
| #include <binder/IPCThreadState.h> |
| #include <media/IAudioPolicyService.h> |
| #include "../includes/common.h" |
| |
| using namespace android; |
| |
| #define MAX_NUMBER_OF_AUDIO_SESSIONS 1024 |
| #define MAX_NUMBER_OF_THREADS 5 |
| #define MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS 2 |
| #define SLEEP_TIME_IN_SECONDS 5 |
| |
| struct pocAudioSessionCtxt { |
| sp<IAudioPolicyService> audioService; |
| audio_session_t audioSession[MAX_NUMBER_OF_AUDIO_SESSIONS]; |
| volatile bool startThread; |
| }; |
| |
| static void* acquireSoundTriggerSessionThread(void *arg) { |
| int i = 0; |
| pocAudioSessionCtxt *ctxt = (pocAudioSessionCtxt *) arg; |
| if (!ctxt) { |
| return nullptr; |
| } |
| time_t currentTime = start_timer(); |
| while (timer_active(currentTime)) { |
| if (ctxt->startThread == true && ctxt->audioService != nullptr) { |
| audio_io_handle_t ioHandle = 0; |
| audio_devices_t device = 0; |
| ctxt->audioService->acquireSoundTriggerSession( |
| &(ctxt->audioSession[++i]), &ioHandle, &device); |
| if (i >= MAX_NUMBER_OF_AUDIO_SESSIONS) { |
| i = 0; |
| } |
| } |
| } |
| return nullptr; |
| } |
| |
| static void* releaseSoundTriggerSessionThread(void *arg) { |
| int i = 0; |
| pocAudioSessionCtxt *ctxt = (pocAudioSessionCtxt *) arg; |
| if (!ctxt) { |
| return nullptr; |
| } |
| time_t currentTime = start_timer(); |
| while (timer_active(currentTime)) { |
| if (ctxt->startThread == true && ctxt->audioService != nullptr) { |
| ctxt->audioService->releaseSoundTriggerSession( |
| ctxt->audioSession[++i]); |
| if (i >= MAX_NUMBER_OF_AUDIO_SESSIONS) { |
| i = 0; |
| } |
| } |
| } |
| return nullptr; |
| } |
| |
| class MyDeathRecipient : public IBinder::DeathRecipient { |
| public: |
| MyDeathRecipient() { |
| } |
| virtual void binderDied(const wp<IBinder>& who __unused) { |
| exit(EXIT_SUCCESS); |
| } |
| }; |
| |
| int main() { |
| pocAudioSessionCtxt ctxt; |
| pthread_t thread[MAX_NUMBER_OF_THREADS]; |
| ctxt.startThread = false; |
| |
| for (int i = 0; i < MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS; ++i) { |
| pthread_create(&thread[i], nullptr, acquireSoundTriggerSessionThread, |
| &ctxt); |
| } |
| |
| for (int i = MAX_NUMBER_OF_ACQUIRE_SESSION_THREADS; |
| i < MAX_NUMBER_OF_THREADS; ++i) { |
| pthread_create(&thread[i], nullptr, releaseSoundTriggerSessionThread, |
| &ctxt); |
| } |
| |
| sp < IServiceManager > sm = defaultServiceManager(); |
| sp < IBinder > binder = sm->getService(String16("media.audio_policy")); |
| if (binder == nullptr) { |
| return EXIT_FAILURE; |
| } |
| ctxt.audioService = interface_cast < IAudioPolicyService > (binder); |
| if (ctxt.audioService == nullptr) { |
| return EXIT_FAILURE; |
| } |
| |
| sp<MyDeathRecipient> deathRecipient = new MyDeathRecipient(); |
| binder->linkToDeath(deathRecipient); |
| ctxt.startThread = true; |
| for (int i = 0; i < MAX_NUMBER_OF_THREADS; ++i) { |
| pthread_join(thread[i], nullptr); |
| } |
| return EXIT_SUCCESS; |
| } |