1 /*
2  * Copyright (c) 2023 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 
16 #include <chrono>
17 #include <mutex>
18 #include <set>
19 #include <string>
20 #include <unistd.h>
21 #include <vector>
22 #include <unordered_set>
23 
24 #include "app_mgr_constants.h"
25 #include "app_mgr_client.h"
26 #include "bundle_mgr_interface.h"
27 #include "iservice_registry.h"
28 #include "nweb_log.h"
29 #include "res_sched_client.h"
30 #include "res_sched_client_adapter.h"
31 #include "res_type.h"
32 #include "singleton.h"
33 #include "system_ability_definition.h"
34 #include "system_properties_adapter_impl.h"
35 
36 namespace OHOS::NWeb {
37 using namespace OHOS::ResourceSchedule;
38 
39 const std::unordered_map<ResSchedTypeAdapter, uint32_t> RES_TYPE_MAP = {
40     { ResSchedTypeAdapter::RES_TYPE_KEY_THREAD, ResType::RES_TYPE_REPORT_KEY_THREAD },
41     { ResSchedTypeAdapter::RES_TYPE_WEB_STATUS_CHANGE, ResType::RES_TYPE_REPORT_WINDOW_STATE },
42     { ResSchedTypeAdapter::RES_TYPE_WEB_SCENE, ResType::RES_TYPE_REPORT_SCENE_SCHED },
43     { ResSchedTypeAdapter::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE, ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE },
44     { ResSchedTypeAdapter::RES_TYPE_WEBVIEW_SCREEN_CAPTURE, ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE },
45     { ResSchedTypeAdapter::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE, ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE },
46 };
47 
48 const std::unordered_map<ResSchedStatusAdapter, int64_t> RES_STATUS_MAP = {
49     { ResSchedStatusAdapter::THREAD_CREATED, ResType::ReportChangeStatus::CREATE },
50     { ResSchedStatusAdapter::THREAD_DESTROYED, ResType::ReportChangeStatus::REMOVE },
51     { ResSchedStatusAdapter::WEB_ACTIVE, ResType::WindowStates::ACTIVE },
52     { ResSchedStatusAdapter::WEB_INACTIVE, ResType::WindowStates::INACTIVE },
53     { ResSchedStatusAdapter::WEB_SCENE_ENTER, ResType::SceneControl::SCENE_IN },
54     { ResSchedStatusAdapter::WEB_SCENE_EXIT, ResType::SceneControl::SCENE_OUT },
55     { ResSchedStatusAdapter::AUDIO_STATUS_START, ResType::AudioStatus::START },
56     { ResSchedStatusAdapter::AUDIO_STATUS_STOP, ResType::AudioStatus::STOP },
57     { ResSchedStatusAdapter::SCREEN_CAPTURE_START, ResType::WebScreenCapture::WEB_SCREEN_CAPTURE_START },
58     { ResSchedStatusAdapter::SCREEN_CAPTURE_STOP, ResType::WebScreenCapture::WEB_SCREEN_CAPTURE_STOP },
59     { ResSchedStatusAdapter::VIDEO_PLAYING_START, ResType::WebVideoState::WEB_VIDEO_PLAYING_START },
60     { ResSchedStatusAdapter::VIDEO_PLAYING_STOP, ResType::WebVideoState::WEB_VIDEO_PLAYING_STOP },
61 };
62 
63 const std::unordered_map<ResSchedRoleAdapter, ResType::ThreadRole> RES_ROLE_MAP = {
64     { ResSchedRoleAdapter::USER_INTERACT, ResType::ThreadRole::USER_INTERACT },
65     { ResSchedRoleAdapter::NORMAL_DISPLAY, ResType::ThreadRole::NORMAL_DISPLAY },
66     { ResSchedRoleAdapter::IMPORTANT_DISPLAY, ResType::ThreadRole::IMPORTANT_DISPLAY },
67     { ResSchedRoleAdapter::NORMAL_AUDIO, ResType::ThreadRole::NORMAL_AUDIO },
68     { ResSchedRoleAdapter::IMPORTANT_AUDIO, ResType::ThreadRole::IMPORTANT_AUDIO },
69     { ResSchedRoleAdapter::IMAGE_DECODE, ResType::ThreadRole::IMAGE_DECODE },
70 };
71 
72 const std::unordered_map<ResSchedSceneAdapter, int32_t> RES_SCENE_MAP = {
73     { ResSchedSceneAdapter::LOAD_URL, ResType::WebScene::WEB_SCENE_LOAD_URL },
74     { ResSchedSceneAdapter::CLICK, ResType::WebScene::WEB_SCENE_CLICK },
75     { ResSchedSceneAdapter::SLIDE, ResType::WebScene::WEB_SCENE_SLIDE },
76     { ResSchedSceneAdapter::RESIZE, ResType::WebScene::WEB_SCENE_RESIZE },
77     { ResSchedSceneAdapter::VISIBLE, ResType::WebScene::WEB_SCENE_VISIBLE },
78     { ResSchedSceneAdapter::KEYBOARD_CLICK, ResType::WebScene::WEB_SCENE_KEYBOARD_CLICK },
79     { ResSchedSceneAdapter::KEY_TASK, ResType::WebScene::WEB_SCENE_KEY_TASK },
80     { ResSchedSceneAdapter::IMAGE_DECODE, ResType::WebScene::WEB_SCENE_IMAGE_DECODE },
81 };
82 
83 const int32_t INVALID_NUMBER = -1;
84 const int64_t INVALID_NUMBER_INT64 = -1;
85 const int64_t SLIDE_PERIOD_MS = 300;
86 const pid_t INVALID_PID = -1;
87 constexpr char PID[] = "pid";
88 constexpr char UID[] = "uid";
89 constexpr char TID[] = "tid";
90 constexpr char ROLE[] = "role";
91 constexpr char WINDOW_ID[] = "windowId";
92 constexpr char SERIAL_NUMBER[] = "serialNum";
93 constexpr char SCENE_ID[] = "sceneId";
94 constexpr char STATE[] = "state";
95 std::set<int32_t> g_nwebSet;
96 std::unordered_map<pid_t, std::unordered_map<int32_t, ResSchedStatusAdapter>> g_pidNwebMap;
97 std::unordered_map<int32_t, std::vector<pid_t>> g_nwebProcessMap;
98 std::unordered_set<pid_t> g_processInUse;
99 std::mutex g_windowIdMutex {};
100 int32_t g_windowId = INVALID_NUMBER;
101 int32_t g_nwebId = INVALID_NUMBER;
102 pid_t g_lastPid = INVALID_PID;
103 int64_t g_lastStatus = INVALID_NUMBER_INT64;
104 int64_t g_timeStamp = 0;
105 int64_t g_preTimeStamp = 0;
106 pid_t g_lastRenderPid = INVALID_PID;
107 int64_t g_lastRenderStatus = INVALID_NUMBER_INT64;
108 bool g_siteIsolationMode = false;
109 
GetUidString()110 std::string GetUidString()
111 {
112     static std::string uidString = std::to_string(getuid());
113     return uidString;
114 }
115 
GetBundleNameByUid(int32_t uid)116 std::string GetBundleNameByUid(int32_t uid)
117 {
118     sptr<ISystemAbilityManager> systemAbilityManager =
119         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
120     if (systemAbilityManager == nullptr) {
121         WVLOG_E("get SystemAbilityManager failed");
122         return "";
123     }
124     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
125     if (remoteObject == nullptr) {
126         WVLOG_E("get Bundle Manager failed");
127         return "";
128     }
129     auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
130     if (bundleMgr == nullptr) {
131         return "";
132     }
133     std::string bundle {""};
134     bundleMgr->GetNameForUid(uid, bundle);
135     return bundle;
136 }
137 
ConvertStatus(ResSchedStatusAdapter statusAdapter,int64_t & status)138 bool ConvertStatus(ResSchedStatusAdapter statusAdapter, int64_t& status)
139 {
140     if (auto it = RES_STATUS_MAP.find(statusAdapter); it == RES_STATUS_MAP.end()) {
141         WVLOG_E("invalid status: %{public}d", statusAdapter);
142         return false;
143     } else {
144         status = it->second;
145     }
146     return true;
147 }
148 
NeedReportScene(ResSchedSceneAdapter sceneAdapter)149 bool NeedReportScene(ResSchedSceneAdapter sceneAdapter)
150 {
151     if (sceneAdapter != ResSchedSceneAdapter::SLIDE) {
152         return true;
153     }
154     auto currentTime = std::chrono::system_clock::now().time_since_epoch();
155     g_timeStamp = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime).count();
156     if (g_timeStamp - g_preTimeStamp > SLIDE_PERIOD_MS) {
157         g_preTimeStamp = g_timeStamp;
158         return true;
159     }
160     return false;
161 }
162 
ReportSceneInternal(ResSchedStatusAdapter statusAdapter,ResSchedSceneAdapter sceneAdapter)163 bool ReportSceneInternal(ResSchedStatusAdapter statusAdapter, ResSchedSceneAdapter sceneAdapter)
164 {
165     // To limit the frequency of events reported in some scenarios
166     if (!NeedReportScene(sceneAdapter)) {
167         return false;
168     }
169 
170     int64_t status;
171     bool ret = ConvertStatus(statusAdapter, status);
172     if (!ret) {
173         return false;
174     }
175 
176     int32_t sceneId;
177     if (auto it = RES_SCENE_MAP.find(sceneAdapter); it == RES_SCENE_MAP.end()) {
178         WVLOG_E("invalid scene id: %{public}d", sceneAdapter);
179         return false;
180     } else {
181         sceneId = it->second;
182     }
183 
184     std::unordered_map<std::string, std::string> mapPayload { { UID, GetUidString() },
185         { SCENE_ID, std::to_string(sceneId) } };
186     ResSchedClient::GetInstance().ReportData(ResType::RES_TYPE_REPORT_SCENE_SCHED, status, mapPayload);
187     WVLOG_D("ReportScene status: %{public}d, uid: %{public}s, sceneId: %{public}d", static_cast<int32_t>(status),
188         GetUidString().c_str(), sceneId);
189     return true;
190 }
191 
IsSameSourceWebSiteActive(ResSchedStatusAdapter statusAdapter,pid_t pid,int32_t nwebId)192 bool IsSameSourceWebSiteActive(ResSchedStatusAdapter statusAdapter, pid_t pid, int32_t nwebId)
193 {
194     g_pidNwebMap[pid][nwebId] = statusAdapter;
195     if (statusAdapter == ResSchedStatusAdapter::WEB_INACTIVE) {
196         auto nwebMap = g_pidNwebMap[pid];
197         for (auto it : nwebMap) {
198             if (it.second == ResSchedStatusAdapter::WEB_ACTIVE) {
199                 WVLOG_D("IsSameSourceWebSiteActive, current nwebId: %{public}d, active nwebId: %{public}d, "
200                         "pid: %{public}d", nwebId, it.first, pid);
201                 return true;
202             }
203         }
204         g_pidNwebMap.erase(pid);
205     }
206     return false;
207 }
208 
ReportStatusData(ResSchedStatusAdapter statusAdapter,pid_t pid,uint32_t windowId,int32_t nwebId,bool isSiteManage)209 void ReportStatusData(ResSchedStatusAdapter statusAdapter,
210                       pid_t pid, uint32_t windowId, int32_t nwebId, bool isSiteManage)
211 {
212     static uint32_t serialNum = 0;
213     static constexpr uint32_t serialNumMax = 10000;
214 
215     if (g_nwebSet.find(nwebId) == g_nwebSet.end() || pid == 0) {
216         WVLOG_D("Don't report window status, nwebId: %{public}d, pid: %{public}d", nwebId, pid);
217         return;
218     }
219 
220     int64_t status;
221     bool ret = ConvertStatus(statusAdapter, status);
222     if (!ret) {
223         return;
224     }
225 
226     ProductDeviceType deviceType = SystemPropertiesAdapterImpl::GetInstance().GetProductDeviceType();
227     if (deviceType == ProductDeviceType::DEVICE_TYPE_MOBILE || g_processInUse.count(pid)) {
228         if (isSiteManage && IsSameSourceWebSiteActive(statusAdapter, pid, nwebId)) {
229             return;
230         }
231     }
232 
233     if (pid == g_lastPid && status == g_lastStatus) {
234         return;
235     }
236     g_lastPid = pid;
237     g_lastStatus = status;
238 
239     std::unordered_map<std::string, std::string> mapPayload { { UID, GetUidString() }, { PID, std::to_string(pid) },
240         { WINDOW_ID, std::to_string(windowId) }, { SERIAL_NUMBER, std::to_string(serialNum) },
241         { STATE, std::to_string(status) } };
242     ResSchedClient::GetInstance().ReportData(
243         ResType::RES_TYPE_REPORT_WINDOW_STATE, ResType::ReportChangeStatus::CREATE, mapPayload);
244 
245     WVLOG_I("ReportWindowStatus status: %{public}d, uid: %{public}s, pid: %{public}d, windowId: %{public}d, "
246             "nwebId: %{public}d, sn: %{public}d",
247             static_cast<int32_t>(status), GetUidString().c_str(), pid, windowId, nwebId, serialNum);
248     serialNum = (serialNum + 1) % serialNumMax;
249 
250     // Report visible scene event again when tab becomes active to solve timing problem
251     if (statusAdapter == ResSchedStatusAdapter::WEB_ACTIVE) {
252         ReportSceneInternal(statusAdapter, ResSchedSceneAdapter::VISIBLE);
253     }
254 }
255 
ReportKeyThread(ResSchedStatusAdapter statusAdapter,pid_t pid,pid_t tid,ResSchedRoleAdapter roleAdapter)256 bool ResSchedClientAdapter::ReportKeyThread(
257     ResSchedStatusAdapter statusAdapter, pid_t pid, pid_t tid, ResSchedRoleAdapter roleAdapter)
258 {
259     int64_t status;
260     bool ret = ConvertStatus(statusAdapter, status);
261     if (!ret) {
262         return false;
263     }
264 
265     ResType::ThreadRole role;
266     if (auto it = RES_ROLE_MAP.find(roleAdapter); it == RES_ROLE_MAP.end()) {
267         WVLOG_E("invalid role: %{public}d", roleAdapter);
268         return false;
269     } else {
270         role = it->second;
271     }
272 
273     std::unordered_map<std::string, std::string> mapPayload { { UID, GetUidString() }, { PID, std::to_string(pid) },
274         { TID, std::to_string(tid) }, { ROLE, std::to_string(role) } };
275 
276     // Report process creation event first when render process is created
277     if (pid == tid) {
278         mapPayload["processType"] = std::to_string(static_cast<uint32_t>(AppExecFwk::ProcessType::RENDER));
279         mapPayload["bundleName"] = GetBundleNameByUid(getuid());
280     }
281 
282     ResSchedClient::GetInstance().ReportData(ResType::RES_TYPE_REPORT_KEY_THREAD, status, mapPayload);
283     WVLOG_D("ReportKeyThread status: %{public}d, uid: %{public}s, pid: %{public}d, tid:%{public}d, role: %{public}d",
284         static_cast<int32_t>(status), GetUidString().c_str(), pid, tid, static_cast<int32_t>(role));
285 
286     if (pid == tid && g_windowId != INVALID_NUMBER && g_nwebId != INVALID_NUMBER) {
287         std::lock_guard<std::mutex> lock(g_windowIdMutex);
288         ReportStatusData(ResSchedStatusAdapter::WEB_ACTIVE, pid, g_windowId, g_nwebId, false);
289     }
290 
291     if (pid == tid && statusAdapter == ResSchedStatusAdapter::THREAD_DESTROYED) {
292         g_processInUse.erase(pid);
293     }
294 
295     // Load url may create new render process, repeat report load url event when
296     // render key thread create to solve timing problem. Later events will overwrite previous events
297     if (statusAdapter == ResSchedStatusAdapter::THREAD_CREATED && pid != getprocpid()) {
298         ReportSceneInternal(statusAdapter, ResSchedSceneAdapter::LOAD_URL);
299     }
300     return true;
301 }
302 
ReportAudioData(ResSchedStatusAdapter statusAdapter,pid_t pid,pid_t tid)303 bool ResSchedClientAdapter::ReportAudioData(ResSchedStatusAdapter statusAdapter, pid_t pid, pid_t tid)
304 {
305     static uint32_t resType = ResType::RES_TYPE_WEBVIEW_AUDIO_STATUS_CHANGE;
306 
307     int64_t status;
308     if (!ConvertStatus(statusAdapter, status)) {
309         return false;
310     }
311 
312     uid_t uid = getuid();
313     std::unordered_map<std::string, std::string> mapPayload { { UID, std::to_string(uid) },
314         { PID, std::to_string(pid) }, { TID, std::to_string(tid) } };
315     WVLOG_D("ReportAudioData status: %{public}d, uid: %{public}d, pid: %{public}d, tid:%{public}d",
316         static_cast<int32_t>(status), uid, pid, tid);
317     ResSchedClient::GetInstance().ReportData(resType, status, mapPayload);
318 
319     return true;
320 }
321 
ReportProcessInUse(pid_t pid)322 void ResSchedClientAdapter::ReportProcessInUse(pid_t pid)
323 {
324     int32_t nwebId = g_nwebId;
325     if (g_pidNwebMap.count(pid)) {
326         nwebId = g_pidNwebMap[pid].begin()->first;
327     }
328 
329     g_processInUse.insert(pid);
330 
331     if (nwebId != INVALID_NUMBER) {
332         g_nwebProcessMap[nwebId].push_back(pid);
333         WVLOG_D("ReportProcessInUse nwebId: %{public}d, pid: %{public}d", nwebId, pid);
334 
335         if (g_siteIsolationMode) {
336             ReportStatusData(ResSchedStatusAdapter::WEB_ACTIVE, pid, g_windowId, nwebId, true);
337         }
338     }
339 }
340 
ReportSiteIsolationMode(bool mode)341 void ResSchedClientAdapter::ReportSiteIsolationMode(bool mode)
342 {
343     g_siteIsolationMode = mode;
344     WVLOG_D("ReportSiteIsolationMode g_siteIsolationMode: %{public}d", mode);
345 }
346 
ReportWindowStatus(ResSchedStatusAdapter statusAdapter,pid_t pid,uint32_t windowId,int32_t nwebId)347 bool ResSchedClientAdapter::ReportWindowStatus(
348     ResSchedStatusAdapter statusAdapter, pid_t pid, uint32_t windowId, int32_t nwebId)
349 {
350     if (g_nwebSet.find(nwebId) == g_nwebSet.end() || pid == 0) {
351         WVLOG_D("Don't report window status, nwebId: %{public}d, pid: %{public}d", nwebId, pid);
352         return false;
353     }
354 
355     int64_t status;
356     if (!ConvertStatus(statusAdapter, status)) {
357         return false;
358     }
359     if (statusAdapter == ResSchedStatusAdapter::WEB_ACTIVE) {
360         ReportWindowId(windowId, nwebId);
361     }
362 
363     ReportStatusData(statusAdapter, pid, windowId, nwebId, true);
364 
365     ProductDeviceType deviceType = SystemPropertiesAdapterImpl::GetInstance().GetProductDeviceType();
366     if (deviceType == ProductDeviceType::DEVICE_TYPE_TABLET || deviceType == ProductDeviceType::DEVICE_TYPE_2IN1) {
367         for (auto pidInNweb : g_nwebProcessMap[nwebId]) {
368             if (pidInNweb == pid) {
369                 continue;
370             }
371             ReportStatusData(statusAdapter, pidInNweb, windowId, nwebId, true);
372         }
373     }
374 
375     return true;
376 }
377 
ReportScene(ResSchedStatusAdapter statusAdapter,ResSchedSceneAdapter sceneAdapter,int32_t nwebId)378 bool ResSchedClientAdapter::ReportScene(
379     ResSchedStatusAdapter statusAdapter, ResSchedSceneAdapter sceneAdapter, int32_t nwebId)
380 {
381     if (nwebId == -1) {
382         return ReportSceneInternal(statusAdapter, sceneAdapter);
383     }
384 
385     if (g_nwebSet.find(nwebId) == g_nwebSet.end()) {
386         WVLOG_E("ReportScene nwebId %{public}d not exist in render set", nwebId);
387         return false;
388     }
389     return ReportSceneInternal(statusAdapter, sceneAdapter);
390 }
391 
ReportWindowId(int32_t windowId,int32_t nwebId)392 void ResSchedClientAdapter::ReportWindowId(int32_t windowId, int32_t nwebId)
393 {
394     std::lock_guard<std::mutex> lock(g_windowIdMutex);
395     g_windowId = windowId;
396     g_nwebId = nwebId;
397     WVLOG_D("ReportWindowId windowId: %{public}d, nwebId: %{public}d", g_windowId, g_nwebId);
398 }
399 
ReportNWebInit(ResSchedStatusAdapter statusAdapter,int32_t nwebId)400 void ResSchedClientAdapter::ReportNWebInit(ResSchedStatusAdapter statusAdapter, int32_t nwebId)
401 {
402     static std::mutex initMutex;
403     std::lock_guard<std::mutex> lock(initMutex);
404     if (statusAdapter == ResSchedStatusAdapter::WEB_SCENE_ENTER) {
405         WVLOG_D("ReportNWebInit %{public}d", nwebId);
406         g_nwebSet.emplace(nwebId);
407     } else if (statusAdapter == ResSchedStatusAdapter::WEB_SCENE_EXIT) {
408         g_nwebSet.erase(nwebId);
409         g_nwebProcessMap.erase(nwebId);
410         for (auto nwebMap : g_pidNwebMap) {
411             auto it = nwebMap.second.find(nwebId);
412             if (it != nwebMap.second.end()) {
413                 nwebMap.second.erase(it);
414             }
415         }
416     }
417 }
418 
ReportRenderProcessStatus(ResSchedStatusAdapter statusAdapter,pid_t pid)419 void ResSchedClientAdapter::ReportRenderProcessStatus(ResSchedStatusAdapter statusAdapter, pid_t pid)
420 {
421     int64_t status;
422     bool ret = ConvertStatus(statusAdapter, status);
423     if (!ret) {
424         WVLOG_E("ReportRenderProcessStatus get appMgrClient failed");
425         return;
426     }
427 
428     if (pid == g_lastRenderPid && status == g_lastRenderStatus) {
429         WVLOG_D("ReportRenderProcessStatus same status and process");
430         return;
431     }
432     g_lastRenderPid = pid;
433     g_lastRenderStatus = status;
434 
435     auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
436     if (appMgrClient == nullptr) {
437         WVLOG_E("ReportRenderProcessStatus get appMgrClient failed");
438         return;
439     }
440     appMgrClient->UpdateRenderState(pid, status);
441     WVLOG_D("ReportRenderProcessStatus status: %{public}d, pid: %{public}d", static_cast<int32_t>(status), pid);
442 }
443 
ReportScreenCapture(ResSchedStatusAdapter statusAdapter,pid_t pid)444 bool ResSchedClientAdapter::ReportScreenCapture(ResSchedStatusAdapter statusAdapter, pid_t pid)
445 {
446     static uint32_t resType = ResType::RES_TYPE_WEBVIEW_SCREEN_CAPTURE;
447 
448     int64_t status;
449     if (!ConvertStatus(statusAdapter, status)) {
450         return false;
451     }
452 
453     uid_t uid = getuid();
454     std::unordered_map<std::string, std::string> mapPayload { { UID, std::to_string(uid) },
455         { PID, std::to_string(pid) } };
456     WVLOG_D("ReportScreenCapture status: %{public}d, uid: %{public}d, pid: %{public}d",
457         static_cast<int32_t>(status), uid, pid);
458     ResSchedClient::GetInstance().ReportData(resType, status, mapPayload);
459 
460     return true;
461 }
462 
ReportVideoPlaying(ResSchedStatusAdapter statusAdapter,pid_t pid)463 bool ResSchedClientAdapter::ReportVideoPlaying(ResSchedStatusAdapter statusAdapter, pid_t pid)
464 {
465     static uint32_t resType = ResType::RES_TYPE_WEBVIEW_VIDEO_STATUS_CHANGE;
466 
467     int64_t status;
468     if (!ConvertStatus(statusAdapter, status)) {
469         return false;
470     }
471 
472     uid_t uid = getuid();
473     std::unordered_map<std::string, std::string> mapPayload { { UID, std::to_string(uid) },
474         { PID, std::to_string(pid) } };
475     WVLOG_D("ReportVideoPlaying status: %{public}d, uid: %{public}d, pid: %{public}d",
476         static_cast<int32_t>(status), uid, pid);
477     ResSchedClient::GetInstance().ReportData(resType, status, mapPayload);
478 
479     return true;
480 }
481 } // namespace OHOS::NWeb
482