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 package com.android.adservices.service.stats; 18 19 import android.annotation.NonNull; 20 21 import com.android.adservices.LogUtil; 22 import com.android.adservices.shared.util.Clock; 23 24 import java.util.Objects; 25 26 import javax.annotation.concurrent.ThreadSafe; 27 28 /** 29 * Class for the Api Service Latency Calculator. This class uses a clock that its 30 * clock#elapsedRealtime() should always be monotonic to track the time points of a process. The 31 * {@link ApiServiceLatencyCalculator} constructor will set the {@link 32 * ApiServiceLatencyCalculator#mStartElapsedTimestamp}. Calling {@link 33 * ApiServiceLatencyCalculator#getApiServiceInternalFinalLatencyInMs()} will stop the time 34 * calculator and return the latency for the process by the start and stop elapsed timestamps. Once 35 * the calculator is stopped, the {@link ApiServiceLatencyCalculator#mStopElapsedTimestamp} will not 36 * be changed. Calling {@link ApiServiceLatencyCalculator#getApiServiceElapsedLatencyInMs()} will 37 * not stop the time calculator, only get the time elapsed since the start elapsed timestamp. 38 */ 39 @ThreadSafe 40 public class ApiServiceLatencyCalculator { 41 private final long mStartElapsedTimestamp; 42 private volatile long mStopElapsedTimestamp; 43 private volatile boolean mRunning; 44 private final Clock mClock; 45 ApiServiceLatencyCalculator(@onNull Clock clock)46 ApiServiceLatencyCalculator(@NonNull Clock clock) { 47 Objects.requireNonNull(clock); 48 mClock = clock; 49 mStartElapsedTimestamp = mClock.elapsedRealtime(); 50 mRunning = true; 51 LogUtil.v("ApiServiceLatencyCalculator has started at %d", mStartElapsedTimestamp); 52 } 53 54 /** 55 * Stops a {@link ApiServiceLatencyCalculator} instance from time calculation. If an instance is 56 * not running, calling this method will do nothing. 57 */ stop()58 private void stop() { 59 if (!mRunning) { 60 return; 61 } 62 synchronized (this) { 63 if (!mRunning) { 64 return; 65 } 66 mStopElapsedTimestamp = mClock.elapsedRealtime(); 67 mRunning = false; 68 LogUtil.v("ApiServiceLatencyCalculator stopped."); 69 } 70 } 71 72 /** @return the calculator's start timestamp since the system boots. */ getStartElapsedTimestamp()73 long getStartElapsedTimestamp() { 74 return mStartElapsedTimestamp; 75 } 76 77 /** 78 * @return the elapsed timestamp since the system boots if the {@link 79 * ApiServiceLatencyCalculator} instance is still running, otherwise the timestamp when it 80 * was stopped. 81 */ getServiceElapsedTimestamp()82 long getServiceElapsedTimestamp() { 83 if (mRunning) { 84 return mClock.elapsedRealtime(); 85 } 86 LogUtil.v("The ApiServiceLatencyCalculator instance has previously been stopped."); 87 return mStopElapsedTimestamp; 88 } 89 90 /** 91 * @return the api service elapsed time latency since {@link ApiServiceLatencyCalculator} starts 92 * in milliseconds on the service side. This method will not stop the {@link 93 * ApiServiceLatencyCalculator} and should be used for getting intermediate stage latency of 94 * a API process. 95 */ getApiServiceElapsedLatencyInMs()96 int getApiServiceElapsedLatencyInMs() { 97 return (int) (getServiceElapsedTimestamp() - mStartElapsedTimestamp); 98 } 99 100 /** 101 * @return the api service overall latency since the {@link ApiServiceLatencyCalculator} starts 102 * in milliseconds without binder latency, on the server side. This method will stop the 103 * calculator if still running and the returned latency value will no longer change once the 104 * calculator is stopped. It should be used to get the complete process latency of an API 105 * within the server side. 106 */ getApiServiceInternalFinalLatencyInMs()107 int getApiServiceInternalFinalLatencyInMs() { 108 stop(); 109 return getApiServiceElapsedLatencyInMs(); 110 } 111 } 112