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