1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "chre/core/host_endpoint_manager.h"
18
19 #include "chre/core/event_loop_manager.h"
20 #include "chre/util/dynamic_vector.h"
21 #include "chre/util/nested_data_ptr.h"
22 #include "chre/util/system/event_callbacks.h"
23
24 namespace chre {
isHostEndpointConnected(uint16_t hostEndpointId,size_t * index)25 bool HostEndpointManager::isHostEndpointConnected(uint16_t hostEndpointId,
26 size_t *index) {
27 for (size_t i = 0; i < mHostEndpoints.size(); i++) {
28 if (mHostEndpoints[i].hostEndpointId == hostEndpointId) {
29 *index = i;
30 return true;
31 }
32 }
33
34 return false;
35 }
36
hostNotificationCallback(uint16_t type,void * data,void * extraData)37 void HostEndpointManager::hostNotificationCallback(uint16_t type, void *data,
38 void *extraData) {
39 uint16_t hostEndpointId = NestedDataPtr<uint16_t>(data);
40
41 SystemCallbackType callbackType = static_cast<SystemCallbackType>(type);
42 if (callbackType == SystemCallbackType::HostEndpointDisconnected) {
43 size_t index;
44 if (isHostEndpointConnected(hostEndpointId, &index)) {
45 mHostEndpoints.erase(index);
46
47 uint16_t eventType = CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION;
48 auto *eventData = memoryAlloc<struct chreHostEndpointNotification>();
49
50 if (eventData == nullptr) {
51 LOG_OOM();
52 } else {
53 eventData->hostEndpointId = hostEndpointId;
54 eventData->notificationType =
55 HOST_ENDPOINT_NOTIFICATION_TYPE_DISCONNECT;
56 eventData->reserved = 0;
57
58 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
59 eventType, eventData, freeEventDataCallback, kBroadcastInstanceId);
60 }
61 } else {
62 LOGW("Got disconnected event for nonexistent host endpoint ID %" PRIu16,
63 hostEndpointId);
64 }
65 } else {
66 auto *info = static_cast<struct chreHostEndpointInfo *>(extraData);
67
68 size_t index;
69 if (!isHostEndpointConnected(hostEndpointId, &index)) {
70 mHostEndpoints.push_back(*info);
71 } else {
72 LOGW("Got connected event for already existing host endpoint ID %" PRIu16,
73 hostEndpointId);
74 }
75 }
76
77 memoryFree(extraData);
78 }
79
getHostNotificationCallback()80 auto HostEndpointManager::getHostNotificationCallback() {
81 return [](uint16_t type, void *data, void *extraData) {
82 EventLoopManagerSingleton::get()
83 ->getHostEndpointManager()
84 .hostNotificationCallback(type, data, extraData);
85 };
86 }
87
getHostEndpointInfo(uint16_t hostEndpointId,struct chreHostEndpointInfo * info)88 bool HostEndpointManager::getHostEndpointInfo(
89 uint16_t hostEndpointId, struct chreHostEndpointInfo *info) {
90 size_t index;
91 if (isHostEndpointConnected(hostEndpointId, &index)) {
92 *info = mHostEndpoints[index];
93 return true;
94 } else {
95 return false;
96 }
97 }
98
postHostEndpointConnected(const struct chreHostEndpointInfo & info)99 void HostEndpointManager::postHostEndpointConnected(
100 const struct chreHostEndpointInfo &info) {
101 auto *infoData = memoryAlloc<struct chreHostEndpointInfo>();
102 if (infoData == nullptr) {
103 LOG_OOM();
104 } else {
105 memcpy(infoData, &info, sizeof(struct chreHostEndpointInfo));
106
107 auto callback = getHostNotificationCallback();
108
109 EventLoopManagerSingleton::get()->deferCallback(
110 SystemCallbackType::HostEndpointConnected,
111 NestedDataPtr<uint16_t>(info.hostEndpointId), callback,
112 infoData /* extraData */);
113 }
114 }
115
postHostEndpointDisconnected(uint16_t hostEndpointId)116 void HostEndpointManager::postHostEndpointDisconnected(
117 uint16_t hostEndpointId) {
118 auto callback = getHostNotificationCallback();
119 EventLoopManagerSingleton::get()->deferCallback(
120 SystemCallbackType::HostEndpointDisconnected,
121 NestedDataPtr<uint16_t>(hostEndpointId), callback, nullptr);
122 }
123
124 } // namespace chre
125