1 /*
2 * Copyright (c) 2022 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 "core/common/layout_inspector.h"
17
18 #include <string>
19
20 #include "third_party/skia/include/core/SkString.h"
21 #include "third_party/skia/include/utils/SkBase64.h"
22 #include "wm/window.h"
23
24 #include "base/thread/background_task_executor.h"
25 #include "base/utils/utils.h"
26 #include "core/common/connect_server_manager.h"
27 #include "core/common/container.h"
28 #include "core/common/ace_engine.h"
29 #include "core/common/container_scope.h"
30 #include "core/components_ng/base/inspector.h"
31 #include "core/components_v2/inspector/inspector.h"
32 #include "foundation/ability/ability_runtime/frameworks/native/runtime/connect_server_manager.h"
33
34 namespace OHOS::Ace {
35
36 bool LayoutInspector::layoutInspectorStatus_ = false;
37
SupportInspector()38 void LayoutInspector::SupportInspector()
39 {
40 auto container = Container::Current();
41 CHECK_NULL_VOID_NOLOG(container);
42 if (!layoutInspectorStatus_) {
43 return;
44 }
45 std::string treeJsonStr;
46 GetInspectorTreeJsonStr(treeJsonStr, ContainerScope::CurrentId());
47 if (treeJsonStr.empty()) {
48 return;
49 }
50 auto message = JsonUtil::Create(true);
51 GetSnapshotJson(ContainerScope::CurrentId(), message);
52 CHECK_NULL_VOID(message);
53
54 auto sendTask = [treeJsonStr, jsonSnapshotStr = message->ToString(), container]() {
55 if (container->IsUseStageModel()) {
56 OHOS::AbilityRuntime::ConnectServerManager::Get().SendInspector(treeJsonStr, jsonSnapshotStr);
57 } else {
58 OHOS::Ace::ConnectServerManager::Get().SendInspector(treeJsonStr, jsonSnapshotStr);
59 }
60 };
61 BackgroundTaskExecutor::GetInstance().PostTask(std::move(sendTask));
62 }
63
SetStatus(bool layoutInspectorStatus)64 void LayoutInspector::SetStatus(bool layoutInspectorStatus)
65 {
66 layoutInspectorStatus_ = layoutInspectorStatus;
67 }
68
SetCallback(int32_t instanceId)69 void LayoutInspector::SetCallback(int32_t instanceId)
70 {
71 LOGI("SetCallback start");
72 auto container = AceEngine::Get().GetContainer(instanceId);
73 CHECK_NULL_VOID_NOLOG(container);
74 if (container->IsUseStageModel()) {
75 OHOS::AbilityRuntime::ConnectServerManager::Get().SetLayoutInspectorCallback(
76 [](int32_t containerId) { return CreateLayoutInfo(containerId); },
77 [](bool status) { return SetStatus(status); });
78 } else {
79 OHOS::Ace::ConnectServerManager::Get().SetLayoutInspectorCallback(
80 [](int32_t containerId) { return CreateLayoutInfo(containerId); },
81 [](bool status) { return SetStatus(status); });
82 }
83 }
84
CreateLayoutInfo(int32_t containerId)85 void LayoutInspector::CreateLayoutInfo(int32_t containerId)
86 {
87 LOGI("CreateLayoutInfo start");
88 ContainerScope sope(containerId);
89 auto container = AceEngine::Get().GetContainer(containerId);
90 CHECK_NULL_VOID_NOLOG(container);
91 std::string treeJsonStr;
92 GetInspectorTreeJsonStr(treeJsonStr, containerId);
93 auto message = JsonUtil::Create(true);
94 GetSnapshotJson(containerId, message);
95 CHECK_NULL_VOID(message);
96
97 auto sendTask = [treeJsonStr, jsonSnapshotStr = message->ToString(), container]() {
98 if (container->IsUseStageModel()) {
99 OHOS::AbilityRuntime::ConnectServerManager::Get().SendInspector(treeJsonStr, jsonSnapshotStr);
100 } else {
101 OHOS::Ace::ConnectServerManager::Get().SendInspector(treeJsonStr, jsonSnapshotStr);
102 }
103 };
104 BackgroundTaskExecutor::GetInstance().PostTask(std::move(sendTask));
105 }
106
GetInspectorTreeJsonStr(std::string & treeJsonStr,int32_t containerId)107 void LayoutInspector::GetInspectorTreeJsonStr(std::string& treeJsonStr, int32_t containerId)
108 {
109 auto container = AceEngine::Get().GetContainer(containerId);
110 CHECK_NULL_VOID_NOLOG(container);
111 if (container->IsUseNewPipeline()) {
112 treeJsonStr = NG::Inspector::GetInspector(true);
113 } else {
114 auto pipelineContext = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext());
115 CHECK_NULL_VOID(pipelineContext);
116 treeJsonStr = V2::Inspector::GetInspectorTree(pipelineContext, true);
117 }
118 }
119
GetSnapshotJson(int32_t containerId,std::unique_ptr<JsonValue> & message)120 void LayoutInspector::GetSnapshotJson(int32_t containerId, std::unique_ptr<JsonValue>& message)
121 {
122 LOGI("GetSnapshotJson start");
123 auto container = AceEngine::Get().GetContainer(containerId);
124 CHECK_NULL_VOID_NOLOG(container);
125
126 OHOS::sptr<OHOS::Rosen::Window> window = OHOS::Rosen::Window::GetTopWindowWithId(container->GetWindowId());
127 CHECK_NULL_VOID_NOLOG(window);
128 auto pixelMap = window->Snapshot();
129 CHECK_NULL_VOID(pixelMap);
130
131 auto data = (*pixelMap).GetPixels();
132 auto height = (*pixelMap).GetHeight();
133 auto stride = (*pixelMap).GetRowBytes();
134 message->Put("type", "snapShot");
135 message->Put("width", (*pixelMap).GetWidth());
136 message->Put("height", height);
137 message->Put("posX", container->GetViewPosX());
138 message->Put("posY", container->GetViewPosY());
139 int32_t encodeLength = SkBase64::Encode(data, height * stride, nullptr);
140 SkString info(encodeLength);
141 SkBase64::Encode(data, height * stride, info.writable_str());
142 message->Put("pixelMapBase64", info.c_str());
143 }
144
145 } // namespace OHOS::Ace