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