Home | History | Annotate | Download | only in condition
      1 /*
      2  * Copyright (C) 2019 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 #pragma once
     17 
     18 #include <gtest/gtest_prod.h>
     19 #include <stdint.h>
     20 
     21 namespace android {
     22 namespace os {
     23 namespace statsd {
     24 
     25 /**
     26  * A simple stopwatch to time the duration of condition being true.
     27  *
     28  * The owner of the stopwatch (MetricProducer) is responsible to notify the stopwatch when condition
     29  * changes (start/pause), and when to start a new bucket (a new lap basically). All timestamps
     30  * should be elapsedRealTime in nano seconds.
     31  *
     32  * Keep the timer simple and inline everything. This class is *NOT* thread safe. Caller is
     33  * responsible for thread safety.
     34  */
     35 class ConditionTimer {
     36 public:
     37     explicit ConditionTimer(bool initCondition, int64_t bucketStartNs) : mCondition(initCondition) {
     38         if (initCondition) {
     39             mLastConditionTrueTimestampNs = bucketStartNs;
     40         }
     41     };
     42 
     43     // Tracks how long the condition has been stayed true in the *current* bucket.
     44     // When a new bucket is created, this value will be reset to 0.
     45     int64_t mTimerNs = 0;
     46 
     47     // Last elapsed real timestamp when condition turned to true
     48     // When a new bucket is created and the condition is true, then the timestamp is set
     49     // to be the bucket start timestamp.
     50     int64_t mLastConditionTrueTimestampNs = 0;
     51 
     52     bool mCondition = false;
     53 
     54     int64_t newBucketStart(int64_t nextBucketStartNs) {
     55         if (mCondition) {
     56             mTimerNs += (nextBucketStartNs - mLastConditionTrueTimestampNs);
     57             mLastConditionTrueTimestampNs = nextBucketStartNs;
     58         }
     59 
     60         int64_t temp = mTimerNs;
     61         mTimerNs = 0;
     62         return temp;
     63     }
     64 
     65     void onConditionChanged(bool newCondition, int64_t timestampNs) {
     66         if (newCondition == mCondition) {
     67             return;
     68         }
     69         mCondition = newCondition;
     70         if (newCondition) {
     71             mLastConditionTrueTimestampNs = timestampNs;
     72         } else {
     73             mTimerNs += (timestampNs - mLastConditionTrueTimestampNs);
     74         }
     75     }
     76 
     77     FRIEND_TEST(ConditionTimerTest, TestTimer_Inital_False);
     78     FRIEND_TEST(ConditionTimerTest, TestTimer_Inital_True);
     79 };
     80 
     81 }  // namespace statsd
     82 }  // namespace os
     83 }  // namespace android