• 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_notifications.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 
23 namespace chre {
24 
25 namespace {
26 
27 //! Connected host endpoint metadata, which should only be accessed by the main
28 //! CHRE event loop.
29 // TODO(b/194287786): Re-organize this code into a class for better
30 // organization.
31 chre::DynamicVector<struct chreHostEndpointInfo> gHostEndpoints;
32 
isHostEndpointConnected(uint16_t hostEndpointId,size_t * index)33 bool isHostEndpointConnected(uint16_t hostEndpointId, size_t *index) {
34   for (size_t i = 0; i < gHostEndpoints.size(); i++) {
35     if (gHostEndpoints[i].hostEndpointId == hostEndpointId) {
36       *index = i;
37       return true;
38     }
39   }
40 
41   return false;
42 }
43 
hostNotificationCallback(uint16_t type,void * data,void * extraData)44 void hostNotificationCallback(uint16_t type, void *data, void *extraData) {
45   uint16_t hostEndpointId = NestedDataPtr<uint16_t>(data);
46 
47   SystemCallbackType callbackType = static_cast<SystemCallbackType>(type);
48   if (callbackType == SystemCallbackType::HostEndpointDisconnected) {
49     size_t index;
50     if (isHostEndpointConnected(hostEndpointId, &index)) {
51       gHostEndpoints.erase(index);
52 
53       uint16_t eventType = CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION;
54       auto *eventData = memoryAlloc<struct chreHostEndpointNotification>();
55 
56       if (eventData == nullptr) {
57         LOG_OOM();
58       } else {
59         eventData->hostEndpointId = hostEndpointId;
60         eventData->notificationType =
61             HOST_ENDPOINT_NOTIFICATION_TYPE_DISCONNECT;
62         eventData->reserved = 0;
63 
64         EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
65             eventType, eventData, freeEventDataCallback, kBroadcastInstanceId);
66       }
67     } else {
68       LOGW("Got disconnected event for nonexistent host endpoint ID %" PRIu16,
69            hostEndpointId);
70     }
71   } else {
72     auto *info = static_cast<struct chreHostEndpointInfo *>(extraData);
73 
74     size_t index;
75     if (!isHostEndpointConnected(hostEndpointId, &index)) {
76       gHostEndpoints.push_back(*info);
77     } else {
78       LOGW("Got connected event for already existing host endpoint ID %" PRIu16,
79            hostEndpointId);
80     }
81   }
82 
83   memoryFree(extraData);
84 }
85 
86 }  // anonymous namespace
87 
getHostEndpointInfo(uint16_t hostEndpointId,struct chreHostEndpointInfo * info)88 bool getHostEndpointInfo(uint16_t hostEndpointId,
89                          struct chreHostEndpointInfo *info) {
90   size_t index;
91   if (isHostEndpointConnected(hostEndpointId, &index)) {
92     *info = gHostEndpoints[index];
93     return true;
94   } else {
95     return false;
96   }
97 }
98 
postHostEndpointConnected(const struct chreHostEndpointInfo & info)99 void postHostEndpointConnected(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     EventLoopManagerSingleton::get()->deferCallback(
107         SystemCallbackType::HostEndpointConnected,
108         NestedDataPtr<uint16_t>(info.hostEndpointId), hostNotificationCallback,
109         infoData /* extraData */);
110   }
111 }
112 
postHostEndpointDisconnected(uint16_t hostEndpointId)113 void postHostEndpointDisconnected(uint16_t hostEndpointId) {
114   EventLoopManagerSingleton::get()->deferCallback(
115       SystemCallbackType::HostEndpointDisconnected,
116       NestedDataPtr<uint16_t>(hostEndpointId), hostNotificationCallback,
117       nullptr);
118 }
119 
120 }  // namespace chre
121