Android, NDK, Аудио маршрутизация, форсирование звука через гарнитуру

Использование регистра

  • Запись звука с гарнитуры Android

Среда

  • Samsung Galaxy 5
  • Android 5.0
  • ОС Windows Desktop с USB-устройством захвата звука

Реализация

  • Подключите выход гарнитуры устройства Android к линейному входу ОС Windows
  • Запишите все, что отправлено с устройства Android

Постановка задачи

  • Если подключить аудиоразъем во время воспроизведения звука на устройстве Android, аудиовыход устройства направляется через разъем для гарнитуры, и запись работает правильно
  • Как только воспроизведение звука (например, песни) остановлено на устройстве Android, при следующем запуске воспроизведения звука будет использоваться динамик устройства, а не разъем для гарнитуры (используется для записи).

Попытка решения проблемы

  • Родной инструмент командной строки C++, работающий под учетной записью оболочки (не могу использовать Java для этого)
  • динамически загрузить libmedia.so и вызвать например. android:: AudioSystem:: setForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_HEADPHONES)
  • отчеты LogCat:
    • 02-26 10: 39: 50.418 289 1707 Ошибка разрешения ServiceManager: android.permission.MODIFY_AUDIO_SETTINGS от uid = 2000 pid = 19577
    • 02-26 10: 39: 50.418 289 1707 Запрос требует android.permission.MODIFY_AUDIO_SETTINGS

Вопросы

  • Имея в виду, что решение должно работать на некорневом устройстве
    • Есть ли способ предоставить разрешение "android.permission.MODIFY_AUDIO_SETTINGS" учетной записи "shell"?
    • Есть ли какой-либо другой способ принудительно использовать общесистемный(и не специфичный для приложения) звук через гарнитуру?

Кодовая привязка

            HRESULT forceAudioThroughHeadPhones() {
                typedef int(*SET_FORCE_USE)(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
                struct sigaction sa, osa;
                sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
                sa.sa_sigaction = [](int signo, siginfo_t* psi, void *data)->void { ucontext_t *uc = (ucontext_t *)data; };
                sigaction(SIGILL, &sa, &osa);
                void* hMod = dlopen("libmedia.so", RTLD_LAZY);
                sigaction(SIGILL, &osa, 0);
                if (0 == hMod)
                    return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
                SET_FORCE_USE setForceUse = (SET_FORCE_USE)dlsym(hMod, "_ZN7android11AudioSystem11setForceUseE24audio_policy_force_use_t25audio_policy_forced_cfg_t");
                if (0 == setForceUse)
                    return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
                android::status_t err;
                if (ERROR_SUCCESS != (err = setForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA, AUDIO_POLICY_FORCE_HEADPHONES)))
                    return E_FAIL;
                if (ERROR_SUCCESS != (err = setForceUse(AUDIO_POLICY_FORCE_FOR_SYSTEM, AUDIO_POLICY_FORCE_HEADPHONES)))
                    return E_FAIL;
                return S_OK;
            }
  • 'setForceUse' возвращает -1, errno равно 'Zero'.

ОБНОВИТЬ:

Я получаю то же разрешение ошибки logcat при использовании вызова службы оболочки adb...:

10|shell@klte:/ $ service call media.audio_policy 1 i32 2 
Result: Parcel(ffffffff    '....')

0 ответов

Другие вопросы по тегам