Home | History | Annotate | Download | only in slpi
      1 /*
      2  * Copyright (C) 2016 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/platform/system_time.h"
     18 #include "chre/platform/slpi/system_time.h"
     19 
     20 #include "chre/platform/fatal_error.h"
     21 #include "chre/platform/host_link.h"
     22 #include "chre/platform/log.h"
     23 #include "chre/platform/system_timer.h"
     24 
     25 extern "C" {
     26 
     27 #include "uTimetick.h"
     28 
     29 }  // extern "C"
     30 
     31 namespace chre {
     32 
     33 namespace {
     34 int64_t gEstimatedHostTimeOffset = 0;
     35 
     36 // A timer for scheduling a time sync request.
     37 SystemTimer gTimeSyncRequestTimer;
     38 bool gTimeSyncRequestTimerInitialized = false;
     39 
     40 Nanoseconds gLastTimeSyncRequestNanos(0);
     41 
     42 void setTimeSyncRequestTimer(Nanoseconds delay) {
     43   // Check for timer init since this method might be called before CHRE
     44   // init is called.
     45   if (!gTimeSyncRequestTimerInitialized) {
     46     if (!gTimeSyncRequestTimer.init()) {
     47       FATAL_ERROR("Failed to initialize time sync request timer.");
     48     } else {
     49       gTimeSyncRequestTimerInitialized = true;
     50     }
     51   }
     52   if (gTimeSyncRequestTimer.isActive()) {
     53     gTimeSyncRequestTimer.cancel();
     54   }
     55   auto callback = [](void* /* data */) {
     56     sendTimeSyncRequest();
     57   };
     58   if (!gTimeSyncRequestTimer.set(callback, nullptr, delay)) {
     59     LOGE("Failed to set time sync request timer.");
     60   }
     61 }
     62 } // anonymous namespace
     63 
     64 Nanoseconds SystemTime::getMonotonicTime() {
     65   constexpr uint64_t kClockFreq = 19200000;  // 19.2MHz QTimer clock
     66 
     67   uint64_t ticks = uTimetick_Get();
     68   uint64_t nsec = 0;
     69   if (ticks >= kClockFreq) {
     70     uint64_t seconds = (ticks / kClockFreq);
     71     ticks %= kClockFreq;
     72 
     73     nsec = (seconds * kOneSecondInNanoseconds);
     74   }
     75   nsec += (ticks * kOneSecondInNanoseconds) / kClockFreq;
     76 
     77   return Nanoseconds(nsec);
     78 }
     79 
     80 int64_t SystemTime::getEstimatedHostTimeOffset() {
     81   return gEstimatedHostTimeOffset;
     82 }
     83 
     84 void setEstimatedHostTimeOffset(int64_t offset) {
     85   gEstimatedHostTimeOffset = offset;
     86 
     87   // Schedule a time sync request since offset may drift
     88   constexpr Seconds kTimeSyncLongInterval = Seconds(60 * 60 * 6); // 6 hours
     89   setTimeSyncRequestTimer(kTimeSyncLongInterval);
     90 }
     91 
     92 void requestTimeSyncIfStale() {
     93   constexpr Seconds kTimeSyncShortInterval = Seconds(60 * 60 * 1); // 1 hour
     94   if (SystemTime::getMonotonicTime() >
     95       gLastTimeSyncRequestNanos + kTimeSyncShortInterval) {
     96     sendTimeSyncRequest();
     97   }
     98 }
     99 
    100 void updateLastTimeSyncRequest() {
    101   gLastTimeSyncRequestNanos = SystemTime::getMonotonicTime();
    102 }
    103 
    104 }  // namespace chre
    105