xref: /aosp_15_r20/system/chre/test/simulation/host_endpoint_notification_test.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 "test_base.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include <cstdint>
22 #include <optional>
23 #include <thread>
24 
25 #include "chre/core/event_loop_manager.h"
26 #include "chre/core/host_endpoint_manager.h"
27 #include "chre/platform/log.h"
28 #include "chre_api/chre/event.h"
29 #include "test_event_queue.h"
30 #include "test_util.h"
31 
32 namespace chre {
33 
34 namespace {
35 
36 //! The host endpoint ID to use for this test.
37 constexpr uint16_t kHostEndpointId = 123;
38 
39 //! Helper function to get Host Endpoint Manager from Event Loop Manager
getHostEndpointManager()40 HostEndpointManager &getHostEndpointManager() {
41   return EventLoopManagerSingleton::get()->getHostEndpointManager();
42 }
43 
44 /**
45  * Verifies basic functionality of chreConfigureHostEndpointNotifications.
46  */
TEST_F(TestBase,HostEndpointDisconnectedTest)47 TEST_F(TestBase, HostEndpointDisconnectedTest) {
48   CREATE_CHRE_TEST_EVENT(SETUP_NOTIFICATION, 0);
49 
50   struct Config {
51     bool enable;
52     uint16_t endpointId;
53   };
54 
55   class App : public TestNanoapp {
56    public:
57     void handleEvent(uint32_t, uint16_t eventType,
58                      const void *eventData) override {
59       switch (eventType) {
60         case CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION: {
61           auto notification = *(struct chreHostEndpointNotification *)eventData;
62           TestEventQueueSingleton::get()->pushEvent(
63               CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION, notification);
64         } break;
65 
66         case CHRE_EVENT_TEST_EVENT: {
67           auto event = static_cast<const TestEvent *>(eventData);
68           switch (event->type) {
69             case SETUP_NOTIFICATION: {
70               auto config = static_cast<const Config *>(event->data);
71               const bool success = chreConfigureHostEndpointNotifications(
72                   config->endpointId, config->enable);
73               TestEventQueueSingleton::get()->pushEvent(SETUP_NOTIFICATION,
74                                                         success);
75             }
76           }
77         }
78       }
79     }
80   };
81 
82   struct chreHostEndpointInfo info;
83   info.hostEndpointId = kHostEndpointId;
84   info.hostEndpointType = CHRE_HOST_ENDPOINT_TYPE_FRAMEWORK;
85   info.isNameValid = true;
86   strcpy(&info.endpointName[0], "Test endpoint name");
87   info.isTagValid = true;
88   strcpy(&info.endpointTag[0], "Test tag");
89   getHostEndpointManager().postHostEndpointConnected(info);
90 
91   uint64_t appId = loadNanoapp(MakeUnique<App>());
92 
93   Config config = {.enable = true, .endpointId = kHostEndpointId};
94 
95   sendEventToNanoapp(appId, SETUP_NOTIFICATION, config);
96   bool success;
97   waitForEvent(SETUP_NOTIFICATION, &success);
98   EXPECT_TRUE(success);
99 
100   struct chreHostEndpointInfo retrievedInfo;
101   ASSERT_TRUE(getHostEndpointManager().getHostEndpointInfo(kHostEndpointId,
102                                                            &retrievedInfo));
103   ASSERT_EQ(retrievedInfo.hostEndpointId, info.hostEndpointId);
104   ASSERT_EQ(retrievedInfo.hostEndpointType, info.hostEndpointType);
105   ASSERT_EQ(retrievedInfo.isNameValid, info.isNameValid);
106   ASSERT_EQ(strcmp(&retrievedInfo.endpointName[0], &info.endpointName[0]), 0);
107   ASSERT_EQ(retrievedInfo.isTagValid, info.isTagValid);
108   ASSERT_EQ(strcmp(&retrievedInfo.endpointTag[0], &info.endpointTag[0]), 0);
109 
110   struct chreHostEndpointNotification notification;
111   getHostEndpointManager().postHostEndpointDisconnected(kHostEndpointId);
112   waitForEvent(CHRE_EVENT_HOST_ENDPOINT_NOTIFICATION, &notification);
113 
114   ASSERT_EQ(notification.hostEndpointId, kHostEndpointId);
115   ASSERT_EQ(notification.notificationType,
116             HOST_ENDPOINT_NOTIFICATION_TYPE_DISCONNECT);
117   ASSERT_EQ(notification.reserved, 0);
118 
119   ASSERT_FALSE(EventLoopManagerSingleton::get()
120                    ->getHostEndpointManager()
121                    .getHostEndpointInfo(kHostEndpointId, &retrievedInfo));
122 }
123 
TEST_F(TestBase,HostEndpointNotRegisteredTest)124 TEST_F(TestBase, HostEndpointNotRegisteredTest) {
125   struct chreHostEndpointInfo retrievedInfo;
126   ASSERT_FALSE(getHostEndpointManager().getHostEndpointInfo(kHostEndpointId,
127                                                             &retrievedInfo));
128 }
129 
TEST_F(TestBase,HostEndpointDisconnectedTwiceTest)130 TEST_F(TestBase, HostEndpointDisconnectedTwiceTest) {
131   struct chreHostEndpointInfo info;
132   info.hostEndpointId = kHostEndpointId;
133   info.hostEndpointType = CHRE_HOST_ENDPOINT_TYPE_FRAMEWORK;
134   info.isNameValid = false;
135   info.isTagValid = false;
136   getHostEndpointManager().postHostEndpointConnected(info);
137 
138   getHostEndpointManager().postHostEndpointDisconnected(kHostEndpointId);
139   // The second invocation should be a silent no-op.
140   getHostEndpointManager().postHostEndpointDisconnected(kHostEndpointId);
141 }
142 
143 }  // anonymous namespace
144 }  // namespace chre
145