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: ConditionTimer(bool initCondition,int64_t bucketStartNs)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 newBucketStart(int64_t nextBucketStartNs)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 onConditionChanged(bool newCondition,int64_t timestampNs)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