From c2ba10260fff3d2bcedbe6fbc9d3554bc8567aa4 Mon Sep 17 00:00:00 2001 From: yuanjinghua Date: Thu, 14 Mar 2024 22:07:10 +0800 Subject: [PATCH] New Feature, add interface to support privacy authority Signed-off-by: yuanjinghua --- .../native/capi/common/native_player_magic.h | 5 + .../screencapture/native_avscreen_capture.cpp | 458 ++++- .../screen_capture/screen_capture_impl.cpp | 102 +- .../screen_capture/screen_capture_impl.h | 6 +- interfaces/inner_api/native/screen_capture.h | 76 +- interfaces/kits/c/BUILD.gn | 1 + .../libnative_avscreen_capture.ndk.json | 9 +- interfaces/kits/c/native_avscreen_capture.h | 126 +- .../kits/c/native_avscreen_capture_base.h | 128 ++ services/include/i_screen_capture_service.h | 5 +- services/services/BUILD.gn | 1 + .../client/screen_capture_client.cpp | 15 +- .../client/screen_capture_client.h | 5 +- .../ipc/i_standard_screen_capture_listener.h | 6 +- .../ipc/i_standard_screen_capture_service.h | 46 +- .../ipc/screen_capture_listener_proxy.cpp | 35 +- .../ipc/screen_capture_listener_proxy.h | 9 +- .../ipc/screen_capture_listener_stub.cpp | 17 +- .../ipc/screen_capture_listener_stub.h | 3 +- .../ipc/screen_capture_service_proxy.cpp | 34 +- .../ipc/screen_capture_service_proxy.h | 5 +- .../ipc/screen_capture_service_stub.cpp | 38 +- .../ipc/screen_capture_service_stub.h | 6 +- .../server/audio_capturer_wrapper.cpp | 218 +++ .../server/audio_capturer_wrapper.h | 94 + .../server/screen_capture_server.cpp | 1515 +++++++++-------- .../server/screen_capture_server.h | 227 +-- services/utils/include/media_log.h | 8 + test/unittest/resources/ohos_test.xml | 2 + .../src/screen_capture_unit_test.cpp | 117 +- 30 files changed, 2360 insertions(+), 957 deletions(-) create mode 100644 services/services/screen_capture/server/audio_capturer_wrapper.cpp create mode 100644 services/services/screen_capture/server/audio_capturer_wrapper.h diff --git a/frameworks/native/capi/common/native_player_magic.h b/frameworks/native/capi/common/native_player_magic.h index b358b2d9d..ad36cbc92 100644 --- a/frameworks/native/capi/common/native_player_magic.h +++ b/frameworks/native/capi/common/native_player_magic.h @@ -25,6 +25,11 @@ struct OH_AVScreenCapture : public OHOS::RefBase { virtual ~OH_AVScreenCapture() = default; }; +struct OH_AVScreenCapture_ContentFilter : public OHOS::RefBase { + OH_AVScreenCapture_ContentFilter() = default; + virtual ~OH_AVScreenCapture_ContentFilter() = default; +}; + struct OH_AVPlayer : public OHOS::RefBase { OH_AVPlayer() = default; virtual ~OH_AVPlayer() = default; diff --git a/frameworks/native/capi/screencapture/native_avscreen_capture.cpp b/frameworks/native/capi/screencapture/native_avscreen_capture.cpp index 1bac2ce80..e8e8e8843 100644 --- a/frameworks/native/capi/screencapture/native_avscreen_capture.cpp +++ b/frameworks/native/capi/screencapture/native_avscreen_capture.cpp @@ -13,12 +13,19 @@ * limitations under the License. */ +#include "native_avscreen_capture.h" + #include +#include +#include + +#include "buffer/avbuffer.h" +#include "common/native_mfmagic.h" #include "media_log.h" #include "media_errors.h" +#include "native_avbuffer.h" #include "native_player_magic.h" #include "surface_buffer_impl.h" -#include "native_avscreen_capture.h" #include "native_window.h" namespace { @@ -40,6 +47,173 @@ struct ScreenCaptureObject : public OH_AVScreenCapture { std::shared_ptr callback_ = nullptr; }; +class NativeScreenCaptureStateChangeCallback { +public: + NativeScreenCaptureStateChangeCallback(OH_AVScreenCapture_OnStateChange callback, void *userData) + : callback_(callback), userData_(userData) {} + virtual ~NativeScreenCaptureStateChangeCallback() = default; + + void OnStateChange(struct OH_AVScreenCapture *capture, AVScreenCaptureStateCode infoType) + { + CHECK_AND_RETURN(capture != nullptr && callback_ != nullptr); + callback_(capture, static_cast(infoType), userData_); + } + +private: + OH_AVScreenCapture_OnStateChange callback_; + void *userData_; +}; + +class NativeScreenCaptureErrorCallback { +public: + NativeScreenCaptureErrorCallback(OH_AVScreenCapture_OnError callback, void *userData) + : callback_(callback), userData_(userData) {} + virtual ~NativeScreenCaptureErrorCallback() = default; + + void OnError(struct OH_AVScreenCapture *capture, int32_t errorCode) + { + CHECK_AND_RETURN(capture != nullptr && callback_ != nullptr); + callback_(capture, errorCode, userData_); + } + +private: + OH_AVScreenCapture_OnError callback_; + void *userData_; +}; + +class NativeScreenCaptureDataCallback { +public: + NativeScreenCaptureDataCallback(OH_AVScreenCapture_OnBufferAvailable callback, void *userData) + : callback_(callback), userData_(userData) {} + virtual ~NativeScreenCaptureDataCallback() = default; + + void OnBufferAvailable(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureBufferType bufferType) + { + CHECK_AND_RETURN(capture != nullptr && callback_ != nullptr); + switch (bufferType) { + case OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO: + OnProcessVideoBuffer(capture); + return; + case OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER: // fall-through + case OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC: + OnProcessAudioBuffer(capture, bufferType); + return; + default: + MEDIA_LOGD("OnBufferAvailable() is called, invalid bufferType:%{public}d", bufferType); + return; + } + } + +private: + OH_AVSCREEN_CAPTURE_ErrCode AcquireAudioBuffer(const std::shared_ptr &screenCapture, + OHOS::sptr &ohAvBuffer, int64_t ×tamp, AudioCaptureSourceType type) + { + std::shared_ptr aBuffer; + int32_t ret = screenCapture->AcquireAudioBuffer(aBuffer, type); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, + "AcquireAudioBuffer failed not permit! ret:%{public}d", ret); + CHECK_AND_RETURN_RET_LOG(aBuffer != nullptr && aBuffer->buffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireAudioBuffer failed aBuffer no memory!"); + std::shared_ptr avBuffer = AVBuffer::CreateAVBuffer(aBuffer->buffer, aBuffer->length, + aBuffer->length); + CHECK_AND_RETURN_RET_LOG(avBuffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireAudioBuffer failed avBuffer no memory!"); + aBuffer->buffer = nullptr; // memory control has transfered to AVBuffer + timestamp = aBuffer->timestamp; + ohAvBuffer = new(std::nothrow) OH_AVBuffer(avBuffer); + + CHECK_AND_RETURN_RET_LOG(ohAvBuffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireAudioBuffer failed ohAvBuffer no memory!"); + return AV_SCREEN_CAPTURE_ERR_OK; + } + + OH_AVSCREEN_CAPTURE_ErrCode ReleaseAudioBuffer(const std::shared_ptr &screenCapture, + AudioCaptureSourceType type) + { + int32_t ret = screenCapture->ReleaseAudioBuffer(type); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, + "ReleaseAudioBuffer failed! ret:%{public}d", ret); + return AV_SCREEN_CAPTURE_ERR_OK; + } + + OH_AVSCREEN_CAPTURE_ErrCode OnProcessAudioBuffer(struct OH_AVScreenCapture *capture, + OH_AVScreenCaptureBufferType bufferType) + { + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture is null"); + + AudioCaptureSourceType audioSourceType; + if (bufferType == OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) { + audioSourceType = AudioCaptureSourceType::ALL_PLAYBACK; + } else if (bufferType == OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) { + audioSourceType = AudioCaptureSourceType::MIC; + } else { + return AV_SCREEN_CAPTURE_ERR_INVALID_VAL; + } + OHOS::sptr ohAvBuffer; + int64_t timestamp = 0; + OH_AVSCREEN_CAPTURE_ErrCode errCode = + AcquireAudioBuffer(screenCaptureObj->screenCapture_, ohAvBuffer, timestamp, audioSourceType); + if (errCode == AV_SCREEN_CAPTURE_ERR_OK) { + callback_(capture, reinterpret_cast(ohAvBuffer.GetRefPtr()), bufferType, timestamp, + userData_); + } + errCode = ReleaseAudioBuffer(screenCaptureObj->screenCapture_, audioSourceType); + return errCode; + } + OH_AVSCREEN_CAPTURE_ErrCode AcquireVideoBuffer(const std::shared_ptr &screenCapture, + OHOS::sptr &ohAvBuffer, int64_t ×tamp) + { + int32_t fence; + OHOS::Rect damage; + OHOS::sptr surfaceBuffer = + screenCapture->AcquireVideoBuffer(fence, timestamp, damage); + CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireVideoBuffer failed surfaceBuffer no memory!"); + std::shared_ptr avBuffer = AVBuffer::CreateAVBuffer(surfaceBuffer); + CHECK_AND_RETURN_RET_LOG(avBuffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireVideoBuffer failed avBuffer no memory!"); + + ohAvBuffer = new(std::nothrow) OH_AVBuffer(avBuffer); + CHECK_AND_RETURN_RET_LOG(ohAvBuffer != nullptr, AV_SCREEN_CAPTURE_ERR_NO_MEMORY, + "AcquireVideoBuffer failed ohAvBuffer no memory!"); + return AV_SCREEN_CAPTURE_ERR_OK; + } + + OH_AVSCREEN_CAPTURE_ErrCode ReleaseVideoBuffer(const std::shared_ptr &screenCapture) + { + int32_t ret = screenCapture->ReleaseVideoBuffer(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, + "ReleaseVideoBuffer failed! ret:%{public}d", ret); + return AV_SCREEN_CAPTURE_ERR_OK; + } + + OH_AVSCREEN_CAPTURE_ErrCode OnProcessVideoBuffer(struct OH_AVScreenCapture *capture) + { + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture is null"); + + OHOS::sptr hoAvBuffer; + int64_t timestamp = 0; + OH_AVSCREEN_CAPTURE_ErrCode errCode = + AcquireVideoBuffer(screenCaptureObj->screenCapture_, hoAvBuffer, timestamp); + if (errCode == AV_SCREEN_CAPTURE_ERR_OK) { + callback_(capture, reinterpret_cast(hoAvBuffer.GetRefPtr()), + OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO, timestamp, userData_); + } + errCode = ReleaseVideoBuffer(screenCaptureObj->screenCapture_); + return errCode; + } + +private: + OH_AVScreenCapture_OnBufferAvailable callback_; + void *userData_; +}; + class NativeScreenCaptureCallback : public ScreenCaptureCallBack { public: NativeScreenCaptureCallback(struct OH_AVScreenCapture *capture, struct OH_AVScreenCaptureCallback callback) @@ -48,27 +222,73 @@ public: void OnError(ScreenCaptureErrorType errorType, int32_t errorCode) override { - MEDIA_LOGI("OnError() is called, errorType %{public}d, errorCode %{public}d", errorType, errorCode); - std::unique_lock lock(mutex_); + MEDIA_LOGE("OnError() is called, errorType %{public}d, errorCode %{public}d", errorType, errorCode); + std::shared_lock lock(mutex_); + CHECK_AND_RETURN(capture_ != nullptr); + + if (errorCallback_ != nullptr) { + errorCallback_->OnError(capture_, errorCode); + return; + } - if (capture_ != nullptr && callback_.onError != nullptr) { + if (callback_.onError != nullptr) { callback_.onError(capture_, errorCode); + return; + } + } + + void OnStateChange(AVScreenCaptureStateCode stateCode) override + { + MEDIA_LOGI("OnError() is called, stateCode %{public}d", stateCode); + std::shared_lock lock(mutex_); + CHECK_AND_RETURN(capture_ != nullptr); + + if (stateChangeCallback_ != nullptr) { + stateChangeCallback_->OnStateChange(capture_, stateCode); + return; } } void OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) override { - MEDIA_LOGD("OnAudioBufferAvailable() is called, isReady:%{public}d", isReady); - std::unique_lock lock(mutex_); - if (capture_ != nullptr && callback_.onAudioBufferAvailable != nullptr) { + MEDIA_LOGD("OnAudioBufferAvailable() is called, isReady:%{public}d, type:%{public}d", isReady, type); + std::shared_lock lock(mutex_); + CHECK_AND_RETURN(capture_ != nullptr); + + if (dataCallback_ != nullptr) { + if (!isReady) { + return; + } + if (type == AudioCaptureSourceType::SOURCE_DEFAULT || type == AudioCaptureSourceType::MIC) { + dataCallback_->OnBufferAvailable(capture_, + OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC); + } else if (type == AudioCaptureSourceType::ALL_PLAYBACK || type == AudioCaptureSourceType::APP_PLAYBACK) { + dataCallback_->OnBufferAvailable(capture_, + OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER); + } else { + MEDIA_LOGD("OnAudioBufferAvailable() is called, invalid audio source type:%{public}d", type); + } + return; + } + if (callback_.onAudioBufferAvailable != nullptr) { callback_.onAudioBufferAvailable(capture_, isReady, static_cast(type)); + return; } } void OnVideoBufferAvailable(bool isReady) override { MEDIA_LOGD("OnVideoBufferAvailable() is called, isReady:%{public}d", isReady); - std::unique_lock lock(mutex_); + std::shared_lock lock(mutex_); + CHECK_AND_RETURN(capture_ != nullptr); + + if (dataCallback_ != nullptr) { + if (!isReady) { + return; + } + dataCallback_->OnBufferAvailable(capture_, + OH_AVScreenCaptureBufferType::OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO); + } if (capture_ != nullptr && callback_.onVideoBufferAvailable != nullptr) { callback_.onVideoBufferAvailable(capture_, isReady); } @@ -76,16 +296,114 @@ public: void StopCallback() { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); capture_ = nullptr; } + void SetCallback(struct OH_AVScreenCaptureCallback callback) + { + std::unique_lock lock(mutex_); + callback_ = callback; + } + + bool IsDataCallbackEnabled() + { + std::shared_lock lock(mutex_); + return dataCallback_ != nullptr; + } + + bool IsStateChangeCallbackEnabled() + { + std::shared_lock lock(mutex_); + return stateChangeCallback_ != nullptr; + } + + bool SetStateChangeCallback(OH_AVScreenCapture_OnStateChange callback, void *userData) + { + std::unique_lock lock(mutex_); + stateChangeCallback_ = std::make_shared(callback, userData); + return stateChangeCallback_ != nullptr; + } + + bool SetErrorCallback(OH_AVScreenCapture_OnError callback, void *userData) + { + std::unique_lock lock(mutex_); + errorCallback_ = std::make_shared(callback, userData); + return errorCallback_ != nullptr; + } + + bool SetDataCallback(OH_AVScreenCapture_OnBufferAvailable callback, void *userData) + { + std::unique_lock lock(mutex_); + dataCallback_ = std::make_shared(callback, userData); + return dataCallback_ != nullptr; + } + private: + std::shared_mutex mutex_; struct OH_AVScreenCapture *capture_; struct OH_AVScreenCaptureCallback callback_; - std::mutex mutex_; + std::shared_ptr stateChangeCallback_; + std::shared_ptr errorCallback_; + std::shared_ptr dataCallback_; }; +struct ScreenCaptureContentFilterObject : public OH_AVScreenCapture_ContentFilter { + ScreenCaptureContentFilterObject() = default; + ~ScreenCaptureContentFilterObject() = default; + + ScreenCaptureContentFilter screenCaptureContentFilter; +}; + +struct OH_AVScreenCapture_ContentFilter *OH_AVScreenCapture_CreateContentFilter(void) +{ + struct ScreenCaptureContentFilterObject *object = new(std::nothrow) ScreenCaptureContentFilterObject(); + CHECK_AND_RETURN_RET_LOG(object != nullptr, nullptr, "failed to new ScreenCaptureContentFilterObject"); + return object; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseContentFilter(struct OH_AVScreenCapture_ContentFilter *filter) +{ + CHECK_AND_RETURN_RET_LOG(filter != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input filter is nullptr!"); + struct ScreenCaptureContentFilterObject *contentFilterObj = + reinterpret_cast(filter); + delete contentFilterObj; + return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ContentFilter_AddAudioContent( + struct OH_AVScreenCapture_ContentFilter *filter, OH_AVScreenCaptureFilterableAudioContent content) +{ + CHECK_AND_RETURN_RET_LOG(filter != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input filter is nullptr!"); + struct ScreenCaptureContentFilterObject *contentFilterObj = + reinterpret_cast(filter); + + CHECK_AND_RETURN_RET_LOG( + content >= OH_AVScreenCaptureFilterableAudioContent::OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO || + content <= OH_AVScreenCaptureFilterableAudioContent::OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input content invalid!"); + contentFilterObj->screenCaptureContentFilter.filteredAudioContents.insert( + static_cast(content)); + return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ContentFilter_ExcludeContent(struct OH_AVScreenCapture *capture, + struct OH_AVScreenCapture_ContentFilter *filter) +{ + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture is null"); + + CHECK_AND_RETURN_RET_LOG(filter != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input filter is nullptr!"); + struct ScreenCaptureContentFilterObject *contentFilterObj = + reinterpret_cast(filter); + + int32_t ret = screenCaptureObj->screenCapture_->ExcludeContent(contentFilterObj->screenCaptureContentFilter); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_UNSUPPORT, "StartScreenCapture failed!"); + return AV_SCREEN_CAPTURE_ERR_OK; +} + struct OH_AVScreenCapture *OH_AVScreenCapture_Create(void) { std::shared_ptr screenCapture = ScreenCaptureFactory::CreateScreenCapture(); @@ -162,6 +480,15 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_Init(struct OH_AVScreenCapture *c return AV_SCREEN_CAPTURE_ERR_OK; } +static int32_t SetPrivacyAuthorityEnabled(struct ScreenCaptureObject *screenCaptureObj) +{ + if (screenCaptureObj->callback_ != nullptr && screenCaptureObj->callback_->IsStateChangeCallbackEnabled()) { + int32_t ret = screenCaptureObj->screenCapture_->SetPrivacyAuthorityEnabled(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetPrivacyAuthorityEnabled failed!"); + } + return MSERR_OK; +} + OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenCapture(struct OH_AVScreenCapture *capture) { CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); @@ -170,7 +497,9 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenCapture(struct OH_AVSc CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); - int32_t ret = screenCaptureObj->screenCapture_->StartScreenCapture(); + int32_t ret = SetPrivacyAuthorityEnabled(screenCaptureObj); + CHECK_AND_RETURN_RET(ret == AV_SCREEN_CAPTURE_ERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT); + ret = screenCaptureObj->screenCapture_->StartScreenCapture(); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "StartScreenCapture failed!"); return AV_SCREEN_CAPTURE_ERR_OK; @@ -188,7 +517,9 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenCaptureWithSurface(str CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); - int32_t ret = screenCaptureObj->screenCapture_->StartScreenCaptureWithSurface(window->surface); + int32_t ret = SetPrivacyAuthorityEnabled(screenCaptureObj); + CHECK_AND_RETURN_RET(ret == AV_SCREEN_CAPTURE_ERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT); + ret = screenCaptureObj->screenCapture_->StartScreenCaptureWithSurface(window->surface); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "StartScreenCapture failed!"); return AV_SCREEN_CAPTURE_ERR_OK; @@ -216,7 +547,9 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenRecording(struct OH_AV CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); - int32_t ret = screenCaptureObj->screenCapture_->StartScreenRecording(); + int32_t ret = SetPrivacyAuthorityEnabled(screenCaptureObj); + CHECK_AND_RETURN_RET(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT); + ret = screenCaptureObj->screenCapture_->StartScreenRecording(); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "StartScreenRecording failed!"); return AV_SCREEN_CAPTURE_ERR_OK; @@ -245,6 +578,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_AcquireAudioBuffer(struct OH_AVSc CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + if (screenCaptureObj->callback_ != nullptr && screenCaptureObj->callback_->IsDataCallbackEnabled()) { + MEDIA_LOGE("AcquireAudioBuffer() not permit for has set DataCallback"); + return AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT; + } std::shared_ptr aBuffer; int32_t ret = screenCaptureObj->screenCapture_->AcquireAudioBuffer(aBuffer, static_cast(type)); @@ -270,6 +607,10 @@ OH_NativeBuffer* OH_AVScreenCapture_AcquireVideoBuffer(struct OH_AVScreenCapture struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, nullptr, "screenCapture_ is null"); + if (screenCaptureObj->callback_ != nullptr && screenCaptureObj->callback_->IsDataCallbackEnabled()) { + MEDIA_LOGE("AcquireVideoBuffer() not permit for has set DataCallback"); + return nullptr; + } OHOS::Rect damage; OHOS::sptr sufacebuffer = screenCaptureObj->screenCapture_->AcquireVideoBuffer(*fence, *timestamp, damage); @@ -292,6 +633,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseVideoBuffer(struct OH_AVSc CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + if (screenCaptureObj->callback_ != nullptr && screenCaptureObj->callback_->IsDataCallbackEnabled()) { + MEDIA_LOGE("ReleaseVideoBuffer() not permit for has set DataCallback"); + return AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT; + } int32_t ret = screenCaptureObj->screenCapture_->ReleaseVideoBuffer(); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "ReleaseVideoBuffer failed!"); @@ -307,6 +652,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseAudioBuffer(struct OH_AVSc CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + if (screenCaptureObj->callback_ != nullptr && screenCaptureObj->callback_->IsDataCallbackEnabled()) { + MEDIA_LOGE("ReleaseAudioBuffer() not permit for has set DataCallback"); + return AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT; + } int32_t ret = screenCaptureObj->screenCapture_->ReleaseAudioBuffer(static_cast(type)); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "ReleaseSurfaceBuffer failed!"); @@ -322,14 +671,17 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetCallback(struct OH_AVScreenCap CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); - screenCaptureObj->callback_ = std::make_shared(capture, callback); - CHECK_AND_RETURN_RET_LOG(screenCaptureObj->callback_ != nullptr, - AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "videoEncoder_ is nullptr!"); + if (screenCaptureObj->callback_ == nullptr) { + screenCaptureObj->callback_ = std::make_shared(capture, callback); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->callback_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "callback_ is nullptr!"); + } else { + screenCaptureObj->callback_->SetCallback(callback); + } int32_t ret = screenCaptureObj->screenCapture_->SetScreenCaptureCallback(screenCaptureObj->callback_); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, "SetScreenCaptureCallback failed!"); - return AV_SCREEN_CAPTURE_ERR_OK; } @@ -372,6 +724,78 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetMicrophoneEnabled(struct OH_AV return AV_SCREEN_CAPTURE_ERR_OK; } +static OH_AVSCREEN_CAPTURE_ErrCode AVScreenCaptureSetCallback(struct OH_AVScreenCapture *capture, + struct ScreenCaptureObject *screenCaptureObj) +{ + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj != nullptr && screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is nullptr!"); + if (screenCaptureObj->callback_ == nullptr) { + OH_AVScreenCaptureCallback dummyCallback = { nullptr, nullptr, nullptr }; + screenCaptureObj->callback_ = std::make_shared(capture, dummyCallback); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->callback_ != nullptr, + AV_SCREEN_CAPTURE_ERR_NO_MEMORY, "callback_ is nullptr!"); + + int32_t ret = screenCaptureObj->screenCapture_->SetScreenCaptureCallback(screenCaptureObj->callback_); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT, + "SetScreenCaptureCallback failed!"); + } + return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetStateCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnStateChange callback, void *userData) +{ + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + + OH_AVSCREEN_CAPTURE_ErrCode errCode = AVScreenCaptureSetCallback(capture, screenCaptureObj); + CHECK_AND_RETURN_RET_LOG(errCode == AV_SCREEN_CAPTURE_ERR_OK, errCode, "SetStateCallback is null"); + + if (screenCaptureObj->callback_ == nullptr || + screenCaptureObj->callback_->SetStateChangeCallback(callback, userData)) { + return AV_SCREEN_CAPTURE_ERR_NO_MEMORY; + } + return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetErrorCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnError callback, void *userData) +{ + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + + OH_AVSCREEN_CAPTURE_ErrCode errCode = AVScreenCaptureSetCallback(capture, screenCaptureObj); + CHECK_AND_RETURN_RET_LOG(errCode == AV_SCREEN_CAPTURE_ERR_OK, errCode, "SetErrorCallback is null"); + + if (screenCaptureObj->callback_ == nullptr || screenCaptureObj->callback_->SetErrorCallback(callback, userData)) { + return AV_SCREEN_CAPTURE_ERR_NO_MEMORY; + } + return AV_SCREEN_CAPTURE_ERR_OK; +} + +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetDataCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnBufferAvailable callback, void *userData) +{ + CHECK_AND_RETURN_RET_LOG(capture != nullptr, AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "input capture is nullptr!"); + struct ScreenCaptureObject *screenCaptureObj = reinterpret_cast(capture); + CHECK_AND_RETURN_RET_LOG(screenCaptureObj->screenCapture_ != nullptr, + AV_SCREEN_CAPTURE_ERR_INVALID_VAL, "screenCapture_ is null"); + + OH_AVSCREEN_CAPTURE_ErrCode errCode = AVScreenCaptureSetCallback(capture, screenCaptureObj); + CHECK_AND_RETURN_RET_LOG(errCode == AV_SCREEN_CAPTURE_ERR_OK, errCode, "SetDataCallback is null"); + + if (screenCaptureObj->callback_ == nullptr || + screenCaptureObj->callback_->SetDataCallback(callback, userData)) { + return AV_SCREEN_CAPTURE_ERR_NO_MEMORY; + } + return AV_SCREEN_CAPTURE_ERR_OK; +} + OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetScreenCanvasRotation(struct OH_AVScreenCapture *capture, bool canvasRotation) { diff --git a/frameworks/native/screen_capture/screen_capture_impl.cpp b/frameworks/native/screen_capture/screen_capture_impl.cpp index b71fb9128..03fd3abb0 100644 --- a/frameworks/native/screen_capture/screen_capture_impl.cpp +++ b/frameworks/native/screen_capture/screen_capture_impl.cpp @@ -76,13 +76,32 @@ int32_t ScreenCaptureImpl::Release() return MSERR_OK; } -bool ScreenCaptureImpl::NeedStartInnerAudio(AudioCaptureSourceType type) +int32_t ScreenCaptureImpl::ExcludeContent(ScreenCaptureContentFilter &contentFilter) { - if ((type == ALL_PLAYBACK) || (type == APP_PLAYBACK)) { - return true; - } - MEDIA_LOGI("No need start inner audiocapture"); - return false; + MEDIA_LOGD("ScreenCaptureImpl:0x%{public}06" PRIXPTR " ExcludeContent in", FAKE_POINTER(this)); + CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_NO_MEMORY, + "screen capture service does not exist.."); + return screenCaptureService_->ExcludeContent(contentFilter); +} + +int32_t ScreenCaptureImpl::SetPrivacyAuthorityEnabled() +{ + CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_NO_MEMORY, + "screen capture service does not exist.."); + isPrivacyAuthorityEnabled_ = true; + MEDIA_LOGI("ScreenCaptureImpl:0x%{public}06" PRIXPTR " isPrivacyAuthorityEnabled:%{public}d", + FAKE_POINTER(this), isPrivacyAuthorityEnabled_); + return MSERR_OK; +} + +bool ScreenCaptureImpl::IsAudioCapInfoIgnored(const AudioCaptureInfo &audioCapInfo) +{ + return audioCapInfo.audioChannels == 0 && audioCapInfo.audioSampleRate == 0; +} + +bool ScreenCaptureImpl::IsVideoCapInfoIgnored(const VideoCaptureInfo &videoCapInfo) +{ + return videoCapInfo.videoFrameWidth == 0 && videoCapInfo.videoFrameHeight == 0; } int32_t ScreenCaptureImpl::SetMicrophoneEnabled(bool isMicrophone) @@ -138,24 +157,34 @@ int32_t ScreenCaptureImpl::Init(AVScreenCaptureConfig config) int32_t ScreenCaptureImpl::InitOriginalStream(AVScreenCaptureConfig config) { - CHECK_AND_RETURN_RET_LOG(config.audioInfo.micCapInfo.audioSource == AudioCaptureSourceType::SOURCE_DEFAULT || - config.audioInfo.micCapInfo.audioSource == AudioCaptureSourceType::MIC, MSERR_INVALID_VAL, - "audioSource source type error"); + // For original stream: + // 1. Any of innerCapInfo/videoCapInfo should be not invalid and should not be both ignored + // 2. micCapInfo should not be invalid int32_t ret = MSERR_OK; - ret = screenCaptureService_->InitAudioCap(config.audioInfo.micCapInfo); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "initMicAudioCap failed"); - ret = screenCaptureService_->InitVideoCap(config.videoInfo.videoCapInfo); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "initVideoCap failed"); - - if (NeedStartInnerAudio(config.audioInfo.innerCapInfo.audioSource)) { + bool isInnerAudioCapInfoIgnored = IsAudioCapInfoIgnored(config.audioInfo.innerCapInfo); + bool isVideoCapInfoIgnored = IsVideoCapInfoIgnored(config.videoInfo.videoCapInfo); + CHECK_AND_RETURN_RET_LOG(!(isInnerAudioCapInfoIgnored && isVideoCapInfoIgnored), MSERR_INVALID_VAL, + "init cap failed, both innerAudioCap and videoCap Info ignored is not allowed"); + if (!isInnerAudioCapInfoIgnored) { ret = screenCaptureService_->InitAudioCap(config.audioInfo.innerCapInfo); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "initInnerAudioCap failed"); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "init innerAudioCap failed"); + } + if (!isVideoCapInfoIgnored) { + ret = screenCaptureService_->InitVideoCap(config.videoInfo.videoCapInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "init videoCap failed"); + } + if (!IsAudioCapInfoIgnored(config.audioInfo.micCapInfo)) { + ret = screenCaptureService_->InitAudioCap(config.audioInfo.micCapInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "init micAudioCap failed"); } return ret; } int32_t ScreenCaptureImpl::InitCaptureFile(AVScreenCaptureConfig config) { + // For capture file: + // 1. All of innerCapInfo/videoCapInfo/audioEncInfo/videoEncInfo should be be valid + // 2. micCapInfo should not be invalid int32_t ret = MSERR_OK; ret = screenCaptureService_->SetRecorderInfo(config.recorderInfo); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetRecorderInfo failed"); @@ -171,24 +200,23 @@ int32_t ScreenCaptureImpl::InitCaptureFile(AVScreenCaptureConfig config) CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetOutputFile failed"); ret = screenCaptureService_->InitAudioEncInfo(config.audioInfo.audioEncInfo); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitAudioEncInfo failed"); - int32_t retMic = MSERR_OK; - int32_t retInner = MSERR_OK; - AudioCaptureSourceType type = config.audioInfo.micCapInfo.audioSource; - if (type == AudioCaptureSourceType::SOURCE_DEFAULT || type == AudioCaptureSourceType::MIC) { - config.audioInfo.micCapInfo.audioSource = AudioCaptureSourceType::MIC; - retMic = screenCaptureService_->InitAudioCap(config.audioInfo.micCapInfo); - } else { - return MSERR_INVALID_VAL; - } - type = config.audioInfo.innerCapInfo.audioSource; - if (type == AudioCaptureSourceType::ALL_PLAYBACK || type == AudioCaptureSourceType::APP_PLAYBACK) { - retInner = screenCaptureService_->InitAudioCap(config.audioInfo.innerCapInfo); - } else if (type == AudioCaptureSourceType::SOURCE_DEFAULT) { - retInner = MSERR_INVALID_VAL; - } else { - return MSERR_INVALID_VAL; + + bool isInnerAudioCapInfoIgnored = IsAudioCapInfoIgnored(config.audioInfo.innerCapInfo); + CHECK_AND_RETURN_RET_LOG(!isInnerAudioCapInfoIgnored, MSERR_INVALID_VAL, + "init innerCapInfo failed, innerCapInfo ignored is now allowed"); + bool isMicAudioCapInfoIgnored = IsAudioCapInfoIgnored(config.audioInfo.micCapInfo); + if (!isMicAudioCapInfoIgnored) { + if ((config.audioInfo.micCapInfo.audioChannels != config.audioInfo.innerCapInfo.audioChannels) || + (config.audioInfo.micCapInfo.audioSampleRate != config.audioInfo.innerCapInfo.audioSampleRate)) { + MEDIA_LOGE("InitCaptureFile error, inner and mic param not consistent"); + return MSERR_INVALID_VAL; + } + ret = screenCaptureService_->InitAudioCap(config.audioInfo.micCapInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "init micAudioCap failed"); } - CHECK_AND_RETURN_RET_LOG(retMic == MSERR_OK || retInner == MSERR_OK, MSERR_INVALID_VAL, "InitAudioCap failed"); + ret = screenCaptureService_->InitAudioCap(config.audioInfo.innerCapInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "init innerCapInfo failed, innerCapInfo should be valid"); + ret = screenCaptureService_->InitVideoEncInfo(config.videoInfo.videoEncInfo); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitVideoEncInfo failed"); ret = screenCaptureService_->InitVideoCap(config.videoInfo.videoCapInfo); @@ -202,7 +230,7 @@ int32_t ScreenCaptureImpl::StartScreenCapture() CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_UNKNOWN, "screen capture service does not exist.."); if (dataType_ == ORIGINAL_STREAM) { - return screenCaptureService_->StartScreenCapture(); + return screenCaptureService_->StartScreenCapture(isPrivacyAuthorityEnabled_); } else { MEDIA_LOGE("ScreenCaptureImpl::StartScreenCapture error , dataType_ : %{public}d", dataType_); return MSERR_INVALID_VAL; @@ -216,7 +244,7 @@ int32_t ScreenCaptureImpl::StartScreenCaptureWithSurface(sptr surface) "screen capture service does not exist.."); CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_UNKNOWN, "surface is nullptr"); if (dataType_ == ORIGINAL_STREAM) { - return screenCaptureService_->StartScreenCaptureWithSurface(surface); + return screenCaptureService_->StartScreenCaptureWithSurface(surface, isPrivacyAuthorityEnabled_); } else { MEDIA_LOGE("ScreenCaptureImpl::StartScreenCapture error , dataType_ : %{public}d", dataType_); return MSERR_INVALID_VAL; @@ -229,6 +257,7 @@ int32_t ScreenCaptureImpl::StopScreenCapture() CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_UNKNOWN, "screen capture service does not exist.."); if (dataType_ == ORIGINAL_STREAM) { + isPrivacyAuthorityEnabled_ = false; return screenCaptureService_->StopScreenCapture(); } else { MEDIA_LOGE("ScreenCaptureImpl::StopScreenCapture error , dataType_ : %{public}d", dataType_); @@ -242,7 +271,7 @@ int32_t ScreenCaptureImpl::StartScreenRecording() CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_UNKNOWN, "screen capture service does not exist.."); if (dataType_ == CAPTURE_FILE) { - return screenCaptureService_->StartScreenCapture(); + return screenCaptureService_->StartScreenCapture(isPrivacyAuthorityEnabled_); } else { MEDIA_LOGE("ScreenCaptureImpl::StartScreenRecording error , dataType_ : %{public}d", dataType_); return MSERR_INVALID_VAL; @@ -255,6 +284,7 @@ int32_t ScreenCaptureImpl::StopScreenRecording() CHECK_AND_RETURN_RET_LOG(screenCaptureService_ != nullptr, MSERR_UNKNOWN, "screen capture service does not exist.."); if (dataType_ == CAPTURE_FILE) { + isPrivacyAuthorityEnabled_ = false; return screenCaptureService_->StopScreenCapture(); } else { MEDIA_LOGE("ScreenCaptureImpl::StopScreenRecording error , dataType_ : %{public}d", dataType_); diff --git a/frameworks/native/screen_capture/screen_capture_impl.h b/frameworks/native/screen_capture/screen_capture_impl.h index 208f9fe42..272a4a845 100644 --- a/frameworks/native/screen_capture/screen_capture_impl.h +++ b/frameworks/native/screen_capture/screen_capture_impl.h @@ -42,13 +42,17 @@ public: int32_t ReleaseVideoBuffer() override; int32_t Release() override; int32_t SetScreenCaptureCallback(const std::shared_ptr &callback) override; + int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) override; + int32_t SetPrivacyAuthorityEnabled() override; private: - bool NeedStartInnerAudio(AudioCaptureSourceType type); + bool IsAudioCapInfoIgnored(const AudioCaptureInfo &audioCapInfo); + bool IsVideoCapInfoIgnored(const VideoCaptureInfo &videoCapInfo); int32_t InitOriginalStream(AVScreenCaptureConfig config); int32_t InitCaptureFile(AVScreenCaptureConfig config); std::shared_ptr screenCaptureService_ = nullptr; DataType dataType_; + bool isPrivacyAuthorityEnabled_ = false; }; } // namespace Media } // namespace OHOS diff --git a/interfaces/inner_api/native/screen_capture.h b/interfaces/inner_api/native/screen_capture.h index 124eb66ef..998be96be 100644 --- a/interfaces/inner_api/native/screen_capture.h +++ b/interfaces/inner_api/native/screen_capture.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "avcodec_info.h" #include "surface.h" #include "recorder.h" @@ -42,6 +43,21 @@ enum ScreenCaptureErrorType : int32_t { SCREEN_CAPTURE_ERROR_EXTEND_START = 0X10000, }; +enum AVScreenCaptureErrorCode { + SCREEN_CAPTURE_ERR_BASE = 0, + SCREEN_CAPTURE_ERR_OK = SCREEN_CAPTURE_ERR_BASE, + SCREEN_CAPTURE_ERR_NO_MEMORY = SCREEN_CAPTURE_ERR_BASE + 1, + SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT = SCREEN_CAPTURE_ERR_BASE + 2, + SCREEN_CAPTURE_ERR_INVALID_VAL = SCREEN_CAPTURE_ERR_BASE + 3, + SCREEN_CAPTURE_ERR_IO = SCREEN_CAPTURE_ERR_BASE + 4, + SCREEN_CAPTURE_ERR_TIMEOUT = SCREEN_CAPTURE_ERR_BASE + 5, + SCREEN_CAPTURE_ERR_UNKNOWN = SCREEN_CAPTURE_ERR_BASE + 6, + SCREEN_CAPTURE_ERR_SERVICE_DIED = SCREEN_CAPTURE_ERR_BASE + 7, + SCREEN_CAPTURE_ERR_INVALID_STATE = SCREEN_CAPTURE_ERR_BASE + 8, + SCREEN_CAPTURE_ERR_UNSUPPORT = SCREEN_CAPTURE_ERR_BASE + 9, + SCREEN_CAPTURE_ERR_EXTEND_START = SCREEN_CAPTURE_ERR_BASE + 100, +}; + enum AudioCaptureSourceType : int32_t { /** Invalid audio source */ SOURCE_INVALID = -1, @@ -73,6 +89,8 @@ enum CaptureMode : int32_t { }; enum AVScreenCaptureStateCode { + /* Screen capture state INVALID */ + SCREEN_CAPTURE_STATE_INVLID = -1, /* Screen capture started by user */ SCREEN_CAPTURE_STATE_STARTED = 0, /* Screen capture canceled by user */ @@ -95,15 +113,41 @@ enum AVScreenCaptureStateCode { SCREEN_CAPTURE_STATE_EXIT_PRIVATE_SCENE = 9, }; +enum AVScreenCaptureBufferType { + /* Buffer of video data from screen */ + SCREEN_CAPTURE_BUFFERTYPE_VIDEO = 0, + /* Buffer of audio data from inner capture */ + SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER = 1, + /* Buffer of audio data from microphone */ + SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC = 2, +}; + +enum AVScreenCaptureFilterableAudioContent { + /* Audio content of notification sound */ + SCREEN_CAPTURE_NOTIFICATION_AUDIO = 0, +}; + +enum AVScreenCaptureParamValidationState : int32_t { + VALIDATION_IGNORE, + VALIDATION_VALID, + VALIDATION_INVALID, +}; + +struct ScreenCaptureContentFilter { + std::set filteredAudioContents; +}; + struct AudioCaptureInfo { - int32_t audioSampleRate; - int32_t audioChannels; - AudioCaptureSourceType audioSource; + int32_t audioSampleRate = 0; + int32_t audioChannels = 0; + AudioCaptureSourceType audioSource = AudioCaptureSourceType::SOURCE_DEFAULT; + AVScreenCaptureParamValidationState state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; }; struct AudioEncInfo { - int32_t audioBitrate; - AudioCodecFormat audioCodecformat; + int32_t audioBitrate = 0; + AudioCodecFormat audioCodecformat = AudioCodecFormat::AUDIO_CODEC_FORMAT_BUTT; + AVScreenCaptureParamValidationState state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; }; struct AudioInfo { @@ -113,17 +157,19 @@ struct AudioInfo { }; struct VideoCaptureInfo { - uint64_t displayId; + uint64_t displayId = -1; std::list taskIDs; - int32_t videoFrameWidth; - int32_t videoFrameHeight; - VideoSourceType videoSource; + int32_t videoFrameWidth = 0; + int32_t videoFrameHeight = 0; + VideoSourceType videoSource = VideoSourceType::VIDEO_SOURCE_BUTT; + AVScreenCaptureParamValidationState state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; }; struct VideoEncInfo { - VideoCodecFormat videoCodec; - int32_t videoBitrate; - int32_t videoFrameRate; + VideoCodecFormat videoCodec = VideoCodecFormat::VIDEO_CODEC_FORMAT_BUTT; + int32_t videoBitrate = 0; + int32_t videoFrameRate = 0; + AVScreenCaptureParamValidationState state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; }; struct VideoInfo { @@ -137,8 +183,8 @@ struct RecorderInfo { }; struct AVScreenCaptureConfig { - CaptureMode captureMode; - DataType dataType; + CaptureMode captureMode = CaptureMode::CAPTURE_INVAILD; + DataType dataType = DataType::INVAILD; AudioInfo audioInfo; VideoInfo videoInfo; RecorderInfo recorderInfo; @@ -206,6 +252,8 @@ public: virtual int32_t ReleaseVideoBuffer() = 0; virtual int32_t Release() = 0; virtual int32_t SetScreenCaptureCallback(const std::shared_ptr &callback) = 0; + virtual int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) = 0; + virtual int32_t SetPrivacyAuthorityEnabled() = 0; }; class __attribute__((visibility("default"))) ScreenCaptureFactory { diff --git a/interfaces/kits/c/BUILD.gn b/interfaces/kits/c/BUILD.gn index 8d957f1bd..834433292 100644 --- a/interfaces/kits/c/BUILD.gn +++ b/interfaces/kits/c/BUILD.gn @@ -80,6 +80,7 @@ ohos_shared_library("native_avscreen_capture") { "c_utils:utils", "graphic_surface:surface", "hilog:libhilog", + "media_foundation:media_foundation", "qos_manager:qos", "window_manager:libdm", ] diff --git a/interfaces/kits/c/avscreen_capture/libnative_avscreen_capture.ndk.json b/interfaces/kits/c/avscreen_capture/libnative_avscreen_capture.ndk.json index 08082214b..8d3405ddf 100644 --- a/interfaces/kits/c/avscreen_capture/libnative_avscreen_capture.ndk.json +++ b/interfaces/kits/c/avscreen_capture/libnative_avscreen_capture.ndk.json @@ -13,5 +13,12 @@ { "name": "OH_AVScreenCapture_SetCallback" }, { "name": "OH_AVScreenCapture_Release" }, { "name": "OH_AVScreenCapture_SetMicrophoneEnabled" }, - { "name": "OH_AVScreenCapture_SetScreenCanvasRotation" } + { "name": "OH_AVScreenCapture_SetScreenCanvasRotation" }, + { "name": "OH_AVScreenCapture_SetStateCallback" }, + { "name": "OH_AVScreenCapture_SetDataCallback" }, + { "name": "OH_AVScreenCapture_SetErrorCallback" }, + { "name": "OH_AVScreenCapture_CreateContentFilter" }, + { "name": "OH_AVScreenCapture_ReleaseContentFilter" }, + { "name": "OH_AVScreenCapture_ContentFilter_AddAudioContent" }, + { "name": "OH_AVScreenCapture_ExcludeContent" } ] \ No newline at end of file diff --git a/interfaces/kits/c/native_avscreen_capture.h b/interfaces/kits/c/native_avscreen_capture.h index 678771f39..95f079a61 100644 --- a/interfaces/kits/c/native_avscreen_capture.h +++ b/interfaces/kits/c/native_avscreen_capture.h @@ -42,7 +42,7 @@ struct OH_AVScreenCapture *OH_AVScreenCapture_Create(void); * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance * @param config Information describing the audio and video config - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -54,8 +54,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_Init(struct OH_AVScreenCapture *c * @brief Start the av screen capture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @param type Information describing the data type of the capture - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -67,7 +66,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenCapture(struct OH_AVSc * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance * @param window Pointer to an OHNativeWindow instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 12 * @version 1.0 @@ -79,7 +78,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenCaptureWithSurface(str * @brief Stop the av screen capture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -90,7 +89,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StopScreenCapture(struct OH_AVScr * @brief Start av screen record use to start save screen record file. * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -101,7 +100,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StartScreenRecording(struct OH_AV * @brief Start av screen record use to stop save screen record file. * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -114,8 +113,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_StopScreenRecording(struct OH_AVS * @param capture Pointer to an OH_AVScreenCapture instance * @param audiobuffer Information describing the audio buffer of the capture * @param type Information describing the audio source type - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -130,6 +131,8 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_AcquireAudioBuffer(struct OH_AVSc * @param timestamp Information about the video buffer * @param region Information about the video buffer * @return Returns a pointer to an OH_NativeBuffer instance + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -141,8 +144,10 @@ OH_NativeBuffer* OH_AVScreenCapture_AcquireVideoBuffer(struct OH_AVScreenCapture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance * @param type Information describing the audio source type - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -153,8 +158,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseAudioBuffer(struct OH_AVSc * @brief Release the video buffer for the av screen capture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -166,8 +173,10 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseVideoBuffer(struct OH_AVSc * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance * @param callback A collection of all callback functions, see {@link OH_AVScreenCaptureCallback} - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_SetErrorCallback} {@link OH_AVScreenCapture_SetDataCallback} * @since 10 * @version 1.0 */ @@ -178,7 +187,7 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetCallback(struct OH_AVScreenCap * @brief Release the av screen capture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 @@ -190,13 +199,57 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_Release(struct OH_AVScreenCapture * @syscap SystemCapability.Multimedia.Media.AVScreenCapture * @param capture Pointer to an OH_AVScreenCapture instance * @param isMicrophone The switch of the microphone - * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} * @since 10 * @version 1.0 */ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetMicrophoneEnabled(struct OH_AVScreenCapture *capture, bool isMicrophone); +/** + * @brief Set the state callback function so that your application can respond to the + * state change events generated by the av screen capture. This interface must be called before Start is called. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param callback State callback function, see {@link OH_AVScreenCapture_OnStateChange} + * @param userData Pointer to user specific data + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetStateCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnStateChange callback, void *userData); + +/** + * @brief Set the data callback function so that your application can respond to the + * data available events generated by the av screen capture. This interface must be called before Start is called. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param callback Data callback function, see {@link OH_AVScreenCapture_OnBufferAvailable} + * @param userData Pointer to user specific data + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetDataCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnBufferAvailable callback, void *userData); + +/** + * @brief Set the error callback function so that your application can respond to the + * error events generated by the av screen capture. This interface must be called before Start is called. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param callback Error callback function, see {@link OH_AVScreenCapture_OnError} + * @param userData Pointer to user specific data + * @return Returns AV_SCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetErrorCallback(struct OH_AVScreenCapture *capture, + OH_AVScreenCapture_OnError callback, void *userData); /** * @brief Controls the Rotation of the Screen, which is no rotate by default @@ -210,6 +263,53 @@ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetMicrophoneEnabled(struct OH_AV */ OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_SetScreenCanvasRotation(struct OH_AVScreenCapture *capture, bool canvasRotation); + +/** + * @brief Create a screen capture content filter + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @return Returns a pointer to an OH_AVScreenCapture_ContentFilter instance + * @since 12 + * @version 1.0 + */ +struct OH_AVScreenCapture_ContentFilter *OH_AVScreenCapture_CreateContentFilter(void); + +/** + * @brief Release the screen capture content filter + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param filter Pointer to an OH_AVScreenCapture_ContentFilter instance + * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ReleaseContentFilter(struct OH_AVScreenCapture_ContentFilter *filter); + +/** + * @brief Add content to the screen capture content filter + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param filter Pointer to an OH_AVScreenCapture_ContentFilter instance + * @param content content to be added + * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ContentFilter_AddAudioContent( + struct OH_AVScreenCapture_ContentFilter *filter, OH_AVScreenCaptureFilterableAudioContent content); + +/** + * @brief Set content filter to screen capture + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param filter Pointer to an OH_AVScreenCapture_ContentFilter instance + * @return Returns AVSCREEN_CAPTURE_ERR_OK if the execution is successful, + * otherwise returns a specific error code, refer to {@link OH_AVSCREEN_CAPTURE_ErrCode} + * @since 12 + * @version 1.0 + */ +OH_AVSCREEN_CAPTURE_ErrCode OH_AVScreenCapture_ExcludeContent(struct OH_AVScreenCapture *capture, + struct OH_AVScreenCapture_ContentFilter *filter); + #ifdef __cplusplus } #endif diff --git a/interfaces/kits/c/native_avscreen_capture_base.h b/interfaces/kits/c/native_avscreen_capture_base.h index 292aa8613..2f3ed120f 100644 --- a/interfaces/kits/c/native_avscreen_capture_base.h +++ b/interfaces/kits/c/native_avscreen_capture_base.h @@ -17,6 +17,7 @@ #define NATIVE_AVSCREEN_CAPTURE_BASE_H #include +#include "native_avbuffer.h" #ifdef __cplusplus extern "C" { @@ -40,6 +41,15 @@ typedef struct OH_NativeBuffer OH_NativeBuffer; */ typedef struct OH_AVScreenCapture OH_AVScreenCapture; +/** + * @brief Initialization of OH_AVScreenCapture_ContentFilter + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * + * @since 12 + * @version 1.0 + */ +typedef struct OH_AVScreenCapture_ContentFilter OH_AVScreenCapture_ContentFilter; + /** * @brief Enumerates screen capture mode. * @syscap SystemCapability.Multimedia.Media.AVScreenCapture @@ -303,6 +313,8 @@ typedef struct OH_AVScreenCaptureConfig { * @param capture Pointer to an OH_AVScreenCapture instance * @param errorCode specific error code * + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnError} * @since 10 * @version 1.0 */ @@ -316,6 +328,8 @@ typedef void (*OH_AVScreenCaptureOnError)(OH_AVScreenCapture *capture, int32_t e * @param isReady Information describing whether audio buffer is available * @param type Information describing the audio source type * + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -329,6 +343,8 @@ typedef void (*OH_AVScreenCaptureOnAudioBufferAvailable)(OH_AVScreenCapture *cap * @param capture Pointer to an OH_AVScreenCapture instance * @param isReady Information describing whether video buffer is available * + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ @@ -343,12 +359,26 @@ typedef void (*OH_AVScreenCaptureOnVideoBufferAvailable)(OH_AVScreenCapture *cap * @param onAudioBufferAvailable Monitor audio buffer, refer to {@link OH_AVScreenCaptureOnAudioBufferAvailable} * @param onVideoBufferAvailable Monitor video buffer, refer to {@link OH_AVScreenCaptureOnVideoBufferAvailable} * + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnError} {@link OH_AVScreenCapture_OnBufferAvailable} * @since 10 * @version 1.0 */ typedef struct OH_AVScreenCaptureCallback { + /** + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnError} + */ OH_AVScreenCaptureOnError onError; + /** + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} + */ OH_AVScreenCaptureOnAudioBufferAvailable onAudioBufferAvailable; + /** + * @deprecated since 12 + * @useinstead {@link OH_AVScreenCapture_OnBufferAvailable} + */ OH_AVScreenCaptureOnVideoBufferAvailable onVideoBufferAvailable; } OH_AVScreenCaptureCallback; @@ -389,6 +419,104 @@ typedef struct OH_AudioBuffer { OH_AudioCaptureSourceType type; } OH_AudioBuffer; +/** + * @brief Enumerates screen capture state code. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * + * @since 12 + * @version 1.0 + */ +typedef enum OH_AVScreenCaptureStateCode { + /* Screen capture started by user */ + OH_SCREEN_CAPTURE_STATE_STARTED = 0, + /* Screen capture canceled by user */ + OH_SCREEN_CAPTURE_STATE_CANCELED = 1, + /* ScreenCapture stopped by user */ + OH_SCREEN_CAPTURE_STATE_STOPPED_BY_USER = 2, + /* ScreenCapture interrupted by other screen capture */ + OH_SCREEN_CAPTURE_STATE_STOPPED_BY_INTERRUPT = 3, + /* ScreenCapture stopped by SIM call */ + OH_SCREEN_CAPTURE_STATE_STOPPED_BY_INCALL = 4, + /* Microphone is temporarily unavailable */ + OH_SCREEN_CAPTURE_STATE_MIC_UNAVAILABLE = 5, + /* Microphone is muted by user */ + OH_SCREEN_CAPTURE_STATE_MIC_MUTED_BY_USER = 6, + /* Microphone is unmuted by user */ + OH_SCREEN_CAPTURE_STATE_MIC_UNMUTED_BY_BSER = 7, + /* Current captured screen has private window */ + OH_SCREEN_CAPTURE_STATE_ENTER_PRIVATE_SCENE = 8, + /* Private window disappeared on current captured screen*/ + OH_SCREEN_CAPTURE_STATE_EXIT_PRIVATE_SCENE = 9, +} OH_AVScreenCaptureStateCode; + +/** + * @brief Enumerates screen capture buffer type. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * + * @since 12 + * @version 1.0 + */ +typedef enum OH_AVScreenCaptureBufferType { + /* Buffer of video data from screen */ + OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO = 0, + /* Buffer of audio data from inner capture */ + OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER = 1, + /* Buffer of audio data from microphone */ + OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC = 2, +} OH_AVScreenCaptureBufferType; + +/** + * @brief Enumerates screen capture filterable audio content. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * + * @since 12 + * @version 1.0 + */ +typedef enum OH_AVScreenCaptureFilterableAudioContent { + /* Audio content of notification sound */ + OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO = 0, +} OH_AVScreenCaptureFilterableAudioContent; + +/** + * @brief When state of OH_AVScreenCapture is changed, the function pointer will be called. + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param stateCode Information describing current state, see {@link OH_AVScreenCaptureStateCode} + * @param userData Pointer to user specific data + * + * @since 12 + * @version 1.0 + */ +typedef void (*OH_AVScreenCapture_OnStateChange)(struct OH_AVScreenCapture *capture, + OH_AVScreenCaptureStateCode stateCode, void *userData); + +/** + * @brief When an error occurs in the running of the OH_AVScreenCapture instance, the function pointer will be called + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param errorCode specific error code + * @param userData Pointer to user specific data + * + * @since 12 + * @version 1.0 + */ +typedef void (*OH_AVScreenCapture_OnError)(OH_AVScreenCapture *capture, int32_t errorCode, void *userData); + +/** + * @brief When data is ready from the OH_AVScreenCapture instance, the function pointer will be called + * @syscap SystemCapability.Multimedia.Media.AVScreenCapture + * @param capture Pointer to an OH_AVScreenCapture instance + * @param buffer Pointer to a buffer containing media data + * @param bufferType Data type of the buffer, see {@link OH_AVScreenCaptureBufferType} + * @param timestamp Timestamp of the buffer + * @param userData Pointer to user specific data + * + * @since 12 + * @version 1.0 + */ +typedef void (*OH_AVScreenCapture_OnBufferAvailable)(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, + OH_AVScreenCaptureBufferType bufferType, int64_t timestamp, void *userData); + #ifdef __cplusplus } #endif diff --git a/services/include/i_screen_capture_service.h b/services/include/i_screen_capture_service.h index d76550602..659112ff8 100644 --- a/services/include/i_screen_capture_service.h +++ b/services/include/i_screen_capture_service.h @@ -37,8 +37,8 @@ public: virtual int32_t InitAudioCap(AudioCaptureInfo audioInfo) = 0; virtual int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) = 0; virtual int32_t InitVideoCap(VideoCaptureInfo videoInfo) = 0; - virtual int32_t StartScreenCapture() = 0; - virtual int32_t StartScreenCaptureWithSurface(sptr surface) = 0; + virtual int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled = false) = 0; + virtual int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled = false) = 0; virtual int32_t StopScreenCapture() = 0; virtual int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) = 0; virtual int32_t AcquireVideoBuffer(sptr &surfacebuffer, int32_t &fence, @@ -49,6 +49,7 @@ public: virtual int32_t SetScreenCanvasRotation(bool canvasRotation) = 0; virtual int32_t SetScreenCaptureCallback(const std::shared_ptr &callback) = 0; virtual void Release() = 0; + virtual int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) = 0; }; } // namespace Media } // namespace OHOS diff --git a/services/services/BUILD.gn b/services/services/BUILD.gn index 478864d25..63890d07a 100644 --- a/services/services/BUILD.gn +++ b/services/services/BUILD.gn @@ -171,6 +171,7 @@ ohos_shared_library("media_service") { "screen_capture/ipc/screen_capture_controller_stub.cpp", "screen_capture/ipc/screen_capture_listener_proxy.cpp", "screen_capture/ipc/screen_capture_service_stub.cpp", + "screen_capture/server/audio_capturer_wrapper.cpp", "screen_capture/server/screen_capture_controller_server.cpp", "screen_capture/server/screen_capture_server.cpp", "screen_capture/server/ui_extension_ability_connection.cpp", diff --git a/services/services/screen_capture/client/screen_capture_client.cpp b/services/services/screen_capture/client/screen_capture_client.cpp index 51ab63e06..0d2381880 100644 --- a/services/services/screen_capture/client/screen_capture_client.cpp +++ b/services/services/screen_capture/client/screen_capture_client.cpp @@ -149,6 +149,13 @@ int32_t ScreenCaptureClient::InitVideoCap(VideoCaptureInfo videoInfo) return screenCaptureProxy_->InitVideoCap(videoInfo); } +int32_t ScreenCaptureClient::ExcludeContent(ScreenCaptureContentFilter &contentFilter) +{ + std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(screenCaptureProxy_ != nullptr, MSERR_NO_MEMORY, "screenCapture service does not exist."); + return screenCaptureProxy_->ExcludeContent(contentFilter); +} + int32_t ScreenCaptureClient::SetMicrophoneEnabled(bool isMicrophone) { std::lock_guard lock(mutex_); @@ -163,18 +170,18 @@ int32_t ScreenCaptureClient::SetScreenCanvasRotation(bool canvasRotation) return screenCaptureProxy_->SetScreenCanvasRotation(canvasRotation); } -int32_t ScreenCaptureClient::StartScreenCapture() +int32_t ScreenCaptureClient::StartScreenCapture(bool isPrivacyAuthorityEnabled) { std::lock_guard lock(mutex_); CHECK_AND_RETURN_RET_LOG(screenCaptureProxy_ != nullptr, MSERR_NO_MEMORY, "screenCapture service does not exist."); - return screenCaptureProxy_->StartScreenCapture(); + return screenCaptureProxy_->StartScreenCapture(isPrivacyAuthorityEnabled); } -int32_t ScreenCaptureClient::StartScreenCaptureWithSurface(sptr surface) +int32_t ScreenCaptureClient::StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) { std::lock_guard lock(mutex_); CHECK_AND_RETURN_RET_LOG(screenCaptureProxy_ != nullptr, MSERR_NO_MEMORY, "screenCapture service does not exist."); - return screenCaptureProxy_->StartScreenCaptureWithSurface(surface); + return screenCaptureProxy_->StartScreenCaptureWithSurface(surface, isPrivacyAuthorityEnabled); } diff --git a/services/services/screen_capture/client/screen_capture_client.h b/services/services/screen_capture/client/screen_capture_client.h index 4940586a4..f1ac21560 100644 --- a/services/services/screen_capture/client/screen_capture_client.h +++ b/services/services/screen_capture/client/screen_capture_client.h @@ -39,8 +39,8 @@ public: int32_t InitAudioCap(AudioCaptureInfo audioInfo) override; int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) override; int32_t InitVideoCap(VideoCaptureInfo videoInfo) override; - int32_t StartScreenCapture() override; - int32_t StartScreenCaptureWithSurface(sptr surface) override; + int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled) override; + int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) override; int32_t StopScreenCapture() override; int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) override; int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, @@ -51,6 +51,7 @@ public: int32_t SetScreenCanvasRotation(bool canvasRotation) override; int32_t SetScreenCaptureCallback(const std::shared_ptr &callback) override; void Release() override; + int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) override; private: sptr screenCaptureProxy_ = nullptr; diff --git a/services/services/screen_capture/ipc/i_standard_screen_capture_listener.h b/services/services/screen_capture/ipc/i_standard_screen_capture_listener.h index 790ca4393..5c66095e5 100644 --- a/services/services/screen_capture/ipc/i_standard_screen_capture_listener.h +++ b/services/services/screen_capture/ipc/i_standard_screen_capture_listener.h @@ -27,16 +27,18 @@ namespace Media { class IStandardScreenCaptureListener : public IRemoteBroker { public: virtual ~IStandardScreenCaptureListener() = default; - virtual void OnError(int32_t errorType, int32_t errorCode) = 0; + virtual void OnError(ScreenCaptureErrorType errorType, int32_t errorCode) = 0; virtual void OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) = 0; virtual void OnVideoBufferAvailable(bool isReady) = 0; + virtual void OnStateChange(AVScreenCaptureStateCode stateCode) = 0; /** * IPC code ID */ enum ScreenCaptureListenerMsg { ON_ERROR = 0, ON_AUDIO_AVAILABLE = 1, - ON_VIDEO_AVAILABLE = 2 + ON_VIDEO_AVAILABLE = 2, + ON_STAGE_CHANGE = 3 }; DECLARE_INTERFACE_DESCRIPTOR(u"IStandardScreenCaptureListener"); diff --git a/services/services/screen_capture/ipc/i_standard_screen_capture_service.h b/services/services/screen_capture/ipc/i_standard_screen_capture_service.h index a15f01c7d..3bf9c87e1 100644 --- a/services/services/screen_capture/ipc/i_standard_screen_capture_service.h +++ b/services/services/screen_capture/ipc/i_standard_screen_capture_service.h @@ -40,8 +40,8 @@ public: virtual int32_t InitAudioCap(AudioCaptureInfo audioInfo) = 0; virtual int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) = 0; virtual int32_t InitVideoCap(VideoCaptureInfo videoInfo) = 0; - virtual int32_t StartScreenCapture() = 0; - virtual int32_t StartScreenCaptureWithSurface(sptr surface) = 0; + virtual int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled = false) = 0; + virtual int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled = false) = 0; virtual int32_t StopScreenCapture() = 0; virtual int32_t SetMicrophoneEnabled(bool isMicrophone) = 0; virtual int32_t SetScreenCanvasRotation(bool canvasRotation) = 0; @@ -51,31 +51,33 @@ public: int64_t ×tamp, OHOS::Rect &damage) = 0; virtual int32_t ReleaseAudioBuffer(AudioCaptureSourceType type) = 0; virtual int32_t ReleaseVideoBuffer() = 0; + virtual int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) = 0; /** * IPC code ID */ enum ScreenCaptureServiceMsg { - SET_LISTENER_OBJ, - RELEASE, - DESTROY, - SET_CAPTURE_MODE, - SET_DATA_TYPE, - SET_RECORDER_INFO, - SET_OUTPUT_FILE, - INIT_AUDIO_ENC_INFO, - INIT_AUDIO_CAP, - INIT_VIDEO_ENC_INFO, - INIT_VIDEO_CAP, - ACQUIRE_AUDIO_BUF, - ACQUIRE_VIDEO_BUF, - RELEASE_AUDIO_BUF, - RELEASE_VIDEO_BUF, - SET_MIC_ENABLE, - START_SCREEN_CAPTURE, - START_SCREEN_CAPTURE_WITH_SURFACE, - STOP_SCREEN_CAPTURE, - SET_SCREEN_ROTATION, + SET_LISTENER_OBJ = 0, + RELEASE = 1, + DESTROY = 2, + SET_CAPTURE_MODE = 3, + SET_DATA_TYPE = 4, + SET_RECORDER_INFO = 5, + SET_OUTPUT_FILE = 6, + INIT_AUDIO_ENC_INFO = 7, + INIT_AUDIO_CAP = 8, + INIT_VIDEO_ENC_INFO = 9, + INIT_VIDEO_CAP = 10, + ACQUIRE_AUDIO_BUF = 11, + ACQUIRE_VIDEO_BUF = 12, + RELEASE_AUDIO_BUF = 13, + RELEASE_VIDEO_BUF = 14, + SET_MIC_ENABLE = 15, + START_SCREEN_CAPTURE = 16, + START_SCREEN_CAPTURE_WITH_SURFACE = 17, + STOP_SCREEN_CAPTURE = 18, + SET_SCREEN_ROTATION = 19, + EXCLUDE_CONTENT = 20, }; DECLARE_INTERFACE_DESCRIPTOR(u"IStandardScreenCaptureService"); diff --git a/services/services/screen_capture/ipc/screen_capture_listener_proxy.cpp b/services/services/screen_capture/ipc/screen_capture_listener_proxy.cpp index 9fe842cfc..625e5e788 100644 --- a/services/services/screen_capture/ipc/screen_capture_listener_proxy.cpp +++ b/services/services/screen_capture/ipc/screen_capture_listener_proxy.cpp @@ -34,7 +34,7 @@ ScreenCaptureListenerProxy::~ScreenCaptureListenerProxy() MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this)); } -void ScreenCaptureListenerProxy::OnError(int32_t errorType, int32_t errorCode) +void ScreenCaptureListenerProxy::OnError(ScreenCaptureErrorType errorType, int32_t errorCode) { MessageParcel data; MessageParcel reply; @@ -78,6 +78,21 @@ void ScreenCaptureListenerProxy::OnVideoBufferAvailable(bool isReady) CHECK_AND_RETURN_LOG(error == MSERR_OK, "OnVideoBufferAvailable failed, error: %{public}d", error); } +void ScreenCaptureListenerProxy::OnStateChange(AVScreenCaptureStateCode stateCode) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + + bool token = data.WriteInterfaceToken(ScreenCaptureListenerProxy::GetDescriptor()); + CHECK_AND_RETURN_LOG(token, "Failed to write descriptor!"); + + data.WriteInt32(stateCode); + int error = Remote()->SendRequest(ScreenCaptureListenerMsg::ON_STAGE_CHANGE, data, reply, option); + CHECK_AND_RETURN_LOG(error == MSERR_OK, "OnStateChange failed, error: %{public}d, stateCode: %{public}d", + error, stateCode); +} + ScreenCaptureListenerCallback::ScreenCaptureListenerCallback(const sptr &listener) : listener_(listener) { @@ -91,6 +106,9 @@ ScreenCaptureListenerCallback::~ScreenCaptureListenerCallback() void ScreenCaptureListenerCallback::OnError(ScreenCaptureErrorType errorType, int32_t errorCode) { + MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances isStopped:%{public}d, errorType:%{public}d, errorCode:%{public}d", + FAKE_POINTER(this), isStopped_.load(), errorType, errorCode); + CHECK_AND_RETURN(isStopped_ == false); if (listener_ != nullptr) { listener_->OnError(errorType, errorCode); } @@ -98,6 +116,9 @@ void ScreenCaptureListenerCallback::OnError(ScreenCaptureErrorType errorType, in void ScreenCaptureListenerCallback::OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) { + MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances isStopped:%{public}d, isReady:%{public}d, type:%{public}d", + FAKE_POINTER(this), isStopped_.load(), isReady, type); + CHECK_AND_RETURN(isStopped_ == false); if (listener_ != nullptr) { listener_->OnAudioBufferAvailable(isReady, type); } @@ -105,9 +126,21 @@ void ScreenCaptureListenerCallback::OnAudioBufferAvailable(bool isReady, AudioCa void ScreenCaptureListenerCallback::OnVideoBufferAvailable(bool isReady) { + MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances isStopped:%{public}d, isReady:%{public}d", + FAKE_POINTER(this), isStopped_.load(), isReady); + CHECK_AND_RETURN(isStopped_ == false); if (listener_ != nullptr) { listener_->OnVideoBufferAvailable(isReady); } } + +void ScreenCaptureListenerCallback::OnStateChange(AVScreenCaptureStateCode stateCode) +{ + MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances isStopped:%{public}d, stateCode:%{public}d", + FAKE_POINTER(this), isStopped_.load(), stateCode); + if (listener_ != nullptr) { + listener_->OnStateChange(stateCode); + } +} } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/services/services/screen_capture/ipc/screen_capture_listener_proxy.h b/services/services/screen_capture/ipc/screen_capture_listener_proxy.h index 302d473d7..9a042dbf6 100644 --- a/services/services/screen_capture/ipc/screen_capture_listener_proxy.h +++ b/services/services/screen_capture/ipc/screen_capture_listener_proxy.h @@ -31,9 +31,15 @@ public: void OnError(ScreenCaptureErrorType errorType, int32_t errorCode) override; void OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) override; void OnVideoBufferAvailable(bool isReady) override; + void OnStateChange(AVScreenCaptureStateCode stateCode) override; + void Stop() + { + isStopped_ = true; + } private: sptr listener_ = nullptr; + std::atomic isStopped_ = false; }; class ScreenCaptureListenerProxy : public IRemoteProxy, public NoCopyable { @@ -41,9 +47,10 @@ public: explicit ScreenCaptureListenerProxy(const sptr &impl); virtual ~ScreenCaptureListenerProxy(); - void OnError(int32_t errorType, int32_t errorCode) override; + void OnError(ScreenCaptureErrorType errorType, int32_t errorCode) override; void OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) override; void OnVideoBufferAvailable(bool isReady) override; + void OnStateChange(AVScreenCaptureStateCode stateCode) override; private: static inline BrokerDelegator delegator_; diff --git a/services/services/screen_capture/ipc/screen_capture_listener_stub.cpp b/services/services/screen_capture/ipc/screen_capture_listener_stub.cpp index 2b4226d1f..65d89fb1d 100644 --- a/services/services/screen_capture/ipc/screen_capture_listener_stub.cpp +++ b/services/services/screen_capture/ipc/screen_capture_listener_stub.cpp @@ -54,12 +54,16 @@ int ScreenCaptureListenerStub::OnRemoteRequest(uint32_t code, MessageParcel &dat OnAudioBufferAvailable(isReady, type); return MSERR_OK; } - case ScreenCaptureListenerMsg::ON_VIDEO_AVAILABLE: { bool isReady = data.ReadBool(); OnVideoBufferAvailable(isReady); return MSERR_OK; } + case ScreenCaptureListenerMsg::ON_STAGE_CHANGE: { + AVScreenCaptureStateCode stateCode = static_cast(data.ReadInt32()); + OnStateChange(stateCode); + return MSERR_OK; + } default: { MEDIA_LOGE("default case, need check RecorderListenerStub"); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -67,10 +71,10 @@ int ScreenCaptureListenerStub::OnRemoteRequest(uint32_t code, MessageParcel &dat } } -void ScreenCaptureListenerStub::OnError(int32_t errorType, int32_t errorCode) +void ScreenCaptureListenerStub::OnError(ScreenCaptureErrorType errorType, int32_t errorCode) { if (callback_ != nullptr) { - callback_->OnError(static_cast(errorType), errorCode); + callback_->OnError(errorType, errorCode); } } @@ -92,5 +96,12 @@ void ScreenCaptureListenerStub::OnVideoBufferAvailable(bool isReady) callback_->OnVideoBufferAvailable(isReady); } } + +void ScreenCaptureListenerStub::OnStateChange(AVScreenCaptureStateCode stateCode) +{ + if (callback_ != nullptr) { + callback_->OnStateChange(stateCode); + } +} } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/services/services/screen_capture/ipc/screen_capture_listener_stub.h b/services/services/screen_capture/ipc/screen_capture_listener_stub.h index 0f42d05c2..684c115ca 100644 --- a/services/services/screen_capture/ipc/screen_capture_listener_stub.h +++ b/services/services/screen_capture/ipc/screen_capture_listener_stub.h @@ -26,9 +26,10 @@ public: ScreenCaptureListenerStub(); virtual ~ScreenCaptureListenerStub(); int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; - void OnError(int32_t errorType, int32_t errorCode) override; + void OnError(ScreenCaptureErrorType errorType, int32_t errorCode) override; void OnAudioBufferAvailable(bool isReady, AudioCaptureSourceType type) override; void OnVideoBufferAvailable(bool isReady) override; + void OnStateChange(AVScreenCaptureStateCode stateCode) override; void SetScreenCaptureCallback(const std::shared_ptr &callback); diff --git a/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp b/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp index 98c4db499..6541564ba 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp +++ b/services/services/screen_capture/ipc/screen_capture_service_proxy.cpp @@ -247,7 +247,7 @@ int32_t ScreenCaptureServiceProxy::InitVideoCap(VideoCaptureInfo videoInfo) return reply.ReadInt32(); } -int32_t ScreenCaptureServiceProxy::StartScreenCapture() +int32_t ScreenCaptureServiceProxy::StartScreenCapture(bool isPrivacyAuthorityEnabled) { MessageParcel data; MessageParcel reply; @@ -256,6 +256,9 @@ int32_t ScreenCaptureServiceProxy::StartScreenCapture() bool token = data.WriteInterfaceToken(ScreenCaptureServiceProxy::GetDescriptor()); CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write descriptor!"); + token = data.WriteBool(isPrivacyAuthorityEnabled); + CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write isPrivacyAuthorityEnabled!"); + int error = Remote()->SendRequest(START_SCREEN_CAPTURE, data, reply, option); CHECK_AND_RETURN_RET_LOG(error == MSERR_OK, MSERR_INVALID_OPERATION, "StartScreenCapture failed, error: %{public}d", error); @@ -263,7 +266,7 @@ int32_t ScreenCaptureServiceProxy::StartScreenCapture() return reply.ReadInt32(); } -int32_t ScreenCaptureServiceProxy::StartScreenCaptureWithSurface(sptr surface) +int32_t ScreenCaptureServiceProxy::StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) { MessageParcel data; MessageParcel reply; @@ -284,6 +287,9 @@ int32_t ScreenCaptureServiceProxy::StartScreenCaptureWithSurface(sptr s return MSERR_INVALID_OPERATION; } + token = data.WriteBool(isPrivacyAuthorityEnabled); + CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write isPrivacyAuthorityEnabled!"); + int error = Remote()->SendRequest(START_SCREEN_CAPTURE_WITH_SURFACE, data, reply, option); CHECK_AND_RETURN_RET_LOG(error == MSERR_OK, MSERR_INVALID_OPERATION, "StartScreenCapture failed, error: %{public}d", error); @@ -407,6 +413,30 @@ int32_t ScreenCaptureServiceProxy::ReleaseVideoBuffer() return reply.ReadInt32(); } +int32_t ScreenCaptureServiceProxy::ExcludeContent(ScreenCaptureContentFilter &contentFilter) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + bool token = data.WriteInterfaceToken(ScreenCaptureServiceProxy::GetDescriptor()); + CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write descriptor!"); + + token = data.WriteInt32(static_cast(contentFilter.filteredAudioContents.size())); + CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write filteredAudioContents size!"); + + // The filteredAudioContents size is limited, no big data risk. + for (const auto &element : contentFilter.filteredAudioContents) { + token = data.WriteInt32(static_cast(element)); + CHECK_AND_RETURN_RET_LOG(token, MSERR_INVALID_OPERATION, "Failed to write filteredAudioContents"); + } + + int error = Remote()->SendRequest(SET_MIC_ENABLE, data, reply, option); + CHECK_AND_RETURN_RET_LOG(error == MSERR_OK, MSERR_INVALID_OPERATION, + "ExcludeContent failed, error: %{public}d", error); + return reply.ReadInt32(); +} + int32_t ScreenCaptureServiceProxy::SetMicrophoneEnabled(bool isMicrophone) { MessageParcel data; diff --git a/services/services/screen_capture/ipc/screen_capture_service_proxy.h b/services/services/screen_capture/ipc/screen_capture_service_proxy.h index 48df6efd9..3d5838413 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_proxy.h +++ b/services/services/screen_capture/ipc/screen_capture_service_proxy.h @@ -35,8 +35,8 @@ public: int32_t InitAudioCap(AudioCaptureInfo audioInfo) override; int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) override; int32_t InitVideoCap(VideoCaptureInfo videoInfo) override; - int32_t StartScreenCapture() override; - int32_t StartScreenCaptureWithSurface(sptr surface) override; + int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled) override; + int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) override; int32_t StopScreenCapture() override; int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) override; int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, @@ -46,6 +46,7 @@ public: int32_t SetMicrophoneEnabled(bool isMicrophone) override; int32_t SetScreenCanvasRotation(bool canvasRotation) override; int32_t SetListenerObject(const sptr &object) override; + int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) override; private: static inline BrokerDelegator delegator_; diff --git a/services/services/screen_capture/ipc/screen_capture_service_stub.cpp b/services/services/screen_capture/ipc/screen_capture_service_stub.cpp index b0e4ad6cf..c400814cc 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_stub.cpp +++ b/services/services/screen_capture/ipc/screen_capture_service_stub.cpp @@ -73,6 +73,7 @@ int32_t ScreenCaptureServiceStub::Init() screenCaptureStubFuncs_[RELEASE_AUDIO_BUF] = &ScreenCaptureServiceStub::ReleaseAudioBuffer; screenCaptureStubFuncs_[RELEASE_VIDEO_BUF] = &ScreenCaptureServiceStub::ReleaseVideoBuffer; screenCaptureStubFuncs_[DESTROY] = &ScreenCaptureServiceStub::DestroyStub; + screenCaptureStubFuncs_[EXCLUDE_CONTENT] = &ScreenCaptureServiceStub::ExcludeContent; return MSERR_OK; } @@ -167,19 +168,19 @@ int32_t ScreenCaptureServiceStub::InitVideoCap(VideoCaptureInfo videoInfo) return screenCaptureServer_->InitVideoCap(videoInfo); } -int32_t ScreenCaptureServiceStub::StartScreenCapture() +int32_t ScreenCaptureServiceStub::StartScreenCapture(bool isPrivacyAuthorityEnabled) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, false, "screen capture server is nullptr"); - return screenCaptureServer_->StartScreenCapture(); + return screenCaptureServer_->StartScreenCapture(isPrivacyAuthorityEnabled); } -int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(sptr surface) +int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, false, "screen capture server is nullptr"); - return screenCaptureServer_->StartScreenCaptureWithSurface(surface); + return screenCaptureServer_->StartScreenCaptureWithSurface(surface, isPrivacyAuthorityEnabled); } int32_t ScreenCaptureServiceStub::StopScreenCapture() @@ -204,6 +205,13 @@ int32_t ScreenCaptureServiceStub::SetListenerObject(const sptr &o return MSERR_OK; } +int32_t ScreenCaptureServiceStub::ExcludeContent(ScreenCaptureContentFilter &contentFilter) +{ + CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, false, + "screen capture server is nullptr"); + return screenCaptureServer_->ExcludeContent(contentFilter); +} + int32_t ScreenCaptureServiceStub::SetMicrophoneEnabled(bool isMicrophone) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, false, @@ -248,6 +256,21 @@ int32_t ScreenCaptureServiceStub::ReleaseVideoBuffer() return screenCaptureServer_->ReleaseVideoBuffer(); } +int32_t ScreenCaptureServiceStub::ExcludeContent(MessageParcel &data, MessageParcel &reply) +{ + CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, MSERR_INVALID_STATE, + "screen capture server is nullptr"); + ScreenCaptureContentFilter contentFilter; + int32_t size = data.ReadInt32(); + for (int32_t i = 0; i < size; i++) { + contentFilter.filteredAudioContents.insert( + static_cast(data.ReadInt32())); + } + int32_t ret = ExcludeContent(contentFilter); + reply.WriteInt32(ret); + return MSERR_OK; +} + int32_t ScreenCaptureServiceStub::SetMicrophoneEnabled(MessageParcel &data, MessageParcel &reply) { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, MSERR_INVALID_STATE, @@ -382,8 +405,8 @@ int32_t ScreenCaptureServiceStub::StartScreenCapture(MessageParcel &data, Messag { CHECK_AND_RETURN_RET_LOG(screenCaptureServer_ != nullptr, MSERR_INVALID_STATE, "screen capture server is nullptr"); - (void)data; - int32_t ret = StartScreenCapture(); + bool isPrivacyAuthorityEnabled = data.ReadBool(); + int32_t ret = StartScreenCapture(isPrivacyAuthorityEnabled); reply.WriteInt32(ret); return MSERR_OK; } @@ -403,7 +426,8 @@ int32_t ScreenCaptureServiceStub::StartScreenCaptureWithSurface(MessageParcel &d sptr surface = Surface::CreateSurfaceAsProducer(producer); CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_NO_MEMORY, "failed to create surface"); - int32_t ret = StartScreenCaptureWithSurface(surface); + bool isPrivacyAuthorityEnabled = data.ReadBool(); + int32_t ret = StartScreenCaptureWithSurface(surface, isPrivacyAuthorityEnabled); reply.WriteInt32(ret); return MSERR_OK; } diff --git a/services/services/screen_capture/ipc/screen_capture_service_stub.h b/services/services/screen_capture/ipc/screen_capture_service_stub.h index 090ab1047..1a4d057ca 100644 --- a/services/services/screen_capture/ipc/screen_capture_service_stub.h +++ b/services/services/screen_capture/ipc/screen_capture_service_stub.h @@ -37,8 +37,8 @@ public: int32_t InitAudioCap(AudioCaptureInfo audioInfo) override; int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) override; int32_t InitVideoCap(VideoCaptureInfo videoInfo) override; - int32_t StartScreenCapture() override; - int32_t StartScreenCaptureWithSurface(sptr surface) override; + int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled) override; + int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) override; int32_t StopScreenCapture() override; int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) override; int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, @@ -49,6 +49,7 @@ public: int32_t SetScreenCanvasRotation(bool canvasRotation) override; int32_t SetListenerObject(const sptr &object) override; int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) override; private: ScreenCaptureServiceStub(); @@ -71,6 +72,7 @@ private: int32_t ReleaseVideoBuffer(MessageParcel &data, MessageParcel &reply); int32_t SetMicrophoneEnabled(MessageParcel &data, MessageParcel &reply); int32_t SetScreenCanvasRotation(MessageParcel &data, MessageParcel &reply); + int32_t ExcludeContent(MessageParcel &data, MessageParcel &reply); int32_t Release(MessageParcel &data, MessageParcel &reply); int32_t DestroyStub(MessageParcel &data, MessageParcel &reply); diff --git a/services/services/screen_capture/server/audio_capturer_wrapper.cpp b/services/services/screen_capture/server/audio_capturer_wrapper.cpp new file mode 100644 index 000000000..4c721c80e --- /dev/null +++ b/services/services/screen_capture/server/audio_capturer_wrapper.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * 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 "audio_capturer_wrapper.h" + +#include "media_log.h" +#include "media_errors.h" + +namespace { +constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ScreenCaptureServer"}; +} + +namespace OHOS { +namespace Media { +void AudioCapturerCallbackImpl::OnInterrupt(const InterruptEvent &interruptEvent) +{ + MEDIA_LOGI("OnInterrupt hintType:%{public}d, eventType:%{public}d, forceType:%{public}d", + interruptEvent.hintType, interruptEvent.eventType, interruptEvent.forceType); +} + +void AudioCapturerCallbackImpl::OnStateChange(const CapturerState state) +{ + MEDIA_LOGI("OnStateChange state:%{public}d", state); + switch (state) { + case CAPTURER_PREPARED: + MEDIA_LOGD("OnStateChange CAPTURER_PREPARED"); + break; + default: + MEDIA_LOGD("OnStateChange NOT A VALID state"); + break; + } +} + +int32_t AudioCapturerWrapper::Start(const OHOS::AudioStandard::AppInfo &appInfo) +{ + std::lock_guard lock(mutex_); + if (isRunning_.load()) { + MEDIA_LOGE("Start failed, is running, threadName:%{public}s", threadName_.c_str()); + return MSERR_UNKNOWN; + } + + std::shared_ptr audioCapturer = CreateAudioCapturer(appInfo); + CHECK_AND_RETURN_RET_LOG(audioCapturer != nullptr, MSERR_UNKNOWN, "Start failed, create AudioCapturer failed"); + if (!audioCapturer->Start()) { + MEDIA_LOGE("Start failed, AudioCapturer Start failed, threadName:%{public}s", threadName_.c_str()); + audioCapturer->Release(); + audioCapturer = nullptr; + OnStartFailed(ScreenCaptureErrorType::SCREEN_CAPTURE_ERROR_INTERNAL, SCREEN_CAPTURE_ERR_UNKNOWN); + return MSERR_UNKNOWN; + } + + MEDIA_LOGI("Start success, threadName:%{public}s", threadName_.c_str()); + isRunning_.store(true); + readAudioLoop_ = std::make_unique(&AudioCapturerWrapper::CaptureAudio, this); + audioCapturer_ = audioCapturer; + return MSERR_OK; +} + +int32_t AudioCapturerWrapper::Stop() +{ + std::lock_guard lock(mutex_); + if (isRunning_.load()) { + isRunning_.store(false); + if (readAudioLoop_ != nullptr && readAudioLoop_->joinable()) { + readAudioLoop_->join(); + readAudioLoop_.reset(); + readAudioLoop_ = nullptr; + } + if (audioCapturer_ != nullptr) { + audioCapturer_->Stop(); + audioCapturer_->Release(); + audioCapturer_ = nullptr; + } + } + + std::unique_lock bufferLock(bufferMutex_); + while (!availBuffers_.empty()) { + if (availBuffers_.front() != nullptr) { + free(availBuffers_.front()->buffer); + availBuffers_.front()->buffer = nullptr; + } + availBuffers_.pop(); + } + return MSERR_OK; +} + +void AudioCapturerWrapper::SetIsMuted(bool isMuted) +{ + isMuted_.store(isMuted); +} + +std::shared_ptr AudioCapturerWrapper::CreateAudioCapturer(const OHOS::AudioStandard::AppInfo &appInfo) +{ + AudioCapturerOptions capturerOptions; + capturerOptions.streamInfo.samplingRate = static_cast(audioInfo_.audioSampleRate); + capturerOptions.streamInfo.channels = static_cast(audioInfo_.audioChannels); + capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM; + capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; + if (audioInfo_.audioSource == AudioCaptureSourceType::MIC) { + capturerOptions.capturerInfo.sourceType = static_cast(0); // Audio Source Type Mic is 0 + } else { + capturerOptions.capturerInfo.sourceType = static_cast(audioInfo_.audioSource); + } + capturerOptions.capturerInfo.capturerFlags = 0; + std::shared_ptr audioCapturer = AudioCapturer::Create(capturerOptions, appInfo); + CHECK_AND_RETURN_RET_LOG(audioCapturer != nullptr, nullptr, "AudioCapturer::Create failed"); + + std::shared_ptr callback = std::make_shared(); + int ret = audioCapturer->SetCapturerCallback(callback); + if (ret != MSERR_OK) { + audioCapturer->Release(); + MEDIA_LOGE("SetCapturerCallback failed, threadName:%{public}s", threadName_.c_str()); + return nullptr; + } + audioCaptureCallback_ = callback; + return audioCapturer; +} + +int32_t AudioCapturerWrapper::CaptureAudio() +{ + MEDIA_LOGI("CaptureAudio start, threadName:%{public}s", threadName_.c_str()); + std::string name = threadName_.substr(0, std::min(threadName_.size(), (size_t)MAX_THREAD_NAME_LENGTH)); + pthread_setname_np(pthread_self(), name.c_str()); + + size_t bufferLen; + CHECK_AND_RETURN_RET_LOG(audioCapturer_ != nullptr && audioCapturer_->GetBufferSize(bufferLen) >= 0, + MSERR_NO_MEMORY, "CaptureAudio GetBufferSize failed"); + + Timestamp timestamp; + std::shared_ptr audioBuffer; + while (true) { + CHECK_AND_RETURN_RET_LOG(isRunning_.load(), MSERR_OK, "CaptureAudio is not running, stop capture"); + uint8_t *buffer = static_cast(malloc(bufferLen)); + CHECK_AND_RETURN_RET_LOG(buffer != nullptr, MSERR_OK, "CaptureAudio buffer is no momery, stop capture"); + audioBuffer = std::make_shared(buffer, 0, 0, audioInfo_.audioSource); + memset_s(audioBuffer->buffer, bufferLen, 0, bufferLen); + int32_t bufferRead = audioCapturer_->Read(*(audioBuffer->buffer), bufferLen, true); + CHECK_AND_CONTINUE_LOG(bufferRead > 0, "CaptureAudio read audio buffer failed, continue"); + audioBuffer->length = bufferRead; + audioCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC); + int64_t audioTime = timestamp.time.tv_nsec + timestamp.time.tv_sec * SEC_TO_NANOSECOND; + audioBuffer->timestamp = audioTime; + { + std::unique_lock lock(bufferMutex_); + CHECK_AND_RETURN_RET_LOG(isRunning_.load(), MSERR_OK, "CaptureAudio is not running, ignore and stop"); + CHECK_AND_CONTINUE_LOG(availBuffers_.size() <= MAX_AUDIO_BUFFER_SIZE, "consume slow, drop audio frame"); + if (isMuted_) { + memset_s(audioBuffer->buffer, bufferLen, 0, bufferLen); + } + availBuffers_.push(audioBuffer); + } + bufferCond_.notify_all(); + CHECK_AND_RETURN_RET_LOG(isRunning_.load(), MSERR_OK, "CaptureAudio is not running, ignore and stop"); + CHECK_AND_RETURN_RET_LOG(screenCaptureCb_ != nullptr, MSERR_OK, "no consumer, will drop audio frame"); + screenCaptureCb_->OnAudioBufferAvailable(true, audioInfo_.audioSource); + } + return MSERR_OK; +} + +int32_t AudioCapturerWrapper::AcquireAudioBuffer(std::shared_ptr &audioBuffer) +{ + using namespace std::chrono_literals; + std::unique_lock lock(bufferMutex_); + CHECK_AND_RETURN_RET_LOG(isRunning_.load(), MSERR_UNKNOWN, "AcquireAudioBuffer failed, not running"); + + if (!bufferCond_.wait_for( + lock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] { return !availBuffers_.empty(); })) { + MEDIA_LOGE("AcquireAudioBuffer timeout, threadName:%{public}s", threadName_.c_str()); + return MSERR_UNKNOWN; + } + audioBuffer = availBuffers_.front(); + return MSERR_OK; +} + +int32_t AudioCapturerWrapper::ReleaseAudioBuffer() +{ + using namespace std::chrono_literals; + std::unique_lock lock(bufferMutex_); + CHECK_AND_RETURN_RET_LOG(isRunning_.load(), MSERR_UNKNOWN, "ReleaseAudioBuffer failed, not running"); + CHECK_AND_RETURN_RET_LOG(!availBuffers_.empty(), MSERR_UNKNOWN, "ReleaseAudioBuffer failed, no frame to release"); + availBuffers_.pop(); + return MSERR_OK; +} + +void AudioCapturerWrapper::OnStartFailed(ScreenCaptureErrorType errorType, int32_t errorCode) +{ + if (screenCaptureCb_ != nullptr) { + screenCaptureCb_->OnError(errorType, errorCode); + } +} + +AudioCapturerWrapper::~AudioCapturerWrapper() +{ + Stop(); +} + +void MicAudioCapturerWrapper::OnStartFailed(ScreenCaptureErrorType errorType, int32_t errorCode) +{ + (void)errorType; + (void)errorCode; + if (screenCaptureCb_ != nullptr) { + screenCaptureCb_->OnStateChange(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_MIC_UNAVAILABLE); + } +} +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/services/services/screen_capture/server/audio_capturer_wrapper.h b/services/services/screen_capture/server/audio_capturer_wrapper.h new file mode 100644 index 000000000..5f67d250d --- /dev/null +++ b/services/services/screen_capture/server/audio_capturer_wrapper.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef SCREEN_CAPTURE_AUDIO_CAPTURER_WRAPPER_H +#define SCREEN_CAPTURE_AUDIO_CAPTURER_WRAPPER_H + +#include +#include +#include +#include +#include +#include +#include + +#include "audio_capturer.h" +#include "screen_capture.h" +#include "securec.h" + +namespace OHOS { +namespace Media { +using namespace AudioStandard; +class AudioCapturerCallbackImpl : public AudioCapturerCallback { +public: + void OnInterrupt(const InterruptEvent &interruptEvent) override; + void OnStateChange(const CapturerState state) override; +}; + +class AudioCapturerWrapper { +public: + explicit AudioCapturerWrapper(AudioCaptureInfo &audioInfo, + std::shared_ptr &screenCaptureCb, std::string &&name) + : screenCaptureCb_(screenCaptureCb), audioInfo_(audioInfo), threadName_(std::move(name)) {} + virtual ~AudioCapturerWrapper(); + int32_t Start(const OHOS::AudioStandard::AppInfo &appInfo); + int32_t Stop(); + void SetIsMuted(bool isMuted); + int32_t CaptureAudio(); + int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer); + int32_t ReleaseAudioBuffer(); + +protected: + virtual void OnStartFailed(ScreenCaptureErrorType errorType, int32_t errorCode); + +private: + std::shared_ptr CreateAudioCapturer(const OHOS::AudioStandard::AppInfo &appInfo); + +protected: + std::shared_ptr screenCaptureCb_; + +private: + std::mutex mutex_; + std::atomic isMuted_ = false; + std::atomic isRunning_ = false; + AudioCaptureInfo audioInfo_; + std::string threadName_; + std::unique_ptr readAudioLoop_ = nullptr; + std::shared_ptr audioCapturer_ = nullptr; + std::shared_ptr audioCaptureCallback_ = nullptr; + + std::mutex bufferMutex_; + std::condition_variable bufferCond_; + std::queue> availBuffers_; + + static constexpr uint32_t MAX_THREAD_NAME_LENGTH = 15; + static constexpr uint32_t MAX_AUDIO_BUFFER_SIZE = 128; + static constexpr uint32_t SEC_TO_NANOSECOND = 1000000000; // 10^9ns + static constexpr uint32_t OPERATION_TIMEOUT_IN_MS = 200; // 200ms +}; + +class MicAudioCapturerWrapper : public AudioCapturerWrapper { +public: + explicit MicAudioCapturerWrapper(AudioCaptureInfo &audioInfo, + std::shared_ptr &screenCaptureCb, std::string &&name) + : AudioCapturerWrapper(audioInfo, screenCaptureCb, std::move(name)) {} + ~MicAudioCapturerWrapper() {} + +protected: + void OnStartFailed(ScreenCaptureErrorType errorType, int32_t errorCode) override; +}; +} // namespace Media +} // namespace OHOS +#endif // SCREEN_CAPTURE_AUDIO_CAPTURER_WRAPPER_H diff --git a/services/services/screen_capture/server/screen_capture_server.cpp b/services/services/screen_capture/server/screen_capture_server.cpp index 695ffc3fe..b5a20e632 100644 --- a/services/services/screen_capture/server/screen_capture_server.cpp +++ b/services/services/screen_capture/server/screen_capture_server.cpp @@ -23,6 +23,8 @@ #include "media_errors.h" #include "uri_helper.h" #include "media_dfx.h" +#include "scope_guard.h" +#include "screen_capture_listener_proxy.h" using OHOS::Rosen::DMError; namespace { @@ -34,8 +36,19 @@ std::mutex mutexGlobal; namespace OHOS { namespace Media { -const int32_t ROOT_UID = 0; -static const std::string USER_CHOICE_TRUE = "true"; +static const std::string MP4 = "mp4"; +static const std::string M4A = "m4a"; + +static const std::string USER_CHOICE_ALLOW = "true"; +static const std::string USER_CHOICE_DENY = "false"; +static const std::string BUTTON_NAME_MIC = "mic"; +static const std::string BUTTON_NAME_STOP = "stop"; +static const std::string ICON_PATH_CAPSULE = "/etc/screencapture/capsule.png"; +static const std::string ICON_PATH_MIC = "/etc/screencapture/mic.png"; +static const std::string ICON_PATH_STOP = "/etc/screencapture/stop.png"; +static const std::string BUNDLE_NAME = "com.ohos.systemui"; +static const std::string ABILITY_NAME = "com.ohos.systemui.dialog"; + static const int32_t MAX_SESSION_ID = 256; static const auto NOTIFICATION_SUBSCRIBER = NotificationSubscriber(); @@ -54,9 +67,9 @@ void NotificationSubscriber::OnResponse(int32_t notificationId, { MEDIA_LOGI("NotificationSubscriber OnResponse notificationId : %{public}d ", notificationId); MEDIA_LOGI("NotificationSubscriber OnResponse ButtonName : %{public}s ", (buttonOption->GetButtonName()).c_str()); - if (buttonNameStop_.compare(buttonOption->GetButtonName()) == 0) { + if (BUTTON_NAME_STOP.compare(buttonOption->GetButtonName()) == 0) { std::shared_ptr server = serverMap.at(notificationId); - server->StopScreenCapture(); + server->StopScreenCaptureByEvent(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STOPPED_BY_USER); } } @@ -96,38 +109,44 @@ int32_t ScreenCaptureServer::ReportAVScreenCaptureUserChoice(int32_t sessionId, MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice user choice is : %{public}s", choice.c_str()); std::shared_ptr server; auto it = serverMap.find(sessionId); - if (it != serverMap.end()) { + if (it != serverMap.end() && it->second != nullptr) { server = it->second; } else { MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice Failed to get report ScreenCaptureServer"); return MSERR_UNKNOWN; } - if (USER_CHOICE_TRUE.compare(choice) == 0) { + if (USER_CHOICE_ALLOW.compare(choice) == 0) { if (activeSessionId.load() >= 0) { std::shared_ptr currentServer = serverMap.at(activeSessionId.load()); - currentServer->StopScreenCapture(); + currentServer->StopScreenCaptureByEvent( + AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STOPPED_BY_INTERRUPT); } - server->StartScreenCaptureInner(); + activeSessionId.store(SESSION_ID_INVALID); + int32_t ret = server->OnReceiveUserPrivacyAuthority(true); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, + "ReportAVScreenCaptureUserChoice user choice is true but start failed"); activeSessionId.store(sessionId); - MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice user choice is true"); + MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice user choice is true and start success"); return MSERR_OK; + } else if (USER_CHOICE_DENY.compare(choice) == 0) { + return server->OnReceiveUserPrivacyAuthority(false); } - MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice user choice is false"); - return MSERR_OK; + MEDIA_LOGI("ScreenCaptureServer::ReportAVScreenCaptureUserChoice user choice is not support"); + return MSERR_UNKNOWN; } ScreenCaptureServer::ScreenCaptureServer() { - MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this)); + MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this)); + InitAppInfo(); } ScreenCaptureServer::~ScreenCaptureServer() { - MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this)); + MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this)); std::lock_guard lock(mutex_); - ReleaseAudioCapture(); - ReleaseVideoCapture(); + StopScreenCaptureInner(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_INVLID); } void ScreenCaptureServer::SetSessionId(int32_t sessionId) @@ -138,34 +157,32 @@ void ScreenCaptureServer::SetSessionId(int32_t sessionId) int32_t ScreenCaptureServer::SetCaptureMode(CaptureMode captureMode) { std::lock_guard lock(mutex_); - MEDIA_LOGI("ScreenCaptureServer::SetCaptureMode start"); - if ((captureMode > CAPTURE_SPECIFIED_WINDOW) || (captureMode < CAPTURE_HOME_SCREEN)) { - MEDIA_LOGI("invalid capture mode"); - return MSERR_INVALID_VAL; - } - captureMode_ = captureMode; + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "SetCaptureMode failed, capture is not CREATED, state:%{public}d, mode:%{public}d", captureState_, captureMode); + MEDIA_LOGI("ScreenCaptureServer::SetCaptureMode start, captureMode:%{public}d", captureMode); + int32_t ret = CheckCaptureMode(captureMode); + CHECK_AND_RETURN_RET(ret == MSERR_OK, ret); + captureConfig_.captureMode = captureMode; return MSERR_OK; } int32_t ScreenCaptureServer::SetDataType(DataType dataType) { std::lock_guard lock(mutex_); - MEDIA_LOGI("ScreenCaptureServer::SetDataType start"); - if ((dataType > DataType::CAPTURE_FILE) || (dataType < DataType::ORIGINAL_STREAM)) { - MEDIA_LOGI("invalid data type"); - return MSERR_INVALID_VAL; - } - if (dataType == DataType::ENCODED_STREAM) { - MEDIA_LOGI("the data type:%{public}d still not supported", dataType); - return MSERR_UNSUPPORT; - } - dataType_ = dataType; + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "SetDataType failed, capture is not CREATED, state:%{public}d, dataType:%{public}d", captureState_, dataType); + MEDIA_LOGI("ScreenCaptureServer::SetDataType start, dataType:%{public}d", dataType); + int32_t ret = CheckDataType(dataType); + CHECK_AND_RETURN_RET(ret == MSERR_OK, ret); + captureConfig_.dataType = dataType; return MSERR_OK; } int32_t ScreenCaptureServer::SetRecorderInfo(RecorderInfo recorderInfo) { std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "SetRecorderInfo failed, capture is not CREATED, state:%{public}d", captureState_); MEDIA_LOGI("ScreenCaptureServer::SetRecorderInfo start"); url_ = recorderInfo.url; @@ -184,6 +201,8 @@ int32_t ScreenCaptureServer::SetRecorderInfo(RecorderInfo recorderInfo) int32_t ScreenCaptureServer::SetOutputFile(int32_t outputFd) { std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "SetOutputFile failed, capture is not CREATED, state:%{public}d", captureState_); MEDIA_LOGI("ScreenCaptureServer::SetOutputFile start"); if (outputFd < 0) { MEDIA_LOGI("invalid outputFd"); @@ -200,9 +219,7 @@ int32_t ScreenCaptureServer::SetOutputFile(int32_t outputFd) return MSERR_INVALID_VAL; } - if (outputFd_ > 0) { - (void)::close(outputFd_); - } + CloseFd(); outputFd_ = dup(outputFd); MEDIA_LOGI("ScreenCaptureServer SetOutputFile ok"); return MSERR_OK; @@ -211,279 +228,544 @@ int32_t ScreenCaptureServer::SetOutputFile(int32_t outputFd) int32_t ScreenCaptureServer::SetScreenCaptureCallback(const std::shared_ptr &callback) { std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "SetScreenCaptureCallback failed, capture is not CREATED, state:%{public}d", captureState_); + CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, + "SetScreenCaptureCallback failed, callback is nullptr, state:%{public}d", captureState_); MEDIA_LOGI("ScreenCaptureServer::SetScreenCaptureCallback start"); - { - std::lock_guard cbLock(cbMutex_); - screenCaptureCb_ = callback; - } + screenCaptureCb_ = callback; return MSERR_OK; } int32_t ScreenCaptureServer::InitAudioEncInfo(AudioEncInfo audioEncInfo) { std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "InitAudioEncInfo failed, capture is not CREATED, state:%{public}d", captureState_); MEDIA_LOGI("ScreenCaptureServer::InitAudioEncInfo start"); - MEDIA_LOGD("audioEncInfo audioBitrate:%{public}d", audioEncInfo.audioBitrate); - MEDIA_LOGD("audioEncInfo audioCodecformat:%{public}d", audioEncInfo.audioCodecformat); - if ((audioEncInfo.audioCodecformat >= AudioCodecFormat::AUDIO_CODEC_FORMAT_BUTT) || - (audioEncInfo.audioCodecformat < AudioCodecFormat::AUDIO_DEFAULT)) { - MEDIA_LOGE("invalid AudioCodecFormat type"); - return MSERR_INVALID_VAL; - } - if (audioEncInfo.audioBitrate < audioBitrateMin_ || audioEncInfo.audioBitrate > audioBitrateMax_) { - MEDIA_LOGE("InitAudioEncInfo Audio encode bitrate is invalid: %{public}d", audioEncInfo.audioBitrate); - return MSERR_INVALID_VAL; - } - audioEncInfo_ = audioEncInfo; + MEDIA_LOGD("audioEncInfo audioBitrate:%{public}d, audioCodecformat:%{public}d", audioEncInfo.audioBitrate, + audioEncInfo.audioCodecformat); + int32_t ret = CheckAudioEncInfo(audioEncInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitAudioEncInfo failed, ret:%{public}d", ret); + captureConfig_.audioInfo.audioEncInfo = audioEncInfo; return MSERR_OK; } int32_t ScreenCaptureServer::InitVideoEncInfo(VideoEncInfo videoEncInfo) { std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "InitVideoEncInfo failed, capture is not CREATED, state:%{public}d", captureState_); MEDIA_LOGI("ScreenCaptureServer::InitVideoEncInfo start"); - MEDIA_LOGD("videoEncInfo videoCodec:%{public}d", videoEncInfo.videoCodec); - MEDIA_LOGD("videoEncInfo videoBitrate:%{public}d", videoEncInfo.videoBitrate); - MEDIA_LOGD("videoEncInfo videoFrameRate:%{public}d", videoEncInfo.videoFrameRate); - if ((videoEncInfo.videoCodec >= VideoCodecFormat::VIDEO_CODEC_FORMAT_BUTT) || - (videoEncInfo.videoCodec < VideoCodecFormat::VIDEO_DEFAULT)) { - MEDIA_LOGE("invalid VideoCodecFormat type"); - return MSERR_INVALID_VAL; - } - if (videoEncInfo.videoBitrate < videoBitrateMin_ || videoEncInfo.videoBitrate > videoBitrateMax_) { - MEDIA_LOGE("InitVideoEncInfo video encode bitrate is invalid: %{public}d", videoEncInfo.videoBitrate); - return MSERR_INVALID_VAL; - } - if (videoEncInfo.videoFrameRate < videoFrameRateMin_ || videoEncInfo.videoFrameRate > videoFrameRateMax_) { - MEDIA_LOGE("InitVideoEncInfo video frame rate is invalid: %{public}d", videoEncInfo.videoFrameRate); - return MSERR_INVALID_VAL; - } - videoEncInfo_ = videoEncInfo; + MEDIA_LOGD("videoEncInfo videoCodec:%{public}d, videoBitrate:%{public}d, videoFrameRate:%{public}d", + videoEncInfo.videoCodec, videoEncInfo.videoBitrate, videoEncInfo.videoFrameRate); + int32_t ret = CheckVideoEncInfo(videoEncInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CheckVideoEncInfo failed, ret:%{public}d", ret); + captureConfig_.videoInfo.videoEncInfo = videoEncInfo; return MSERR_OK; } bool ScreenCaptureServer::CheckScreenCapturePermission() { - auto callerUid = IPCSkeleton::GetCallingUid(); // Root users should be whitelisted - if (callerUid == ROOT_UID) { + if (appInfo_.appUid == ROOT_UID) { MEDIA_LOGI("Root user. Permission Granted"); return true; } - Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID(); - clientTokenId = tokenCaller; - int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, + int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(appInfo_.appTokenId, "ohos.permission.CAPTURE_SCREEN"); if (result == Security::AccessToken::PERMISSION_GRANTED) { MEDIA_LOGI("user have the right to access capture screen!"); + return true; } else { MEDIA_LOGE("user do not have the right to access capture screen!"); return false; } +} - return true; +int32_t ScreenCaptureServer::CheckCaptureMode(CaptureMode captureMode) +{ + MEDIA_LOGD("CheckCaptureMode start, captureMode:%{public}d", captureMode); + if ((captureMode > CAPTURE_SPECIFIED_WINDOW) || (captureMode < CAPTURE_HOME_SCREEN)) { + MEDIA_LOGE("invalid captureMode:%{public}d", captureMode); + return MSERR_INVALID_VAL; + } + return MSERR_OK; } -int32_t ScreenCaptureServer::CheckAudioParam(AudioCaptureInfo audioInfo) +int32_t ScreenCaptureServer::CheckDataType(DataType dataType) { + MEDIA_LOGD("CheckDataType start, dataType:%{public}d", dataType); + if ((dataType > DataType::CAPTURE_FILE) || (dataType < DataType::ORIGINAL_STREAM)) { + MEDIA_LOGE("invalid dataType:%{public}d", dataType); + return MSERR_INVALID_VAL; + } + if (dataType == DataType::ENCODED_STREAM) { + MEDIA_LOGE("not supported dataType:%{public}d", dataType); + return MSERR_UNSUPPORT; + } + return MSERR_OK; +} + +int32_t ScreenCaptureServer::CheckAudioCapParam(const AudioCaptureInfo &audioCapInfo) +{ + MEDIA_LOGD("CheckAudioCapParam sampleRate:%{public}d, channels:%{public}d, source:%{public}d, state:%{public}d", + audioCapInfo.audioSampleRate, audioCapInfo.audioChannels, audioCapInfo.audioSource, audioCapInfo.state); std::vector supportedSamplingRates = AudioStandard::AudioCapturer::GetSupportedSamplingRates(); bool foundSupportSample = false; for (auto iter = supportedSamplingRates.begin(); iter != supportedSamplingRates.end(); ++iter) { - if (static_cast(audioInfo.audioSampleRate) == *iter) { + if (static_cast(audioCapInfo.audioSampleRate) == *iter) { foundSupportSample = true; } } if (!foundSupportSample) { - MEDIA_LOGE("set audioSampleRate is not support"); + MEDIA_LOGE("invalid audioSampleRate:%{public}d", audioCapInfo.audioSampleRate); return MSERR_UNSUPPORT; } std::vector supportedChannelList = AudioStandard::AudioCapturer::GetSupportedChannels(); bool foundSupportChannel = false; for (auto iter = supportedChannelList.begin(); iter != supportedChannelList.end(); ++iter) { - if (static_cast(audioInfo.audioChannels) == *iter) { + if (static_cast(audioCapInfo.audioChannels) == *iter) { foundSupportChannel = true; } } if (!foundSupportChannel) { - MEDIA_LOGE("set audioChannel is not support"); + MEDIA_LOGE("invalid audioChannels:%{public}d", audioCapInfo.audioChannels); return MSERR_UNSUPPORT; } - if ((audioInfo.audioSource <= SOURCE_INVALID) || (audioInfo.audioSource > APP_PLAYBACK)) { - MEDIA_LOGE("audioSource is invalid"); + if ((audioCapInfo.audioSource <= SOURCE_INVALID) || (audioCapInfo.audioSource > APP_PLAYBACK)) { + MEDIA_LOGE("invalid audioSource:%{public}d", audioCapInfo.audioSource); return MSERR_INVALID_VAL; } return MSERR_OK; } -int32_t ScreenCaptureServer::CheckVideoParam(VideoCaptureInfo videoInfo) +int32_t ScreenCaptureServer::CheckVideoCapParam(const VideoCaptureInfo &videoCapInfo) { - if ((videoInfo.videoFrameWidth <= 0) || (videoInfo.videoFrameHeight <= 0)) { - MEDIA_LOGE("videoInfo size is invalid, videoFrameWidth:%{public}d,videoFrameHeight:%{public}d", - videoInfo.videoFrameWidth, videoInfo.videoFrameHeight); + MEDIA_LOGD("CheckVideoCapParam width:%{public}d, height:%{public}d, source:%{public}d, state:%{public}d", + videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state); + if ((videoCapInfo.videoFrameWidth <= 0) || (videoCapInfo.videoFrameWidth > VIDEO_FRAME_WIDTH_MAX)) { + MEDIA_LOGE("videoCapInfo size is invalid, videoFrameWidth:%{public}d, videoFrameHeight:%{public}d", + videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight); + return MSERR_INVALID_VAL; + } + if ((videoCapInfo.videoFrameWidth <= 0) || (videoCapInfo.videoFrameWidth > VIDEO_FRAME_HEIGHT_MAX)) { + MEDIA_LOGE("videoCapInfo size is invalid, videoFrameWidth:%{public}d, videoFrameHeight:%{public}d", + videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight); return MSERR_INVALID_VAL; } - if (videoInfo.videoSource != VIDEO_SOURCE_SURFACE_RGBA) { + if (videoCapInfo.videoSource != VIDEO_SOURCE_SURFACE_RGBA) { MEDIA_LOGE("videoSource is invalid"); return MSERR_INVALID_VAL; } return MSERR_OK; } -bool ScreenCaptureServer::CheckAudioCaptureMicPermission() +int32_t ScreenCaptureServer::CheckAudioEncParam(const AudioEncInfo &audioEncInfo) { - auto callerUid = IPCSkeleton::GetCallingUid(); - // Root users should be whitelisted - if (callerUid == ROOT_UID) { - MEDIA_LOGI("Root user. Permission Granted"); - return true; + MEDIA_LOGD("CheckAudioEncParam audioBitrate:%{public}d, audioCodecformat:%{public}d", + audioEncInfo.audioBitrate, audioEncInfo.audioCodecformat); + if ((audioEncInfo.audioCodecformat >= AudioCodecFormat::AUDIO_CODEC_FORMAT_BUTT) || + (audioEncInfo.audioCodecformat < AudioCodecFormat::AUDIO_DEFAULT)) { + MEDIA_LOGE("invalid AudioCodecFormat:%{public}d", audioEncInfo.audioCodecformat); + return MSERR_INVALID_VAL; + } + if (audioEncInfo.audioBitrate < AUDIO_BITRATE_MIN || audioEncInfo.audioBitrate > AUDIO_BITRATE_MAX) { + MEDIA_LOGE("invalid audioBitrate:%{public}d", audioEncInfo.audioBitrate); + return MSERR_INVALID_VAL; } + return MSERR_OK; +} - Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID(); - int result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, - "ohos.permission.MICROPHONE"); - if (result == Security::AccessToken::PERMISSION_GRANTED) { - MEDIA_LOGI("user have the right to access microphone !"); - return true; - } else { - MEDIA_LOGE("user do not have the right to access microphone!"); - return false; +int32_t ScreenCaptureServer::CheckVideoEncParam(const VideoEncInfo &videoEncInfo) +{ + MEDIA_LOGD("CheckVideoEncParam videoCodec:%{public}d, videoBitrate:%{public}d, videoFrameRate:%{public}d", + videoEncInfo.videoCodec, videoEncInfo.videoBitrate, videoEncInfo.videoFrameRate); + if ((videoEncInfo.videoCodec >= VideoCodecFormat::VIDEO_CODEC_FORMAT_BUTT) || + (videoEncInfo.videoCodec < VideoCodecFormat::VIDEO_DEFAULT)) { + MEDIA_LOGE("invalid VideoCodecFormat:%{public}d", videoEncInfo.videoCodec); + return MSERR_INVALID_VAL; } + if (videoEncInfo.videoBitrate < VIDEO_BITRATE_MIN || videoEncInfo.videoBitrate > VIDEO_BITRATE_MAX) { + MEDIA_LOGE("invalid videoBitrate:%{public}d", videoEncInfo.videoBitrate); + return MSERR_INVALID_VAL; + } + if (videoEncInfo.videoFrameRate < VIDEO_FRAME_RATE_MIN || videoEncInfo.videoFrameRate > VIDEO_FRAME_RATE_MAX) { + MEDIA_LOGE("invalid videoFrameRate:%{public}d", videoEncInfo.videoFrameRate); + return MSERR_INVALID_VAL; + } + return MSERR_OK; } -int32_t ScreenCaptureServer::InitAudioCap(AudioCaptureInfo audioInfo) +int32_t ScreenCaptureServer::CheckAudioCapInfo(AudioCaptureInfo &audioCapInfo) { - std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::InitAudioCap"); - MEDIA_LOGI("ScreenCaptureServer::InitAudioCap start"); - int ret = MSERR_OK; - ret = CheckAudioParam(audioInfo); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CheckAudioParam failed"); - - if (dataType_ == DataType::CAPTURE_FILE) { - CHECK_AND_RETURN_RET_LOG(audioInfo.audioSource >= AudioCaptureSourceType::SOURCE_DEFAULT && - audioInfo.audioSource <= AudioCaptureSourceType::APP_PLAYBACK, MSERR_UNKNOWN, - "audio source type error"); - audioInfo_ = audioInfo; - } else { - switch (audioInfo.audioSource) { - case SOURCE_DEFAULT: - case MIC: { - if (!CheckAudioCaptureMicPermission()) { - return MSERR_INVALID_OPERATION; - } - audioMicCapturer_ = CreateAudioCapture(audioInfo); - CHECK_AND_RETURN_RET_LOG(audioMicCapturer_ != nullptr, MSERR_UNKNOWN, "initMicAudioCap failed"); - break; - } - case ALL_PLAYBACK: - case APP_PLAYBACK: { - audioInnerCapturer_ = CreateAudioCapture(audioInfo); - audioCurrentInnerType_ = audioInfo.audioSource; - CHECK_AND_RETURN_RET_LOG(audioInnerCapturer_ != nullptr, MSERR_UNKNOWN, "initInnerAudioCap failed"); - break; - } - default: - MEDIA_LOGE("the audio source Type is invalid"); - return MSERR_INVALID_OPERATION; + if (audioCapInfo.audioChannels == 0 && audioCapInfo.audioSampleRate == 0) { + audioCapInfo.state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; + return MSERR_OK; + } + MEDIA_LOGD("CheckAudioCapParam S sampleRate:%{public}d, channels:%{public}d, source:%{public}d, state:%{public}d", + audioCapInfo.audioSampleRate, audioCapInfo.audioChannels, audioCapInfo.audioSource, audioCapInfo.state); + int32_t ret = CheckAudioCapParam(audioCapInfo); + audioCapInfo.state = ret == MSERR_OK ? AVScreenCaptureParamValidationState::VALIDATION_VALID : + AVScreenCaptureParamValidationState::VALIDATION_INVALID; + MEDIA_LOGD("CheckAudioCapParam E sampleRate:%{public}d, channels:%{public}d, source:%{public}d, state:%{public}d", + audioCapInfo.audioSampleRate, audioCapInfo.audioChannels, audioCapInfo.audioSource, audioCapInfo.state); + return ret; +} + +int32_t ScreenCaptureServer::CheckVideoCapInfo(VideoCaptureInfo &videoCapInfo) +{ + if (videoCapInfo.videoFrameWidth == 0 && videoCapInfo.videoFrameHeight == 0) { + videoCapInfo.state = AVScreenCaptureParamValidationState::VALIDATION_IGNORE; + return MSERR_OK; + } + MEDIA_LOGD("CheckVideoCapParam S width:%{public}d, height:%{public}d, source:%{public}d, state:%{public}d", + videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state); + int32_t ret = CheckVideoCapParam(videoCapInfo); + videoCapInfo.state = ret == MSERR_OK ? AVScreenCaptureParamValidationState::VALIDATION_VALID : + AVScreenCaptureParamValidationState::VALIDATION_INVALID; + MEDIA_LOGD("CheckVideoCapParam E width:%{public}d, height:%{public}d, source:%{public}d, state:%{public}d", + videoCapInfo.videoFrameWidth, videoCapInfo.videoFrameHeight, videoCapInfo.videoSource, videoCapInfo.state); + return ret; +} + +int32_t ScreenCaptureServer::CheckAudioEncInfo(AudioEncInfo &audioEncInfo) +{ + int32_t ret = CheckAudioEncParam(audioEncInfo); + audioEncInfo.state = ret == MSERR_OK ? AVScreenCaptureParamValidationState::VALIDATION_VALID : + AVScreenCaptureParamValidationState::VALIDATION_INVALID; + return ret; +} + +int32_t ScreenCaptureServer::CheckVideoEncInfo(VideoEncInfo &videoEncInfo) +{ + int32_t ret = CheckVideoEncParam(videoEncInfo); + videoEncInfo.state = ret == MSERR_OK ? AVScreenCaptureParamValidationState::VALIDATION_VALID : + AVScreenCaptureParamValidationState::VALIDATION_INVALID; + return ret; +} + +int32_t ScreenCaptureServer::CheckAllParams() +{ + int32_t ret = CheckDataType(captureConfig_.dataType); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CheckAllParams CheckDataType failed, ret:%{public}d", ret); + + ret = CheckCaptureMode(captureConfig_.captureMode); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CheckAllParams CheckCaptureMode failed, ret:%{public}d", ret); + + if (captureConfig_.dataType == DataType::ORIGINAL_STREAM) { + return CheckCaptureStreamParams(); + } + if (captureConfig_.dataType == DataType::CAPTURE_FILE) { + return CheckCaptureFileParams(); + } + return MSERR_INVALID_VAL; +} + +int32_t ScreenCaptureServer::CheckCaptureStreamParams() +{ + // For original stream: + // 1. Any of innerCapInfo/videoCapInfo should be not invalid and should not be both ignored + // 2. micCapInfo should not be invalid + // 3. For surface mode, videoCapInfo should be valid + CheckAudioCapInfo(captureConfig_.audioInfo.micCapInfo); + CheckAudioCapInfo(captureConfig_.audioInfo.innerCapInfo); + CheckVideoCapInfo(captureConfig_.videoInfo.videoCapInfo); + if (isSurfaceMode_) { + // surface mode, surface must not nullptr and videoCapInfo must valid. + if (surface_ == nullptr || + captureConfig_.videoInfo.videoCapInfo.state != AVScreenCaptureParamValidationState::VALIDATION_VALID) { + return MSERR_INVALID_VAL; } } + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID || + captureConfig_.videoInfo.videoCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID) { + return MSERR_INVALID_VAL; + } + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_IGNORE && + captureConfig_.videoInfo.videoCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_IGNORE) { + return MSERR_INVALID_VAL; + } + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID) { + return MSERR_INVALID_VAL; + } return MSERR_OK; } -std::shared_ptr ScreenCaptureServer::CreateAudioCapture(AudioCaptureInfo audioInfo) +int32_t ScreenCaptureServer::CheckCaptureFileParams() { - AudioCapturerOptions capturerOptions; - std::shared_ptr audioCapture; - capturerOptions.streamInfo.samplingRate = static_cast(audioInfo.audioSampleRate); - capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM; - capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; - capturerOptions.streamInfo.channels = static_cast(audioInfo.audioChannels); - if (audioInfo.audioSource == MIC) { - /* Audio SourceType Mic is 0 */ - capturerOptions.capturerInfo.sourceType = static_cast(audioInfo.audioSource - MIC); - } else { - capturerOptions.capturerInfo.sourceType = static_cast(audioInfo.audioSource); + // For capture file: + // 1. All of innerCapInfo/videoCapInfo/audioEncInfo/videoEncInfo should be be valid + // 2. micCapInfo should not be invalid + CheckAudioCapInfo(captureConfig_.audioInfo.micCapInfo); + CheckAudioCapInfo(captureConfig_.audioInfo.innerCapInfo); + CheckVideoCapInfo(captureConfig_.videoInfo.videoCapInfo); + CheckAudioEncInfo(captureConfig_.audioInfo.audioEncInfo); + CheckVideoEncInfo(captureConfig_.videoInfo.videoEncInfo); + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID || + captureConfig_.videoInfo.videoCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID || + captureConfig_.audioInfo.audioEncInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID || + captureConfig_.videoInfo.videoEncInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID) { + return MSERR_INVALID_VAL; + } + if (captureConfig_.audioInfo.micCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_INVALID) { + return MSERR_INVALID_VAL; + } + if (captureConfig_.audioInfo.micCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_IGNORE) { + return MSERR_OK; } - capturerOptions.capturerInfo.capturerFlags = 0; - uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); - int32_t appUid = IPCSkeleton::GetCallingUid(); - int32_t appPid = IPCSkeleton::GetCallingPid(); - appinfo_.appUid = appUid; - appinfo_.appTokenId = tokenId; - appinfo_.appPid = appPid; - audioCapture = AudioCapturer::Create(capturerOptions, appinfo_); - CHECK_AND_RETURN_RET_LOG(audioCapture != nullptr, nullptr, "initAudioCap failed"); + AudioCaptureInfo &micCapInfo = captureConfig_.audioInfo.micCapInfo; + AudioCaptureInfo &innerCapInfo = captureConfig_.audioInfo.innerCapInfo; + if (micCapInfo.audioSampleRate == innerCapInfo.audioSampleRate && + micCapInfo.audioChannels == innerCapInfo.audioChannels) { + return MSERR_OK; + } + MEDIA_LOGE("CheckCaptureFileParams failed, inner and mic param not consistent"); + return MSERR_INVALID_VAL; +} - int ret = audioCapture->SetCapturerCallback(cb1_); - CHECK_AND_RETURN_RET_LOG(ret != MSERR_OK, nullptr, "SetCapturerCallback failed"); - return audioCapture; +// Should call in ipc thread +void ScreenCaptureServer::InitAppInfo() +{ + appInfo_.appTokenId = IPCSkeleton::GetCallingTokenID(); + appInfo_.appFullTokenId = IPCSkeleton::GetCallingFullTokenID(); + appInfo_.appUid = IPCSkeleton::GetCallingUid(); + appInfo_.appPid = IPCSkeleton::GetCallingPid(); } -int32_t ScreenCaptureServer::InitVideoCap(VideoCaptureInfo videoInfo) +int32_t ScreenCaptureServer::RequestUserPrivacyAuthority() { - std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::InitVideoCap"); - MEDIA_LOGI("ScreenCaptureServer::InitVideoCap start"); - if (!CheckScreenCapturePermission()) { - return MSERR_INVALID_OPERATION; + captureState_ = AVScreenCaptureState::STARTING; + // If Root is treated as whitelisted, how to guarantee RequestUserPrivacyAuthority function by TDD cases. + // Root users should be whitelisted + if (appInfo_.appUid == ROOT_UID) { + MEDIA_LOGI("Root user. Permission Granted"); + return MSERR_OK; } + return StartPrivacyWindow(); +} - int ret = CheckVideoParam(videoInfo); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CheckVideoParam failed"); +int32_t ScreenCaptureServer::OnReceiveUserPrivacyAuthority(bool isAllowed) +{ + // Should callback be running in seperate thread? + std::lock_guard lock(mutex_); + MEDIA_LOGI("OnReceiveUserPrivacyAuthority start, isAllowed:%{public}d, state:%{public}d", isAllowed, captureState_); + if (screenCaptureCb_ == nullptr) { + MEDIA_LOGE("OnReceiveUserPrivacyAuthority failed, screenCaptureCb is nullptr, state:%{public}d", captureState_); + captureState_ = AVScreenCaptureState::STOPPED; + return MSERR_UNKNOWN; + } - videoInfo_ = videoInfo; - if (dataType_ == DataType::CAPTURE_FILE) { - InitRecorder(); + if (captureState_ != AVScreenCaptureState::STARTING) { + MEDIA_LOGE("OnReceiveUserPrivacyAuthority failed, capture is not STARTING"); + screenCaptureCb_->OnError(ScreenCaptureErrorType::SCREEN_CAPTURE_ERROR_INTERNAL, + AVScreenCaptureErrorCode::SCREEN_CAPTURE_ERR_UNKNOWN); + return MSERR_UNKNOWN; + } + if (!isAllowed) { + captureState_ = AVScreenCaptureState::CREATED; + screenCaptureCb_->OnStateChange(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_CANCELED); + return MSERR_UNKNOWN; + } + int32_t ret = OnStartScreenCapture(); + if (ret == MSERR_OK) { + MEDIA_LOGI("OnReceiveUserPrivacyAuthority capture start success"); + captureState_ = AVScreenCaptureState::STARTED; + screenCaptureCb_->OnStateChange(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STARTED); + #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION + ret = StartNotification(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "StartNotification failed"); + #endif + return MSERR_OK; } else { - consumer_ = OHOS::Surface::CreateSurfaceAsConsumer(); + captureState_ = AVScreenCaptureState::STOPPED; + screenCaptureCb_->OnError(ScreenCaptureErrorType::SCREEN_CAPTURE_ERROR_INTERNAL, + AVScreenCaptureErrorCode::SCREEN_CAPTURE_ERR_UNKNOWN); + return MSERR_UNKNOWN; } - if (consumer_ == nullptr) { - MEDIA_LOGE("CreateSurfaceAsConsumer failed"); - return MSERR_NO_MEMORY; +} + +int32_t ScreenCaptureServer::StartAudioCapture() +{ + CHECK_AND_RETURN_RET(captureConfig_.dataType == DataType::ORIGINAL_STREAM, MSERR_INVALID_OPERATION); + std::shared_ptr innerCapture; + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_VALID) { + MediaTrace trace("ScreenCaptureServer::StartAudioCaptureInner"); + innerCapture = std::make_shared(captureConfig_.audioInfo.innerCapInfo, screenCaptureCb_, + std::string("OS_InnerAudioCapture")); + int32_t ret = innerCapture->Start(appInfo_); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "StartAudioCapture innerCapture failed"); + } + std::shared_ptr micCapture; + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_VALID) { + MediaTrace trace("ScreenCaptureServer::StartAudioCaptureMic"); + micCapture = std::make_shared(captureConfig_.audioInfo.micCapInfo, screenCaptureCb_, + std::string("OS_MicAudioCapture")); + int32_t ret = micCapture->Start(appInfo_); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "StartAudioCapture micCapture failed"); + micCapture->SetIsMuted(!isMicrophoneOn_); + } + innerAudioCapture_ = innerCapture; + micAudioCapture_ = micCapture; + return MSERR_OK; +} + +int32_t ScreenCaptureServer::StartScreenCaptureStream() +{ + CHECK_AND_RETURN_RET(captureConfig_.dataType == DataType::ORIGINAL_STREAM, MSERR_INVALID_OPERATION); + + int32_t ret = StartAudioCapture(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "StartAudioCapture failed, ret:%{public}d, dataType:%{public}d", + ret, captureConfig_.dataType); + + ret = StartVideoCapture(); + if (ret != MSERR_OK) { + StopAudioCapture(); + MEDIA_LOGE("StartScreenCaptureStream failed"); + return ret; } - + MEDIA_LOGI("StartScreenCaptureStream success"); + return ret; +} + +int32_t ScreenCaptureServer::StartScreenCaptureFile() +{ + CHECK_AND_RETURN_RET(captureConfig_.dataType == DataType::CAPTURE_FILE, MSERR_INVALID_OPERATION); + + MEDIA_LOGI("StartScreenCaptureFile S"); + int32_t ret = InitRecorder(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitRecorder failed, ret:%{public}d, dataType:%{public}d", + ret, captureConfig_.dataType); + + ON_SCOPE_EXIT(0) { + if (recorder_ != nullptr) { + recorder_->Release(); + recorder_ = nullptr; + consumer_ = nullptr; + } + }; + std::string virtualScreenName = "screen_capture_file"; + ret = CreateVirtualScreen(virtualScreenName, consumer_); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "CreateVirtualScreen failed, ret:%{public}d, dataType:%{public}d", + ret, captureConfig_.dataType); + + ON_SCOPE_EXIT(1) { + DestroyVirtualScreen(); + }; + + MEDIA_LOGI("StartScreenCaptureFile RecorderServer S"); + ret = recorder_->Start(); + MEDIA_LOGI("StartScreenCaptureFile RecorderServer E"); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "recorder failed, ret:%{public}d, dataType:%{public}d", + ret, captureConfig_.dataType); + CANCEL_SCOPE_EXIT_GUARD(1); + CANCEL_SCOPE_EXIT_GUARD(0); + + MEDIA_LOGI("StartScreenCaptureFile E"); + return ret; +} + +int32_t ScreenCaptureServer::OnStartScreenCapture() +{ + MediaTrace trace("ScreenCaptureServer::OnStartScreenCapture"); + MEDIA_LOGI("OnStartScreenCapture start, dataType:%{public}d", captureConfig_.dataType); + int32_t ret = MSERR_UNSUPPORT; + if (captureConfig_.dataType == DataType::ORIGINAL_STREAM) { + ret = StartScreenCaptureStream(); + } + if (captureConfig_.dataType == DataType::CAPTURE_FILE) { + ret = StartScreenCaptureFile(); + } + if (ret == MSERR_OK) { + if (!UpdatePrivacyUsingPermissionState(START_VIDEO)) { + MEDIA_LOGE("UpdatePrivacyUsingPermissionState START failed, dataType:%{public}d", captureConfig_.dataType); + } + BehaviorEventWriteForScreenCapture("start", "AVScreenCapture", appInfo_.appUid, appInfo_.appPid); + } else { + MEDIA_LOGE("OnStartScreenCapture start failed, dataType:%{public}d", captureConfig_.dataType); + } + return ret; +} + +int32_t ScreenCaptureServer::InitAudioCap(AudioCaptureInfo audioInfo) +{ + std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "InitAudioCap failed, capture is not CREATED, state:%{public}d", captureState_); + + int ret = CheckAudioCapInfo(audioInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitAudioCap CheckAudioCapInfo failed, audioSource:%{public}d", + audioInfo.audioSource); + if (audioInfo.audioSource == AudioCaptureSourceType::SOURCE_DEFAULT || + audioInfo.audioSource == AudioCaptureSourceType::MIC) { + captureConfig_.audioInfo.micCapInfo = audioInfo; + } else if (audioInfo.audioSource == AudioCaptureSourceType::ALL_PLAYBACK || + audioInfo.audioSource == AudioCaptureSourceType::APP_PLAYBACK) { + captureConfig_.audioInfo.innerCapInfo = audioInfo; + } + MEDIA_LOGI("InitAudioCap success sampleRate:%{public}d, channels:%{public}d, source:%{public}d, state:%{public}d", + audioInfo.audioSampleRate, audioInfo.audioChannels, audioInfo.audioSource, audioInfo.state); + return MSERR_OK; +} + +int32_t ScreenCaptureServer::InitVideoCap(VideoCaptureInfo videoInfo) +{ + std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "InitVideoCap failed, capture is not CREATED, state:%{public}d", captureState_); + + int ret = CheckVideoCapInfo(videoInfo); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "InitVideoCap CheckVideoCapInfo failed"); + captureConfig_.videoInfo.videoCapInfo = videoInfo; + MEDIA_LOGI("InitVideoCap success width:%{public}d, height:%{public}d, source:%{public}d, state:%{public}d", + videoInfo.videoFrameWidth, videoInfo.videoFrameHeight, videoInfo.videoSource, videoInfo.state); return MSERR_OK; } int32_t ScreenCaptureServer::InitRecorder() { CHECK_AND_RETURN_RET_LOG(outputFd_>0, MSERR_INVALID_OPERATION, "the outputFd is invalid"); - MEDIA_LOGI("recorder start init"); + MEDIA_LOGI("InitRecorder start"); + MediaTrace trace("ScreenCaptureServer::InitRecorder"); recorder_ = Media::RecorderServer::Create(); CHECK_AND_RETURN_RET_LOG(recorder_ != nullptr, MSERR_UNKNOWN, "init Recoder failed"); - int32_t ret = MSERR_OK; - ret = recorder_->SetVideoSource(videoInfo_.videoSource, videoSourceId_); + ON_SCOPE_EXIT(0) { + recorder_->Release(); + }; + int32_t ret = recorder_->SetVideoSource(captureConfig_.videoInfo.videoCapInfo.videoSource, videoSourceId_); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioSource failed"); - if (audioInfo_.audioSource == AudioCaptureSourceType::SOURCE_DEFAULT || - audioInfo_.audioSource == AudioCaptureSourceType::MIC) { - ret = recorder_->SetAudioSource(AudioSourceType::AUDIO_MIC, audioSourceId_); - } else if (audioInfo_.audioSource == AudioCaptureSourceType::ALL_PLAYBACK || - audioInfo_.audioSource == AudioCaptureSourceType::APP_PLAYBACK) { + AudioCaptureInfo audioInfo; + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_VALID) { + audioInfo = captureConfig_.audioInfo.innerCapInfo; ret = recorder_->SetAudioSource(AudioSourceType::AUDIO_INNER, audioSourceId_); + } else if (captureConfig_.audioInfo.micCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_VALID) { + audioInfo = captureConfig_.audioInfo.micCapInfo; + ret = recorder_->SetAudioSource(AudioSourceType::AUDIO_MIC, audioSourceId_); } CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioSource failed"); ret = recorder_->SetOutputFormat(fileFormat_); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetOutputFormat failed"); - ret = recorder_->SetAudioEncoder(audioSourceId_, audioEncInfo_.audioCodecformat); + ret = recorder_->SetAudioEncoder(audioSourceId_, captureConfig_.audioInfo.audioEncInfo.audioCodecformat); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioEncoder failed"); - ret = recorder_->SetAudioSampleRate(audioSourceId_, audioInfo_.audioSampleRate); + ret = recorder_->SetAudioSampleRate(audioSourceId_, audioInfo.audioSampleRate); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioSampleRate failed"); - ret = recorder_->SetAudioChannels(audioSourceId_, audioInfo_.audioChannels); + ret = recorder_->SetAudioChannels(audioSourceId_, audioInfo.audioChannels); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioChannels failed"); - ret = recorder_->SetAudioEncodingBitRate(audioSourceId_, audioEncInfo_.audioBitrate); + ret = recorder_->SetAudioEncodingBitRate(audioSourceId_, captureConfig_.audioInfo.audioEncInfo.audioBitrate); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetAudioEncodingBitRate failed"); - ret = recorder_->SetVideoEncoder(videoSourceId_, videoEncInfo_.videoCodec); + ret = recorder_->SetVideoEncoder(videoSourceId_, captureConfig_.videoInfo.videoEncInfo.videoCodec); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetVideoEncoder failed"); - ret = recorder_->SetVideoSize(videoSourceId_, videoInfo_.videoFrameWidth, videoInfo_.videoFrameHeight); + ret = recorder_->SetVideoSize(videoSourceId_, captureConfig_.videoInfo.videoCapInfo.videoFrameWidth, + captureConfig_.videoInfo.videoCapInfo.videoFrameHeight); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetVideoSize failed"); - ret = recorder_->SetVideoFrameRate(videoSourceId_, videoEncInfo_.videoFrameRate); + ret = recorder_->SetVideoFrameRate(videoSourceId_, captureConfig_.videoInfo.videoEncInfo.videoFrameRate); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetVideoFrameRate failed"); - ret = recorder_->SetVideoEncodingBitRate(videoSourceId_, videoEncInfo_.videoBitrate); + ret = recorder_->SetVideoEncodingBitRate(videoSourceId_, captureConfig_.videoInfo.videoEncInfo.videoBitrate); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetVideoEncodingBitRate failed"); ret = recorder_->SetOutputFile(outputFd_); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "SetOutputFile failed"); @@ -491,96 +773,65 @@ int32_t ScreenCaptureServer::InitRecorder() CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "recorder Prepare failed"); consumer_ = recorder_->GetSurface(videoSourceId_); CHECK_AND_RETURN_RET_LOG(consumer_ != nullptr, MSERR_UNKNOWN, "recorder GetSurface failed"); - MEDIA_LOGI("recorder prepare success"); + CANCEL_SCOPE_EXIT_GUARD(0); + MEDIA_LOGI("InitRecorder success"); return MSERR_OK; } -bool ScreenCaptureServer::GetUsingPermissionFromPrivacy(VideoPermissionState state) +bool ScreenCaptureServer::UpdatePrivacyUsingPermissionState(VideoPermissionState state) { - auto callerUid = IPCSkeleton::GetCallingUid(); // Root users should be whitelisted - if (callerUid == ROOT_UID) { + if (appInfo_.appUid == ROOT_UID) { MEDIA_LOGI("Root user. Privacy Granted"); return true; } - if (clientTokenId == 0) { - clientTokenId = IPCSkeleton::GetCallingTokenID(); - } int res = 0; if (state == START_VIDEO) { - res = PrivacyKit::StartUsingPermission(clientTokenId, "ohos.permission.CAPTURE_SCREEN"); + res = PrivacyKit::StartUsingPermission(appInfo_.appTokenId, "ohos.permission.CAPTURE_SCREEN"); if (res != 0) { - MEDIA_LOGE("start using perm error for client %{public}d", clientTokenId); + MEDIA_LOGE("start using perm error for client %{public}d", appInfo_.appTokenId); } } else if (state == STOP_VIDEO) { - res = PrivacyKit::StopUsingPermission(clientTokenId, "ohos.permission.CAPTURE_SCREEN"); + res = PrivacyKit::StopUsingPermission(appInfo_.appTokenId, "ohos.permission.CAPTURE_SCREEN"); if (res != 0) { - MEDIA_LOGE("stop using perm error for client %{public}d", clientTokenId); + MEDIA_LOGE("stop using perm error for client %{public}d", appInfo_.appTokenId); } } return true; } -int32_t ScreenCaptureServer::StartScreenCapture() +int32_t ScreenCaptureServer::StartScreenCaptureInner(bool isPrivacyAuthorityEnabled) { - std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::StartScreenCapture"); - MEDIA_LOGI("ScreenCaptureServer::StartScreenCapture start"); + MediaTrace trace("ScreenCaptureServer::StartScreenCaptureInner"); + int32_t ret = CheckAllParams(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "StartScreenCaptureInner failed, invalid params"); - isSurfaceMode_ = false; + isPrivacyAuthorityEnabled_ = isPrivacyAuthorityEnabled; + if (isPrivacyAuthorityEnabled) { #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION - StartPrivacyWindow(); + return RequestUserPrivacyAuthority(); #else - StartScreenCaptureInner(); - #endif - return MSERR_OK; -} - -int32_t ScreenCaptureServer::StartScreenCaptureInner() -{ - #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION - std::lock_guard lock(mutex_); + MEDIA_LOGE("StartScreenCaptureInner privacy notification window not support, check CAPTURE_SCREEN permission"); + isPrivacyAuthorityEnabled_ = false; #endif - MediaTrace trace("ScreenCaptureServer::StartScreenCapture"); - MEDIA_LOGI("ScreenCaptureServer::StartScreenCaptureInner start"); - - isAudioStart_ = true; - if (audioMicCapturer_ != nullptr) { - if (!audioMicCapturer_->Start()) { - MEDIA_LOGE("Start mic audio stream failed"); - audioMicCapturer_->Release(); - audioMicCapturer_ = nullptr; - isAudioStart_ = false; - } - if (isAudioStart_) { - MEDIA_LOGE("Capturing started"); - isRunning_.store(true); - readAudioLoop_ = std::make_unique(&ScreenCaptureServer::StartAudioCapture, this); - } } - isAudioInnerStart_ = true; - if (audioInnerCapturer_ != nullptr) { - if (!audioInnerCapturer_->Start()) { - MEDIA_LOGE("Start inner audio stream failed"); - audioInnerCapturer_->Release(); - audioInnerCapturer_ = nullptr; - isAudioInnerStart_ = false; - } - if (isAudioInnerStart_) { - MEDIA_LOGE("Capturing started"); - isInnerRunning_.store(true); - readInnerAudioLoop_ = std::make_unique(&ScreenCaptureServer::StartAudioInnerCapture, this); - } + if (!CheckScreenCapturePermission()) { + captureState_ = AVScreenCaptureState::STOPPED; + MEDIA_LOGE("StartScreenCaptureInner CheckScreenCapturePermission failed"); + return MSERR_INVALID_OPERATION; } - int32_t ret = StartVideoCapture(); + + ret = OnStartScreenCapture(); if (ret == MSERR_OK) { - BehaviorEventWriteForScreenCapture("start", "AVScreenCapture", appinfo_.appUid, appinfo_.appPid); + MEDIA_LOGI("StartScreenCaptureInner OnStartScreenCapture success"); + captureState_ = AVScreenCaptureState::STARTED; + } else { + isPrivacyAuthorityEnabled_ = false; + isSurfaceMode_ = false; + captureState_ = AVScreenCaptureState::STOPPED; + MEDIA_LOGE("StartScreenCaptureInner OnStartScreenCapture failed"); } - #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION - ret = StartNotification(); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "StartNotification failed"); - #endif return ret; } @@ -588,15 +839,14 @@ int32_t ScreenCaptureServer::StartPrivacyWindow() { std::string comStr = "{\"ability.want.params.uiExtensionType\":\"sys/commonUI\",\"sessionId\":\""; comStr += std::to_string(sessionId_).c_str(); - auto callerUid = IPCSkeleton::GetCallingUid(); comStr += "\",\"callerUid\":\""; - comStr += std::to_string(callerUid).c_str(); + comStr += std::to_string(appInfo_.appUid).c_str(); comStr += "\"}"; AAFwk::Want want; - want.SetElementName(bundleName_, abilityName_); + want.SetElementName(BUNDLE_NAME, ABILITY_NAME); auto connection_ = sptr(new (std::nothrow) UIExtensionAbilityConnection(comStr)); - auto ret = OHOS::AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want, connection_,\ + auto ret = OHOS::AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want, connection_, nullptr, -1); MEDIA_LOGI("ConnectServiceExtensionAbility end %{public}d", ret); return MSERR_OK; @@ -657,11 +907,11 @@ std::shared_ptr ScreenCaptureServer::GetLocalL localLiveViewContent->addFlag(NotificationLocalLiveViewContent::LiveViewContentInner::TIME); auto testButton = NotificationLocalLiveViewButton(); - testButton.addSingleButtonName(buttonNameMic_); + testButton.addSingleButtonName(BUTTON_NAME_MIC); std::shared_ptr pixelMapSpr = GetPixelMap(ICON_PATH_MIC); testButton.addSingleButtonIcon(pixelMapSpr); - testButton.addSingleButtonName(buttonNameStop_); + testButton.addSingleButtonName(BUTTON_NAME_STOP); std::shared_ptr pixelMapStopSpr = GetPixelMap(ICON_PATH_STOP); testButton.addSingleButtonIcon(pixelMapStopSpr); @@ -684,91 +934,79 @@ std::shared_ptr ScreenCaptureServer::GetPixelMap(std::string path) return pixelMapSpr; } -int32_t ScreenCaptureServer::StartScreenCaptureWithSurface(sptr surface) +int32_t ScreenCaptureServer::StartScreenCapture(bool isPrivacyAuthorityEnabled) { std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::StartScreenCaptureWithSurface"); - MEDIA_LOGI("ScreenCaptureServer::StartScreenCaptureWithSurface start"); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "StartScreenCapture failed, capture is not CREATED, state:%{public}d", captureState_); + MEDIA_LOGI("StartScreenCapture isPrivacyAuthorityEnabled:%{public}d", isPrivacyAuthorityEnabled); + isSurfaceMode_ = false; + return StartScreenCaptureInner(isPrivacyAuthorityEnabled); +} +int32_t ScreenCaptureServer::StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) +{ + std::lock_guard lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "StartScreenCapture failed, capture is not CREATED, state:%{public}d", captureState_); + MEDIA_LOGI("StartScreenCapture isPrivacyAuthorityEnabled:%{public}d", isPrivacyAuthorityEnabled); + if (surface == nullptr) { + MEDIA_LOGE("surface is nullptr"); + return MSERR_INVALID_OPERATION; + } surface_ = surface; isSurfaceMode_ = true; - - #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION - StartPrivacyWindow(); - #else - StartScreenCaptureInner(); - #endif - return MSERR_OK; + return StartScreenCaptureInner(isPrivacyAuthorityEnabled); } int32_t ScreenCaptureServer::StartVideoCapture() { - if (!GetUsingPermissionFromPrivacy(START_VIDEO)) { - MEDIA_LOGE("getUsingPermissionFromPrivacy"); - } - if (captureMode_ == CAPTURE_HOME_SCREEN || captureMode_ == CAPTURE_SPECIFIED_SCREEN || - captureMode_ == CAPTURE_SPECIFIED_WINDOW) { - if (dataType_ == DataType::CAPTURE_FILE) { - return StartHomeVideoCaptureFile(); - } else { - return StartHomeVideoCapture(); - } - } else { - MEDIA_LOGE("The capture Mode Init still not supported,start failed"); - return MSERR_UNSUPPORT; + if (captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_IGNORE) { + MEDIA_LOGI("StartVideoCapture is ignored"); + return MSERR_OK; } + CHECK_AND_RETURN_RET_LOG( + captureConfig_.audioInfo.innerCapInfo.state == AVScreenCaptureParamValidationState::VALIDATION_VALID, + MSERR_INVALID_VAL, "StartScreenCapture failed, invalid param, dataType:%{public}d", captureConfig_.dataType); + + int32_t ret = StartHomeVideoCapture(); + CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, + "StartHomeVideoCapture failed, invalid param, dataType:%{public}d", captureConfig_.dataType); return MSERR_OK; } int32_t ScreenCaptureServer::StartHomeVideoCapture() { - if (consumer_ == nullptr) { - MEDIA_LOGE("consumer_ is not created"); - return MSERR_INVALID_OPERATION; - } - surfaceCb_ = new ScreenCapBufferConsumerListener(consumer_, screenCaptureCb_); - consumer_->RegisterConsumerListener((sptr &)surfaceCb_); - auto producer = consumer_->GetProducer(); - auto psurface = OHOS::Surface::CreateSurfaceAsProducer(producer); - CHECK_AND_RETURN_RET_LOG(psurface != nullptr, MSERR_UNKNOWN, "CreateSurfaceAsProducer failed"); - std::string virtualScreenName = "screen_capture"; - if (isSurfaceMode_ == false) { - int32_t ret = CreateVirtualScreen(virtualScreenName, psurface); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "create virtual screen failed"); - } else { + if (isSurfaceMode_) { int32_t ret = CreateVirtualScreen(virtualScreenName, surface_); CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "create virtual screen with surface failed"); + return MSERR_OK; } - return MSERR_OK; -} - -int32_t ScreenCaptureServer::StartHomeVideoCaptureFile() -{ - if (recorder_ == nullptr) { - MEDIA_LOGE("recorder_ is not created"); - return MSERR_INVALID_OPERATION; - } - if (consumer_ == nullptr) { - MEDIA_LOGE("consumer_ is not created"); - return MSERR_INVALID_OPERATION; - } - - std::string virtualScreenName = "screen_capture_file"; - int32_t ret = CreateVirtualScreen(virtualScreenName, consumer_); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "create virtual screen failed"); - - ret = recorder_->Start(); - CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_UNKNOWN, "recorder Start failed"); - MEDIA_LOGI("recorder start success"); - + ON_SCOPE_EXIT(0) { + DestroyVirtualScreen(); + consumer_ = nullptr; + surfaceCb_ = nullptr; + }; + consumer_ = OHOS::Surface::CreateSurfaceAsConsumer(); + CHECK_AND_RETURN_RET_LOG(consumer_ != nullptr, MSERR_UNKNOWN, "CreateSurfaceAsConsumer failed"); + auto producer = consumer_->GetProducer(); + CHECK_AND_RETURN_RET_LOG(producer != nullptr, MSERR_UNKNOWN, "GetProducer failed"); + auto producerSurface = OHOS::Surface::CreateSurfaceAsProducer(producer); + CHECK_AND_RETURN_RET_LOG(producerSurface != nullptr, MSERR_UNKNOWN, "CreateSurfaceAsProducer failed"); + + surfaceCb_ = OHOS::sptr::MakeSptr(consumer_, screenCaptureCb_); + CHECK_AND_RETURN_RET_LOG(surfaceCb_ != nullptr, MSERR_UNKNOWN, "MakeSptr surfaceCb_ failed"); + consumer_->RegisterConsumerListener(surfaceCb_); + CANCEL_SCOPE_EXIT_GUARD(0); return MSERR_OK; } int32_t ScreenCaptureServer::CreateVirtualScreen(const std::string &name, sptr consumer) { - isConsumerStart_ = true; + MEDIA_LOGI("CreateVirtualScreen Start"); + isConsumerStart_ = false; VirtualScreenOption virScrOption = InitVirtualScreenOption(name, consumer); sptr display = Rosen::DisplayManager::GetInstance().GetDefaultDisplaySync(); if (display != nullptr) { @@ -776,53 +1014,95 @@ int32_t ScreenCaptureServer::CreateVirtualScreen(const std::string &name, sptrGetHeight(), display->GetDpi()); virScrOption.density_ = display->GetDpi(); } - if (missionIds_.size() > 0 && captureMode_ == CAPTURE_SPECIFIED_WINDOW) { + if (missionIds_.size() > 0 && captureConfig_.captureMode == CAPTURE_SPECIFIED_WINDOW) { virScrOption.missionIds_ = missionIds_; } else { - if (videoInfo_.taskIDs.size() > 0 && captureMode_ == CAPTURE_SPECIFIED_WINDOW) { + if (captureConfig_.videoInfo.videoCapInfo.taskIDs.size() > 0 && + captureConfig_.captureMode == CAPTURE_SPECIFIED_WINDOW) { GetMissionIds(missionIds_); virScrOption.missionIds_ = missionIds_; } } screenId_ = ScreenManager::GetInstance().CreateVirtualScreen(virScrOption); - if (screenId_ < 0) { - isConsumerStart_ = false; - MEDIA_LOGE("CreateVirtualScreen failed"); - return MSERR_INVALID_OPERATION; - } + CHECK_AND_RETURN_RET_LOG(screenId_ >= 0, MSERR_UNKNOWN, "CreateVirtualScreen failed"); + auto screen = ScreenManager::GetInstance().GetScreenById(screenId_); if (screen == nullptr) { - isConsumerStart_ = false; MEDIA_LOGE("GetScreenById failed"); - return MSERR_INVALID_OPERATION; + DestroyVirtualScreen(); + return MSERR_UNKNOWN; } + + int32_t ret = MakeVirtualScreenMirror(); + if (ret != MSERR_OK) { + MEDIA_LOGE("MakeVirtualScreenMirror failed"); + DestroyVirtualScreen(); + return MSERR_UNKNOWN; + } + + isConsumerStart_ = true; MEDIA_LOGI("CreateVirtualScreen success"); + return MSERR_OK; +} + +int32_t ScreenCaptureServer::MakeVirtualScreenMirror() +{ + CHECK_AND_RETURN_RET_LOG(screenId_ >= 0 && screenId_ != SCREEN_ID_INVALID, MSERR_UNKNOWN, + "MakeVirtualScreenMirror failed, invalid screenId"); std::vector> screens; ScreenManager::GetInstance().GetAllScreens(screens); std::vector mirrorIds; mirrorIds.push_back(screenId_); ScreenId mirrorGroup = static_cast(1); - if (captureMode_ == CAPTURE_SPECIFIED_SCREEN) { - for (uint32_t i = 0; i < screens.size() ; i++) { - if (screens[i]->GetId() == videoInfo_.displayId) { - ScreenManager::GetInstance().MakeMirror(screens[i]->GetId(), mirrorIds, mirrorGroup); - MEDIA_LOGI("MakeMirror extand screen success"); - return MSERR_OK; - } + DMError ret = DMError::DM_OK; + if (captureConfig_.captureMode != CAPTURE_SPECIFIED_SCREEN) { + ret = ScreenManager::GetInstance().MakeMirror(screens[0]->GetId(), mirrorIds, mirrorGroup); + MEDIA_LOGI("MakeVirtualScreenMirror main screen"); + } + for (uint32_t i = 0; i < screens.size() ; i++) { + if (screens[i]->GetId() == captureConfig_.videoInfo.videoCapInfo.displayId) { + ret = ScreenManager::GetInstance().MakeMirror(screens[i]->GetId(), mirrorIds, mirrorGroup); + MEDIA_LOGI("MakeVirtualScreenMirror extand screen"); + break; + } + } + if (ret == DMError::DM_OK) { + MEDIA_LOGI("MakeMirror success"); + return MSERR_OK; + } else { + MEDIA_LOGI("MakeMirror fail"); + return MSERR_UNKNOWN; + } +} + +void ScreenCaptureServer::DestroyVirtualScreen() +{ + if (screenId_ >=0 && screenId_ != SCREEN_ID_INVALID) { + if (isConsumerStart_) { + std::vector screenIds; + screenIds.push_back(screenId_); + ScreenManager::GetInstance().StopMirror(screenIds); } + ScreenManager::GetInstance().DestroyVirtualScreen(screenId_); + screenId_ = SCREEN_ID_INVALID; + isConsumerStart_ = false; } - ScreenManager::GetInstance().MakeMirror(screens[0]->GetId(), mirrorIds, mirrorGroup); - MEDIA_LOGI("MakeMirror main screen success"); - return MSERR_OK; } +void ScreenCaptureServer::CloseFd() +{ + if (outputFd_ > 0) { + (void)::close(outputFd_); + outputFd_ = -1; + } +} VirtualScreenOption ScreenCaptureServer::InitVirtualScreenOption(const std::string &name, sptr consumer) { VirtualScreenOption virScrOption = { .name_ = name, - .width_ = videoInfo_.videoFrameWidth, - .height_ = videoInfo_.videoFrameHeight, + .width_ = captureConfig_.videoInfo.videoCapInfo.videoFrameWidth, + .height_ = captureConfig_.videoInfo.videoCapInfo.videoFrameHeight, .density_ = 0, .surface_ = consumer, .flags_ = 0, @@ -834,8 +1114,8 @@ VirtualScreenOption ScreenCaptureServer::InitVirtualScreenOption(const std::stri int32_t ScreenCaptureServer::GetMissionIds(std::vector &missionIds) { - int32_t size = videoInfo_.taskIDs.size(); - std::list taskIDListTemp = videoInfo_.taskIDs; + int32_t size = captureConfig_.videoInfo.videoCapInfo.taskIDs.size(); + std::list taskIDListTemp = captureConfig_.videoInfo.videoCapInfo.taskIDs; for (int32_t i = 0; i < size; i++) { int32_t taskId = taskIDListTemp.front(); taskIDListTemp.pop_front(); @@ -846,177 +1126,52 @@ int32_t ScreenCaptureServer::GetMissionIds(std::vector &missionIds) return MSERR_OK; } -int32_t ScreenCaptureServer::StartAudioInnerCapture() +int32_t ScreenCaptureServer::AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) { - size_t bufferLen; - CHECK_AND_RETURN_RET_LOG(audioInnerCapturer_ != nullptr, MSERR_NO_MEMORY, "audioInner capture is nullptr"); - if (audioInnerCapturer_->GetBufferSize(bufferLen) < 0) { - MEDIA_LOGE("audioMicCapturer_ GetBufferSize failed"); - return MSERR_NO_MEMORY; - } - int32_t bufferRead = 0; - Timestamp timestamp; - int64_t audioTime; - - while (true) { - if (audioInnerCapturer_ == nullptr || !(isAudioInnerStart_) || !(isInnerRunning_.load())) { - MEDIA_LOGI("audioInnerCapturer_ has been released, end the capture!!"); - break; - } - uint8_t *buffer = static_cast(malloc(bufferLen)); - if (buffer == nullptr) - return MSERR_NO_MEMORY; - memset_s(buffer, bufferLen, 0, bufferLen); - bufferRead = audioInnerCapturer_->Read(*buffer, bufferLen, true); - if (bufferRead <= 0) { - free(buffer); - buffer = nullptr; - MEDIA_LOGE("read audioBuffer failed, continue"); - continue; - } - audioInnerCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC); - audioTime = timestamp.time.tv_nsec + timestamp.time.tv_sec * SEC_TO_NANOSECOND; - std::unique_lock lock(audioInnerMutex_); - if (availableInnerAudioBuffers_.size() > MAX_AUDIO_BUFFER_SIZE) { - free(buffer); - buffer = nullptr; - MEDIA_LOGE("no client consumer the buffer, drop the frame!!"); - continue; - } - availableInnerAudioBuffers_.push(std::make_unique(buffer, bufferRead, - audioTime, audioCurrentInnerType_)); - if (screenCaptureCb_ != nullptr) { - std::lock_guard cbLock(cbMutex_); - screenCaptureCb_->OnAudioBufferAvailable(true, audioCurrentInnerType_); - } - bufferInnerCond_.notify_all(); - } - return MSERR_OK; -} + std::unique_lock lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "AcquireAudioBuffer failed, capture is not STARTED, state:%{public}d, type:%{public}d", captureState_, type); -int32_t ScreenCaptureServer::StartAudioCapture() -{ - size_t bufferLen; - CHECK_AND_RETURN_RET_LOG(audioMicCapturer_ != nullptr, MSERR_NO_MEMORY, "audiomic capture is nullptr"); - if (audioMicCapturer_->GetBufferSize(bufferLen) < 0) { - MEDIA_LOGE("audioMicCapturer_ GetBufferSize failed"); - return MSERR_NO_MEMORY; - } - int32_t bufferRead = 0; - Timestamp timestamp; - int64_t audioTime; - while (true) { - if (audioMicCapturer_ == nullptr || !(isAudioStart_) || !(isRunning_.load())) { - MEDIA_LOGI("audioMicCapturer_ has been released,end the capture!!"); - break; - } - uint8_t *buffer = static_cast(malloc(bufferLen)); - if (buffer == nullptr) - return MSERR_NO_MEMORY; - memset_s(buffer, bufferLen, 0, bufferLen); - bufferRead = audioMicCapturer_->Read(*buffer, bufferLen, true); - if (bufferRead <= 0) { - free(buffer); - buffer = nullptr; - MEDIA_LOGE("read audioBuffer failed,continue"); - continue; - } - audioMicCapturer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC); - audioTime = timestamp.time.tv_nsec + timestamp.time.tv_sec * SEC_TO_NANOSECOND; - std::unique_lock lock(audioMutex_); - if (availableAudioBuffers_.size() > MAX_AUDIO_BUFFER_SIZE) { - free(buffer); - buffer = nullptr; - MEDIA_LOGE("no client consumer the buffer, drop the frame!!"); - continue; - } - if (!isMicrophoneOn) { - memset_s(buffer, bufferLen, 0, bufferLen); - availableAudioBuffers_.push(std::make_unique(buffer, bufferRead, audioTime, MIC)); - } else { - availableAudioBuffers_.push(std::make_unique(buffer, bufferRead, audioTime, MIC)); - } - if (screenCaptureCb_ != nullptr) { - std::lock_guard cbLock(cbMutex_); - screenCaptureCb_->OnAudioBufferAvailable(true, MIC); - } - bufferCond_.notify_all(); + if (((type == AudioCaptureSourceType::MIC) || (type == AudioCaptureSourceType::SOURCE_DEFAULT)) && + micAudioCapture_ != nullptr) { + return micAudioCapture_->AcquireAudioBuffer(audioBuffer); } - return MSERR_OK; -} - -int32_t ScreenCaptureServer::AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) -{ - if ((type == MIC) || (type == SOURCE_DEFAULT)) { - using namespace std::chrono_literals; - std::unique_lock alock(audioMutex_); - if (availableAudioBuffers_.empty()) { - if (bufferCond_.wait_for(alock, 200ms) == std::cv_status::timeout) { - MEDIA_LOGE("AcquireAudioBuffer timeout return!"); - return MSERR_UNKNOWN; - } - } - if (availableAudioBuffers_.front() != nullptr) { - audioBuffer = availableAudioBuffers_.front(); - return MSERR_OK; - } - } else if ((type == ALL_PLAYBACK) || (type == APP_PLAYBACK)) { - using namespace std::chrono_literals; - std::unique_lock alock(audioInnerMutex_); - if (availableInnerAudioBuffers_.empty()) { - if (bufferInnerCond_.wait_for(alock, 200ms) == std::cv_status::timeout) { - MEDIA_LOGE("AcquireAudioBuffer timeout return!"); - return MSERR_UNKNOWN; - } - } - if (availableInnerAudioBuffers_.front() != nullptr) { - audioBuffer = availableInnerAudioBuffers_.front(); - return MSERR_OK; - } - } else { - MEDIA_LOGE("The Type you request not support"); - return MSERR_UNSUPPORT; + if (((type == AudioCaptureSourceType::ALL_PLAYBACK) || (type == AudioCaptureSourceType::APP_PLAYBACK)) && + innerAudioCapture_ != nullptr) { + return innerAudioCapture_->AcquireAudioBuffer(audioBuffer); } + MEDIA_LOGE("AcquireAudioBuffer failed, source type not support, type:%{public}d", type); return MSERR_UNKNOWN; } int32_t ScreenCaptureServer::ReleaseAudioBuffer(AudioCaptureSourceType type) { - if (type == MIC) { - std::unique_lock alock(audioMutex_); - if (availableAudioBuffers_.empty()) { - MEDIA_LOGE("availableAudioBuffers_ is empty, no frame need release"); - return MSERR_OK; - } - if (availableAudioBuffers_.front() != nullptr) { - free(availableAudioBuffers_.front()->buffer); - availableAudioBuffers_.front()->buffer = nullptr; - } - availableAudioBuffers_.pop(); - } else if ((type == ALL_PLAYBACK) || (type == APP_PLAYBACK)) { - std::unique_lock alock(audioInnerMutex_); - if (availableInnerAudioBuffers_.empty()) { - MEDIA_LOGE("availableAudioBuffers_ is empty, no frame need release"); - return MSERR_OK; - } - if (availableInnerAudioBuffers_.front() != nullptr) { - free(availableInnerAudioBuffers_.front()->buffer); - availableInnerAudioBuffers_.front()->buffer = nullptr; - } - availableInnerAudioBuffers_.pop(); - } else { - MEDIA_LOGE("The Type you release not support"); - return MSERR_UNSUPPORT; + std::unique_lock lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "ReleaseAudioBuffer failed, capture is not STARTED, state:%{public}d, type:%{public}d", captureState_, type); + + if (((type == AudioCaptureSourceType::MIC) || (type == AudioCaptureSourceType::SOURCE_DEFAULT)) && + micAudioCapture_ != nullptr) { + return micAudioCapture_->ReleaseAudioBuffer(); } - return MSERR_OK; + if (((type == AudioCaptureSourceType::ALL_PLAYBACK) || (type == AudioCaptureSourceType::APP_PLAYBACK)) && + innerAudioCapture_ != nullptr) { + return innerAudioCapture_->ReleaseAudioBuffer(); + } + MEDIA_LOGE("ReleaseAudioBuffer failed, source type not support, type:%{public}d", type); + return MSERR_UNKNOWN; } int32_t ScreenCaptureServer::AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, int64_t ×tamp, OHOS::Rect &damage) { - CHECK_AND_RETURN_RET_LOG(surfaceCb_ != nullptr, MSERR_NO_MEMORY, - "Failed to AcquireVideoBuffer,no callback object"); - surfaceCb_->AcquireVideoBuffer(surfaceBuffer, fence, timestamp, damage); + std::unique_lock lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "AcquireVideoBuffer failed, capture is not STARTED, state:%{public}d", captureState_); + + CHECK_AND_RETURN_RET_LOG(surfaceCb_ != nullptr, MSERR_NO_MEMORY, "AcquireVideoBuffer failed, callback is nullptr"); + (static_cast(surfaceCb_.GetRefPtr()))-> + AcquireVideoBuffer(surfaceBuffer, fence, timestamp, damage); if (surfaceBuffer != nullptr) { MEDIA_LOGD("getcurrent surfaceBuffer info, size:%{public}u", surfaceBuffer->GetSize()); return MSERR_OK; @@ -1026,17 +1181,41 @@ int32_t ScreenCaptureServer::AcquireVideoBuffer(sptr &surfa int32_t ScreenCaptureServer::ReleaseVideoBuffer() { - CHECK_AND_RETURN_RET_LOG(surfaceCb_ != nullptr, MSERR_NO_MEMORY, - "Failed to ReleaseVideoBuffer,no callback object"); - return surfaceCb_->ReleaseVideoBuffer(); + std::unique_lock lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "AcquireVideoBuffer failed, capture is not STARTED, state:%{public}d", captureState_); + + CHECK_AND_RETURN_RET_LOG(surfaceCb_ != nullptr, MSERR_NO_MEMORY, "AcquireVideoBuffer failed, callback is nullptr"); + return (static_cast(surfaceCb_.GetRefPtr()))->ReleaseVideoBuffer(); +} + +int32_t ScreenCaptureServer::ExcludeContent(ScreenCaptureContentFilter &contentFilter) +{ + std::unique_lock lock(mutex_); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::CREATED, MSERR_INVALID_OPERATION, + "AcquireVideoBuffer failed, capture is not STARTED, state:%{public}d", captureState_); + + MEDIA_LOGI("ScreenCaptureServer::SetMicrophoneEnabled start"); + contentFilter_ = contentFilter; + + // For the moment, not support: + // For STREAM, should call AudioCapturer interface to make effect when start + // For CAPTURE FILE, should call Recorder interface to make effect when start + return MSERR_UNSUPPORT; } int32_t ScreenCaptureServer::SetMicrophoneEnabled(bool isMicrophone) { std::lock_guard lock(mutex_); - MEDIA_LOGI("ScreenCaptureServer::SetMicrophoneEnabled start"); - MEDIA_LOGI("SetMicrophoneEnabled:%{public}d", isMicrophone); - isMicrophoneOn = isMicrophone; + MEDIA_LOGI("SetMicrophoneEnabled isMicrophoneOn_:%{public}d, new isMicrophone:%{public}d", + isMicrophoneOn_, isMicrophone); + isMicrophoneOn_ = isMicrophone; + if (captureState_ == AVScreenCaptureState::STARTED) { + if (micAudioCapture_ != nullptr) { + micAudioCapture_->SetIsMuted(!isMicrophone); + } + // For CAPTURE FILE, should call Recorder interface to make effect + } return MSERR_OK; } @@ -1054,286 +1233,218 @@ int32_t ScreenCaptureServer::SetScreenCanvasRotation(bool canvasRotation) int32_t ScreenCaptureServer::StopAudioCapture() { - isRunning_.store(false); - if (readAudioLoop_ != nullptr && readAudioLoop_->joinable()) { - readAudioLoop_->join(); - readAudioLoop_.reset(); - readAudioLoop_ = nullptr; - audioMicCapturer_->Stop(); + if (micAudioCapture_ != nullptr) { + MediaTrace trace("ScreenCaptureServer::StopAudioCaptureMic"); + micAudioCapture_->Stop(); + micAudioCapture_ = nullptr; } - isInnerRunning_.store(false); - if (readInnerAudioLoop_ != nullptr && readInnerAudioLoop_->joinable()) { - readInnerAudioLoop_->join(); - readInnerAudioLoop_.reset(); - readInnerAudioLoop_ = nullptr; - audioInnerCapturer_->Stop(); + if (innerAudioCapture_ != nullptr) { + MediaTrace trace("ScreenCaptureServer::StopAudioCaptureInner"); + innerAudioCapture_->Stop(); + innerAudioCapture_ = nullptr; } return MSERR_OK; } int32_t ScreenCaptureServer::StopVideoCapture() { + MediaTrace trace("ScreenCaptureServer::StopVideoCapture"); MEDIA_LOGI("StopVideoCapture"); - int32_t stopVideoSuccess = MSERR_OK; - if (!GetUsingPermissionFromPrivacy(STOP_VIDEO)) { - MEDIA_LOGE("getUsingPermissionFromPrivacy"); - } - if ((screenId_ < 0) || (consumer_ == nullptr) || !isConsumerStart_) { - MEDIA_LOGI("video start failed, stop"); - stopVideoSuccess = MSERR_INVALID_OPERATION; + MEDIA_LOGI("StopVideoCapture failed, stop"); surfaceCb_ = nullptr; - return stopVideoSuccess; - } - - if (screenId_ != SCREEN_ID_INVALID) { - ScreenManager::GetInstance().DestroyVirtualScreen(screenId_); + return MSERR_INVALID_OPERATION; } - if ((consumer_ != nullptr) && isConsumerStart_) { - isConsumerStart_ = false; + DestroyVirtualScreen(); + if ((consumer_ != nullptr)) { consumer_->UnregisterConsumerListener(); } if (surfaceCb_ != nullptr) { - surfaceCb_->Release(); + (static_cast(surfaceCb_.GetRefPtr()))->Release(); surfaceCb_ = nullptr; } - return stopVideoSuccess; + return MSERR_OK; } int32_t ScreenCaptureServer::StopScreenCaptureRecorder() { - int32_t stopRecorderSuccess = MSERR_OK; - if ((screenId_ < 0) || (consumer_ == nullptr) || !isConsumerStart_) { - MEDIA_LOGI("video start failed, stop"); - stopRecorderSuccess = MSERR_INVALID_OPERATION; - return stopRecorderSuccess; - } - stopRecorderSuccess = recorder_->Stop(true); - CHECK_AND_RETURN_RET_LOG(stopRecorderSuccess == MSERR_OK, stopRecorderSuccess, "recorder Stop failed"); - - if (screenId_ != SCREEN_ID_INVALID) { - ScreenManager::GetInstance().DestroyVirtualScreen(screenId_); + MEDIA_LOGE("StopScreenCaptureRecorder start"); + MediaTrace trace("ScreenCaptureServer::StopScreenCaptureRecorder"); + int32_t ret = MSERR_OK; + if (recorder_ != nullptr) { + ret = recorder_->Stop(true); + if (ret != MSERR_OK) { + MEDIA_LOGE("StopScreenCaptureRecorder recorder stop failed, ret:%{public}d", ret); + } + DestroyVirtualScreen(); + recorder_->Release(); + recorder_ = nullptr; } - stopRecorderSuccess = recorder_->Release(); - CHECK_AND_RETURN_RET_LOG(stopRecorderSuccess == MSERR_OK, stopRecorderSuccess, "recorder Release failed"); - return stopRecorderSuccess; + isConsumerStart_ = false; + CloseFd(); + return ret; } -int32_t ScreenCaptureServer::StopScreenCapture() +int32_t ScreenCaptureServer::StopScreenCaptureByEvent(AVScreenCaptureStateCode stateCode) { + MEDIA_LOGE("StopScreenCaptureByEvent start"); + MediaTrace trace("ScreenCaptureServer::StopScreenCaptureByEvent"); std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::StopScreenCapture"); - MEDIA_LOGI("ScreenCaptureServer::StopScreenCapture start"); - int32_t stopFlagSuccess = MSERR_OK; - if (dataType_ == DataType::CAPTURE_FILE) { - stopFlagSuccess = StopScreenCaptureRecorder(); - } else { - int32_t retAudio = StopAudioCapture(); - int32_t retVideo = StopVideoCapture(); - stopFlagSuccess = retAudio == MSERR_OK && retVideo == MSERR_OK ? MSERR_OK : MSERR_STOP_FAILED; - } - activeSessionId.store(-1); - if (stopFlagSuccess == MSERR_OK) { - BehaviorEventWriteForScreenCapture("stop", "AVScreenCapture", appinfo_.appUid, appinfo_.appPid); - } - #ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION - int32_t result = NotificationHelper::CancelNotification(notificationId_); - MEDIA_LOGI("NotificationSubscriber CancelNotification result : %{public}d ", result); - #endif - MEDIA_LOGI("ScreenCaptureServer stop result :%{public}d", stopFlagSuccess); - return stopFlagSuccess; + return StopScreenCaptureInner(stateCode); } -void ScreenCaptureServer::ReleaseAudioCapture() +int32_t ScreenCaptureServer::StopScreenCaptureInner(AVScreenCaptureStateCode stateCode) { - if ((audioMicCapturer_ != nullptr) && isAudioStart_) { - isRunning_.store(false); - if (readAudioLoop_ != nullptr && readAudioLoop_->joinable()) { - readAudioLoop_->join(); - readAudioLoop_.reset(); - readAudioLoop_ = nullptr; - } - audioMicCapturer_->Release(); - isAudioStart_ = false; - audioMicCapturer_ = nullptr; + if (screenCaptureCb_ != nullptr) { + (static_cast(screenCaptureCb_.get()))->Stop(); + } + if (captureState_ == AVScreenCaptureState::CREATED || captureState_ == AVScreenCaptureState::STARTING) { + CloseFd(); + captureState_ = AVScreenCaptureState::STOPPED; + isSurfaceMode_ = false; + surface_ = nullptr; + return MSERR_OK; } + CHECK_AND_RETURN_RET(captureState_ != AVScreenCaptureState::STOPPED, MSERR_OK); - if ((audioInnerCapturer_ != nullptr) && isAudioInnerStart_) { - isInnerRunning_.store(false); - if (readInnerAudioLoop_ != nullptr && readInnerAudioLoop_->joinable()) { - readInnerAudioLoop_->join(); - readInnerAudioLoop_.reset(); - readInnerAudioLoop_ = nullptr; - } - audioInnerCapturer_->Release(); - isAudioInnerStart_ = false; - audioInnerCapturer_ = nullptr; + int32_t ret = MSERR_OK; + if (captureConfig_.dataType == DataType::CAPTURE_FILE) { + ret = StopScreenCaptureRecorder(); + } else if (captureConfig_.dataType == DataType::ORIGINAL_STREAM) { + int32_t retAudio = StopAudioCapture(); + int32_t retVideo = StopVideoCapture(); + ret = (retAudio == MSERR_OK && retVideo == MSERR_OK) ? MSERR_OK : MSERR_STOP_FAILED; + } else { + MEDIA_LOGW("StopScreenCaptureInner unsupport and ignore"); + return MSERR_OK; } - std::unique_lock alock(audioMutex_); - while (!availableAudioBuffers_.empty()) { - if (availableAudioBuffers_.front() != nullptr) { - free(availableAudioBuffers_.front()->buffer); - availableAudioBuffers_.front()->buffer = nullptr; - } - availableAudioBuffers_.pop(); + CHECK_AND_RETURN_RET_LOG(captureState_ == AVScreenCaptureState::STARTED, ret, "state:%{public}d", captureState_); + if (screenCaptureCb_ != nullptr) { + screenCaptureCb_->OnStateChange(stateCode); } - - std::unique_lock alock_inner(audioInnerMutex_); - while (!availableInnerAudioBuffers_.empty()) { - if (availableInnerAudioBuffers_.front() != nullptr) { - free(availableInnerAudioBuffers_.front()->buffer); - availableInnerAudioBuffers_.front()->buffer = nullptr; - } - availableInnerAudioBuffers_.pop(); + if (isPrivacyAuthorityEnabled_) { + // Remove real time notification +#ifdef SUPPORT_SCREEN_CAPTURE_WINDOW_NOTIFICATION + int32_t ret = NotificationHelper::CancelNotification(notificationId_); + MEDIA_LOGI("StopScreenCaptureInner CancelNotification ret:%{public}d ", ret); +#endif + isPrivacyAuthorityEnabled_ = false; } -} -void ScreenCaptureServer::ReleaseVideoCapture() -{ - if (screenId_ != SCREEN_ID_INVALID) { - ScreenManager::GetInstance().DestroyVirtualScreen(screenId_); + if (!UpdatePrivacyUsingPermissionState(STOP_VIDEO)) { + MEDIA_LOGE("UpdatePrivacyUsingPermissionState STOP failed, dataType:%{public}d", captureConfig_.dataType); } + BehaviorEventWriteForScreenCapture("stop", "AVScreenCapture", appInfo_.appUid, appInfo_.appPid); - if ((consumer_ != nullptr) && isConsumerStart_) { - if (dataType_ != DataType::CAPTURE_FILE) { - consumer_->UnregisterConsumerListener(); - } - isConsumerStart_ = false; - } - consumer_ = nullptr; - if (surfaceCb_ != nullptr) { - surfaceCb_->Release(); - surfaceCb_ = nullptr; - } - if (recorder_ != nullptr) { - recorder_->Release(); - recorder_ = nullptr; - } - if (outputFd_ > 0) { - (void)::close(outputFd_); + MEDIA_LOGI("StopScreenCaptureInner sessionId:%{public}d, activeSessionId:%{public}d", sessionId_, + activeSessionId.load()); + if (sessionId_ == activeSessionId.load()) { + activeSessionId.store(SESSION_ID_INVALID); } + return ret; } -void ScreenCaptureServer::Release() +int32_t ScreenCaptureServer::StopScreenCapture() { - std::lock_guard lock(mutex_); - MediaTrace trace("ScreenCaptureServer::Release"); - MEDIA_LOGI("ScreenCaptureServer::Release start"); - - screenCaptureCb_ = nullptr; - ReleaseAudioCapture(); - ReleaseVideoCapture(); - serverMap.erase(sessionId_); - MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances Release", FAKE_POINTER(this)); -} + MediaTrace trace("ScreenCaptureServer::StopScreenCapture"); + MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances StopScreenCapture", FAKE_POINTER(this)); -void AudioCapturerCallbackImpl::OnInterrupt(const InterruptEvent &interruptEvent) -{ - MEDIA_LOGD("AudioCapturerCallbackImpl: OnInterrupt Hint : %{public}d eventType : %{public}d forceType : %{public}d", - interruptEvent.hintType, interruptEvent.eventType, interruptEvent.forceType); + std::lock_guard lock(mutex_); + return StopScreenCaptureInner(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_INVLID); } -void AudioCapturerCallbackImpl::OnStateChange(const CapturerState state) +void ScreenCaptureServer::Release() { - MEDIA_LOGD("AudioCapturerCallbackImpl:: OnStateChange"); - switch (state) { - case CAPTURER_PREPARED: - MEDIA_LOGD("AudioCapturerCallbackImpl: OnStateChange CAPTURER_PREPARED"); - break; - default: - MEDIA_LOGD("AudioCapturerCallbackImpl: OnStateChange NOT A VALID state"); - break; + MediaTrace trace("ScreenCaptureServer::Release"); + MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances Release", FAKE_POINTER(this)); + int32_t sessionId; + { + std::lock_guard lock(mutex_); + sessionId = sessionId_; + sessionId_ = SESSION_ID_INVALID; + } + { + std::lock_guard lock(mutexGlobal); + serverMap.erase(sessionId); } + + std::lock_guard lock(mutex_); + StopScreenCaptureInner(AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_INVLID); } void ScreenCapBufferConsumerListener::OnBufferAvailable() { + CHECK_AND_RETURN(consumer_ != nullptr); int32_t flushFence = 0; int64_t timestamp = 0; OHOS::Rect damage; OHOS::sptr buffer = nullptr; - if (consumer_ == nullptr) { - MEDIA_LOGE("consumer_ is nullptr"); + consumer_->AcquireBuffer(buffer, flushFence, timestamp, damage); + CHECK_AND_RETURN_LOG(buffer != nullptr, "Acquire SurfaceBuffer failed"); + + void *addr = buffer->GetVirAddr(); + if (addr == nullptr) { + MEDIA_LOGE("Acquire SurfaceBuffer addr invalid"); + consumer_->ReleaseBuffer(buffer, flushFence); return; } - consumer_->AcquireBuffer(buffer, flushFence, timestamp, damage); - if (buffer != nullptr) { - void* addr = buffer->GetVirAddr(); - uint32_t size = buffer->GetSize(); - if (addr != nullptr) { - MEDIA_LOGD("consumer receive buffer length:%{public}u", size); - std::unique_lock vlock(vmutex_); - if (availableVideoBuffers_.size() > MAX_BUFFER_SIZE) { - consumer_->ReleaseBuffer(buffer, flushFence); - MEDIA_LOGE("no client consumer the buffer,drop the frame!!"); - return; - } - availableVideoBuffers_.push(std::make_unique(buffer, flushFence, - timestamp, damage)); - if (screenCaptureCb_ != nullptr) { - std::lock_guard cbLock(cbMutex_); - screenCaptureCb_->OnVideoBufferAvailable(true); - } else { - MEDIA_LOGE("no callback client consumer the buffer,drop the frame!!"); - } - bufferCond_.notify_all(); + MEDIA_LOGD("SurfaceBuffer size:%{public}u", buffer->GetSize()); + + { + std::unique_lock lock(bufferMutex_); + if (availBuffers_.size() > MAX_BUFFER_SIZE) { + MEDIA_LOGE("consume slow, drop video frame"); + consumer_->ReleaseBuffer(buffer, flushFence); + return; } - } else { - MEDIA_LOGE("consumer receive buffer failed"); - return; + availBuffers_.push(std::make_unique(buffer, flushFence, timestamp, damage)); } + bufferCond_.notify_all(); + + std::lock_guard lock(mutex_); + CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "no consumer, will drop video frame"); + screenCaptureCb_->OnVideoBufferAvailable(true); } -int32_t ScreenCapBufferConsumerListener::AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, - int64_t ×tamp, OHOS::Rect &damage) +int32_t ScreenCapBufferConsumerListener::AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, + int64_t ×tamp, OHOS::Rect &damage) { using namespace std::chrono_literals; - std::unique_lock vlock(vmutex_); - if (availableVideoBuffers_.empty()) { - if (bufferCond_.wait_for(vlock, 1000ms) == std::cv_status::timeout) { - return MSERR_UNKNOWN; - } + std::unique_lock lock(bufferMutex_); + if (!bufferCond_.wait_for( + lock, std::chrono::milliseconds(OPERATION_TIMEOUT_IN_MS), [this] { return !availBuffers_.empty(); })) { + return MSERR_UNKNOWN; } - surfaceBuffer = availableVideoBuffers_.front()->buffer; - fence = availableVideoBuffers_.front()->flushFence; - timestamp = availableVideoBuffers_.front()->timeStamp; - damage = availableVideoBuffers_.front()->damageRect; + surfaceBuffer = availBuffers_.front()->buffer; + fence = availBuffers_.front()->flushFence; + timestamp = availBuffers_.front()->timeStamp; + damage = availBuffers_.front()->damageRect; return MSERR_OK; } int32_t ScreenCapBufferConsumerListener::ReleaseVideoBuffer() { - std::unique_lock vlock(vmutex_); - if (availableVideoBuffers_.empty()) { - MEDIA_LOGE("availableVideoBuffers_ is empty,no video frame need release"); - return MSERR_OK; - } + std::unique_lock lock(bufferMutex_); + CHECK_AND_RETURN_RET_LOG(!availBuffers_.empty(), MSERR_OK, "buffer queue is empty, no video frame to release"); + if (consumer_ != nullptr) { - consumer_->ReleaseBuffer(availableVideoBuffers_.front()->buffer, - availableVideoBuffers_.front()->flushFence); + consumer_->ReleaseBuffer(availBuffers_.front()->buffer, availBuffers_.front()->flushFence); } - availableVideoBuffers_.pop(); + availBuffers_.pop(); return MSERR_OK; } int32_t ScreenCapBufferConsumerListener::Release() { - MEDIA_LOGI("release ScreenCapBufferConsumerListener"); - std::unique_lock vlock(vmutex_); - while (!availableVideoBuffers_.empty()) { - if (consumer_ != nullptr) { - consumer_->ReleaseBuffer(availableVideoBuffers_.front()->buffer, - availableVideoBuffers_.front()->flushFence); - } - availableVideoBuffers_.pop(); - } - return MSERR_OK; + std::unique_lock lock(bufferMutex_); + MEDIA_LOGI("Release"); + return ReleaseBuffer(); } } // namespace Media } // namespace OHOS diff --git a/services/services/screen_capture/server/screen_capture_server.h b/services/services/screen_capture/server/screen_capture_server.h index 92def7983..8e6eda29c 100644 --- a/services/services/screen_capture/server/screen_capture_server.h +++ b/services/services/screen_capture/server/screen_capture_server.h @@ -24,7 +24,8 @@ #include #include #include -#include "securec.h" + +#include "audio_capturer_wrapper.h" #include "i_screen_capture_service.h" #include "nocopyable.h" #include "uri_helper.h" @@ -65,11 +66,21 @@ public: std::string buttonNameStop_ = "stop"; }; +enum VideoPermissionState : int32_t { + START_VIDEO = 0, + STOP_VIDEO = 1 +}; + +enum AVScreenCaptureState : int32_t { + CREATED = 0, + STARTING = 1, + STARTED = 2, + STOPPED = 3 +}; + struct SurfaceBufferEntry { SurfaceBufferEntry(sptr buf, int32_t fence, int64_t timeStamp, OHOS::Rect& damage) - : buffer(std::move(buf)), flushFence(fence), timeStamp(timeStamp), damageRect(damage) - { - } + : buffer(std::move(buf)), flushFence(fence), timeStamp(timeStamp), damageRect(damage) {} ~SurfaceBufferEntry() noexcept = default; sptr buffer; @@ -78,50 +89,47 @@ struct SurfaceBufferEntry { OHOS::Rect damageRect = {0, 0, 0, 0}; }; -enum VideoPermissionState : int32_t { - START_VIDEO = 0, - STOP_VIDEO = 1 -}; - class ScreenCapBufferConsumerListener : public IBufferConsumerListener { public: - ScreenCapBufferConsumerListener(sptr consumer, - const std::shared_ptr &screenCaptureCb) : consumer_(consumer), - screenCaptureCb_(screenCaptureCb) - { - } + ScreenCapBufferConsumerListener( + sptr consumer, const std::shared_ptr &screenCaptureCb) + : consumer_(consumer), screenCaptureCb_(screenCaptureCb) {} ~ScreenCapBufferConsumerListener() { - std::unique_lock vlock(vmutex_); - while (!availableVideoBuffers_.empty()) { - if (consumer_ != nullptr) { - consumer_->ReleaseBuffer(availableVideoBuffers_.front()->buffer, - availableVideoBuffers_.front()->flushFence); - } - availableVideoBuffers_.pop(); - } + std::unique_lock lock(bufferMutex_); + ReleaseBuffer(); } void OnBufferAvailable() override; - int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, - int64_t ×tamp, OHOS::Rect &damage); + int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, int64_t ×tamp, + OHOS::Rect &damage); int32_t ReleaseVideoBuffer(); int32_t Release(); - static constexpr uint32_t MAX_BUFFER_SIZE = 3; private: + int32_t ReleaseBuffer() + { + while (!availBuffers_.empty()) { + if (consumer_ != nullptr) { + consumer_->ReleaseBuffer(availBuffers_.front()->buffer, + availBuffers_.front()->flushFence); + } + availBuffers_.pop(); + } + return MSERR_OK; + } + +private: + std::mutex mutex_; sptr consumer_ = nullptr; - std::mutex cbMutex_; - std::mutex vmutex_; - std::condition_variable bufferCond_; std::shared_ptr screenCaptureCb_ = nullptr; - std::queue> availableVideoBuffers_; -}; -class AudioCapturerCallbackImpl : public AudioCapturerCallback { -public: - void OnInterrupt(const InterruptEvent &interruptEvent) override; - void OnStateChange(const CapturerState state) override; + std::mutex bufferMutex_; + std::condition_variable bufferCond_; + std::queue> availBuffers_; + + static constexpr uint32_t MAX_BUFFER_SIZE = 3; + static constexpr uint32_t OPERATION_TIMEOUT_IN_MS = 1000; // 1000ms }; class ScreenCaptureServer : public IScreenCaptureService, public NoCopyable { @@ -139,111 +147,122 @@ public: int32_t InitAudioCap(AudioCaptureInfo audioInfo) override; int32_t InitVideoEncInfo(VideoEncInfo videoEncInfo) override; int32_t InitVideoCap(VideoCaptureInfo videoInfo) override; - int32_t StartScreenCapture() override; - int32_t StartScreenCaptureWithSurface(sptr surface) override; + int32_t StartScreenCapture(bool isPrivacyAuthorityEnabled) override; + int32_t StartScreenCaptureWithSurface(sptr surface, bool isPrivacyAuthorityEnabled) override; int32_t StopScreenCapture() override; int32_t SetScreenCaptureCallback(const std::shared_ptr &callback) override; int32_t AcquireAudioBuffer(std::shared_ptr &audioBuffer, AudioCaptureSourceType type) override; int32_t AcquireVideoBuffer(sptr &surfaceBuffer, int32_t &fence, - int64_t ×tamp, OHOS::Rect &damage) override; + int64_t ×tamp, OHOS::Rect &damage) override; int32_t ReleaseAudioBuffer(AudioCaptureSourceType type) override; int32_t ReleaseVideoBuffer() override; int32_t SetMicrophoneEnabled(bool isMicrophone) override; int32_t SetScreenCanvasRotation(bool canvasRotation) override; void Release() override; - int32_t StartScreenCaptureInner(); + int32_t ExcludeContent(ScreenCaptureContentFilter &contentFilter) override; + void SetSessionId(int32_t sessionId); + int32_t OnReceiveUserPrivacyAuthority(bool isAllowed); + int32_t StopScreenCaptureByEvent(AVScreenCaptureStateCode stateCode); private: - bool CheckAudioCaptureMicPermission(); - bool CheckScreenCapturePermission(); - bool GetUsingPermissionFromPrivacy(VideoPermissionState state); - int32_t CheckVideoParam(VideoCaptureInfo videoInfo); - int32_t CheckAudioParam(AudioCaptureInfo audioInfo); - std::shared_ptr CreateAudioCapture(AudioCaptureInfo audioInfo); + int32_t StartScreenCaptureInner(bool isPrivacyAuthorityEnabled); + int32_t OnStartScreenCapture(); int32_t InitRecorder(); + int32_t StartScreenCaptureFile(); + int32_t StartScreenCaptureStream(); int32_t StartAudioCapture(); - int32_t StartAudioInnerCapture(); int32_t StartVideoCapture(); int32_t StartHomeVideoCapture(); - int32_t StartHomeVideoCaptureFile(); - int32_t CreateVirtualScreen(const std::string &name, sptr consumer); - VirtualScreenOption InitVirtualScreenOption(const std::string &name, sptr consumer); - int32_t GetMissionIds(std::vector &missionIds); + int32_t StopScreenCaptureInner(AVScreenCaptureStateCode stateCode); int32_t StopAudioCapture(); int32_t StopVideoCapture(); int32_t StopScreenCaptureRecorder(); - void ReleaseAudioCapture(); - void ReleaseVideoCapture(); + int32_t CheckAllParams(); + int32_t CheckCaptureStreamParams(); + int32_t CheckCaptureFileParams(); + void InitAppInfo(); + void CloseFd(); + + VirtualScreenOption InitVirtualScreenOption(const std::string &name, sptr consumer); + int32_t GetMissionIds(std::vector &missionIds); + int32_t MakeVirtualScreenMirror(); + int32_t CreateVirtualScreen(const std::string &name, sptr consumer); + void DestroyVirtualScreen(); + + bool CheckScreenCapturePermission(); + bool UpdatePrivacyUsingPermissionState(VideoPermissionState state); + int32_t RequestUserPrivacyAuthority(); int32_t StartPrivacyWindow(); int32_t StartNotification(); std::shared_ptr GetLocalLiveViewContent(); std::shared_ptr GetPixelMap(std::string path); - std::shared_ptr screenCaptureCb_ = nullptr; +private: std::mutex mutex_; - std::mutex audioMutex_; - std::mutex audioInnerMutex_; std::mutex cbMutex_; - std::condition_variable bufferCond_; - std::condition_variable bufferInnerCond_; - /* use Mic AudioCaptureHandler */ - std::shared_ptr audioMicCapturer_ = nullptr; - std::shared_ptr cb1_ = nullptr; - std::atomic isRunning_ = false; - std::unique_ptr readAudioLoop_ = nullptr; - std::queue> availableAudioBuffers_; - bool isMicrophoneOn = true; - /* use Inner AudioCaptureHandler */ - std::shared_ptr audioInnerCapturer_ = nullptr; - std::atomic isInnerRunning_ = false; - std::unique_ptr readInnerAudioLoop_ = nullptr; - std::queue> availableInnerAudioBuffers_; - /* use VideoCapture */ - sptr consumer_ = nullptr; - ScreenCapBufferConsumerListener* surfaceCb_ = nullptr; - ScreenId screenId_ = SCREEN_ID_INVALID; - bool isConsumerStart_ = false; - bool isAudioStart_ = false; - bool isAudioInnerStart_ = false; - AudioCaptureSourceType audioCurrentInnerType_; - VideoCaptureInfo videoInfo_; - Security::AccessToken::AccessTokenID clientTokenId = 0; - CaptureMode captureMode_ = CAPTURE_HOME_SCREEN; - int32_t outputFd_ = -1; - std::shared_ptr recorder_ = nullptr; - int32_t audioSourceId_; - int32_t videoSourceId_; - AudioCaptureInfo audioInfo_; - DataType dataType_ = ORIGINAL_STREAM; - std::string url_; - OutputFormatType fileFormat_; - AudioEncInfo audioEncInfo_; - VideoEncInfo videoEncInfo_; - std::vector missionIds_; - const int32_t audioBitrateMin_ = 8000; - const int32_t audioBitrateMax_ = 384000; - const int32_t videoBitrateMin_ = 1; - const int32_t videoBitrateMax_ = 30000000; - const int32_t videoFrameRateMin_ = 1; - const int32_t videoFrameRateMax_ = 60; - const std::string MP4 = "mp4"; - const std::string M4A = "m4a"; - OHOS::AudioStandard::AppInfo appinfo_; - sptr surface_ = nullptr; - bool isSurfaceMode_ = false; + std::shared_ptr screenCaptureCb_ = nullptr; + bool isMicrophoneOn_ = true; + bool isPrivacyAuthorityEnabled_ = false; + int32_t sessionId_; int32_t notificationId_; std::string buttonNameMic_ = "mic"; std::string buttonNameStop_ = "stop"; - std::string ICON_PATH_CAPSULE = "/etc/screencapture/capsule.png"; std::string ICON_PATH_MIC = "/etc/screencapture/mic.png"; std::string ICON_PATH_STOP = "/etc/screencapture/stop.png"; - static constexpr uint32_t MAX_AUDIO_BUFFER_SIZE = 128; - static constexpr uint64_t SEC_TO_NANOSECOND = 1000000000; std::string bundleName_ = "com.ohos.systemui"; std::string abilityName_ = "com.ohos.systemui.dialog"; + + /* used for both CAPTURE STREAM and CAPTURE FILE */ + OHOS::AudioStandard::AppInfo appInfo_; + AVScreenCaptureConfig captureConfig_; + sptr consumer_ = nullptr; + bool isConsumerStart_ = false; + ScreenId screenId_ = SCREEN_ID_INVALID; + std::vector missionIds_; + ScreenCaptureContentFilter contentFilter_; + AVScreenCaptureState captureState_ = AVScreenCaptureState::CREATED; + + /* used for CAPTURE STREAM */ + sptr surfaceCb_ = nullptr; + sptr surface_ = nullptr; + bool isSurfaceMode_ = false; + std::shared_ptr innerAudioCapture_; + std::shared_ptr micAudioCapture_; + + /* used for CAPTURE FILE */ + std::shared_ptr recorder_ = nullptr; + std::string url_; + OutputFormatType fileFormat_; + int32_t outputFd_ = -1; + int32_t audioSourceId_; + int32_t videoSourceId_; + +private: + static int32_t CheckAudioCapParam(const AudioCaptureInfo &audioCapInfo); + static int32_t CheckVideoCapParam(const VideoCaptureInfo &videoCapInfo); + static int32_t CheckAudioEncParam(const AudioEncInfo &audioEncInfo); + static int32_t CheckVideoEncParam(const VideoEncInfo &videoEncInfo); + static int32_t CheckAudioCapInfo(AudioCaptureInfo &audioCapInfo); + static int32_t CheckVideoCapInfo(VideoCaptureInfo &videoCapInfo); + static int32_t CheckAudioEncInfo(AudioEncInfo &audioEncInfo); + static int32_t CheckVideoEncInfo(VideoEncInfo &videoEncInfo); + static int32_t CheckCaptureMode(CaptureMode captureMode); + static int32_t CheckDataType(DataType dataType); + +private: + static constexpr int32_t ROOT_UID = 0; + static constexpr int32_t AUDIO_BITRATE_MIN = 8000; + static constexpr int32_t AUDIO_BITRATE_MAX = 384000; + static constexpr int32_t VIDEO_BITRATE_MIN = 1; + static constexpr int32_t VIDEO_BITRATE_MAX = 30000000; + static constexpr int32_t VIDEO_FRAME_RATE_MIN = 1; + static constexpr int32_t VIDEO_FRAME_RATE_MAX = 60; + static constexpr int32_t VIDEO_FRAME_WIDTH_MAX = 10240; + static constexpr int32_t VIDEO_FRAME_HEIGHT_MAX = 4320; + static constexpr int32_t SESSION_ID_INVALID = -1; }; } // namespace Media } // namespace OHOS diff --git a/services/utils/include/media_log.h b/services/utils/include/media_log.h index f7cafa023..ac81403c5 100644 --- a/services/utils/include/media_log.h +++ b/services/utils/include/media_log.h @@ -123,6 +123,14 @@ namespace OHOS { } \ } else void (0) +#define CHECK_AND_CONTINUE_LOG(cond, fmt, ...) \ + if (1) { \ + if (!(cond)) { \ + MEDIA_LOGE(fmt, ##__VA_ARGS__); \ + continue; \ + } \ + } else void (0) + #define POINTER_MASK 0x00FFFFFF #define FAKE_POINTER(addr) (POINTER_MASK & reinterpret_cast(addr)) } // namespace OHOS diff --git a/test/unittest/resources/ohos_test.xml b/test/unittest/resources/ohos_test.xml index 0d59f6204..5f0bfd55d 100644 --- a/test/unittest/resources/ohos_test.xml +++ b/test/unittest/resources/ohos_test.xml @@ -108,6 +108,7 @@