From d053e0bd173d9a50791ba0e4692baf2f768927c4 Mon Sep 17 00:00:00 2001 From: Mok Jeongho Date: Mon, 23 May 2016 17:52:10 +0900 Subject: [PATCH] Check record privilege in audio_in_create Previously record privilege was checked in prepare state when pulse record stream is created, which is wrong. So now, we check previlege in audio_in_create with newly created pulse api(pa_context_check_privilege). [Version] 0.3.35 [Profile] Common [Issue Type] Privilege Change-Id: I696f5a861adcce0b43796f52646ed0cc11a1a18b --- packaging/capi-media-audio-io.spec | 2 +- src/cpp/CAudioInput.cpp | 101 +++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 305624a..6c38ccb 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.3.34 +Version: 0.3.35 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index 453b846..a0e9d41 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -15,12 +15,19 @@ */ +#include #include "CAudioIODef.h" +#define RECORDER_PRIVILEGE "http://tizen.org/privilege/recorder" +#define CLIENT_NAME "AUDIO_IO_PA_CLIENT" using namespace std; using namespace tizen_media_audio; +struct PrivilegeData { + bool isPrivilegeAllowed; + pa_threaded_mainloop *paMainloop; +}; /** * class CAudioInput inherited by CAudioIO @@ -91,6 +98,97 @@ bool CAudioInput::__IsReady() { return CAudioIO::IsReady(); } +static void __contextStateChangeCb(pa_context* c, void* user_data) { + pa_threaded_mainloop *paMainloop = static_cast(user_data); + assert(paMainloop); + assert(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_READY: + AUDIO_IO_LOGD("The context is ready"); + pa_threaded_mainloop_signal(paMainloop, 0); + break; + + case PA_CONTEXT_FAILED: + case PA_CONTEXT_TERMINATED: + AUDIO_IO_LOGD("The context is lost"); + pa_threaded_mainloop_signal(paMainloop, 0); + break; + + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } +} + +static void __checkPrivilegeCb(pa_context *c, int success, void *user_data) { + AUDIO_IO_LOGD("pa_context[%p], success[%d], user_data[%p]", c, success, user_data); + assert(c); + assert(user_data); + + PrivilegeData* prData= static_cast(user_data); + prData->isPrivilegeAllowed = success ? true : false; + + pa_threaded_mainloop_signal(prData->paMainloop, 0); +} + +static bool __IsPrivilegeAllowed() { + pa_operation *o; + pa_context *c; + int err = 0; + PrivilegeData prData; + + prData.paMainloop = pa_threaded_mainloop_new(); + if (prData.paMainloop == NULL) + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_threaded_mainloop_new()"); + c = pa_context_new(pa_threaded_mainloop_get_api(prData.paMainloop), CLIENT_NAME); + if (c == NULL) + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_context_new()"); + + pa_context_set_state_callback(c, __contextStateChangeCb, prData.paMainloop); + + if (pa_context_connect(c, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) + THROW_ERROR_MSG(CAudioError::EError::ERROR_OUT_OF_MEMORY, "Failed pa_context_connect()"); + + pa_threaded_mainloop_lock(prData.paMainloop); + + if (pa_threaded_mainloop_start(prData.paMainloop) < 0) { + pa_threaded_mainloop_unlock(prData.paMainloop); + THROW_ERROR_MSG(CAudioError::EError::ERROR_FAILED_OPERATION, "Failed pa_threaded_mainloop_start()"); + } + + while (true) { + pa_context_state_t state; + state = pa_context_get_state(c); + + if (state == PA_CONTEXT_READY) + break; + + if (!PA_CONTEXT_IS_GOOD(state)) { + err = pa_context_errno(c); + pa_threaded_mainloop_unlock(prData.paMainloop); + THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INTERNAL_OPERATION, "pa_context's state is not good : err[%d]", err); + } + + /* Wait until the context is ready */ + pa_threaded_mainloop_wait(prData.paMainloop); + } + + o = pa_context_check_privilege(c, RECORDER_PRIVILEGE, __checkPrivilegeCb, &prData); + while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(prData.paMainloop); + + pa_threaded_mainloop_unlock(prData.paMainloop); + pa_threaded_mainloop_stop(prData.paMainloop); + pa_context_disconnect(c); + pa_context_unref(c); + pa_threaded_mainloop_free(prData.paMainloop); + + return prData.isPrivilegeAllowed; +} + void CAudioInput::initialize() throw(CAudioError) { if (__IsInit() == true) { return; @@ -98,6 +196,9 @@ void CAudioInput::initialize() throw(CAudioError) { try { CAudioIO::initialize(); + if (__IsPrivilegeAllowed() == false) { + THROW_ERROR_MSG(CAudioError::EError::ERROR_PERMISSION_DENIED, "No privilege for record"); + } // Create ASM Handler mpAudioSessionHandler = new CAudioSessionHandler(CAudioSessionHandler::EAudioSessionType::AUDIO_SESSION_TYPE_CAPTURE, mAudioInfo, this); -- 2.34.1