CallTracker.java revision befe0bf21cf06c47b1f099caed9e6c6b7125c0fe
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
17package com.android.internal.telephony;
18
19import android.os.AsyncResult;
20import android.os.Handler;
21import android.os.Message;
22import android.os.SystemProperties;
23import android.text.TextUtils;
24import com.android.internal.telephony.CommandException;
25
26import java.io.FileDescriptor;
27import java.io.PrintWriter;
28
29
30/**
31 * {@hide}
32 */
33public 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    protected Connection mHandoverConnection;
45
46    public CommandsInterface mCi;
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 notifySrvccState(Call.SrvccState state, Connection c) {
93        if (state == Call.SrvccState.STARTED) {
94            mHandoverConnection = c;
95        } else if (state != Call.SrvccState.COMPLETED) {
96            mHandoverConnection = null;
97        }
98    }
99
100    protected void handleRadioAvailable() {
101        pollCallsWhenSafe();
102    }
103
104    /**
105     * Obtain a complete message that indicates that this operation
106     * does not require polling of getCurrentCalls(). However, if other
107     * operations that do need getCurrentCalls() are pending or are
108     * scheduled while this operation is pending, the invocation
109     * of getCurrentCalls() will be postponed until this
110     * operation is also complete.
111     */
112    protected Message
113    obtainNoPollCompleteMessage(int what) {
114        mPendingOperations++;
115        mLastRelevantPoll = null;
116        return obtainMessage(what);
117    }
118
119    /**
120     * @return true if we're idle or there's a call to getCurrentCalls() pending
121     * but nothing else
122     */
123    private boolean
124    checkNoOperationsPending() {
125        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
126                mPendingOperations);
127        return mPendingOperations == 0;
128    }
129
130    /**
131     * Routine called from dial to check if the number is a test Emergency number
132     * and if so remap the number. This allows a short emergency number to be remapped
133     * to a regular number for testing how the frameworks handles emergency numbers
134     * without actually calling an emergency number.
135     *
136     * This is not a full test and is not a substitute for testing real emergency
137     * numbers but can be useful.
138     *
139     * To use this feature set a system property ril.test.emergencynumber to a pair of
140     * numbers separated by a colon. If the first number matches the number parameter
141     * this routine returns the second number. Example:
142     *
143     * ril.test.emergencynumber=112:1-123-123-45678
144     *
145     * To test Dial 112 take call then hang up on MO device to enter ECM
146     * see RIL#processSolicited RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND
147     *
148     * @param dialString to test if it should be remapped
149     * @return the same number or the remapped number.
150     */
151    protected String checkForTestEmergencyNumber(String dialString) {
152        String testEn = SystemProperties.get("ril.test.emergencynumber");
153        if (DBG_POLL) {
154            log("checkForTestEmergencyNumber: dialString=" + dialString +
155                " testEn=" + testEn);
156        }
157        if (!TextUtils.isEmpty(testEn)) {
158            String values[] = testEn.split(":");
159            log("checkForTestEmergencyNumber: values.length=" + values.length);
160            if (values.length == 2) {
161                if (values[0].equals(
162                        android.telephony.PhoneNumberUtils.stripSeparators(dialString))) {
163                    mCi.testingEmergencyCall();
164                    log("checkForTestEmergencyNumber: remap " +
165                            dialString + " to " + values[1]);
166                    dialString = values[1];
167                }
168            }
169        }
170        return dialString;
171    }
172
173    //***** Overridden from Handler
174    @Override
175    public abstract void handleMessage (Message msg);
176    public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj);
177    public abstract void unregisterForVoiceCallStarted(Handler h);
178    public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj);
179    public abstract void unregisterForVoiceCallEnded(Handler h);
180
181    protected abstract void log(String msg);
182
183    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
184        pw.println("CallTracker:");
185        pw.println(" mPendingOperations=" + mPendingOperations);
186        pw.println(" mNeedsPoll=" + mNeedsPoll);
187        pw.println(" mLastRelevantPoll=" + mLastRelevantPoll);
188    }
189}
190