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