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 class App : public TestNanoapp {
50 public:
51 void handleEvent(uint32_t, uint16_t eventType,
52 const void *eventData) override {
53 switch (eventType) {
54 case CHRE_EVENT_TIMER: {
55 auto data = static_cast<const uint32_t *>(eventData);
56 if (*data == mCookie) {
57 mCount++;
58 if (mCount == 3) {
59 TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_TIMER);
60 }
61 }
62 break;
63 }
64
65 case CHRE_EVENT_TEST_EVENT: {
66 auto event = static_cast<const TestEvent *>(eventData);
67 switch (event->type) {
68 case START_TIMER: {
69 uint32_t handle = chreTimerSet(10 * kOneMillisecondInNanoseconds,
70 &mCookie, false /*oneShot*/);
71 TestEventQueueSingleton::get()->pushEvent(START_TIMER, handle);
72 break;
73 }
74 case STOP_TIMER: {
75 auto handle = static_cast<const uint32_t *>(event->data);
76 bool success = chreTimerCancel(*handle);
77 TestEventQueueSingleton::get()->pushEvent(STOP_TIMER, success);
78 break;
79 }
80 }
81 }
82 }
83 }
84
85 protected:
86 const uint32_t mCookie = 123;
87 int mCount = 0;
88 };
89
90 uint64_t appId = loadNanoapp(MakeUnique<App>());
91
92 TimerPool &timerPool =
93 EventLoopManagerSingleton::get()->getEventLoop().getTimerPool();
94
95 uint16_t instanceId;
96 EXPECT_TRUE(EventLoopManagerSingleton::get()
97 ->getEventLoop()
98 .findNanoappInstanceIdByAppId(appId, &instanceId));
99
100 uint32_t handle;
101 sendEventToNanoapp(appId, START_TIMER);
102 waitForEvent(START_TIMER, &handle);
103 EXPECT_NE(handle, CHRE_TIMER_INVALID);
104 EXPECT_TRUE(hasNanoappTimers(timerPool, instanceId));
105
106 waitForEvent(CHRE_EVENT_TIMER);
107
108 bool success;
109
110 // Cancelling an active timer should be successful.
111 sendEventToNanoapp(appId, STOP_TIMER, handle);
112 waitForEvent(STOP_TIMER, &success);
113 EXPECT_TRUE(success);
114 EXPECT_FALSE(hasNanoappTimers(timerPool, instanceId));
115
116 // Cancelling an inactive time should return false.
117 sendEventToNanoapp(appId, STOP_TIMER, handle);
118 waitForEvent(STOP_TIMER, &success);
119 EXPECT_FALSE(success);
120 }
121
TEST_F(TestTimer,CancelPeriodicTimerOnUnload)122 TEST_F(TestTimer, CancelPeriodicTimerOnUnload) {
123 CREATE_CHRE_TEST_EVENT(START_TIMER, 0);
124
125 class App : public TestNanoapp {
126 public:
127 void handleEvent(uint32_t, uint16_t eventType, const void *eventData) {
128 switch (eventType) {
129 case CHRE_EVENT_TIMER: {
130 auto data = static_cast<const uint32_t *>(eventData);
131 if (*data == mCookie) {
132 mCount++;
133 if (mCount == 3) {
134 TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_TIMER);
135 }
136 }
137 break;
138 }
139
140 case CHRE_EVENT_TEST_EVENT: {
141 auto event = static_cast<const TestEvent *>(eventData);
142 switch (event->type) {
143 case START_TIMER: {
144 uint32_t handle = chreTimerSet(10 * kOneMillisecondInNanoseconds,
145 &mCookie, false /*oneShot*/);
146 TestEventQueueSingleton::get()->pushEvent(START_TIMER, handle);
147 break;
148 }
149 }
150 }
151 }
152 }
153
154 protected:
155 const uint32_t mCookie = 123;
156 int mCount = 0;
157 };
158
159 uint64_t appId = loadNanoapp(MakeUnique<App>());
160
161 TimerPool &timerPool =
162 EventLoopManagerSingleton::get()->getEventLoop().getTimerPool();
163
164 uint16_t instanceId;
165 EXPECT_TRUE(EventLoopManagerSingleton::get()
166 ->getEventLoop()
167 .findNanoappInstanceIdByAppId(appId, &instanceId));
168
169 uint32_t handle;
170 sendEventToNanoapp(appId, START_TIMER);
171 waitForEvent(START_TIMER, &handle);
172 EXPECT_NE(handle, CHRE_TIMER_INVALID);
173 EXPECT_TRUE(hasNanoappTimers(timerPool, instanceId));
174
175 waitForEvent(CHRE_EVENT_TIMER);
176
177 unloadNanoapp(appId);
178 EXPECT_FALSE(hasNanoappTimers(timerPool, instanceId));
179 }
180
181 } // namespace
182 } // namespace chre
183