1 /* 2 * Copyright (C) 2014 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 android.util; 18 19 /** 20 * This class tracks the timing of important state changes in camera app (e.g latency 21 * of cold/warm start of the activity, mode switch duration, etc). We can then query 22 * these values from the instrument tests, which will be helpful for tracking camera 23 * app performance and regression tests. 24 */ 25 public class CameraPerformanceTracker { 26 27 // Event types to track. 28 public static final int ACTIVITY_START = 0; 29 public static final int ACTIVITY_PAUSE = 1; 30 public static final int ACTIVITY_RESUME = 2; 31 public static final int MODE_SWITCH_START = 3; 32 public static final int FIRST_PREVIEW_FRAME = 5; 33 public static final int UNSET = -1; 34 35 private static final String TAG = "CameraPerformanceTracker"; 36 private static final boolean DEBUG = false; 37 private static CameraPerformanceTracker sInstance; 38 39 // Internal tracking time. 40 private long mAppStartTime = UNSET; 41 private long mAppResumeTime = UNSET; 42 private long mModeSwitchStartTime = UNSET; 43 44 // Duration and/or latency or later querying. 45 private long mFirstPreviewFrameLatencyColdStart = UNSET; 46 private long mFirstPreviewFrameLatencyWarmStart = UNSET; 47 // TODO: Need to how to best track the duration for each switch from/to pair. 48 private long mModeSwitchDuration = UNSET; 49 50 private CameraPerformanceTracker() { 51 // Private constructor to ensure that it can only be created from within 52 // the class. 53 } 54 55 /** 56 * This gets called when an important state change happens. Based on the type 57 * of the event/state change, either we will record the time of the event, or 58 * calculate the duration/latency. 59 * 60 * @param eventType type of a event to track 61 */ 62 public static void onEvent(int eventType) { 63 if (sInstance == null) { 64 sInstance = new CameraPerformanceTracker(); 65 } 66 long currentTime = System.currentTimeMillis(); 67 switch (eventType) { 68 case ACTIVITY_START: 69 sInstance.mAppStartTime = currentTime; 70 break; 71 case ACTIVITY_PAUSE: 72 sInstance.mFirstPreviewFrameLatencyWarmStart = UNSET; 73 break; 74 case ACTIVITY_RESUME: 75 sInstance.mAppResumeTime = currentTime; 76 break; 77 case FIRST_PREVIEW_FRAME: 78 Log.d(TAG, "First preview frame received"); 79 if (sInstance.mFirstPreviewFrameLatencyColdStart == UNSET) { 80 // Cold start. 81 sInstance.mFirstPreviewFrameLatencyColdStart = 82 currentTime - sInstance.mAppStartTime; 83 } else { 84 // Warm Start. 85 sInstance.mFirstPreviewFrameLatencyWarmStart = 86 currentTime - sInstance.mAppResumeTime; 87 } 88 // If the new frame is triggered by the mode switch, track the duration. 89 if (sInstance.mModeSwitchStartTime != UNSET) { 90 sInstance.mModeSwitchDuration = currentTime - sInstance.mModeSwitchStartTime; 91 sInstance.mModeSwitchStartTime = UNSET; 92 } 93 break; 94 case MODE_SWITCH_START: 95 sInstance.mModeSwitchStartTime = currentTime; 96 break; 97 default: 98 break; 99 } 100 if (DEBUG && eventType == FIRST_PREVIEW_FRAME) { 101 Log.d(TAG, "Mode switch duration: " + (sInstance.mModeSwitchDuration 102 == UNSET ? "UNSET" : sInstance.mModeSwitchDuration)); 103 Log.d(TAG, "Cold start latency: " + (sInstance.mFirstPreviewFrameLatencyColdStart 104 == UNSET ? "UNSET" : sInstance.mFirstPreviewFrameLatencyColdStart)); 105 Log.d(TAG, "Warm start latency: " + (sInstance.mFirstPreviewFrameLatencyWarmStart 106 == UNSET ? "UNSET" : sInstance.mFirstPreviewFrameLatencyWarmStart)); 107 } 108 } 109 110 //TODO: Hook up these getters in the instrument tests. 111 /** 112 * Gets the latency of a cold start of the app, measured from the time onCreate 113 * gets called to the time first preview frame gets received. 114 * 115 * @return latency of a cold start. If no instances have been created, return 116 * UNSET. 117 */ 118 public static long getColdStartLatency() { 119 if (sInstance == null) { 120 return UNSET; 121 } 122 return sInstance.mFirstPreviewFrameLatencyColdStart; 123 } 124 125 /** 126 * Gets the latency of a warm start of the app, measured from the time onResume 127 * gets called to the time next preview frame gets received. 128 * 129 * @return latency of a warm start. If no instances have been created, 130 * return UNSET. 131 */ 132 public static long getWarmStartLatency() { 133 if (sInstance == null) { 134 return UNSET; 135 } 136 return sInstance.mFirstPreviewFrameLatencyWarmStart; 137 } 138 139 /** 140 * Gets the duration of the mode switch, measured from the start of a mode switch 141 * to the time next preview frame gets received. 142 * 143 * @return duration of the mode switch. If no instances have been created, 144 * return UNSET. 145 */ 146 public static long getModeSwitchDuration() { 147 if (sInstance == null) { 148 return UNSET; 149 } 150 return sInstance.mModeSwitchDuration; 151 } 152 } 153