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