1b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/* 2b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 3b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 4b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * you may not use this file except in compliance with the License. 6b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * You may obtain a copy of the License at 7b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 8b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 10b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * See the License for the specific language governing permissions and 14b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * limitations under the License. 15b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 16b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 17b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpackage com.android.phone; 18b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 19b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Debug; 21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 22b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.SystemClock; 23b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Call; 24b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Connection; 25b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.io.File; 28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.List; 29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Helper class used to keep track of various "elapsed time" indications 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * in the Phone app, and also to start and stop tracing / profiling. 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class CallTime extends Handler { 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String LOG_TAG = "PHONE/CallTime"; 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean DBG = false; 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static final boolean PROFILE = true; 38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int PROFILE_STATE_NONE = 0; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int PROFILE_STATE_READY = 1; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int PROFILE_STATE_RUNNING = 2; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static int sProfileState = PROFILE_STATE_NONE; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mCall; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long mLastReportedTime; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mTimerRunning; 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long mInterval; 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private PeriodicTimerCallback mTimerCallback; 50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private OnTickListener mListener; 51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 52b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project interface OnTickListener { 53b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project void onTickForCallTimeElapsed(long timeElapsed); 54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 55b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public CallTime(OnTickListener listener) { 57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mListener = listener; 58b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mTimerCallback = new PeriodicTimerCallback(); 59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 60b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 61b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 62b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Sets the call timer to "active call" mode, where the timer will 63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * periodically update the UI to show how long the specified call 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * has been active. 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * After calling this you should also call reset() and 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * periodicUpdateTimer() to get the timer started. 68b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 69b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void setActiveCallMode(Call call) { 70b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("setActiveCallMode(" + call + ")..."); 71b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCall = call; 72b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 73b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // How frequently should we update the UI? 74b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mInterval = 1000; // once per second 75b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void reset() { 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("reset()..."); 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLastReportedTime = SystemClock.uptimeMillis() - mInterval; 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void periodicUpdateTimer() { 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mTimerRunning) { 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mTimerRunning = true; 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long now = SystemClock.uptimeMillis(); 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long nextReport = mLastReportedTime + mInterval; 88b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 89b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (now >= nextReport) { 90b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project nextReport += mInterval; 91b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("periodicUpdateTimer() @ " + nextReport); 94b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project postAtTime(mTimerCallback, nextReport); 95b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLastReportedTime = nextReport; 96b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 97b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCall != null) { 98b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call.State state = mCall.getState(); 99b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (state == Call.State.ACTIVE) { 101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateElapsedTime(mCall); 102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (PROFILE && isTraceReady()) { 106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project startTrace(); 107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("periodicUpdateTimer: timer already running, bail"); 110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void cancelTimer() { 114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("cancelTimer()..."); 115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project removeCallbacks(mTimerCallback); 116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mTimerRunning = false; 117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void updateElapsedTime(Call call) { 120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mListener != null) { 121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long duration = getCallDuration(call); 122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mListener.onTickForCallTimeElapsed(duration / 1000); 123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns a "call duration" value for the specified Call, in msec, 128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * suitable for display in the UI. 129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static long getCallDuration(Call call) { 131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long duration = 0; 132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project List connections = call.getConnections(); 133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int count = connections.size(); 134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection c; 135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (count == 1) { 137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = (Connection) connections.get(0); 138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //duration = (state == Call.State.ACTIVE 139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ? c.getDurationMillis() : c.getHoldDurationMillis()); 140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project duration = c.getDurationMillis(); 141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < count; i++) { 143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = (Connection) connections.get(i); 144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //long t = (state == Call.State.ACTIVE 145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ? c.getDurationMillis() : c.getHoldDurationMillis()); 146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long t = c.getDurationMillis(); 147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (t > duration) { 148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project duration = t; 149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("updateElapsedTime, count=" + count + ", duration=" + duration); 154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return duration; 155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.d(LOG_TAG, "[CallTime] " + msg); 159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class PeriodicTimerCallback implements Runnable { 162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PeriodicTimerCallback() { 163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void run() { 167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (PROFILE && isTraceRunning()) { 168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stopTrace(); 169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mTimerRunning = false; 172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project periodicUpdateTimer(); 173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void setTraceReady() { 177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sProfileState == PROFILE_STATE_NONE) { 178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sProfileState = PROFILE_STATE_READY; 179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project log("trace ready..."); 180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project log("current trace state = " + sProfileState); 182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean isTraceReady() { 186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sProfileState == PROFILE_STATE_READY; 187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean isTraceRunning() { 190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sProfileState == PROFILE_STATE_RUNNING; 191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project void startTrace() { 194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (PROFILE & sProfileState == PROFILE_STATE_READY) { 195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // For now, we move away from temp directory in favor of 196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the application's data directory to store the trace 197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // information (/data/data/com.android.phone). 198a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn File file = PhoneGlobals.getInstance().getDir ("phoneTrace", Context.MODE_PRIVATE); 199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (file.exists() == false) { 200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project file.mkdirs(); 201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String baseName = file.getPath() + File.separator + "callstate"; 203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String dataFile = baseName + ".data"; 204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String keyFile = baseName + ".key"; 205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project file = new File(dataFile); 207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (file.exists() == true) { 208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project file.delete(); 209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project file = new File(keyFile); 212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (file.exists() == true) { 213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project file.delete(); 214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sProfileState = PROFILE_STATE_RUNNING; 217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project log("startTrace"); 218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Debug.startMethodTracing(baseName, 8 * 1024 * 1024); 219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project void stopTrace() { 223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (PROFILE) { 224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sProfileState == PROFILE_STATE_RUNNING) { 225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sProfileState = PROFILE_STATE_NONE; 226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project log("stopTrace"); 227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Debug.stopMethodTracing(); 228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 232