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 #include <algorithm>
17 #include <cinttypes>
18 
19 #include "chre/platform/fatal_error.h"
20 #include "chre/platform/log.h"
21 #include "chre/platform/system_timer.h"
22 #include "chre/util/time.h"
23 
24 namespace chre {
25 
invokeCallback(void * instance)26 void SystemTimerBase::invokeCallback(void *instance) {
27   auto *timer = static_cast<SystemTimer *>(instance);
28   timer->mCallback(timer->mData);
29 }
30 
SystemTimer()31 SystemTimer::SystemTimer() {}
32 
~SystemTimer()33 SystemTimer::~SystemTimer() {
34   // cancel an existing timer if any, and delete the timer instance.
35   cancel();
36   OS_DeleteTimerEx(&mTimer);
37 }
38 
init()39 bool SystemTimer::init() {
40   constexpr uint32_t kSomeInitialPeriod = 100;
41   OS_CreateTimerEx(&mTimer, SystemTimerBase::invokeCallback, kSomeInitialPeriod,
42                    this /*context*/);
43   return true;
44 }
45 
set(SystemTimerCallback * callback,void * data,Nanoseconds delay)46 bool SystemTimer::set(SystemTimerCallback *callback, void *data,
47                       Nanoseconds delay) {
48   // The public EmbOS documentation does not specify how it handles calls to
49   // its timer create API if the values lie beyond the specified interval of
50   // 1 ≤ Period ≤ 0x7FFFFFFF. Since there's not return value to assess API
51   // call success, we clamp the delay to the supported interval.
52   // Note that since the EmbOS timer is a millisecond tick timer, an additional
53   // delay of 1ms is added to the requested delay to avoid clipping/zeroing
54   // during the time factor conversion.
55   // TODO(b/237819962): Investigate the possibility of a spare hardware timer
56   // available on SLSI that we can eventually switch to.
57   constexpr uint64_t kMinDelayMs = 1;
58   constexpr uint64_t kMaxDelayMs = INT32_MAX;
59   uint64_t delayMs = Milliseconds(delay).getMilliseconds();
60   delayMs = std::min(std::max(delayMs + 1, kMinDelayMs), kMaxDelayMs);
61 
62   OS_StopTimerEx(&mTimer);
63   OS_SetTimerPeriodEx(&mTimer, static_cast<OS_TIME>(delayMs));
64 
65   mCallback = callback;
66   mData = data;
67 
68   OS_RetriggerTimerEx(&mTimer);
69   return true;
70 }
71 
72 // The return value for this function is not guaranteed to be correct - please
73 // see the note in @ref SystemTimerBase.
cancel()74 bool SystemTimer::cancel() {
75   bool success = false;
76   if (isActive()) {
77     OS_StopTimerEx(&mTimer);
78     success = true;
79   }
80   return success;
81 }
82 
isActive()83 bool SystemTimer::isActive() {
84   return (OS_GetTimerStatusEx(&mTimer) != 0);
85 }
86 
87 }  // namespace chre
88