CallTracker.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
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 pendingOperations;
42    protected boolean needsPoll;
43    protected Message lastRelevantPoll;
44
45    public CommandsInterface cm;
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        needsPoll = true;
68
69        if (checkNoOperationsPending()) {
70            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
71            cm.getCurrentCalls(lastRelevantPoll);
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        pendingOperations++;
107        lastRelevantPoll = 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                pendingOperations);
119        return pendingOperations == 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                    cm.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(" pendingOperations=" + pendingOperations);
178        pw.println(" needsPoll=" + needsPoll);
179        pw.println(" lastRelevantPoll=" + lastRelevantPoll);
180    }
181}
182