1 /* 2 * Copyright (C) 2006 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.internal.telephony; 18 19 import android.os.AsyncResult; 20 import android.os.Handler; 21 import android.os.Message; 22 import android.os.SystemProperties; 23 import android.text.TextUtils; 24 import com.android.internal.telephony.CommandException; 25 26 import java.io.FileDescriptor; 27 import java.io.PrintWriter; 28 29 30 /** 31 * {@hide} 32 */ 33 public abstract class CallTracker extends Handler { 34 35 private static final boolean DBG_POLL = false; 36 37 //***** Constants 38 39 static final int POLL_DELAY_MSEC = 250; 40 41 protected int mPendingOperations; 42 protected boolean mNeedsPoll; 43 protected Message mLastRelevantPoll; 44 45 public CommandsInterface mCi; 46 47 48 //***** Events 49 50 protected static final int EVENT_POLL_CALLS_RESULT = 1; 51 protected static final int EVENT_CALL_STATE_CHANGE = 2; 52 protected static final int EVENT_REPOLL_AFTER_DELAY = 3; 53 protected static final int EVENT_OPERATION_COMPLETE = 4; 54 protected static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5; 55 56 protected static final int EVENT_SWITCH_RESULT = 8; 57 protected static final int EVENT_RADIO_AVAILABLE = 9; 58 protected static final int EVENT_RADIO_NOT_AVAILABLE = 10; 59 protected static final int EVENT_CONFERENCE_RESULT = 11; 60 protected static final int EVENT_SEPARATE_RESULT = 12; 61 protected static final int EVENT_ECT_RESULT = 13; 62 protected static final int EVENT_EXIT_ECM_RESPONSE_CDMA = 14; 63 protected static final int EVENT_CALL_WAITING_INFO_CDMA = 15; 64 protected static final int EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA = 16; 65 66 protected void pollCallsWhenSafe() { 67 mNeedsPoll = true; 68 69 if (checkNoOperationsPending()) { 70 mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); 71 mCi.getCurrentCalls(mLastRelevantPoll); 72 } 73 } 74 75 protected void 76 pollCallsAfterDelay() { 77 Message msg = obtainMessage(); 78 79 msg.what = EVENT_REPOLL_AFTER_DELAY; 80 sendMessageDelayed(msg, POLL_DELAY_MSEC); 81 } 82 83 protected boolean 84 isCommandExceptionRadioNotAvailable(Throwable e) { 85 return e != null && e instanceof CommandException 86 && ((CommandException)e).getCommandError() 87 == CommandException.Error.RADIO_NOT_AVAILABLE; 88 } 89 90 protected abstract void handlePollCalls(AsyncResult ar); 91 92 protected void handleRadioAvailable() { 93 pollCallsWhenSafe(); 94 } 95 96 /** 97 * Obtain a complete message that indicates that this operation 98 * does not require polling of getCurrentCalls(). However, if other 99 * operations that do need getCurrentCalls() are pending or are 100 * scheduled while this operation is pending, the invocation 101 * of getCurrentCalls() will be postponed until this 102 * operation is also complete. 103 */ 104 protected Message 105 obtainNoPollCompleteMessage(int what) { 106 mPendingOperations++; 107 mLastRelevantPoll = null; 108 return obtainMessage(what); 109 } 110 111 /** 112 * @return true if we're idle or there's a call to getCurrentCalls() pending 113 * but nothing else 114 */ 115 private boolean 116 checkNoOperationsPending() { 117 if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" + 118 mPendingOperations); 119 return mPendingOperations == 0; 120 } 121 122 /** 123 * Routine called from dial to check if the number is a test Emergency number 124 * and if so remap the number. This allows a short emergency number to be remapped 125 * to a regular number for testing how the frameworks handles emergency numbers 126 * without actually calling an emergency number. 127 * 128 * This is not a full test and is not a substitute for testing real emergency 129 * numbers but can be useful. 130 * 131 * To use this feature set a system property ril.test.emergencynumber to a pair of 132 * numbers separated by a colon. If the first number matches the number parameter 133 * this routine returns the second number. Example: 134 * 135 * ril.test.emergencynumber=112:1-123-123-45678 136 * 137 * To test Dial 112 take call then hang up on MO device to enter ECM 138 * see RIL#processSolicited RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND 139 * 140 * @param dialString to test if it should be remapped 141 * @return the same number or the remapped number. 142 */ 143 protected String checkForTestEmergencyNumber(String dialString) { 144 String testEn = SystemProperties.get("ril.test.emergencynumber"); 145 if (DBG_POLL) { 146 log("checkForTestEmergencyNumber: dialString=" + dialString + 147 " testEn=" + testEn); 148 } 149 if (!TextUtils.isEmpty(testEn)) { 150 String values[] = testEn.split(":"); 151 log("checkForTestEmergencyNumber: values.length=" + values.length); 152 if (values.length == 2) { 153 if (values[0].equals( 154 android.telephony.PhoneNumberUtils.stripSeparators(dialString))) { 155 mCi.testingEmergencyCall(); 156 log("checkForTestEmergencyNumber: remap " + 157 dialString + " to " + values[1]); 158 dialString = values[1]; 159 } 160 } 161 } 162 return dialString; 163 } 164 165 //***** Overridden from Handler 166 @Override 167 public abstract void handleMessage (Message msg); 168 public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj); 169 public abstract void unregisterForVoiceCallStarted(Handler h); 170 public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj); 171 public abstract void unregisterForVoiceCallEnded(Handler h); 172 173 protected abstract void log(String msg); 174 175 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 176 pw.println("CallTracker:"); 177 pw.println(" mPendingOperations=" + mPendingOperations); 178 pw.println(" mNeedsPoll=" + mNeedsPoll); 179 pw.println(" mLastRelevantPoll=" + mLastRelevantPoll); 180 } 181 } 182