1 /*
2 * Copyright (c) 2025 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 "on_screen_server.h"
17
18 #include <algorithm>
19 #include <dlfcn.h>
20 #include <vector>
21
22 #include "accesstoken_kit.h"
23 #include "devicestatus_define.h"
24 #include "tokenid_kit.h"
25
26 #undef LOG_TAG
27 #define LOG_TAG "OnScreenServer"
28
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 namespace OnScreen {
33 namespace {
34 const char *LIB_ON_SCREEN_ALGO_PATH = "/system/lib64/libon_screen.z.so";
35 const char *PERMISSION_GET_PAGE_CONTENT = "ohos.permission.GET_SCREEN_CONTENT";
36 const char *PERMISSION_SEND_CONTROL_EVENT = "ohos.permission.SIMULATE_USER_INPUT";
37 constexpr int32_t RET_NO_SUPPORT = 801;
38 constexpr int32_t RET_NO_PERMISSION = 201;
39 constexpr int32_t RET_NO_SYSTEM_CALLING = 202;
40 }
41
~OnScreenAlgorithmHandle()42 OnScreenAlgorithmHandle::~OnScreenAlgorithmHandle()
43 {
44 Clear();
45 }
46
Clear()47 void OnScreenAlgorithmHandle::Clear()
48 {
49 handle = nullptr;
50 pAlgorithm = nullptr;
51 create = nullptr;
52 destroy = nullptr;
53 }
54
~OnScreenServer()55 OnScreenServer::~OnScreenServer()
56 {
57 UnloadAlgoLib();
58 }
59
GetPageContent(const CallingContext & context,const ContentOption & option,PageContent & pageContent)60 int32_t OnScreenServer::GetPageContent(const CallingContext &context, const ContentOption &option,
61 PageContent &pageContent)
62 {
63 std::lock_guard lockGrd(mtx_);
64 int32_t ret = RET_OK;
65 if (!CheckPermission(context, PERMISSION_GET_PAGE_CONTENT)) {
66 FI_HILOGE("checkpermission failed, premission = %{public}s", PERMISSION_GET_PAGE_CONTENT);
67 return RET_NO_PERMISSION;
68 }
69 if (!IsSystemCalling(context)) {
70 FI_HILOGE("calling is not system calling");
71 return RET_NO_SYSTEM_CALLING;
72 }
73 if (ConnectAlgoLib() != RET_OK) {
74 FI_HILOGE("failed to load algo lib");
75 return RET_NO_SUPPORT;
76 }
77 OnScreenCallingContext onScreenContext {
78 .fullTokenId = context.fullTokenId,
79 .tokenId = context.tokenId,
80 .uid = context.uid,
81 .pid = context.pid,
82 };
83 FI_HILOGI("get page content invoke algo lib");
84 ret = handle_.pAlgorithm->GetPageContent(onScreenContext, option, pageContent);
85 if (ret != RET_OK) {
86 FI_HILOGE("failed to get page content, err=%{public}d", ret);
87 return ret;
88 }
89 return RET_OK;
90 }
91
SendControlEvent(const CallingContext & context,const ControlEvent & event)92 int32_t OnScreenServer::SendControlEvent(const CallingContext &context, const ControlEvent &event)
93 {
94 std::lock_guard lockGrd(mtx_);
95 int32_t ret = RET_OK;
96 if (!CheckPermission(context, PERMISSION_SEND_CONTROL_EVENT)) {
97 FI_HILOGE("checkpermission failed, premission = %{public}s", PERMISSION_SEND_CONTROL_EVENT);
98 return RET_NO_PERMISSION;
99 }
100 if (!IsSystemCalling(context)) {
101 FI_HILOGE("calling is not system calling");
102 return RET_NO_SYSTEM_CALLING;
103 }
104 if (ConnectAlgoLib() != RET_OK) {
105 FI_HILOGE("failed to load algo lib");
106 return RET_NO_SUPPORT;
107 }
108 OnScreenCallingContext onScreenContext {
109 .fullTokenId = context.fullTokenId,
110 .tokenId = context.tokenId,
111 .uid = context.uid,
112 .pid = context.pid,
113 };
114 FI_HILOGI("send control event invoke algo lib");
115 ret = handle_.pAlgorithm->SendControlEvent(onScreenContext, event);
116 if (ret != RET_OK) {
117 FI_HILOGE("failed to send control event, err=%{public}d", ret);
118 return ret;
119 }
120 return RET_OK;
121 }
122
ConnectAlgoLib()123 int32_t OnScreenServer::ConnectAlgoLib()
124 {
125 return handle_.pAlgorithm == nullptr ? LoadAlgoLib() : RET_OK;
126 }
127
LoadAlgoLib()128 int32_t OnScreenServer::LoadAlgoLib()
129 {
130 char libRealPath[PATH_MAX] = { 0 };
131 if (realpath(LIB_ON_SCREEN_ALGO_PATH, libRealPath) == nullptr) {
132 FI_HILOGE("get absolute path failed, ret = %{public}d", errno);
133 return RET_ERR;
134 }
135 handle_.handle = dlopen(libRealPath, RTLD_LAZY);
136 if (handle_.handle == nullptr) {
137 FI_HILOGE("dlopen failed, err:%{public}sn", dlerror());
138 return RET_ERR;
139 }
140 handle_.create = reinterpret_cast<IOnScreenAlgorithm*(*)()>(dlsym(handle_.handle, "Create"));
141 handle_.destroy = reinterpret_cast<void(*)(const IOnScreenAlgorithm*)>(dlsym(handle_.handle, "Destroy"));
142 if (handle_.create == nullptr || handle_.destroy == nullptr) {
143 FI_HILOGE("create is null or destoy is null");
144 return RET_ERR;
145 }
146 if (handle_.pAlgorithm == nullptr) {
147 FI_HILOGI("get on screen algo object");
148 handle_.pAlgorithm = handle_.create();
149 if (handle_.pAlgorithm == nullptr) {
150 FI_HILOGE("create on screen algo object failed");
151 return RET_ERR;
152 }
153 }
154 return RET_OK;
155 }
156
UnloadAlgoLib()157 int32_t OnScreenServer::UnloadAlgoLib()
158 {
159 FI_HILOGE("unload exit");
160 if (handle_.pAlgorithm != nullptr && handle_.destroy != nullptr) {
161 handle_.destroy(handle_.pAlgorithm);
162 handle_.pAlgorithm = nullptr;
163 }
164 handle_.Clear();
165 return RET_OK;
166 }
167
CheckPermission(const CallingContext & context,const std::string & permission)168 bool OnScreenServer::CheckPermission(const CallingContext &context, const std::string &permission)
169 {
170 auto type = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(context.tokenId);
171 FI_HILOGD("called tokenType is %{public}d", type);
172 if (type == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL) {
173 FI_HILOGD("called tokenType is shell, verify succ");
174 }
175 return Security::AccessToken::AccessTokenKit::VerifyAccessToken(context.tokenId, permission) == RET_OK;
176 }
177
IsSystemCalling(const CallingContext & context)178 bool OnScreenServer::IsSystemCalling(const CallingContext &context)
179 {
180 if (IsSystemServiceCalling(context)) {
181 return true;
182 }
183 return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(context.fullTokenId);
184 }
185
IsSystemServiceCalling(const CallingContext & context)186 bool OnScreenServer::IsSystemServiceCalling(const CallingContext &context)
187 {
188 auto flag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(context.tokenId);
189 if ((flag == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) ||
190 (flag == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL)) {
191 FI_HILOGI("system service calling, flag:%{public}u", flag);
192 return true;
193 }
194 return false;
195 }
196 } // namespace OnScreen
197 } // namespace DeviceStatus
198 } // namespace Msdp
199 } // namespace OHOS