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