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 "hisysevent_observer.h"
17 
18 #ifdef RESSCHED_COMMUNICATION_BLUETOOTH_ENABLE
19 #include "bluetooth_def.h"
20 #endif
21 #include "res_sched_log.h"
22 #include "res_sched_mgr.h"
23 #include "res_type.h"
24 
25 namespace OHOS {
26 namespace ResourceSchedule {
27 namespace {
28     static const std::string WIFI_CONNECTION = "WIFI_CONNECTION";
29     static const std::string WIFI_SCAN = "WIFI_SCAN";
30     static const std::string CAMERA_CONNECT = "CAMERA_CONNECT";
31     constexpr int32_t INDENT                    = -1;
32     constexpr int32_t WIFISCAN                  = 2;
33     constexpr int32_t WIFICONNECTED             = 3;
34     constexpr int32_t WIFIDISCONNECTED          = 5;
35     constexpr int32_t CAMERACONNECT             = 0;
36     constexpr int32_t CAMERADISCONNECT          = 1;
37     constexpr int32_t RUNNINGLOCK_DISABLE       = 0;
38     constexpr int32_t RUNNINGLOCK_ENABLE        = 1;
39     constexpr int32_t RUNNINGLOCK_PROXIED       = 2;
40     constexpr int32_t MAX_LENGTH                = 1024;
41 }
42 
HiSysEventObserver()43 HiSysEventObserver::HiSysEventObserver() : HiviewDFX::HiSysEventListener()
44 {
45     handleObserverMap_ = {
46         {"RUNNINGLOCK", [this](const nlohmann::json& root, const std::string& eventName) {
47             this->ProcessRunningLockEvent(root, eventName);
48         }},
49         {"STREAM_CHANGE", [this](const nlohmann::json& root, const std::string& eventName) {
50             this->ProcessAudioEvent(root, eventName);
51         }},
52         {"CAMERA_CONNECT", [this](const nlohmann::json& root, const std::string& eventName) {
53             this->ProcessCameraEvent(root, eventName);
54         }},
55         {"CAMERA_DISCONNECT", [this](const nlohmann::json& root, const std::string& eventName) {
56             this->ProcessCameraEvent(root, eventName);
57         }},
58         {"BR_SWITCH_STATE", [this](const nlohmann::json& root, const std::string& eventName) {
59             this->ProcessBluetoothEvent(root, eventName);
60         }},
61         {"BLE_SWITCH_STATE", [this](const nlohmann::json& root, const std::string& eventName) {
62             this->ProcessBluetoothEvent(root, eventName);
63         }},
64         {"WIFI_CONNECTION", [this](const nlohmann::json& root, const std::string& eventName) {
65             this->ProcessWifiEvent(root, eventName);
66         }},
67         {"WIFI_SCAN", [this](const nlohmann::json& root, const std::string& eventName) {
68             this->ProcessWifiEvent(root, eventName);
69         }},
70     };
71 }
72 
~HiSysEventObserver()73 HiSysEventObserver::~HiSysEventObserver()
74 {
75     handleObserverMap_.clear();
76 }
77 
CheckJsonValue(const nlohmann::json & value,std::initializer_list<std::string> params)78 bool HiSysEventObserver::CheckJsonValue(const nlohmann::json& value, std::initializer_list<std::string> params)
79 {
80     for (const auto& param : params) {
81         if (value.find(param) == value.end()) {
82             return false;
83         }
84     }
85     return true;
86 }
87 
OnEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent)88 void HiSysEventObserver::OnEvent(std::shared_ptr<HiviewDFX::HiSysEventRecord> sysEvent)
89 {
90     if (sysEvent == nullptr) {
91         RESSCHED_LOGE("OnEvent hisysevent info is null");
92         return;
93     }
94     std::string eventDetail = sysEvent->AsJson();
95     if (eventDetail.length() > MAX_LENGTH) {
96         RESSCHED_LOGE("eventDetail length is invalid");
97         return;
98     }
99     RESSCHED_LOGD("Process hisysevent event, detail:%{public}s", eventDetail.c_str());
100     nlohmann::json root = nlohmann::json::parse(eventDetail, nullptr, false);
101     if (root.is_discarded()) {
102         RESSCHED_LOGE("Parse hisysevent data failed");
103         return;
104     }
105     if (!CheckJsonValue(root, { "domain_", "name_" })
106         || !root.at("domain_").is_string() || !root.at("name_").is_string()) {
107         RESSCHED_LOGE("hisysevent data domain info lost");
108         return;
109     }
110     std::string domainName = root.at("domain_").get<std::string>();
111     std::string eventName = root.at("name_").get<std::string>();
112     RESSCHED_LOGD("hisysevent info, domain: %{public}s, name:%{public}s", domainName.c_str(), eventName.c_str());
113     ProcessHiSysEvent(eventName, root);
114 }
115 
ProcessHiSysEvent(const std::string & eventName,const nlohmann::json & root)116 void HiSysEventObserver::ProcessHiSysEvent(const std::string& eventName, const nlohmann::json& root)
117 {
118     if (root.at("domain_").get<std::string>() == "AV_CODEC") {
119         ProcessAvCodecEvent(root, eventName);
120         return;
121     }
122 
123     auto funcIter = handleObserverMap_.find(eventName.c_str());
124     if (funcIter != handleObserverMap_.end()) {
125         auto function = funcIter->second;
126         if (function) {
127             function(root, eventName);
128         }
129     }
130 }
131 
ProcessAvCodecEvent(const nlohmann::json & root,const std::string & eventName)132 void HiSysEventObserver::ProcessAvCodecEvent(const nlohmann::json& root, const std::string& eventName)
133 {
134     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
135     RESSCHED_LOGD("Process av_codec event, event root:%{public}s", str.c_str());
136     nlohmann::json payload;
137     if (root.contains("CLIENT_UID") && root.at("CLIENT_UID").is_number_integer()) {
138         payload["uid"] = std::to_string(root.at("CLIENT_UID").get<std::int32_t>());
139     } else {
140         RESSCHED_LOGE("av_codec event uid format error!");
141         return;
142     }
143     if (root.contains("CLIENT_PID") && root.at("CLIENT_PID").is_number_integer()) {
144         payload["pid"] = std::to_string(root.at("CLIENT_PID").get<std::int32_t>());
145     } else {
146         RESSCHED_LOGE("av_codec event pid format error!");
147         return;
148     }
149     if (root.contains("CODEC_INSTANCE_ID") && root.at("CODEC_INSTANCE_ID").is_number_integer()) {
150         payload["instanceId"] = std::to_string(root.at("CODEC_INSTANCE_ID").get<std::int32_t>());
151     } else {
152         RESSCHED_LOGE("av_codec event instanceId format error!");
153         return;
154     }
155 
156     if (eventName == "CODEC_START_INFO") {
157         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AV_CODEC_STATE,
158             ResType::AvCodecState::CODEC_START_INFO, payload);
159     } else if (eventName == "CODEC_STOP_INFO") {
160         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AV_CODEC_STATE,
161             ResType::AvCodecState::CODEC_STOP_INFO, payload);
162     }
163 }
164 
ProcessRunningLockEvent(const nlohmann::json & root,const std::string & eventName)165 void HiSysEventObserver::ProcessRunningLockEvent(const nlohmann::json& root, const std::string& eventName)
166 {
167     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
168     RESSCHED_LOGD("Process runninglock event, event root:%{public}s", str.c_str());
169     nlohmann::json payload;
170     if (root.contains("UID") && root.at("UID").is_number_integer()) {
171         payload["uid"] = std::to_string(root.at("UID").get<std::int32_t>());
172     } else {
173         RESSCHED_LOGE("running lock event uid format error!");
174         return;
175     }
176     if (root.contains("PID") && root.at("PID").is_number_integer()) {
177         payload["pid"] = std::to_string(root.at("PID").get<std::int32_t>());
178     } else {
179         RESSCHED_LOGE("running lock event pid format error!");
180         return;
181     }
182     if (root.contains("TYPE") && root.at("TYPE").is_number_integer()) {
183         payload["type"] = std::to_string(root.at("TYPE").get<std::uint32_t>());
184     } else {
185         RESSCHED_LOGE("running lock event lock type format error!");
186         return;
187     }
188 
189     if (root.contains("STATE") && root.at("STATE").is_number_integer()) {
190         RunningLockState lockState = RunningLockState(root.at("STATE").get<std::int32_t>());
191         RESSCHED_LOGD("Process runninglock event, event type is:%{public}d", lockState);
192         switch (lockState) {
193             case RunningLockState::RUNNINGLOCK_STATE_DISABLE: {
194                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_RUNNINGLOCK_STATE,
195                     RUNNINGLOCK_DISABLE, payload);
196                 break;
197             }
198             case RunningLockState::RUNNINGLOCK_STATE_ENABLE: {
199                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_RUNNINGLOCK_STATE,
200                     RUNNINGLOCK_ENABLE, payload);
201                 break;
202             }
203             case RunningLockState::RUNNINGLOCK_STATE_PROXIED:
204             case RunningLockState::RUNNINGLOCK_STATE_UNPROXIED_RESTORE: {
205                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_RUNNINGLOCK_STATE,
206                     RUNNINGLOCK_PROXIED, payload);
207                 break;
208             }
209             default:
210                 break;
211         }
212     } else {
213         RESSCHED_LOGE("running lock event state format error!");
214         return;
215     }
216 }
217 
ProcessAudioEvent(const nlohmann::json & root,const std::string & eventName)218 void HiSysEventObserver::ProcessAudioEvent(const nlohmann::json& root, const std::string& eventName)
219 {
220     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
221     RESSCHED_LOGD("Process audio event, event root :%{public}s", str.c_str());
222     nlohmann::json payload;
223     if (root.contains("UID") && root.at("UID").is_number_integer()) {
224         payload["uid"] = root.at("UID").get<std::int32_t>();
225     } else {
226         RESSCHED_LOGE("audio event uid format error!");
227         return;
228     }
229     if (root.contains("PID") && root.at("PID").is_number_integer()) {
230         payload["pid"] = root.at("PID").get<std::int32_t>();
231     } else {
232         RESSCHED_LOGE("audio event pid format error!");
233         return;
234     }
235 
236     if (root.contains("STATE") && root.at("STATE").is_number_integer()) {
237         AudioState audioState = AudioState(root.at("STATE").get<std::int32_t>());
238         RESSCHED_LOGD("Process audio event, event type is:%{public}d", audioState);
239         switch (audioState) {
240             case AudioState::AUDIO_STATE_RUNNING:
241                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
242                     ResType::AudioStatus::RENDERER_RUNNING, payload);
243                 break;
244             case AudioState::AUDIO_STATE_STOPPED:
245                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
246                     ResType::AudioStatus::RENDERER_STOPPED, payload);
247                 break;
248             case AudioState::AUDIO_STATE_RELEASED:
249                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
250                     ResType::AudioStatus::RENDERER_RELEASED, payload);
251                 break;
252             case AudioState::AUDIO_STATE_PAUSED:
253                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
254                     ResType::AudioStatus::RENDERER_PAUSED, payload);
255                 break;
256             default:
257                 break;
258         }
259     } else {
260         RESSCHED_LOGE("audio event state format error!");
261         return;
262     }
263 }
264 
ProcessCameraEvent(const nlohmann::json & root,const std::string & eventName)265 void HiSysEventObserver::ProcessCameraEvent(const nlohmann::json& root, const std::string& eventName)
266 {
267     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
268     RESSCHED_LOGD("Process camera event, event root:%{public}s, eventName:%{public}s", str.c_str(), eventName.c_str());
269     nlohmann::json payload;
270     if (root.contains("UID") && root.at("UID").is_number_integer()) {
271         payload["uid"] = std::to_string(root.at("UID").get<std::int32_t>());
272     } else {
273         RESSCHED_LOGE("camera event uid format error!");
274         return;
275     }
276     if (root.contains("PID") && root.at("PID").is_number_integer()) {
277         payload["pid"] = std::to_string(root.at("PID").get<std::int32_t>());
278     } else {
279         RESSCHED_LOGE("camera event pid format error!");
280         return;
281     }
282 
283     if (eventName == CAMERA_CONNECT) {
284         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_REPORT_CAMERA_STATE, CAMERACONNECT, payload);
285     } else {
286         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_REPORT_CAMERA_STATE, CAMERADISCONNECT, payload);
287     }
288 }
289 
ProcessBluetoothEvent(const nlohmann::json & root,const std::string & eventName)290 void HiSysEventObserver::ProcessBluetoothEvent(const nlohmann::json& root, const std::string& eventName)
291 {
292     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
293     RESSCHED_LOGD("Process bluetooth event, event root :%{public}s", str.c_str());
294     nlohmann::json payload;
295     if (root.contains("UID") && root.at("UID").is_number_integer()) {
296         payload["uid"] = std::to_string(root.at("UID").get<std::int32_t>());
297     } else {
298         RESSCHED_LOGE("bluetooth event uid format error!");
299         return;
300     }
301     if (root.contains("PID") && root.at("PID").is_number_integer()) {
302         payload["pid"] = std::to_string(root.at("PID").get<std::int32_t>());
303     } else {
304         RESSCHED_LOGE("bluetooth event pid format error!");
305         return;
306     }
307 
308 #ifdef RESSCHED_COMMUNICATION_BLUETOOTH_ENABLE
309     if (root.contains("STATE") && root.at("STATE").is_number_integer()) {
310         RESSCHED_LOGD("Process bluetooth event, event type is:%{public}d", root.at("STATE").get<std::int32_t>());
311         if (root.at("STATE").get<std::int32_t>() == Bluetooth::BTStateID::STATE_TURN_ON) {
312             ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE,
313                 Bluetooth::BTStateID::STATE_TURN_ON, payload);
314         } else if (root.at("STATE").get<std::int32_t>() == Bluetooth::BTStateID::STATE_TURN_OFF) {
315             ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_BLUETOOTH_A2DP_CONNECT_STATE_CHANGE,
316                 Bluetooth::BTStateID::STATE_TURN_OFF, payload);
317         }
318     } else {
319         RESSCHED_LOGE("Bluetooth event type not support!");
320         return;
321     }
322 #endif
323 }
324 
ProcessWifiEvent(const nlohmann::json & root,const std::string & eventName)325 void HiSysEventObserver::ProcessWifiEvent(const nlohmann::json& root, const std::string& eventName)
326 {
327     std::string str = root.dump(INDENT, ' ', false, nlohmann::json::error_handler_t::replace);
328     RESSCHED_LOGD("Process wifi event, event root :%{public}s, eventName:%{public}s", str.c_str(), eventName.c_str());
329     nlohmann::json payload;
330     if (root.contains("uid_") && root.at("uid_").is_number_integer()) {
331         payload["uid"] = std::to_string(root.at("uid_").get<std::int32_t>());
332     } else {
333         RESSCHED_LOGE("Wifi event uid format error!");
334         return;
335     }
336     if (root.contains("pid_") && root.at("pid_").is_number_integer()) {
337         payload["pid"] = std::to_string(root.at("pid_").get<std::int32_t>());
338     } else {
339         RESSCHED_LOGE("Wifi event pid format error!");
340         return;
341     }
342 
343     WifiState connectionType;
344     if (root.contains("TYPE") && root.at("TYPE").is_number_integer()) {
345         connectionType = WifiState(root.at("TYPE").get<std::int32_t>());
346     } else {
347         RESSCHED_LOGE("Wifi event type format error!");
348         return;
349     }
350     if (eventName == WIFI_CONNECTION) {
351         switch (connectionType) {
352             case WifiState::CONNECTED:
353                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE,
354                     WIFICONNECTED, payload);
355                 break;
356             case WifiState::DISCONNECTED:
357                 ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE,
358                     WIFIDISCONNECTED, payload);
359                 break;
360             default:
361                 break;
362         }
363     } else if (eventName == WIFI_SCAN) {
364         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_WIFI_CONNECT_STATE_CHANGE, WIFISCAN, payload);
365     } else {
366         RESSCHED_LOGE("Wifi event name not support!");
367         return;
368     }
369 }
370 
OnServiceDied()371 void HiSysEventObserver::OnServiceDied()
372 {
373     RESSCHED_LOGE("HiSysEventObserver service disconnected");
374 }
375 } // namespace ResourceSchedule
376 } // namespace OHOS
377