• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_api/chre/re.h"
18 
19 #include <cstdint>
20 
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/core/settings.h"
23 #include "chre/platform/log.h"
24 #include "chre/util/time.h"
25 #include "chre_api/chre/event.h"
26 
27 #include "gtest/gtest.h"
28 #include "inc/test_util.h"
29 #include "test_base.h"
30 #include "test_event.h"
31 #include "test_event_queue.h"
32 #include "test_util.h"
33 
34 namespace chre {
35 
36 // TestTimer is required to access private members of the TimerPool.
37 class TestTimer : public TestBase {
38  protected:
hasNanoappTimers(TimerPool & pool,uint16_t instanceId)39   bool hasNanoappTimers(TimerPool &pool, uint16_t instanceId) {
40     return pool.hasNanoappTimers(instanceId);
41   }
42 };
43 
44 namespace {
TEST_F(TestTimer,SetupAndCancelPeriodicTimer)45 TEST_F(TestTimer, SetupAndCancelPeriodicTimer) {
46   CREATE_CHRE_TEST_EVENT(START_TIMER, 0);
47   CREATE_CHRE_TEST_EVENT(STOP_TIMER, 1);
48 
49   struct App : public TestNanoapp {
50     void (*handleEvent)(uint32_t, uint16_t,
51                         const void *) = [](uint32_t, uint16_t eventType,
52                                            const void *eventData) {
53       const uint32_t cookie = 123;
54       switch (eventType) {
55         static int count = 0;
56 
57         case CHRE_EVENT_TIMER: {
58           auto data = static_cast<const uint32_t *>(eventData);
59           if (*data == cookie) {
60             count++;
61             if (count == 3) {
62               TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_TIMER);
63             }
64           }
65           break;
66         }
67 
68         case CHRE_EVENT_TEST_EVENT: {
69           auto event = static_cast<const TestEvent *>(eventData);
70           switch (event->type) {
71             case START_TIMER: {
72               uint32_t handle = chreTimerSet(kOneMillisecondInNanoseconds,
73                                              &cookie, false /*oneShot*/);
74               TestEventQueueSingleton::get()->pushEvent(START_TIMER, handle);
75               break;
76             }
77             case STOP_TIMER: {
78               auto handle = static_cast<const uint32_t *>(event->data);
79               bool success = chreTimerCancel(*handle);
80               TestEventQueueSingleton::get()->pushEvent(STOP_TIMER, success);
81               break;
82             }
83           }
84         }
85       }
86     };
87   };
88 
89   auto app = loadNanoapp<App>();
90 
91   TimerPool &timerPool =
92       EventLoopManagerSingleton::get()->getEventLoop().getTimerPool();
93 
94   uint16_t instanceId;
95   EXPECT_TRUE(EventLoopManagerSingleton::get()
96                   ->getEventLoop()
97                   .findNanoappInstanceIdByAppId(app.id, &instanceId));
98 
99   uint32_t handle;
100   sendEventToNanoapp(app, START_TIMER);
101   waitForEvent(START_TIMER, &handle);
102   EXPECT_NE(handle, CHRE_TIMER_INVALID);
103   EXPECT_TRUE(hasNanoappTimers(timerPool, instanceId));
104 
105   waitForEvent(CHRE_EVENT_TIMER);
106 
107   bool success;
108 
109   // Cancelling an active timer should be successful.
110   sendEventToNanoapp(app, STOP_TIMER, handle);
111   waitForEvent(STOP_TIMER, &success);
112   EXPECT_TRUE(success);
113   EXPECT_FALSE(hasNanoappTimers(timerPool, instanceId));
114 
115   // Cancelling an inactive time should return false.
116   sendEventToNanoapp(app, STOP_TIMER, handle);
117   waitForEvent(STOP_TIMER, &success);
118   EXPECT_FALSE(success);
119 }
120 
TEST_F(TestTimer,CancelPeriodicTimerOnUnload)121 TEST_F(TestTimer, CancelPeriodicTimerOnUnload) {
122   CREATE_CHRE_TEST_EVENT(START_TIMER, 0);
123 
124   struct App : public TestNanoapp {
125     void (*handleEvent)(uint32_t, uint16_t,
126                         const void *) = [](uint32_t, uint16_t eventType,
127                                            const void *eventData) {
128       const uint32_t cookie = 123;
129       switch (eventType) {
130         static int count = 0;
131 
132         case CHRE_EVENT_TIMER: {
133           auto data = static_cast<const uint32_t *>(eventData);
134           if (*data == cookie) {
135             count++;
136             if (count == 3) {
137               TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_TIMER);
138             }
139           }
140           break;
141         }
142 
143         case CHRE_EVENT_TEST_EVENT: {
144           auto event = static_cast<const TestEvent *>(eventData);
145           switch (event->type) {
146             case START_TIMER: {
147               uint32_t handle = chreTimerSet(kOneMillisecondInNanoseconds,
148                                              &cookie, false /*oneShot*/);
149               TestEventQueueSingleton::get()->pushEvent(START_TIMER, handle);
150               break;
151             }
152           }
153         }
154       }
155     };
156   };
157 
158   auto app = loadNanoapp<App>();
159 
160   TimerPool &timerPool =
161       EventLoopManagerSingleton::get()->getEventLoop().getTimerPool();
162 
163   uint16_t instanceId;
164   EXPECT_TRUE(EventLoopManagerSingleton::get()
165                   ->getEventLoop()
166                   .findNanoappInstanceIdByAppId(app.id, &instanceId));
167 
168   uint32_t handle;
169   sendEventToNanoapp(app, START_TIMER);
170   waitForEvent(START_TIMER, &handle);
171   EXPECT_NE(handle, CHRE_TIMER_INVALID);
172   EXPECT_TRUE(hasNanoappTimers(timerPool, instanceId));
173 
174   waitForEvent(CHRE_EVENT_TIMER);
175 
176   unloadNanoapp(app);
177   EXPECT_FALSE(hasNanoappTimers(timerPool, instanceId));
178 }
179 
180 }  // namespace
181 }  // namespace chre
182