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.gsm;
18
19import com.android.internal.telephony.Call;
20import com.android.internal.telephony.CallStateException;
21import com.android.internal.telephony.Connection;
22import com.android.internal.telephony.DriverCall;
23import com.android.internal.telephony.Phone;
24
25import java.util.ArrayList;
26import java.util.List;
27
28/**
29 * {@hide}
30 */
31class GsmCall extends Call {
32    /*************************** Instance Variables **************************/
33
34    /*package*/ ArrayList<Connection> connections = new ArrayList<Connection>();
35    /*package*/ GsmCallTracker owner;
36
37
38    /***************************** Class Methods *****************************/
39
40    static State
41    stateFromDCState (DriverCall.State dcState) {
42        switch (dcState) {
43            case ACTIVE:        return State.ACTIVE;
44            case HOLDING:       return State.HOLDING;
45            case DIALING:       return State.DIALING;
46            case ALERTING:      return State.ALERTING;
47            case INCOMING:      return State.INCOMING;
48            case WAITING:       return State.WAITING;
49            default:            throw new RuntimeException ("illegal call state:" + dcState);
50        }
51    }
52
53
54    /****************************** Constructors *****************************/
55    /*package*/
56    GsmCall (GsmCallTracker owner) {
57        this.owner = owner;
58    }
59
60    public void dispose() {
61    }
62
63    /************************** Overridden from Call *************************/
64
65    public List<Connection>
66    getConnections() {
67        // FIXME should return Collections.unmodifiableList();
68        return connections;
69    }
70
71    public Phone
72    getPhone() {
73        return owner.phone;
74    }
75
76    public boolean
77    isMultiparty() {
78        return connections.size() > 1;
79    }
80
81    /** Please note: if this is the foreground call and a
82     *  background call exists, the background call will be resumed
83     *  because an AT+CHLD=1 will be sent
84     */
85    public void
86    hangup() throws CallStateException {
87        owner.hangup(this);
88    }
89
90    public String
91    toString() {
92        return state.toString();
93    }
94
95    //***** Called from GsmConnection
96
97    /*package*/ void
98    attach(Connection conn, DriverCall dc) {
99        connections.add(conn);
100
101        state = stateFromDCState (dc.state);
102    }
103
104    /*package*/ void
105    attachFake(Connection conn, State state) {
106        connections.add(conn);
107
108        this.state = state;
109    }
110
111    /**
112     * Called by GsmConnection when it has disconnected
113     */
114    void
115    connectionDisconnected(GsmConnection conn) {
116        if (state != State.DISCONNECTED) {
117            /* If only disconnected connections remain, we are disconnected*/
118
119            boolean hasOnlyDisconnectedConnections = true;
120
121            for (int i = 0, s = connections.size()  ; i < s; i ++) {
122                if (connections.get(i).getState()
123                    != State.DISCONNECTED
124                ) {
125                    hasOnlyDisconnectedConnections = false;
126                    break;
127                }
128            }
129
130            if (hasOnlyDisconnectedConnections) {
131                state = State.DISCONNECTED;
132            }
133        }
134    }
135
136
137    /*package*/ void
138    detach(GsmConnection conn) {
139        connections.remove(conn);
140
141        if (connections.size() == 0) {
142            state = State.IDLE;
143        }
144    }
145
146    /*package*/ boolean
147    update (GsmConnection conn, DriverCall dc) {
148        State newState;
149        boolean changed = false;
150
151        newState = stateFromDCState(dc.state);
152
153        if (newState != state) {
154            state = newState;
155            changed = true;
156        }
157
158        return changed;
159    }
160
161    /**
162     * @return true if there's no space in this call for additional
163     * connections to be added via "conference"
164     */
165    /*package*/ boolean
166    isFull() {
167        return connections.size() == GsmCallTracker.MAX_CONNECTIONS_PER_CALL;
168    }
169
170    //***** Called from GsmCallTracker
171
172
173    /**
174     * Called when this Call is being hung up locally (eg, user pressed "end")
175     * Note that at this point, the hangup request has been dispatched to the radio
176     * but no response has yet been received so update() has not yet been called
177     */
178    void
179    onHangupLocal() {
180        for (int i = 0, s = connections.size()
181                ; i < s; i++
182        ) {
183            GsmConnection cn = (GsmConnection)connections.get(i);
184
185            cn.onHangupLocal();
186        }
187        state = State.DISCONNECTING;
188    }
189
190    /**
191     * Called when it's time to clean up disconnected Connection objects
192     */
193    void
194    clearDisconnected() {
195        for (int i = connections.size() - 1 ; i >= 0 ; i--) {
196            GsmConnection cn = (GsmConnection)connections.get(i);
197
198            if (cn.getState() == State.DISCONNECTED) {
199                connections.remove(i);
200            }
201        }
202
203        if (connections.size() == 0) {
204            state = State.IDLE;
205        }
206    }
207}
208
209