• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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