1 /*
2 * Copyright (c) 2020-2021 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 "dfx_module.h"
17 #include "ace_log.h"
18 #include "ui_dump_dom_tree.h"
19 #ifdef FEATURE_ACELITE_MC_DFX_MODULE
20 #include "ui_snapshot.h"
21 #elif (FEATURE_ACELITE_LITE_DFX_MODULE == 1)
22 #ifdef __LITEOS_A__
23 #include "ability_env.h"
24 #endif
25 #include "ace_mem_base.h"
26 #include "js_fwk_common.h"
27 #include "ui_screenshot.h"
28 #endif
29 #ifdef __LITEOS_A__
30 #include "window/window.h"
31 #endif
32
33 namespace OHOS {
34 namespace ACELite {
35 const char * const DfxModule::DOM_TREE_PATH = "dump_dom_tree.json";
36
37 const char * const DfxModule::SCREEN_SNAP_PATH = "screensnap.bin";
38
PreCheck(uint8_t argsNum)39 bool DfxModule::PreCheck(uint8_t argsNum)
40 {
41 if (argsNum > 1) {
42 HILOG_ERROR(HILOG_MODULE_ACE, "Dfx Module args num(%{public}d) is invalid, at most one parameter", argsNum);
43 return false;
44 }
45 return true;
46 }
47
GetDomViewId(const JSIValue * args)48 char *DfxModule::GetDomViewId(const JSIValue *args)
49 {
50 if (args == nullptr) {
51 return nullptr;
52 }
53 return JSI::ValueToString(args[0]);
54 }
55
IsEventInjectorRegistered(EventDataType type)56 bool DfxModule::IsEventInjectorRegistered(EventDataType type)
57 {
58 EventInjector* eventInjector = EventInjector::GetInstance();
59 if ((eventInjector == nullptr) || (!eventInjector->IsEventInjectorRegistered(type) &&
60 !eventInjector->RegisterEventInjector(type))) {
61 HILOG_ERROR(HILOG_MODULE_ACE, "register event error");
62 return false;
63 }
64 #ifdef __LITEOS_A__
65 #if ENABLE_WINDOW
66 RootView* rootView = RootView::GetInstance();
67 if (rootView == nullptr) {
68 HILOG_ERROR(HILOG_MODULE_ACE, "get root view error");
69 return false;
70 }
71 Window *window = rootView->GetBoundWindow();
72 if (window == nullptr) {
73 HILOG_ERROR(HILOG_MODULE_ACE, "set window id error");
74 return false;
75 }
76 eventInjector->SetWindowId(window->GetWindowId());
77 #endif
78 #endif
79 return true;
80 }
81
82 #if (FEATURE_ACELITE_DFX_MODULE == 1)
Screenshot(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)83 JSIValue DfxModule::Screenshot(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
84 {
85 #ifdef FEATURE_ACELITE_MC_DFX_MODULE
86 JSIValue retVal = JSI::CreateBoolean(true);
87 if (!UISnapShot::ScreenshotToFile()) {
88 HILOG_ERROR(HILOG_MODULE_ACE, "screenshot failed");
89 JSI::ReleaseValue(retVal);
90 retVal = JSI::CreateBoolean(false);
91 }
92 return retVal;
93 #elif (FEATURE_ACELITE_LITE_DFX_MODULE == 1)
94 JSIValue retVal = JSI::CreateBoolean(true);
95 #ifdef __LITEOS_A__
96 const char * const savingPath = GetDataPath();
97 #elif defined(__linux__)
98 const char * const savingPath = "/storage/nfs";
99 #else
100 const char * const savingPath = "user/log";
101 #endif
102 char *path = RelocateResourceFilePath(savingPath, SCREEN_SNAP_PATH);
103 // uikit will deal with if path is null
104 UIScreenshot* screenshot = UIScreenshot::GetInstance();
105 if ((screenshot == nullptr) || (!screenshot->ScreenshotToFile(path))) {
106 HILOG_ERROR(HILOG_MODULE_ACE, "screenshot failed");
107 JSI::ReleaseValue(retVal);
108 retVal = JSI::CreateBoolean(false);
109 }
110 if (path != nullptr) {
111 ace_free(path);
112 }
113 return retVal;
114 #endif
115 }
116 #endif
117
DumpDomTree(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)118 JSIValue DfxModule::DumpDomTree(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
119 {
120 JSIValue retVal = JSI::CreateBoolean(false);
121 if (!PreCheck(argsNum)) {
122 return retVal;
123 }
124 UIDumpDomTree* uIDumpDomTree = UIDumpDomTree::GetInstance();
125 char *viewId = GetDomViewId(args);
126 #if (FEATURE_ACELITE_LITE_DFX_MODULE == 1)
127 #ifdef __LITEOS_A__
128 const char * const savingPath = GetDataPath();
129 #elif defined(__linux__)
130 const char * const savingPath = "/storage/nfs";
131 #else
132 const char * const savingPath = "user/log";
133 #endif
134 char *path = RelocateResourceFilePath(savingPath, DOM_TREE_PATH);
135 // uikit will deal with if path and viewid is null
136 if ((uIDumpDomTree != nullptr) && (uIDumpDomTree->DumpDomTree(viewId, path))) {
137 #else
138 if ((uIDumpDomTree != nullptr) && (uIDumpDomTree->DumpDomTree(viewId))) {
139 #endif
140 JSI::ReleaseValue(retVal);
141 retVal = JSI::CreateBoolean(true);
142 }
143
144 #if (FEATURE_ACELITE_LITE_DFX_MODULE == 1)
145 if (path != nullptr) {
146 ace_free(path);
147 }
148 #endif
149 JSI::ReleaseString(viewId);
150 return retVal;
151 }
152
153 JSIValue DfxModule::DumpDomNode(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
154 {
155 UIDumpDomTree* uIDumpDomTree = UIDumpDomTree::GetInstance();
156 if (!PreCheck(argsNum) || (uIDumpDomTree == nullptr)) {
157 return JSI::CreateUndefined();
158 }
159
160 char *viewId = GetDomViewId(args);
161 char *msg = uIDumpDomTree->DumpDomNode(viewId);
162 if (msg == nullptr) {
163 JSI::ReleaseString(viewId);
164 return JSI::CreateUndefined();
165 }
166 JSIValue retVal = JSI::CreateString(msg);
167 cJSON_free(msg); // use cjson malloc memory, use cJSON_free() instead of ace_free()
168 JSI::ReleaseString(viewId);
169 return retVal;
170 }
171
172 JSIValue DfxModule::InjectPointEvent(const JSIValue *args, EventDataType type)
173 {
174 JSIValue retVal = JSI::CreateBoolean(true);
175 const uint8_t index = 2;
176 const uint32_t maxLen = 40;
177 // over 40 are ignored, ignore from beginning of the array
178 uint32_t len = JSI::GetArrayLength(args[0]);
179 uint32_t arrIndex = 0;
180 uint32_t realLen = (len > maxLen) ? maxLen : len;
181 DeviceData *data = (realLen > 0) ? static_cast<DeviceData *>(ace_malloc(sizeof(DeviceData) * realLen)) : nullptr;
182 if (len > maxLen) {
183 arrIndex = len - maxLen;
184 }
185 if (data == nullptr) {
186 HILOG_ERROR(HILOG_MODULE_ACE, "create device data failed");
187 JSI::ReleaseValue(retVal);
188 return JSI::CreateBoolean(false);
189 }
190
191 for (uint16_t i = 0; arrIndex < len; i++, arrIndex++) {
192 JSIValue point = JSI::GetPropertyByIndex(args[0], arrIndex);
193 if (JSI::ValueIsUndefined(point)) {
194 HILOG_ERROR(HILOG_MODULE_ACE, "point is error");
195 ace_free(data);
196 JSI::ReleaseValue(retVal);
197 return JSI::CreateBoolean(false);
198 }
199 JSIValue point_x = JSI::GetPropertyByIndex(point, 0);
200 JSIValue point_y = JSI::GetPropertyByIndex(point, 1);
201 JSIValue state = JSI::GetPropertyByIndex(point, index);
202 data[i].point = {
203 static_cast<int16_t>(JSI::ValueToNumber(point_x)),
204 static_cast<int16_t>(JSI::ValueToNumber(point_y))
205 };
206 data[i].state = static_cast<uint16_t>(JSI::ValueToNumber(state));
207 JSI::ReleaseValueList(point_x, point_y, state, point);
208 }
209
210 // simulate point event
211 EventInjector* eventInjector = EventInjector::GetInstance();
212 if ((eventInjector != nullptr) &&
213 (eventInjector->SetInjectEvent(data, realLen, type))) {
214 ace_free(data);
215 return retVal;
216 }
217 HILOG_ERROR(HILOG_MODULE_ACE, "simulator point event error");
218 ace_free(data);
219 JSI::ReleaseValue(retVal);
220 return JSI::CreateBoolean(false);
221 }
222
223 JSIValue DfxModule::InjectEvent(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
224 {
225 // pre check
226 const uint8_t num = 2;
227 if (argsNum != num) {
228 HILOG_ERROR(HILOG_MODULE_ACE, "Dfx Module args num(%{public}d) is invalid, only one parameter", argsNum);
229 return JSI::CreateBoolean(false);
230 }
231
232 // dispatch register event
233 char *eventType = JSI::ValueToString(args[1]);
234 if (eventType == nullptr) {
235 return JSI::CreateBoolean(false);
236 }
237 if (!strcmp(eventType, "point")) {
238 JSI::ReleaseString(eventType);
239 EventDataType type = EventDataType::POINT_TYPE;
240 if (!IsEventInjectorRegistered(type)) {
241 return JSI::CreateBoolean(false);
242 }
243 return InjectPointEvent(args, type);
244 }
245 HILOG_ERROR(HILOG_MODULE_ACE, "only support point event");
246
247 JSI::ReleaseString(eventType);
248 return JSI::CreateBoolean(false);
249 }
250
251 void DfxModule::OnDestroy()
252 {
253 EventInjector* eventInjector = EventInjector::GetInstance();
254 // iterator remove all registered event
255 if (eventInjector != nullptr) {
256 eventInjector->UnregisterEventInjector(EventDataType::POINT_TYPE);
257 eventInjector->UnregisterEventInjector(EventDataType::OTHERS);
258 }
259 }
260 } // namespace ACELite
261 } // namespace OHOS
262