xref: /aosp_15_r20/system/chre/core/host_endpoint_manager.cc (revision 84e339476a462649f82315436d70fd732297a399)
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   auto 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 0x%" PRIx16,
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 an existing host endpoint ID 0x%" PRIx16,
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   bool isConnected = isHostEndpointConnected(hostEndpointId, &index);
92   if (isConnected) {
93     *info = mHostEndpoints[index];
94   }
95   return isConnected;
96 }
97 
postHostEndpointConnected(const struct chreHostEndpointInfo & info)98 void HostEndpointManager::postHostEndpointConnected(
99     const struct chreHostEndpointInfo &info) {
100   auto *infoData = memoryAlloc<struct chreHostEndpointInfo>();
101   if (infoData == nullptr) {
102     LOG_OOM();
103   } else {
104     memcpy(infoData, &info, sizeof(struct chreHostEndpointInfo));
105 
106     auto callback = getHostNotificationCallback();
107 
108     EventLoopManagerSingleton::get()->deferCallback(
109         SystemCallbackType::HostEndpointConnected,
110         NestedDataPtr<uint16_t>(info.hostEndpointId), callback,
111         infoData /* extraData */);
112   }
113 }
114 
postHostEndpointDisconnected(uint16_t hostEndpointId)115 void HostEndpointManager::postHostEndpointDisconnected(
116     uint16_t hostEndpointId) {
117   auto callback = getHostNotificationCallback();
118   EventLoopManagerSingleton::get()->deferCallback(
119       SystemCallbackType::HostEndpointDisconnected,
120       NestedDataPtr<uint16_t>(hostEndpointId), callback, nullptr);
121 }
122 
123 }  // namespace chre
124