1 /*
2  * Copyright (c) 2024 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 "socperf_stub.h"
17 #include "accesstoken_kit.h"
18 #include "ipc_skeleton.h"
19 #include "parameters.h"
20 #include "socperf_ipc_interface_code.h"
21 #include "socperf_log.h"
22 #include "tokenid_kit.h"
23 
24 namespace OHOS {
25 namespace SOCPERF {
26 namespace {
27     constexpr int32_t HIVIEW_UID = 1201;
28     constexpr int32_t MSG_STRING_MAX_LEN = 1024;
29     constexpr int32_t MSG_VECTOR_MAX_LEN = 1024;
30     constexpr int32_t MSG_VECTOR_INVALID_LEN = 0;
31     const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
32 }
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)33 int32_t SocPerfStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
34     MessageParcel &reply, MessageOption &option)
35 {
36     auto remoteDescriptor = data.ReadInterfaceToken();
37     if (GetDescriptor() != remoteDescriptor || !HasPerfPermission()) {
38         return ERR_INVALID_STATE;
39     }
40 
41     int32_t ret = ERR_OK;
42     switch (code) {
43         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_PERF_REQUEST): {
44             ret = StubPerfRequest(data);
45             break;
46         }
47         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_PERF_REQUEST_EX): {
48             ret = StubPerfRequestEx(data);
49             break;
50         }
51         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_POWER_LIMIT_BOOST_FREQ): {
52             ret = StubPowerLimitBoost(data);
53             break;
54         }
55         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_THERMAL_LIMIT_BOOST_FREQ): {
56             ret = StubThermalLimitBoost(data);
57             break;
58         }
59         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_LIMIT_REQUEST): {
60             ret = StubLimitRequest(data);
61             break;
62         }
63         default:
64             return OnRemoteRequestExt(code, data, reply, option);
65     }
66     return ret;
67 }
68 
OnRemoteRequestExt(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)69 int32_t SocPerfStub::OnRemoteRequestExt(uint32_t code, MessageParcel &data,
70     MessageParcel &reply, MessageOption &option)
71 {
72     int32_t ret = ERR_OK;
73     switch (code) {
74         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_SET_STATUS): {
75             ret = StubSetRequestStatus(data);
76             break;
77         }
78         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_SET_THERMAL_LEVEL): {
79             ret = StubSetThermalLevel(data);
80             break;
81         }
82         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_SET_DEVICE_MODE): {
83             ret = StubRequestDeviceMode(data);
84             break;
85         }
86         case static_cast<uint32_t>(SocPerfInterfaceCode::TRANS_IPC_ID_REQUEST_CMDID_COUNT): {
87             ret = StubRequestCmdIdCount(data, reply);
88             break;
89         }
90         default:
91             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
92     }
93     return ret;
94 }
95 
StubPerfRequest(MessageParcel & data)96 int32_t SocPerfStub::StubPerfRequest(MessageParcel &data)
97 {
98     int32_t cmdId = 0;
99     if (!data.ReadInt32(cmdId)) {
100         SOC_PERF_LOGE("SocPerfStub::%{public}s read cmdId failed", __func__);
101         return ERR_INVALID_STATE;
102     }
103 
104     std::string msg;
105     if (!data.ReadString(msg)) {
106         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
107         return ERR_INVALID_STATE;
108     }
109     if (msg.length() > MSG_STRING_MAX_LEN) {
110         return ERR_INVALID_STATE;
111     }
112 
113     PerfRequest(cmdId, msg);
114     return ERR_OK;
115 }
116 
StubPerfRequestEx(MessageParcel & data)117 int32_t SocPerfStub::StubPerfRequestEx(MessageParcel &data)
118 {
119     int32_t cmdId = 0;
120     if (!data.ReadInt32(cmdId)) {
121         SOC_PERF_LOGE("SocPerfStub::%{public}s read cmdId failed", __func__);
122         return ERR_INVALID_STATE;
123     }
124 
125     bool onOffTag = false;
126     if (!data.ReadBool(onOffTag)) {
127         SOC_PERF_LOGE("SocPerfStub::%{public}s read onOffTag failed", __func__);
128         return ERR_INVALID_STATE;
129     }
130 
131     std::string msg;
132     if (!data.ReadString(msg)) {
133         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
134         return ERR_INVALID_STATE;
135     }
136     if (msg.length() > MSG_STRING_MAX_LEN) {
137         return ERR_INVALID_STATE;
138     }
139 
140     PerfRequestEx(cmdId, onOffTag, msg);
141     return ERR_OK;
142 }
143 
StubPowerLimitBoost(MessageParcel & data)144 int32_t SocPerfStub::StubPowerLimitBoost(MessageParcel &data)
145 {
146     bool onOffTag = false;
147     if (!data.ReadBool(onOffTag)) {
148         SOC_PERF_LOGE("SocPerfStub::%{public}s read onOffTag failed", __func__);
149         return ERR_INVALID_STATE;
150     }
151 
152     std::string msg;
153     if (!data.ReadString(msg)) {
154         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
155         return ERR_INVALID_STATE;
156     }
157     if (msg.length() > MSG_STRING_MAX_LEN) {
158         return ERR_INVALID_STATE;
159     }
160 
161     PowerLimitBoost(onOffTag, msg);
162     return ERR_OK;
163 }
164 
StubThermalLimitBoost(MessageParcel & data)165 int32_t SocPerfStub::StubThermalLimitBoost(MessageParcel &data)
166 {
167     bool onOffTag = false;
168     if (!data.ReadBool(onOffTag)) {
169         SOC_PERF_LOGE("SocPerfStub::%{public}s read onOffTag failed", __func__);
170         return ERR_INVALID_STATE;
171     }
172 
173     std::string msg;
174     if (!data.ReadString(msg)) {
175         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
176         return ERR_INVALID_STATE;
177     }
178     if (msg.length() > MSG_STRING_MAX_LEN) {
179         return ERR_INVALID_STATE;
180     }
181 
182     ThermalLimitBoost(onOffTag, msg);
183     return ERR_OK;
184 }
185 
StubLimitRequest(MessageParcel & data)186 int32_t SocPerfStub::StubLimitRequest(MessageParcel &data)
187 {
188     int32_t clientId;
189     if (!data.ReadInt32(clientId)) {
190         SOC_PERF_LOGE("SocPerfStub::%{public}s read clientId failed", __func__);
191         return ERR_INVALID_STATE;
192     }
193 
194     std::vector<int32_t> tags;
195     if (!data.ReadInt32Vector(&tags)) {
196         SOC_PERF_LOGE("error tags to do StubLimitRequest");
197         return ERR_INVALID_STATE;
198     }
199     if (tags.size() == MSG_VECTOR_INVALID_LEN || tags.size() > MSG_VECTOR_MAX_LEN) {
200         SOC_PERF_LOGE("error tags to do StubLimitRequest");
201         return ERR_INVALID_STATE;
202     }
203 
204     std::vector<int64_t> configs;
205     if (!data.ReadInt64Vector(&configs)) {
206         SOC_PERF_LOGE("error configs to do StubLimitRequest");
207         return ERR_INVALID_STATE;
208     }
209     if (configs.size() == MSG_VECTOR_INVALID_LEN || configs.size() > MSG_VECTOR_MAX_LEN) {
210         SOC_PERF_LOGE("error configs to do StubLimitRequest");
211         return ERR_INVALID_STATE;
212     }
213 
214     std::string msg;
215     if (!data.ReadString(msg)) {
216         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
217         return ERR_INVALID_STATE;
218     }
219     if (msg.length() > MSG_STRING_MAX_LEN) {
220         return ERR_INVALID_STATE;
221     }
222 
223     LimitRequest(clientId, tags, configs, msg);
224     return ERR_OK;
225 }
226 
StubSetRequestStatus(MessageParcel & data)227 int32_t SocPerfStub::StubSetRequestStatus(MessageParcel &data)
228 {
229     bool requestEnable;
230     if (!data.ReadBool(requestEnable)) {
231         SOC_PERF_LOGE("SocPerfStub::%{public}s read requestEnable failed", __func__);
232         return ERR_INVALID_STATE;
233     }
234 
235     std::string msg;
236     if (!data.ReadString(msg)) {
237         SOC_PERF_LOGE("SocPerfStub::%{public}s read msg failed", __func__);
238         return ERR_INVALID_STATE;
239     }
240     if (msg.length() > MSG_STRING_MAX_LEN) {
241         return ERR_INVALID_STATE;
242     }
243 
244     SetRequestStatus(requestEnable, msg);
245     return ERR_OK;
246 }
247 
StubSetThermalLevel(MessageParcel & data)248 int32_t SocPerfStub::StubSetThermalLevel(MessageParcel &data)
249 {
250     int32_t levelId;
251     if (!data.ReadInt32(levelId)) {
252         SOC_PERF_LOGE("SocPerfStub::%{public}s read levelId failed", __func__);
253         return ERR_INVALID_STATE;
254     }
255 
256     SetThermalLevel(levelId);
257     return ERR_OK;
258 }
259 
StubRequestDeviceMode(MessageParcel & data)260 int32_t SocPerfStub::StubRequestDeviceMode(MessageParcel &data)
261 {
262     std::string mode;
263     if (!data.ReadString(mode)) {
264         SOC_PERF_LOGE("SocPerfStub::%{public}s read mode failed", __func__);
265         return ERR_INVALID_STATE;
266     }
267     if (mode.length() > MSG_STRING_MAX_LEN) {
268         return ERR_INVALID_STATE;
269     }
270 
271     bool status;
272     if (!data.ReadBool(status)) {
273         SOC_PERF_LOGE("SocPerfStub::%{public}s read status failed", __func__);
274         return ERR_INVALID_STATE;
275     }
276 
277     RequestDeviceMode(mode, status);
278     return ERR_OK;
279 }
280 
StubRequestCmdIdCount(MessageParcel & data,MessageParcel & reply)281 int32_t SocPerfStub::StubRequestCmdIdCount(MessageParcel &data, MessageParcel &reply)
282 {
283     int32_t callingUid = IPCSkeleton::GetCallingUid();
284     std::string msg;
285     if ((ENG_MODE == 0 && callingUid != HIVIEW_UID) || !data.ReadString(msg)) {
286         SOC_PERF_LOGE("not have right to do RequestCmdIdCount");
287         return ERR_INVALID_STATE;
288     }
289     if (!reply.WriteString(RequestCmdIdCount(msg))) {
290         SOC_PERF_LOGE("write RequestCmdIdCount ret failed");
291         return ERR_INVALID_STATE;
292     }
293     return ERR_OK;
294 }
295 
296 const std::string NEEDED_PERMISSION = "ohos.permission.REPORT_RESOURCE_SCHEDULE_EVENT";
297 
HasPerfPermission()298 bool SocPerfStub::HasPerfPermission()
299 {
300     uint32_t accessToken = IPCSkeleton::GetCallingTokenID();
301     auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(accessToken);
302     if (int(tokenType) == OHOS::Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
303         uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
304         if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId)) {
305             SOC_PERF_LOGE("Invalid Permission to SocPerf");
306             return false;
307         }
308     }
309     int32_t hasPermission = Security::AccessToken::AccessTokenKit::VerifyAccessToken(accessToken, NEEDED_PERMISSION);
310     if (hasPermission != 0) {
311         SOC_PERF_LOGE("SocPerf: not have Permission");
312         return false;
313     }
314     return true;
315 }
316 } // namespace SOCPERF
317 } // namespace OHOS
318