1 /*
2  * Copyright (c) 2021-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 "distributed_hardware_stub.h"
17 
18 #include <cinttypes>
19 
20 #include "accesstoken_kit.h"
21 #include "ipc_skeleton.h"
22 #include "tokenid_kit.h"
23 
24 #include "device_manager.h"
25 
26 #include "anonymous_string.h"
27 #include "constants.h"
28 #include "dhardware_ipc_interface_code.h"
29 #include "dh_context.h"
30 #include "dh_utils_tool.h"
31 #include "distributed_hardware_errno.h"
32 #include "distributed_hardware_log.h"
33 #include "publisher_listener_proxy.h"
34 
35 namespace OHOS {
36 namespace DistributedHardware {
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)37 int32_t DistributedHardwareStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
38     MessageOption &option)
39 {
40     if (data.ReadInterfaceToken() != GetDescriptor()) {
41         DHLOGE("IPC Token valid fail!");
42         return ERR_INVALID_DATA;
43     }
44     switch (code) {
45         case static_cast<uint32_t>(DHMsgInterfaceCode::REG_PUBLISHER_LISTNER): {
46             return RegisterPublisherListenerInner(data, reply);
47         }
48         case static_cast<uint32_t>(DHMsgInterfaceCode::UNREG_PUBLISHER_LISTENER): {
49             return UnregisterPublisherListenerInner(data, reply);
50         }
51         case static_cast<uint32_t>(DHMsgInterfaceCode::PUBLISH_MESSAGE): {
52             return PublishMessageInner(data, reply);
53         }
54         case static_cast<uint32_t>(DHMsgInterfaceCode::INIT_CTL_CEN): {
55             return InitializeAVCenterInner(data, reply);
56         }
57         case static_cast<uint32_t>(DHMsgInterfaceCode::RELEASE_CTL_CEN): {
58             return ReleaseAVCenterInner(data, reply);
59         }
60         case static_cast<uint32_t>(DHMsgInterfaceCode::CREATE_CTL_CEN_CHANNEL): {
61             return CreateControlChannelInner(data, reply);
62         }
63         case static_cast<uint32_t>(DHMsgInterfaceCode::NOTIFY_AV_EVENT): {
64             return NotifyAVCenterInner(data, reply);
65         }
66         case static_cast<uint32_t>(DHMsgInterfaceCode::REGISTER_CTL_CEN_CALLBACK): {
67             return RegisterControlCenterCallbackInner(data, reply);
68         }
69         case static_cast<uint32_t>(DHMsgInterfaceCode::QUERY_LOCAL_SYS_SPEC): {
70             return QueryLocalSysSpecInner(data, reply);
71         }
72         case static_cast<uint32_t>(DHMsgInterfaceCode::NOTIFY_SOURCE_DEVICE_REMOTE_DMSDP_STARTED): {
73             return HandleNotifySourceRemoteSinkStarted(data, reply);
74         }
75         case static_cast<uint32_t>(DHMsgInterfaceCode::PAUSE_DISTRIBUTED_HARDWARE): {
76             return PauseDistributedHardwareInner(data, reply);
77         }
78         case static_cast<uint32_t>(DHMsgInterfaceCode::RESUME_DISTRIBUTED_HARDWARE): {
79             return ResumeDistributedHardwareInner(data, reply);
80         }
81         case static_cast<uint32_t>(DHMsgInterfaceCode::STOP_DISTRIBUTED_HARDWARE): {
82             return StopDistributedHardwareInner(data, reply);
83         }
84         default:
85             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
86     }
87     return DH_FWK_SUCCESS;
88 }
89 
RegisterPublisherListenerInner(MessageParcel & data,MessageParcel & reply)90 int32_t DistributedHardwareStub::RegisterPublisherListenerInner(MessageParcel &data, MessageParcel &reply)
91 {
92     if (!HasAccessDHPermission()) {
93         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
94         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
95     }
96 
97     uint32_t topicInt = data.ReadUint32();
98     if (!ValidTopic(topicInt)) {
99         DHLOGE("Topic invalid: %{public}" PRIu32, topicInt);
100         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
101         return ERR_DH_FWK_PARA_INVALID;
102     }
103 
104     DHTopic topic = (DHTopic)topicInt;
105     sptr<IPublisherListener> listener = iface_cast<IPublisherListener>(data.ReadRemoteObject());
106     if (listener == nullptr) {
107         DHLOGE("Register publisher listener is null");
108         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
109         return ERR_DH_FWK_PARA_INVALID;
110     }
111     DHLOGI("Register listener, topic: %{public}" PRIu32, (uint32_t)topic);
112     RegisterPublisherListener(topic, listener);
113     reply.WriteInt32(DH_FWK_SUCCESS);
114     return DH_FWK_SUCCESS;
115 }
116 
UnregisterPublisherListenerInner(MessageParcel & data,MessageParcel & reply)117 int32_t DistributedHardwareStub::UnregisterPublisherListenerInner(MessageParcel &data, MessageParcel &reply)
118 {
119     if (!HasAccessDHPermission()) {
120         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
121         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
122     }
123 
124     uint32_t topicInt = data.ReadUint32();
125     if (!ValidTopic(topicInt)) {
126         DHLOGE("Topic invalid: %{public}" PRIu32, topicInt);
127         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
128         return ERR_DH_FWK_PARA_INVALID;
129     }
130 
131     DHTopic topic = (DHTopic)topicInt;
132     sptr<IPublisherListener> listener = iface_cast<IPublisherListener>(data.ReadRemoteObject());
133     if (listener == nullptr) {
134         DHLOGE("Unregister publisher listener is null");
135         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
136         return ERR_DH_FWK_PARA_INVALID;
137     }
138     DHLOGI("Unregister listener, topic: %{public}" PRIu32, (uint32_t)topic);
139     UnregisterPublisherListener(topic, listener);
140     reply.WriteInt32(DH_FWK_SUCCESS);
141     return DH_FWK_SUCCESS;
142 }
143 
PublishMessageInner(MessageParcel & data,MessageParcel & reply)144 int32_t DistributedHardwareStub::PublishMessageInner(MessageParcel &data, MessageParcel &reply)
145 {
146     if (!HasAccessDHPermission()) {
147         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
148         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
149     }
150 
151     uint32_t topicInt = data.ReadUint32();
152     if (!ValidTopic(topicInt)) {
153         DHLOGE("Topic invalid: %{public}" PRIu32, topicInt);
154         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
155         return ERR_DH_FWK_PARA_INVALID;
156     }
157 
158     DHTopic topic = (DHTopic)topicInt;
159     std::string message = data.ReadString();
160     DHLOGI("Publish message, topic: %{public}" PRIu32, (uint32_t)topic);
161     PublishMessage(topic, message);
162     reply.WriteInt32(DH_FWK_SUCCESS);
163     return DH_FWK_SUCCESS;
164 }
165 
QueryLocalSysSpecInner(MessageParcel & data,MessageParcel & reply)166 int32_t DistributedHardwareStub::QueryLocalSysSpecInner(MessageParcel &data, MessageParcel &reply)
167 {
168     if (!HasAccessDHPermission()) {
169         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
170         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
171     }
172 
173     uint32_t specInt = data.ReadUint32();
174     if (!ValidQueryLocalSpec(specInt)) {
175         DHLOGE("Spec invalid: %{public}" PRIu32, specInt);
176         reply.WriteInt32(ERR_DH_FWK_PARA_INVALID);
177         return ERR_DH_FWK_PARA_INVALID;
178     }
179 
180     QueryLocalSysSpecType spec = (QueryLocalSysSpecType)specInt;
181     DHLOGI("Query Local Sys Spec: %{public}" PRIu32, (uint32_t)spec);
182     std::string res = QueryLocalSysSpec(spec);
183     DHLOGI("Get Local spec: %{public}s", res.c_str());
184     reply.WriteString(res);
185     return DH_FWK_SUCCESS;
186 }
187 
InitializeAVCenterInner(MessageParcel & data,MessageParcel & reply)188 int32_t DistributedHardwareStub::InitializeAVCenterInner(MessageParcel &data, MessageParcel &reply)
189 {
190     if (!HasAccessDHPermission()) {
191         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
192         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
193     }
194 
195     TransRole transRole = (TransRole)(data.ReadUint32());
196     int32_t engineId = 0;
197     int32_t ret = InitializeAVCenter(transRole, engineId);
198     if (!reply.WriteInt32(engineId)) {
199         DHLOGE("Write engine id failed");
200         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
201     }
202     if (!reply.WriteInt32(ret)) {
203         DHLOGE("Write ret code failed");
204         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
205     }
206     return DH_FWK_SUCCESS;
207 }
208 
ReleaseAVCenterInner(MessageParcel & data,MessageParcel & reply)209 int32_t DistributedHardwareStub::ReleaseAVCenterInner(MessageParcel &data, MessageParcel &reply)
210 {
211     if (!HasAccessDHPermission()) {
212         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
213         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
214     }
215 
216     int32_t engineId = data.ReadInt32();
217     int32_t ret = ReleaseAVCenter(engineId);
218     if (!reply.WriteInt32(ret)) {
219         DHLOGE("Write ret code failed");
220         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
221     }
222     return DH_FWK_SUCCESS;
223 }
224 
CreateControlChannelInner(MessageParcel & data,MessageParcel & reply)225 int32_t DistributedHardwareStub::CreateControlChannelInner(MessageParcel &data, MessageParcel &reply)
226 {
227     if (!HasAccessDHPermission()) {
228         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
229         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
230     }
231 
232     int32_t engineId = data.ReadInt32();
233     std::string peerDevId = data.ReadString();
234     int32_t ret = CreateControlChannel(engineId, peerDevId);
235     if (!reply.WriteInt32(ret)) {
236         DHLOGE("Write ret code failed");
237         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
238     }
239     return DH_FWK_SUCCESS;
240 }
241 
NotifyAVCenterInner(MessageParcel & data,MessageParcel & reply)242 int32_t DistributedHardwareStub::NotifyAVCenterInner(MessageParcel &data, MessageParcel &reply)
243 {
244     if (!HasAccessDHPermission()) {
245         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
246         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
247     }
248 
249     int32_t engineId = data.ReadInt32();
250     uint32_t type = data.ReadUint32();
251     std::string content = data.ReadString();
252     std::string peerDevId = data.ReadString();
253     int32_t ret = NotifyAVCenter(engineId, AVTransEvent{ (EventType)type, content, peerDevId });
254     if (!reply.WriteInt32(ret)) {
255         DHLOGE("Write ret code failed");
256         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
257     }
258     return DH_FWK_SUCCESS;
259 }
260 
RegisterControlCenterCallbackInner(MessageParcel & data,MessageParcel & reply)261 int32_t DistributedHardwareStub::RegisterControlCenterCallbackInner(MessageParcel &data, MessageParcel &reply)
262 {
263     if (!HasAccessDHPermission()) {
264         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
265         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
266     }
267 
268     int32_t engineId = data.ReadInt32();
269     sptr<IAVTransControlCenterCallback> callback = iface_cast<IAVTransControlCenterCallback>(data.ReadRemoteObject());
270     if (callback == nullptr) {
271         DHLOGE("Input av control center callback is null");
272         return ERR_DH_FWK_PARA_INVALID;
273     }
274 
275     int32_t ret = RegisterCtlCenterCallback(engineId, callback);
276     if (!reply.WriteInt32(ret)) {
277         DHLOGE("Write ret code failed");
278         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
279     }
280     return DH_FWK_SUCCESS;
281 }
282 
HandleNotifySourceRemoteSinkStarted(MessageParcel & data,MessageParcel & reply)283 int32_t OHOS::DistributedHardware::DistributedHardwareStub::HandleNotifySourceRemoteSinkStarted(MessageParcel &data,
284     MessageParcel &reply)
285 {
286     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
287     std::string udid = data.ReadString();
288     if (!IsIdLengthValid(udid)) {
289         DHLOGE("the udid is invalid, %{public}s", GetAnonyString(udid).c_str());
290         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
291     }
292     std::string networkId = "";
293     DeviceManager::GetInstance().GetNetworkIdByUdid(DH_FWK_PKG_NAME, udid, networkId);
294     if (!IsIdLengthValid(networkId)) {
295         DHLOGE("the networkId is invalid, %{public}s", GetAnonyString(networkId).c_str());
296         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
297     }
298     uint32_t dAccessToken = Security::AccessToken::AccessTokenKit::AllocLocalTokenID(networkId, callerToken);
299     const std::string permissionName = "ohos.permission.ACCESS_DISTRIBUTED_HARDWARE";
300     int32_t result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(dAccessToken, permissionName);
301     if (result != Security::AccessToken::PERMISSION_GRANTED) {
302         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
303         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
304     }
305 
306     DHLOGI("DistributedHardwareStub HandleNotifySourceRemoteSinkStarted Start.");
307     int32_t ret = NotifySourceRemoteSinkStarted(udid);
308     if (!reply.WriteInt32(ret)) {
309         DHLOGE("write ret failed.");
310         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
311     }
312     DHLOGI("DistributedHardwareStub HandleNotifySourceRemoteSinkStarted End.");
313     return DH_FWK_SUCCESS;
314 }
315 
ValidTopic(uint32_t topic)316 bool DistributedHardwareStub::ValidTopic(uint32_t topic)
317 {
318     if (topic <= (uint32_t)DHTopic::TOPIC_MIN || topic >= (uint32_t)DHTopic::TOPIC_MAX) {
319         return false;
320     }
321     return true;
322 }
323 
ValidQueryLocalSpec(uint32_t spec)324 bool DistributedHardwareStub::ValidQueryLocalSpec(uint32_t spec)
325 {
326     if (spec <= (uint32_t)QueryLocalSysSpecType::MIN || spec >= (uint32_t)QueryLocalSysSpecType::MAX) {
327         return false;
328     }
329     return true;
330 }
331 
PauseDistributedHardwareInner(MessageParcel & data,MessageParcel & reply)332 int32_t DistributedHardwareStub::PauseDistributedHardwareInner(MessageParcel &data, MessageParcel &reply)
333 {
334     if (!IsSystemHap()) {
335         DHLOGE("GetCallerProcessName not system hap.");
336         return ERR_DH_FWK_IS_SYSTEM_HAP_CHECK_FAIL;
337     }
338     if (!HasAccessDHPermission()) {
339         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
340         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
341     }
342     DHType dhType = static_cast<DHType>(data.ReadInt32());
343     std::string networkId = data.ReadString();
344     int32_t ret = PauseDistributedHardware(dhType, networkId);
345     if (!reply.WriteInt32(ret)) {
346         DHLOGE("Write ret code failed");
347         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
348     }
349     return DH_FWK_SUCCESS;
350 }
351 
ResumeDistributedHardwareInner(MessageParcel & data,MessageParcel & reply)352 int32_t DistributedHardwareStub::ResumeDistributedHardwareInner(MessageParcel &data, MessageParcel &reply)
353 {
354     if (!IsSystemHap()) {
355         DHLOGE("GetCallerProcessName not system hap.");
356         return ERR_DH_FWK_IS_SYSTEM_HAP_CHECK_FAIL;
357     }
358     if (!HasAccessDHPermission()) {
359         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
360         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
361     }
362     DHType dhType = static_cast<DHType>(data.ReadInt32());
363     std::string networkId = data.ReadString();
364     int32_t ret = ResumeDistributedHardware(dhType, networkId);
365     if (!reply.WriteInt32(ret)) {
366         DHLOGE("Write ret code failed");
367         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
368     }
369     return DH_FWK_SUCCESS;
370 }
371 
StopDistributedHardwareInner(MessageParcel & data,MessageParcel & reply)372 int32_t DistributedHardwareStub::StopDistributedHardwareInner(MessageParcel &data, MessageParcel &reply)
373 {
374     if (!IsSystemHap()) {
375         DHLOGE("GetCallerProcessName not system hap.");
376         return ERR_DH_FWK_IS_SYSTEM_HAP_CHECK_FAIL;
377     }
378     if (!HasAccessDHPermission()) {
379         DHLOGE("The caller has no ACCESS_DISTRIBUTED_HARDWARE permission.");
380         return ERR_DH_FWK_ACCESS_PERMISSION_CHECK_FAIL;
381     }
382     DHType dhType = static_cast<DHType>(data.ReadInt32());
383     std::string networkId = data.ReadString();
384     int32_t ret = StopDistributedHardware(dhType, networkId);
385     if (!reply.WriteInt32(ret)) {
386         DHLOGE("Write ret code failed");
387         return ERR_DH_FWK_SERVICE_WRITE_INFO_FAIL;
388     }
389     return DH_FWK_SUCCESS;
390 }
391 
HasAccessDHPermission()392 bool DistributedHardwareStub::HasAccessDHPermission()
393 {
394     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
395     const std::string permissionName = "ohos.permission.ACCESS_DISTRIBUTED_HARDWARE";
396     int32_t result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken,
397         permissionName);
398     return (result == Security::AccessToken::PERMISSION_GRANTED);
399 }
400 
IsSystemHap()401 bool DistributedHardwareStub::IsSystemHap()
402 {
403     uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
404     if (!OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId)) {
405         return false;
406     }
407     return true;
408 }
409 } // namespace DistributedHardware
410 } // namespace OHOS
411