1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "screen_capture_monitor_callback.h"
16 #include "screen_capture_monitor_napi.h"
17 #include "media_log.h"
18 #include "scope_guard.h"
19
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_RECORDER, "ScreenCaptureMonitorCallback"};
22 }
23
24 namespace OHOS {
25 namespace Media {
ScreenCaptureMonitorCallback(napi_env env)26 ScreenCaptureMonitorCallback::ScreenCaptureMonitorCallback(napi_env env) : env_(env)
27 {
28 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
29 }
30
~ScreenCaptureMonitorCallback()31 ScreenCaptureMonitorCallback::~ScreenCaptureMonitorCallback()
32 {
33 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
34 }
35
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)36 void ScreenCaptureMonitorCallback::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
37 {
38 std::lock_guard<std::mutex> lock(mutex_);
39 refMap_[name] = ref;
40 MEDIA_LOGI("Set callback type: %{public}s", name.c_str());
41 }
42
CancelCallbackReference(const std::string & name)43 void ScreenCaptureMonitorCallback::CancelCallbackReference(const std::string &name)
44 {
45 std::lock_guard<std::mutex> lock(mutex_);
46 auto iter = refMap_.find(name);
47 if (iter != refMap_.end()) {
48 refMap_.erase(iter);
49 }
50 MEDIA_LOGI("Cancel callback type: %{public}s", name.c_str());
51 }
52
OnScreenCaptureStarted(int32_t pid)53 void ScreenCaptureMonitorCallback::OnScreenCaptureStarted(int32_t pid)
54 {
55 MEDIA_LOGI("OnScreenCaptureStarted S %{public}d", pid);
56 std::lock_guard<std::mutex> lock(mutex_);
57 if (refMap_.find(EVENT_SYSTEM_SCREEN_RECORD) == refMap_.end()) {
58 MEDIA_LOGW("can not find systemScreenRecorder callback!");
59 return;
60 }
61
62 bool shouldSendCb = ScreenCaptureMonitor::GetInstance()->IsSystemScreenRecorder(pid);
63 if (!shouldSendCb) {
64 MEDIA_LOGW("pid not match, do not send callback!");
65 return;
66 }
67
68 ScreenCaptureMonitorJsCallback *cb = new(std::nothrow) ScreenCaptureMonitorJsCallback();
69 CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
70 cb->autoRef = refMap_.at(EVENT_SYSTEM_SCREEN_RECORD);
71 cb->callbackName = EVENT_SYSTEM_SCREEN_RECORD;
72 cb->captureEvent = ScreenCaptureMonitorEvent::SCREENCAPTURE_STARTED;
73 MEDIA_LOGI("OnScreenCaptureStarted E");
74 return OnJsCaptureCallBack(cb);
75 }
76
OnScreenCaptureFinished(int32_t pid)77 void ScreenCaptureMonitorCallback::OnScreenCaptureFinished(int32_t pid)
78 {
79 MEDIA_LOGI("OnScreenCaptureFinished S %{public}d", pid);
80 std::lock_guard<std::mutex> lock(mutex_);
81 if (refMap_.find(EVENT_SYSTEM_SCREEN_RECORD) == refMap_.end()) {
82 MEDIA_LOGW("can not find systemScreenRecorder callback!");
83 return;
84 }
85
86 bool shouldSendCb = ScreenCaptureMonitor::GetInstance()->IsSystemScreenRecorder(pid);
87 if (!shouldSendCb) {
88 MEDIA_LOGW("pid not match, do not send callback!");
89 return;
90 }
91
92 ScreenCaptureMonitorJsCallback *cb = new(std::nothrow) ScreenCaptureMonitorJsCallback();
93 CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
94 cb->autoRef = refMap_.at(EVENT_SYSTEM_SCREEN_RECORD);
95 cb->callbackName = EVENT_SYSTEM_SCREEN_RECORD;
96 cb->captureEvent = ScreenCaptureMonitorEvent::SCREENCAPTURE_STOPPED;
97 MEDIA_LOGI("OnScreenCaptureFinished E");
98 return OnJsCaptureCallBack(cb);
99 }
100
OnJsCaptureCallBack(ScreenCaptureMonitorJsCallback * jsCb) const101 void ScreenCaptureMonitorCallback::OnJsCaptureCallBack(ScreenCaptureMonitorJsCallback *jsCb) const
102 {
103 ON_SCOPE_EXIT(0) {
104 delete jsCb;
105 };
106
107 auto task = [jsCb]() {
108 std::string request = jsCb->callbackName;
109 do {
110 std::shared_ptr<AutoRef> ref = jsCb->autoRef.lock();
111 CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
112
113 napi_handle_scope scope = nullptr;
114 napi_open_handle_scope(ref->env_, &scope);
115 CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
116 ON_SCOPE_EXIT(0) {
117 napi_close_handle_scope(ref->env_, scope);
118 };
119
120 napi_value jsCallback = nullptr;
121 napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
122 CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
123 request.c_str());
124
125 napi_value args[1] = { nullptr };
126 nstatus = napi_create_int32(ref->env_, jsCb->captureEvent, &args[0]);
127 CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
128 "%{public}s fail to create callback", request.c_str());
129
130 const size_t argCount = 1;
131 napi_value result = nullptr;
132 nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
133 CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
134 } while (0);
135 delete jsCb;
136 };
137 CHECK_AND_RETURN_LOG(napi_send_event(env_, task, napi_eprio_immediate) == napi_status::napi_ok,
138 "OnJsCaptureCallBack napi_send_event failed");
139
140 CANCEL_SCOPE_EXIT_GUARD(0);
141 }
142 } // namespace Media
143 } // namespace OHOS