blob: ad3f49cb71e563cb12a7e882352b27650d874ffc [file] [log] [blame]
Alexandre Savard4a19d752012-09-19 13:19:24 -04001/*
2 * Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
3 *
Alexandre Savarda1404652012-09-20 13:34:08 -04004 * Author: Alexandre Savard <alexandre.savard@gmail.com>
Alexandre Savard4a19d752012-09-19 13:19:24 -04005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Additional permission under GNU GPL version 3 section 7:
21 *
22 * If you modify this program, or any covered work, by linking or
23 * combining it with the OpenSSL project's OpenSSL library (or a
24 * modified version of that library), containing parts covered by the
25 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26 * grants you additional permission to convey the resulting work.
27 * Corresponding Source for a non-source form of such a combination
28 * shall include the source code for the parts of OpenSSL used as well
29 * as that of the covered work.
30 */
alisionf76de3b2013-04-16 15:35:22 -040031package com.savoirfairelinux.sflphone.model;
Alexandre Savard4a19d752012-09-19 13:19:24 -040032
alisiona4325152013-04-19 11:10:03 -040033import java.util.ArrayList;
34
Alexandre Savard3bdce7b2012-10-24 18:27:45 -040035import android.content.Context;
36import android.content.Intent;
37import android.os.Bundle;
Alexandre Savard557a5742012-10-24 13:54:53 -040038import android.os.Parcel;
alisiona4325152013-04-19 11:10:03 -040039import android.os.Parcelable;
Alexandre Savard74c1cad2012-10-24 16:39:00 -040040import android.os.RemoteException;
Alexandre Savard4a19d752012-09-19 13:19:24 -040041import android.util.Log;
Alexandre Savardd1976532012-10-26 15:32:45 -040042import android.view.View;
Alexandre Savard4a19d752012-09-19 13:19:24 -040043
alisiona4325152013-04-19 11:10:03 -040044import com.savoirfairelinux.sflphone.adapters.CallElementAdapter.CallElementView;
Alexandre Savard4f42ade2012-10-24 18:03:31 -040045import com.savoirfairelinux.sflphone.client.CallActivity;
alisionf76de3b2013-04-16 15:35:22 -040046import com.savoirfairelinux.sflphone.client.SFLPhoneHomeActivity;
47import com.savoirfairelinux.sflphone.fragments.CallElementListFragment;
alisiona4325152013-04-19 11:10:03 -040048import com.savoirfairelinux.sflphone.service.ISipService;
Alexandre Savard74c1cad2012-10-24 16:39:00 -040049
Alexandre Savard557a5742012-10-24 13:54:53 -040050public class SipCall
Alexandre Savard4a19d752012-09-19 13:19:24 -040051{
52 final static String TAG = "SipCall";
Alexandre Savard7a46f542012-09-20 11:23:33 -040053 public CallInfo mCallInfo;
Alexandre Savarda949eec2012-10-25 17:30:49 -040054 // Update UI on actions (answer, hangup)
alisionf76de3b2013-04-16 15:35:22 -040055 static private CallElementListFragment mCallElementList = null;
56 static private SFLPhoneHomeActivity mHome = null;
Alexandre Savardd1976532012-10-26 15:32:45 -040057 private View mRowView = null;
Alexandre Savard7a46f542012-09-20 11:23:33 -040058
Alexandre Savard2f1ae542012-10-26 17:05:00 -040059 public static final int CALL_TYPE_UNDETERMINED = 0;
60 public static final int CALL_TYPE_INCOMING = 1;
61 public static final int CALL_TYPE_OUTGOING = 2;
62
Alexandre Savard27a51132012-10-25 18:35:14 -040063 public static final int CALL_STATE_NONE = 0;
Alexandre Savarddf544262012-10-25 14:24:08 -040064 public static final int CALL_STATE_INCOMING = 1;
65 public static final int CALL_STATE_RINGING = 2;
66 public static final int CALL_STATE_CURRENT = 3;
67 public static final int CALL_STATE_HUNGUP = 4;
68 public static final int CALL_STATE_BUSY = 5;
69 public static final int CALL_STATE_FAILURE = 6;
70 public static final int CALL_STATE_HOLD = 7;
71 public static final int CALL_STATE_UNHOLD = 8;
Alexandre Savard2b01c822012-09-20 15:00:37 -040072
Alexandre Savarddf544262012-10-25 14:24:08 -040073 public static final int MEDIA_STATE_NONE = 0; // No media currently
74 public static final int MEDIA_STATE_ACTIVE = 1; // Media is active
75 public static final int MEDIA_STATE_LOCAL_HOLD = 2; // Media is put on hold bu user
76 public static final int MEDIA_STATE_REMOTE_HOLD = 3; // Media is put on hold by peer
77 public static final int MEDIA_STATE_ERROR = 5; // Media is in error state
Alexandre Savard2b01c822012-09-20 15:00:37 -040078
Alexandre Savard557a5742012-10-24 13:54:53 -040079 public static class CallInfo implements Parcelable
Alexandre Savard7a46f542012-09-20 11:23:33 -040080 {
Alexandre Savard2b01c822012-09-20 15:00:37 -040081 public String mCallID = "";
Alexandre Savard73bc56f2012-10-25 13:35:54 -040082 public String mAccountID = "";
Alexandre Savard7a46f542012-09-20 11:23:33 -040083 public String mDisplayName = "";
84 public String mPhone = "";
85 public String mEmail = "";
Alexandre Savard2b01c822012-09-20 15:00:37 -040086 public String mRemoteContact = "";
Alexandre Savard2f1ae542012-10-26 17:05:00 -040087 public int mCallType = CALL_TYPE_UNDETERMINED;
Alexandre Savard27a51132012-10-25 18:35:14 -040088 public int mCallState = CALL_STATE_NONE;
Alexandre Savard557a5742012-10-24 13:54:53 -040089 public int mMediaState = MEDIA_STATE_NONE;
90
91 @Override
92 public int describeContents() {
93 return 0;
94 }
95
96 @Override
97 public void writeToParcel(Parcel out, int flags) {
98 ArrayList<String> list = new ArrayList<String>();
Alexandre Savard74c1cad2012-10-24 16:39:00 -040099
100 // Don't mess with this order!!!
Alexandre Savard557a5742012-10-24 13:54:53 -0400101 list.add(mCallID);
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400102 list.add(mAccountID);
Alexandre Savard557a5742012-10-24 13:54:53 -0400103 list.add(mDisplayName);
104 list.add(mPhone);
105 list.add(mEmail);
106 list.add(mRemoteContact);
107
108 out.writeStringList(list);
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400109 out.writeInt(mCallType);
Alexandre Savard557a5742012-10-24 13:54:53 -0400110 out.writeInt(mCallState);
111 out.writeInt(mMediaState);
112 }
113
114 public static final Parcelable.Creator<CallInfo> CREATOR
115 = new Parcelable.Creator<CallInfo>() {
116 public CallInfo createFromParcel(Parcel in) {
117 return new CallInfo(in);
118 }
119
120 public CallInfo[] newArray(int size) {
121 return new CallInfo[size];
122 }
123 };
124
125 public CallInfo() {}
126
127 private CallInfo(Parcel in) {
128 ArrayList<String> list = in.createStringArrayList();
Alexandre Savard74c1cad2012-10-24 16:39:00 -0400129
130 // Don't mess with this order!!!
Alexandre Savard557a5742012-10-24 13:54:53 -0400131 mCallID = list.get(0);
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400132 mAccountID = list.get(1);
133 mDisplayName = list.get(2);
134 mPhone = list.get(3);
135 mEmail = list.get(4);
136 mRemoteContact = list.get(5);
Alexandre Savard557a5742012-10-24 13:54:53 -0400137
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400138 mCallType = in.readInt();
Alexandre Savard557a5742012-10-24 13:54:53 -0400139 mCallState = in.readInt();
140 mMediaState = in.readInt();
141 }
Alexandre Savard7a46f542012-09-20 11:23:33 -0400142 }
Alexandre Savard4a19d752012-09-19 13:19:24 -0400143
144 public SipCall()
145 {
Alexandre Savard7a46f542012-09-20 11:23:33 -0400146 mCallInfo = new CallInfo();
Alexandre Savard4a19d752012-09-19 13:19:24 -0400147 }
148
Alexandre Savard7a46f542012-09-20 11:23:33 -0400149 public SipCall(CallInfo info)
Alexandre Savard4a19d752012-09-19 13:19:24 -0400150 {
Alexandre Savard7a46f542012-09-20 11:23:33 -0400151 mCallInfo = info;
Alexandre Savard4a19d752012-09-19 13:19:24 -0400152 }
153
alisionf76de3b2013-04-16 15:35:22 -0400154 public static void setCallElementList(CallElementListFragment list)
Alexandre Savarda1404652012-09-20 13:34:08 -0400155 {
156 mCallElementList = list;
157 }
158
alisionf76de3b2013-04-16 15:35:22 -0400159 public static void setSFLPhoneHomeContext(SFLPhoneHomeActivity home)
Alexandre Savarda949eec2012-10-25 17:30:49 -0400160 {
161 mHome = home;
162 }
163
Alexandre Savardd1976532012-10-26 15:32:45 -0400164 public void setAssociatedRowView(View view)
165 {
166 mRowView = view;
167 }
168
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400169 public void setCallID(String callID) {
170 mCallInfo.mCallID = callID;
171 }
172
173 public String getCallId() {
174 return mCallInfo.mCallID;
175 }
176
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400177 public void setAccountID(String accountID) {
178 mCallInfo.mAccountID = accountID;
179 }
180
181 public String getAccountID() {
182 return mCallInfo.mAccountID;
183 }
184
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400185 public void setDisplayName(String displayName) {
186 mCallInfo.mDisplayName = displayName;
187 }
188
189 public String getDisplayName() {
190 return mCallInfo.mDisplayName;
191 }
192
193 public void setPhone(String phone) {
194 mCallInfo.mPhone = phone;
195 }
196
197 public String getPhone() {
198 return mCallInfo.mPhone;
199 }
200
201 public void setEmail(String email) {
202 mCallInfo.mEmail = email;
203 }
204
205 public String getEmail() {
206 return mCallInfo.mEmail;
207 }
208
209 public void setRemoteContact(String remoteContact) {
210 mCallInfo.mRemoteContact = remoteContact;
211 }
212
213 public String getRemoteContact() {
214 return mCallInfo.mRemoteContact;
215 }
216
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400217 public void setCallType(int callType) {
218 mCallInfo.mCallType = callType;
219 }
220
221 public int getCallType() {
222 return mCallInfo.mCallType;
223 }
224
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400225 public void setCallState(int callState) {
226 mCallInfo.mCallState = callState;
Alexandre Savardde820072012-10-26 15:39:21 -0400227
228 // Check if this call is associated to a view in CallElementList
Alexandre Savardd1976532012-10-26 15:32:45 -0400229 if(mRowView == null)
230 return;
231
Alexandre Savardde820072012-10-26 15:39:21 -0400232 // Update the state to the view
Alexandre Savardd1976532012-10-26 15:32:45 -0400233 CallElementView entryView = (CallElementView) mRowView.getTag();
234 final String CURRENT_STATE_LABEL = " CURRENT STATE: ";
235 entryView.state.setText(CURRENT_STATE_LABEL + getCallStateString());
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400236 }
237
Alexandre Savarddf544262012-10-25 14:24:08 -0400238 public int getCallStateInt() {
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400239 return mCallInfo.mCallState;
240 }
241
Alexandre Savarddf544262012-10-25 14:24:08 -0400242 public String getCallStateString() {
243 String state;
244
245 switch(mCallInfo.mCallState) {
246 case CALL_STATE_INCOMING:
247 state = "INCOMING";
248 break;
249 case CALL_STATE_RINGING:
250 state = "RINGING";
251 break;
252 case CALL_STATE_CURRENT:
253 state = "CURRENT";
254 break;
255 case CALL_STATE_HUNGUP:
256 state = "HUNGUP";
257 break;
258 case CALL_STATE_BUSY:
259 state = "BUSY";
260 break;
261 case CALL_STATE_FAILURE:
262 state = "FAILURE";
263 break;
264 case CALL_STATE_HOLD:
265 state = "HOLD";
266 break;
267 case CALL_STATE_UNHOLD:
268 state = "UNHOLD";
269 break;
270 default:
271 state = "NULL";
272 }
273
274 return state;
275 }
276
277
Alexandre Savardc58c0fd2012-10-25 10:44:08 -0400278 public void setMediaState(int mediaState) {
279 mCallInfo.mMediaState = mediaState;
280 }
281
282 public int getMediaState() {
283 return mCallInfo.mMediaState;
284 }
285
Alexandre Savarda949eec2012-10-25 17:30:49 -0400286 public void placeCallUpdateUi()
287 {
288 if(mCallElementList != null)
289 mCallElementList.addCall(this);
290
291 if(mHome != null)
292 mHome.onSelectedCallAction(this);
293 }
294
Alexandre Savard27a51132012-10-25 18:35:14 -0400295
Alexandre Savarda949eec2012-10-25 17:30:49 -0400296 public void receiveCallUpdateUi()
Alexandre Savard23240c12012-09-19 18:23:44 -0400297 {
Alexandre Savard74c1cad2012-10-24 16:39:00 -0400298 if(mCallElementList != null)
299 mCallElementList.addCall(this);
Alexandre Savarda949eec2012-10-25 17:30:49 -0400300
301 if(mHome != null)
302 mHome.onSelectedCallAction(this);
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400303 }
304
Alexandre Savarda949eec2012-10-25 17:30:49 -0400305 public void answerUpdateUi()
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400306 {
Alexandre Savarda949eec2012-10-25 17:30:49 -0400307 if(mHome != null)
308 mHome.onSelectedCallAction(this);
Alexandre Savardf17e3172012-10-25 16:09:09 -0400309
310 }
Alexandre Savard4a19d752012-09-19 13:19:24 -0400311
Alexandre Savard08545ae2012-10-26 16:11:42 -0400312 public boolean notifyServiceAnswer(ISipService service)
Alexandre Savardf17e3172012-10-25 16:09:09 -0400313 {
Alexandre Savard27a51132012-10-25 18:35:14 -0400314 int callState = getCallStateInt();
315 if((callState != CALL_STATE_RINGING) &&
316 (callState != CALL_STATE_NONE)) {
Alexandre Savard08545ae2012-10-26 16:11:42 -0400317 return false;
Alexandre Savard27a51132012-10-25 18:35:14 -0400318 }
Alexandre Savardf17e3172012-10-25 16:09:09 -0400319
320 try {
321 service.accept(mCallInfo.mCallID);
322 } catch (RemoteException e) {
323 Log.e(TAG, "Cannot call service method", e);
324 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400325
326 return true;
Alexandre Savard4a19d752012-09-19 13:19:24 -0400327 }
328
Alexandre Savard4f42ade2012-10-24 18:03:31 -0400329 /**
330 * Perform hangup action without sending request to the service
Alexandre Savarda949eec2012-10-25 17:30:49 -0400331 * Used when SipService haved been notified that this call hung up
Alexandre Savard4f42ade2012-10-24 18:03:31 -0400332 */
Alexandre Savarda949eec2012-10-25 17:30:49 -0400333 public void hangupUpdateUi() {
Alexandre Savard74c1cad2012-10-24 16:39:00 -0400334 Log.i(TAG, "Hangup call " + mCallInfo.mCallID);
335
336 if(mCallElementList != null)
337 mCallElementList.removeCall(this);
Alexandre Savarda949eec2012-10-25 17:30:49 -0400338
339 if(mHome != null)
340 mHome.onUnselectedCallAction();
Alexandre Savard4f42ade2012-10-24 18:03:31 -0400341 }
342
343 /**
344 * Perform hangup action and send request to the service
345 */
Alexandre Savard08545ae2012-10-26 16:11:42 -0400346 public boolean notifyServiceHangup(ISipService service)
Alexandre Savard4f42ade2012-10-24 18:03:31 -0400347 {
Alexandre Savard74c1cad2012-10-24 16:39:00 -0400348 try {
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400349 if((getCallStateInt() == CALL_STATE_NONE) ||
350 (getCallStateInt() == CALL_STATE_CURRENT) ||
351 (getCallStateInt() == CALL_STATE_HOLD)) {
Alexandre Savard08545ae2012-10-26 16:11:42 -0400352 service.hangUp(mCallInfo.mCallID);
353 return true;
354
355 }
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400356 else if(getCallStateInt() == CALL_STATE_RINGING) {
357 if(getCallType() == CALL_TYPE_INCOMING) {
358 service.refuse(mCallInfo.mCallID);
359 return true;
360 }
361 else if(getCallType() == CALL_TYPE_OUTGOING) {
362 service.hangUp(mCallInfo.mCallID);
363 return true;
364 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400365 }
Alexandre Savard74c1cad2012-10-24 16:39:00 -0400366 } catch (RemoteException e) {
367 Log.e(TAG, "Cannot call service method", e);
368 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400369
370 return false;
Alexandre Savard4a19d752012-09-19 13:19:24 -0400371 }
Alexandre Savardaef9d802012-09-20 17:31:32 -0400372
Alexandre Savard08545ae2012-10-26 16:11:42 -0400373 public boolean notifyServiceRefuse(ISipService service)
Alexandre Savard83869852012-10-26 09:14:12 -0400374 {
375 try {
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400376 if(getCallStateInt() == CALL_STATE_RINGING) {
Alexandre Savard08545ae2012-10-26 16:11:42 -0400377 service.refuse(mCallInfo.mCallID);
378 return true;
379 }
Alexandre Savard83869852012-10-26 09:14:12 -0400380 } catch (RemoteException e) {
381 Log.e(TAG, "Cannot call service method", e);
382 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400383
384 return false;
Alexandre Savard83869852012-10-26 09:14:12 -0400385 }
386
Alexandre Savard08545ae2012-10-26 16:11:42 -0400387 public boolean notifyServiceHold(ISipService service)
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400388 {
389 try {
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400390 if(getCallStateInt() == CALL_STATE_CURRENT) {
Alexandre Savard08545ae2012-10-26 16:11:42 -0400391 service.hold(mCallInfo.mCallID);
392 return true;
393 }
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400394 } catch (RemoteException e) {
395 Log.e(TAG, "Cannot call service method", e);
396 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400397
398 return false;
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400399 }
400
Alexandre Savard08545ae2012-10-26 16:11:42 -0400401 public boolean notifyServiceUnhold(ISipService service)
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400402 {
403 try {
Alexandre Savard2f1ae542012-10-26 17:05:00 -0400404 if(getCallStateInt() == CALL_STATE_HOLD) {
Alexandre Savard08545ae2012-10-26 16:11:42 -0400405 service.unhold(mCallInfo.mCallID);
406 return true;
407 }
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400408 } catch (RemoteException e) {
409 Log.e(TAG, "Cannot call service method", e);
410 }
Alexandre Savard08545ae2012-10-26 16:11:42 -0400411
412 return false;
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400413 }
Alexandre Savard83869852012-10-26 09:14:12 -0400414
Alexandre Savardaef9d802012-09-20 17:31:32 -0400415 public void addToConference()
416 {
417 Log.i(TAG, "Add call to conference");
418 }
419
420 public void sendTextMessage()
421 {
422 Log.i(TAG, "Send text message");
423 }
Alexandre Savard3bdce7b2012-10-24 18:27:45 -0400424
Alexandre Savard73bc56f2012-10-25 13:35:54 -0400425 public void printCallInfo()
426 {
427 Log.i(TAG, "CallInfo: CallID: " + mCallInfo.mCallID);
428 Log.i(TAG, " AccountID: " + mCallInfo.mAccountID);
429 Log.i(TAG, " Display Name: " + mCallInfo.mDisplayName);
430 Log.i(TAG, " Phone: " + mCallInfo.mPhone);
431 Log.i(TAG, " Email: " + mCallInfo.mEmail);
432 Log.i(TAG, " Contact: " + mCallInfo.mRemoteContact);
433 }
434
Alexandre Savard3bdce7b2012-10-24 18:27:45 -0400435 public void launchCallActivity(Context context)
436 {
437 Log.i(TAG, "Launch Call Activity");
438 Bundle bundle = new Bundle();
439 bundle.putParcelable("CallInfo", mCallInfo);
440 Intent intent = new Intent().setClass(context, CallActivity.class);
441 intent.putExtras(bundle);
442 context.startActivity(intent);
443 }
alision5f899632013-04-22 17:26:56 -0400444
445 /**
446 * Compare sip calls based on call ID
447 */
448 @Override
449 public boolean equals(Object c){
450 if(c instanceof SipCall && ((SipCall) c).mCallInfo.mCallID == mCallInfo.mCallID){
451 return true;
452 }
453 return false;
454
455 }
Alexandre Savard4a19d752012-09-19 13:19:24 -0400456}