17cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu/* 27cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Copyright (C) 2014 The Android Open Source Project 37cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 47cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Licensed under the Apache License, Version 2.0 (the "License"); 57cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * you may not use this file except in compliance with the License. 67cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * You may obtain a copy of the License at 77cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 87cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * http://www.apache.org/licenses/LICENSE-2.0 97cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 107cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Unless required by applicable law or agreed to in writing, software 117cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * distributed under the License is distributed on an "AS IS" BASIS, 127cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * See the License for the specific language governing permissions and 147cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * limitations under the License. 157cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 167cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 177cbeceed6d03d0550797c435f3db6205714cd49fDoris Liupackage android.util; 187cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 197cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu/** 207cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * This class tracks the timing of important state changes in camera app (e.g latency 217cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * of cold/warm start of the activity, mode switch duration, etc). We can then query 227cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * these values from the instrument tests, which will be helpful for tracking camera 237cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * app performance and regression tests. 247cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 257cbeceed6d03d0550797c435f3db6205714cd49fDoris Liupublic class CameraPerformanceTracker { 267cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 277cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Event types to track. 287cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int ACTIVITY_START = 0; 297cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int ACTIVITY_PAUSE = 1; 307cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int ACTIVITY_RESUME = 2; 317cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int MODE_SWITCH_START = 3; 327cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int FIRST_PREVIEW_FRAME = 5; 337cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static final int UNSET = -1; 347cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 357cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private static final String TAG = "CameraPerformanceTracker"; 367cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private static final boolean DEBUG = false; 377cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private static CameraPerformanceTracker sInstance; 387cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 397cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Internal tracking time. 407cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mAppStartTime = UNSET; 417cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mAppResumeTime = UNSET; 427cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mModeSwitchStartTime = UNSET; 437cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 447cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Duration and/or latency or later querying. 457cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mFirstPreviewFrameLatencyColdStart = UNSET; 467cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mFirstPreviewFrameLatencyWarmStart = UNSET; 477cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // TODO: Need to how to best track the duration for each switch from/to pair. 487cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private long mModeSwitchDuration = UNSET; 497cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 507cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu private CameraPerformanceTracker() { 517cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Private constructor to ensure that it can only be created from within 527cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // the class. 537cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 547cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 557cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu /** 567cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * This gets called when an important state change happens. Based on the type 577cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * of the event/state change, either we will record the time of the event, or 587cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * calculate the duration/latency. 597cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 607cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * @param eventType type of a event to track 617cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 627cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static void onEvent(int eventType) { 637cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance == null) { 647cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance = new CameraPerformanceTracker(); 657cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 667cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu long currentTime = System.currentTimeMillis(); 677cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu switch (eventType) { 687cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu case ACTIVITY_START: 697cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mAppStartTime = currentTime; 707cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 717cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu case ACTIVITY_PAUSE: 727cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mFirstPreviewFrameLatencyWarmStart = UNSET; 737cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 747cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu case ACTIVITY_RESUME: 757cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mAppResumeTime = currentTime; 767cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 777cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu case FIRST_PREVIEW_FRAME: 7854092780951fd84ffd98cc6ea3e54ad388e7db4cPuneet Lall Log.d(TAG, "First preview frame received"); 797cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance.mFirstPreviewFrameLatencyColdStart == UNSET) { 807cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Cold start. 817cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mFirstPreviewFrameLatencyColdStart = 827cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu currentTime - sInstance.mAppStartTime; 837cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } else { 847cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // Warm Start. 857cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mFirstPreviewFrameLatencyWarmStart = 867cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu currentTime - sInstance.mAppResumeTime; 877cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 887cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu // If the new frame is triggered by the mode switch, track the duration. 897cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance.mModeSwitchStartTime != UNSET) { 907cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mModeSwitchDuration = currentTime - sInstance.mModeSwitchStartTime; 917cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mModeSwitchStartTime = UNSET; 927cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 937cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 947cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu case MODE_SWITCH_START: 957cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu sInstance.mModeSwitchStartTime = currentTime; 967cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 977cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu default: 987cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu break; 997cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1005f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren if (DEBUG && eventType == FIRST_PREVIEW_FRAME) { 1015f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren Log.d(TAG, "Mode switch duration: " + (sInstance.mModeSwitchDuration 1025f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren == UNSET ? "UNSET" : sInstance.mModeSwitchDuration)); 1035f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren Log.d(TAG, "Cold start latency: " + (sInstance.mFirstPreviewFrameLatencyColdStart 1045f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren == UNSET ? "UNSET" : sInstance.mFirstPreviewFrameLatencyColdStart)); 1055f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren Log.d(TAG, "Warm start latency: " + (sInstance.mFirstPreviewFrameLatencyWarmStart 1065f38da866e2f0eb057662619ef8703ace40eb64cErin Dahlgren == UNSET ? "UNSET" : sInstance.mFirstPreviewFrameLatencyWarmStart)); 1077cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1087cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1097cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 1107cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu //TODO: Hook up these getters in the instrument tests. 1117cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu /** 1127cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Gets the latency of a cold start of the app, measured from the time onCreate 1137cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * gets called to the time first preview frame gets received. 1147cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 1157cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * @return latency of a cold start. If no instances have been created, return 1167cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * UNSET. 1177cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 1187cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static long getColdStartLatency() { 1197cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance == null) { 1207cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return UNSET; 1217cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1227cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return sInstance.mFirstPreviewFrameLatencyColdStart; 1237cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1247cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 1257cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu /** 1267cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Gets the latency of a warm start of the app, measured from the time onResume 1277cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * gets called to the time next preview frame gets received. 1287cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 1297cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * @return latency of a warm start. If no instances have been created, 1307cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * return UNSET. 1317cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 1327cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static long getWarmStartLatency() { 1337cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance == null) { 1347cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return UNSET; 1357cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1367cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return sInstance.mFirstPreviewFrameLatencyWarmStart; 1377cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1387cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu 1397cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu /** 1407cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * Gets the duration of the mode switch, measured from the start of a mode switch 1417cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * to the time next preview frame gets received. 1427cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * 1437cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * @return duration of the mode switch. If no instances have been created, 1447cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu * return UNSET. 1457cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu */ 1467cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu public static long getModeSwitchDuration() { 1477cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu if (sInstance == null) { 1487cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return UNSET; 1497cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1507cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu return sInstance.mModeSwitchDuration; 1517cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu } 1527cbeceed6d03d0550797c435f3db6205714cd49fDoris Liu} 153