blob: 7bc169610509afad125394db160fdf7a63014129 [file] [log] [blame]
Emeric Vigier6119d782012-09-21 18:04:14 -04001/**
2 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
alisionb1763882013-06-18 17:30:51 -04003 * Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
Emeric Vigier6119d782012-09-21 18:04:14 -04004 *
5 * Author: Regis Montoya <r3gis.3R@gmail.com>
6 * Author: Emeric Vigier <emeric.vigier@savoirfairelinux.com>
alision11e8e162013-05-28 10:33:14 -04007 * Alexandre Lision <alexandre.lision@savoirfairelinux.com>
Emeric Vigier6119d782012-09-21 18:04:14 -04008 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 * If you own a pjsip commercial license you can also redistribute it
14 * and/or modify it under the terms of the GNU Lesser General Public License
15 * as an android library.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 */
Emeric Vigiereaf2c492012-09-19 14:38:20 -040025package com.savoirfairelinux.sflphone.service;
26
Emeric Vigier6119d782012-09-21 18:04:14 -040027import java.lang.ref.WeakReference;
alision17052d42013-04-22 10:39:38 -040028import java.util.ArrayList;
29import java.util.HashMap;
alisioncc7bb422013-06-06 15:31:39 -040030import java.util.Iterator;
alision7f18fc82013-05-01 09:37:33 -040031import java.util.List;
alision17052d42013-04-22 10:39:38 -040032import java.util.Map;
alision2cb99562013-05-30 17:02:20 -040033import java.util.Random;
Emeric Vigier6119d782012-09-21 18:04:14 -040034
alision2cb99562013-05-30 17:02:20 -040035import android.app.Notification;
36import android.app.NotificationManager;
37import android.app.PendingIntent;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040038import android.app.Service;
alision17052d42013-04-22 10:39:38 -040039import android.content.Context;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040040import android.content.Intent;
alision17052d42013-04-22 10:39:38 -040041import android.content.IntentFilter;
alision7f18fc82013-05-01 09:37:33 -040042import android.os.Bundle;
Emeric Vigier6119d782012-09-21 18:04:14 -040043import android.os.Handler;
44import android.os.HandlerThread;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040045import android.os.IBinder;
Emeric Vigier6119d782012-09-21 18:04:14 -040046import android.os.Looper;
47import android.os.Message;
alision5f899632013-04-22 17:26:56 -040048import android.os.RemoteException;
alision2cb99562013-05-30 17:02:20 -040049import android.support.v4.app.NotificationCompat;
alision17052d42013-04-22 10:39:38 -040050import android.support.v4.content.LocalBroadcastManager;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040051import android.util.Log;
52import android.widget.Toast;
53
alision2cb99562013-05-30 17:02:20 -040054import com.savoirfairelinux.sflphone.R;
alisionf76de3b2013-04-16 15:35:22 -040055import com.savoirfairelinux.sflphone.account.AccountDetailsHandler;
alisiond295ec22013-05-17 10:12:13 -040056import com.savoirfairelinux.sflphone.account.AudioHandler;
alisione2a38e12013-04-25 14:20:20 -040057import com.savoirfairelinux.sflphone.account.HistoryHandler;
alision2cb99562013-05-30 17:02:20 -040058import com.savoirfairelinux.sflphone.client.SFLPhoneHomeActivity;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040059import com.savoirfairelinux.sflphone.client.SFLphoneApplication;
alisionfde875f2013-05-28 17:01:54 -040060import com.savoirfairelinux.sflphone.model.SipCall;
alisioncc7bb422013-06-06 15:31:39 -040061import com.savoirfairelinux.sflphone.receivers.IncomingReceiver;
Alexandre Savard713a34d2012-09-26 15:50:41 -040062
Emeric Vigiereaf2c492012-09-19 14:38:20 -040063public class SipService extends Service {
64
65 static final String TAG = "SipService";
66 static final int DELAY = 5000; /* 5 sec */
67 private boolean runFlag = false;
68 private SipServiceThread sipServiceThread;
Emeric Vigier84e05da2012-09-20 14:53:05 -040069 private SFLphoneApplication sflphoneApp;
Emeric Vigier6119d782012-09-21 18:04:14 -040070 private SipServiceExecutor mExecutor;
71 private static HandlerThread executorThread;
72 private CallManagerJNI callManagerJNI;
Emeric Vigier0007dee2012-09-24 11:35:58 -040073 private CallManagerCallBack callManagerCallBack;
Alexandre Savardc1b08fe2012-09-25 16:24:47 -040074 private ConfigurationManagerJNI configurationManagerJNI;
Alexandre Savardfccd1dc2012-10-17 17:31:38 -040075 private ConfigurationManagerCallback configurationManagerCallback;
Emeric Vigier0007dee2012-09-24 11:35:58 -040076 private ManagerImpl managerImpl;
Emeric Vigier6119d782012-09-21 18:04:14 -040077 private boolean isPjSipStackStarted = false;
alisioncc7bb422013-06-06 15:31:39 -040078
alision2cb99562013-05-30 17:02:20 -040079 public static final String NOTIF_CREATION = "notif_creation";
80 public static final String NOTIF_DELETION = "notif_deletion";
alision04a00182013-05-10 17:05:29 -040081
alision2cb99562013-05-30 17:02:20 -040082 private HashMap<String, SipCall> current_calls = new HashMap<String, SipCall>();
Emeric Vigier6119d782012-09-21 18:04:14 -040083
alision2cb99562013-05-30 17:02:20 -040084 private IncomingReceiver receiver = new IncomingReceiver(this);
alision43a9b362013-05-01 16:30:15 -040085
86 @Override
87 public boolean onUnbind(Intent i) {
88 super.onUnbind(i);
89 Log.i(TAG, "onUnbind(intent)");
90 return false;
91
92 }
93
94 /* called once by startService() */
95 @Override
96 public void onCreate() {
97 Log.i(TAG, "onCreated");
98 super.onCreate();
99
100 sflphoneApp = (SFLphoneApplication) getApplication();
101 sipServiceThread = new SipServiceThread();
102
103 IntentFilter callFilter = new IntentFilter(CallManagerCallBack.CALL_STATE_CHANGED);
104 callFilter.addAction(CallManagerCallBack.INCOMING_CALL);
105 callFilter.addAction(CallManagerCallBack.NEW_CALL_CREATED);
alision4a0eb092013-05-07 13:52:03 -0400106 callFilter.addAction(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED);
107 callFilter.addAction(ConfigurationManagerCallback.ACCOUNTS_CHANGED);
alision04a00182013-05-10 17:05:29 -0400108 callFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
109
alision2cb99562013-05-30 17:02:20 -0400110 LocalBroadcastManager.getInstance(this).registerReceiver(receiver, callFilter);
alision2cb99562013-05-30 17:02:20 -0400111
alisioncc7bb422013-06-06 15:31:39 -0400112 getExecutor().execute(new StartRunnable());
113
114 }
alision43a9b362013-05-01 16:30:15 -0400115
116 /* called for each startService() */
117 @Override
118 public int onStartCommand(Intent intent, int flags, int startId) {
119 Log.i(TAG, "onStarted");
120 super.onStartCommand(intent, flags, startId);
121
122 if (!runFlag) {
123 sipServiceThread.start();
124 runFlag = true;
125 sflphoneApp.setServiceRunning(true);
126 Toast.makeText(this, "Sflphone Service started", Toast.LENGTH_SHORT).show();
127 }
128
129 return START_STICKY; /* started and stopped explicitly */
130 }
131
132 @Override
133 public void onDestroy() {
134 /* called once by stopService() */
135 sipServiceThread.interrupt();
136 sipServiceThread = null;
137 runFlag = false;
alision2cb99562013-05-30 17:02:20 -0400138 unregisterReceiver(receiver);
139
alision43a9b362013-05-01 16:30:15 -0400140 sflphoneApp.setServiceRunning(false);
141 Toast.makeText(this, "Sflphone Service stopped", Toast.LENGTH_SHORT).show();
142 super.onDestroy();
143
144 Log.i(TAG, "onDestroyed");
145 }
146
147 @Override
148 public IBinder onBind(Intent arg0) {
149 Log.i(TAG, "onBound");
150 return mBinder;
151 }
152
153 private static Looper createLooper() {
154 if (executorThread == null) {
155 Log.d(TAG, "Creating new handler thread");
156 // ADT gives a fake warning due to bad parse rule.
157 executorThread = new HandlerThread("SipService.Executor");
158 executorThread.start();
159 }
160 return executorThread.getLooper();
161 }
162
163 public SipServiceExecutor getExecutor() {
164 // create mExecutor lazily
165 if (mExecutor == null) {
166 mExecutor = new SipServiceExecutor(this);
167 }
168 return mExecutor;
169 }
170
171 // Executes immediate tasks in a single executorThread.
172 public static class SipServiceExecutor extends Handler {
173 WeakReference<SipService> handlerService;
174
175 SipServiceExecutor(SipService s) {
176 super(createLooper());
177 handlerService = new WeakReference<SipService>(s);
178 }
179
180 public void execute(Runnable task) {
181 // TODO: add wakelock
182 Message.obtain(this, 0/* don't care */, task).sendToTarget();
183 }
184
185 @Override
186 public void handleMessage(Message msg) {
187 if (msg.obj instanceof Runnable) {
188 executeInternal((Runnable) msg.obj);
189 } else {
190 Log.w(TAG, "can't handle msg: " + msg);
191 }
192 }
193
194 private void executeInternal(Runnable task) {
195 try {
196 task.run();
197 } catch (Throwable t) {
198 Log.e(TAG, "run task: " + task, t);
199 }
200 }
201 }
202
203 private void startPjSipStack() throws SameThreadException {
204 if (isPjSipStackStarted)
205 return;
206
207 try {
208 System.loadLibrary("gnustl_shared");
209 System.loadLibrary("expat");
210 System.loadLibrary("yaml");
211 System.loadLibrary("ccgnu2");
212 System.loadLibrary("crypto");
213 System.loadLibrary("ssl");
214 System.loadLibrary("ccrtp1");
215 System.loadLibrary("dbus");
216 System.loadLibrary("dbus-c++-1");
217 System.loadLibrary("samplerate");
218 System.loadLibrary("codec_ulaw");
219 System.loadLibrary("codec_alaw");
alisiond8c83882013-05-17 17:00:42 -0400220 System.loadLibrary("codec_g722");
alision43a9b362013-05-01 16:30:15 -0400221 System.loadLibrary("speexresampler");
222 System.loadLibrary("sflphone");
223 isPjSipStackStarted = true;
224 } catch (UnsatisfiedLinkError e) {
225 Log.e(TAG, "Problem with the current Pj stack...", e);
226 isPjSipStackStarted = false;
227 return;
228 } catch (Exception e) {
229 Log.e(TAG, "Problem with the current Pj stack...", e);
230 }
231
232 /* get unique instance of managerImpl */
233 managerImpl = SFLPhoneservice.instance();
234
235 /* set static AppPath before calling manager.init */
236 managerImpl.setPath(sflphoneApp.getAppPath());
237
238 callManagerJNI = new CallManagerJNI();
239 callManagerCallBack = new CallManagerCallBack(this);
240 SFLPhoneservice.setCallbackObject(callManagerCallBack);
241
242 configurationManagerJNI = new ConfigurationManagerJNI();
243 configurationManagerCallback = new ConfigurationManagerCallback(this);
244 SFLPhoneservice.setConfigurationCallbackObject(configurationManagerCallback);
245
246 managerImpl.init("");
247 return;
248 }
249
alision2cb99562013-05-30 17:02:20 -0400250 public HashMap<String, SipCall> getCurrent_calls() {
251 return current_calls;
252 }
253
254 public void setCurrent_calls(HashMap<String, SipCall> current_calls) {
255 this.current_calls = current_calls;
256 }
257
alision43a9b362013-05-01 16:30:15 -0400258 // Enforce same thread contract to ensure we do not call from somewhere else
259 public class SameThreadException extends Exception {
260 private static final long serialVersionUID = -905639124232613768L;
261
262 public SameThreadException() {
263 super("Should be launched from a single worker thread");
264 }
265 }
266
267 public abstract static class SipRunnable implements Runnable {
268 protected abstract void doRun() throws SameThreadException, RemoteException;
269
270 public void run() {
271 try {
272 doRun();
273 } catch (SameThreadException e) {
274 Log.e(TAG, "Not done from same thread");
275 } catch (RemoteException e) {
276 Log.e(TAG, e.toString());
277 }
278 }
279 }
280
281 public abstract static class SipRunnableWithReturn implements Runnable {
282 Object obj = null;
283 boolean done = false;
284
285 protected abstract Object doRun() throws SameThreadException;
286
287 public Object getVal() {
288 return obj;
289 }
290
291 public boolean isDone() {
292 return done;
293 }
294
295 public void run() {
296 try {
297 obj = doRun();
298 done = true;
299 } catch (SameThreadException e) {
300 Log.e(TAG, "Not done from same thread");
301 }
302 }
303 }
304
305 class StartRunnable extends SipRunnable {
306 @Override
307 protected void doRun() throws SameThreadException {
308 startPjSipStack();
309 }
310 }
311
312 private class SipServiceThread extends Thread {
313
314 public SipServiceThread() {
315 super("sipServiceThread");
316 }
317
318 @Override
319 public void run() {
320 Log.i(TAG, "SipService thread running...");
321 SipService sipService = SipService.this;
322 while (sipService.runFlag) {
323 try {
324 Thread.sleep(DELAY);
325 } catch (InterruptedException e) {
326 sipService.runFlag = false;
327 Log.w(TAG, "service thread interrupted!");
328 }
329 }
330 }
331 }
332
333 /* ************************************
334 *
335 * Implement public interface for the service
336 *
337 *
338 * **********************************
339 */
Emeric Vigier6119d782012-09-21 18:04:14 -0400340 private final ISipService.Stub mBinder = new ISipService.Stub() {
341
342 @Override
alisionfde875f2013-05-28 17:01:54 -0400343 public void placeCall(final SipCall call) {
Emeric Vigier6119d782012-09-21 18:04:14 -0400344 getExecutor().execute(new SipRunnable() {
345 @Override
346 protected void doRun() throws SameThreadException {
347 Log.i(TAG, "SipService.placeCall() thread running...");
alisionfde875f2013-05-28 17:01:54 -0400348 callManagerJNI.placeCall(call.getAccountID(), call.getCallId(), call.getContacts().get(0).getPhones().get(0).getNumber());
alision2cb99562013-05-30 17:02:20 -0400349 getCurrent_calls().put(call.getCallId(), call);
Emeric Vigier6119d782012-09-21 18:04:14 -0400350 }
351 });
352 }
353
354 @Override
355 public void refuse(final String callID) {
356 getExecutor().execute(new SipRunnable() {
357 @Override
358 protected void doRun() throws SameThreadException {
359 Log.i(TAG, "SipService.refuse() thread running...");
360 callManagerJNI.refuse(callID);
361 }
362 });
363 }
364
365 @Override
366 public void accept(final String callID) {
367 getExecutor().execute(new SipRunnable() {
368 @Override
369 protected void doRun() throws SameThreadException {
370 Log.i(TAG, "SipService.placeCall() thread running...");
371 callManagerJNI.accept(callID);
372 }
373 });
374 }
375
376 @Override
377 public void hangUp(final String callID) {
378 getExecutor().execute(new SipRunnable() {
379 @Override
380 protected void doRun() throws SameThreadException {
381 Log.i(TAG, "SipService.hangUp() thread running...");
382 callManagerJNI.hangUp(callID);
383 }
384 });
385 }
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400386
387 @Override
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400388 public void hold(final String callID) {
389 getExecutor().execute(new SipRunnable() {
390 @Override
391 protected void doRun() throws SameThreadException {
392 Log.i(TAG, "SipService.hold() thread running...");
393 callManagerJNI.hold(callID);
394 }
395 });
396 }
397
398 @Override
399 public void unhold(final String callID) {
400 getExecutor().execute(new SipRunnable() {
401 @Override
402 protected void doRun() throws SameThreadException {
403 Log.i(TAG, "SipService.unhold() thread running...");
404 callManagerJNI.unhold(callID);
405 }
406 });
407 }
408
409 @Override
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400410 public void setAudioPlugin(final String audioPlugin) {
411 getExecutor().execute(new SipRunnable() {
alision371b77e2013-04-23 14:51:26 -0400412 @Override
413 protected void doRun() throws SameThreadException {
414 Log.i(TAG, "SipService.setAudioPlugin() thread running...");
415 configurationManagerJNI.setAudioPlugin(audioPlugin);
416 }
Alexandre Savard31d27c62012-10-04 16:05:08 -0400417 });
418 }
419
420 @Override
421 public String getCurrentAudioOutputPlugin() {
422 class CurrentAudioPlugin extends SipRunnableWithReturn {
423 @Override
424 protected String doRun() throws SameThreadException {
425 Log.i(TAG, "SipService.getCurrentAudioOutputPlugin() thread running...");
426 return configurationManagerJNI.getCurrentAudioOutputPlugin();
427 }
alision371b77e2013-04-23 14:51:26 -0400428 }
429 ;
Alexandre Savard31d27c62012-10-04 16:05:08 -0400430
431 CurrentAudioPlugin runInstance = new CurrentAudioPlugin();
432 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400433 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400434 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400435 }
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400436 return (String) runInstance.getVal();
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400437 }
Alexandre Savard713a34d2012-09-26 15:50:41 -0400438
439 @Override
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400440 public ArrayList<String> getAccountList() {
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400441 class AccountList extends SipRunnableWithReturn {
442 @Override
443 protected StringVect doRun() throws SameThreadException {
444 Log.i(TAG, "SipService.getAccountList() thread running...");
445 return configurationManagerJNI.getAccountList();
446 }
alision371b77e2013-04-23 14:51:26 -0400447 }
448 ;
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400449 AccountList runInstance = new AccountList();
450 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400451 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400452 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400453 }
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400454 StringVect swigvect = (StringVect) runInstance.getVal();
455
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400456 ArrayList<String> nativelist = new ArrayList<String>();
Alexandre Savard52a72522012-09-27 16:40:13 -0400457
alision371b77e2013-04-23 14:51:26 -0400458 for (int i = 0; i < swigvect.size(); i++)
459 nativelist.add(swigvect.get(i));
Alexandre Savard52a72522012-09-27 16:40:13 -0400460
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400461 return nativelist;
alision371b77e2013-04-23 14:51:26 -0400462 }
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400463
464 @Override
alision371b77e2013-04-23 14:51:26 -0400465 public HashMap<String, String> getAccountDetails(final String accountID) {
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400466 class AccountDetails extends SipRunnableWithReturn {
467 private String id;
alision371b77e2013-04-23 14:51:26 -0400468
469 AccountDetails(String accountId) {
470 id = accountId;
471 }
472
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400473 @Override
474 protected StringMap doRun() throws SameThreadException {
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400475 Log.i(TAG, "SipService.getAccountDetails() thread running...");
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400476 return configurationManagerJNI.getAccountDetails(id);
477 }
alision371b77e2013-04-23 14:51:26 -0400478 }
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400479
480 AccountDetails runInstance = new AccountDetails(accountID);
481 getExecutor().execute(runInstance);
alisionfde875f2013-05-28 17:01:54 -0400482
alision371b77e2013-04-23 14:51:26 -0400483 while (!runInstance.isDone()) {
484 }
485 StringMap swigmap = (StringMap) runInstance.getVal();
Alexandre Savard713a34d2012-09-26 15:50:41 -0400486
Alexandre Savard3bbb4792012-10-05 11:30:01 -0400487 HashMap<String, String> nativemap = AccountDetailsHandler.convertSwigToNative(swigmap);
Alexandre Savard713a34d2012-09-26 15:50:41 -0400488
489 return nativemap;
490 }
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400491
492 @Override
alisioncc7bb422013-06-06 15:31:39 -0400493 public void setAccountDetails(final String accountId, final Map map) {
alision371b77e2013-04-23 14:51:26 -0400494 HashMap<String, String> nativemap = (HashMap<String, String>) map;
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400495
Alexandre Savard3bbb4792012-10-05 11:30:01 -0400496 final StringMap swigmap = AccountDetailsHandler.convertFromNativeToSwig(nativemap);
Alexandre Savard718d49f2012-10-02 15:17:13 -0400497
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400498 getExecutor().execute(new SipRunnable() {
499 @Override
500 protected void doRun() throws SameThreadException {
alisioncc7bb422013-06-06 15:31:39 -0400501
502 configurationManagerJNI.setCredentials(accountId, extractCredentials(map));
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400503 configurationManagerJNI.setAccountDetails(accountId, swigmap);
alisioncc7bb422013-06-06 15:31:39 -0400504
505 convertSwigToNative(configurationManagerJNI.getCredentials(accountId));
506 Log.i(TAG, "SipService.setAccountDetails() thread running...");
507 }
508
509 private VectMap extractCredentials(Map map) {
510 VectMap swigmap = new VectMap();
511 StringMap entry = new StringMap();
512 entry.set(ServiceConstants.CONFIG_ACCOUNT_USERNAME, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_USERNAME));
513 if((String) map.get(ServiceConstants.CONFIG_ACCOUNT_REALM) != null)
514 entry.set(ServiceConstants.CONFIG_ACCOUNT_REALM, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_REALM));
515 else
516 entry.set(ServiceConstants.CONFIG_ACCOUNT_REALM, "*");
517 entry.set(ServiceConstants.CONFIG_ACCOUNT_PASSWORD, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_PASSWORD));
518 swigmap.add(entry);
519 return swigmap;
520
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400521 }
522 });
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400523 }
524
alisioncc7bb422013-06-06 15:31:39 -0400525 public ArrayList<HashMap<String, String>> convertSwigToNative(VectMap swigmap) {
526
527 ArrayList<HashMap<String, String>> nativemap = new ArrayList<HashMap<String, String>>();
528 Log.i(TAG, "swigmap size " + swigmap.size());
529 for (int i = 0; i < swigmap.size(); ++i) {
530 Log.i(TAG, "Entry " + i);
531 StringMap tmp = swigmap.get(i);
532 Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_USERNAME));
533// Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_REALM));
534 Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_PASSWORD));
535 }
536
537 return nativemap;
538 }
539
Alexandre Savard46036572012-10-05 13:56:49 -0400540 @Override
541 public String addAccount(Map map) {
542 class AddAccount extends SipRunnableWithReturn {
543 StringMap map;
alision371b77e2013-04-23 14:51:26 -0400544
545 AddAccount(StringMap m) {
546 map = m;
547 }
548
Alexandre Savard46036572012-10-05 13:56:49 -0400549 @Override
550 protected String doRun() throws SameThreadException {
551 Log.i(TAG, "SipService.getAccountDetails() thread running...");
552 return configurationManagerJNI.addAccount(map);
553 }
alision371b77e2013-04-23 14:51:26 -0400554 }
Alexandre Savard46036572012-10-05 13:56:49 -0400555
alision371b77e2013-04-23 14:51:26 -0400556 final StringMap swigmap = AccountDetailsHandler.convertFromNativeToSwig((HashMap<String, String>) map);
Alexandre Savard46036572012-10-05 13:56:49 -0400557
558 AddAccount runInstance = new AddAccount(swigmap);
559 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400560 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400561 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400562 }
Alexandre Savard46036572012-10-05 13:56:49 -0400563 String accountId = (String) runInstance.getVal();
564
565 return accountId;
566 }
567
568 @Override
569 public void removeAccount(final String accountId) {
570 getExecutor().execute(new SipRunnable() {
571 @Override
572 protected void doRun() throws SameThreadException {
573 Log.i(TAG, "SipService.setAccountDetails() thread running...");
574 configurationManagerJNI.removeAccount(accountId);
575 }
576 });
577 }
alision5f899632013-04-22 17:26:56 -0400578
alisione2a38e12013-04-25 14:20:20 -0400579 @Override
580 public ArrayList<HashMap<String, String>> getHistory() throws RemoteException {
581 class History extends SipRunnableWithReturn {
582
583 @Override
584 protected VectMap doRun() throws SameThreadException {
585 Log.i(TAG, "SipService.getHistory() thread running...");
alision7f18fc82013-05-01 09:37:33 -0400586
alisione2a38e12013-04-25 14:20:20 -0400587 return configurationManagerJNI.getHistory();
588 }
589 }
590
591 History runInstance = new History();
592 getExecutor().execute(runInstance);
593 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400594 // Log.w(TAG, "Waiting for getHistory");
alisione2a38e12013-04-25 14:20:20 -0400595 }
596 VectMap swigmap = (VectMap) runInstance.getVal();
597
598 ArrayList<HashMap<String, String>> nativemap = HistoryHandler.convertSwigToNative(swigmap);
599
600 return nativemap;
601 }
alision7f18fc82013-05-01 09:37:33 -0400602
alision43a9b362013-05-01 16:30:15 -0400603 /*************************
604 * Transfer related API
605 *************************/
606
alision7f18fc82013-05-01 09:37:33 -0400607 @Override
608 public void transfer(final String callID, final String to) throws RemoteException {
609 getExecutor().execute(new SipRunnable() {
610 @Override
611 protected void doRun() throws SameThreadException, RemoteException {
612 Log.i(TAG, "SipService.transfer() thread running...");
613 if (callManagerJNI.transfer(callID, to)) {
614 Bundle bundle = new Bundle();
615 bundle.putString("CallID", callID);
616 bundle.putString("State", "HUNGUP");
617 Intent intent = new Intent(CallManagerCallBack.CALL_STATE_CHANGED);
alision7f18fc82013-05-01 09:37:33 -0400618 intent.putExtra("com.savoirfairelinux.sflphone.service.newstate", bundle);
alision84813a12013-05-27 17:40:39 -0400619 sendBroadcast(intent);
alision7f18fc82013-05-01 09:37:33 -0400620 } else
621 Log.i(TAG, "NOT OK");
622 }
623 });
624
625 }
alision43a9b362013-05-01 16:30:15 -0400626
alision7f18fc82013-05-01 09:37:33 -0400627 @Override
628 public void attendedTransfer(final String transferID, final String targetID) throws RemoteException {
629 getExecutor().execute(new SipRunnable() {
630 @Override
631 protected void doRun() throws SameThreadException, RemoteException {
alision43a9b362013-05-01 16:30:15 -0400632 Log.i(TAG, "SipService.attendedTransfer() thread running...");
alision7f18fc82013-05-01 09:37:33 -0400633 if (callManagerJNI.attendedTransfer(transferID, targetID)) {
634 Log.i(TAG, "OK");
alision7f18fc82013-05-01 09:37:33 -0400635 } else
636 Log.i(TAG, "NOT OK");
637 }
638 });
alision43a9b362013-05-01 16:30:15 -0400639
640 }
641
642 /*************************
643 * Conference related API
644 *************************/
645
646 @Override
647 public void removeConference(final String confID) throws RemoteException {
648 getExecutor().execute(new SipRunnable() {
649 @Override
650 protected void doRun() throws SameThreadException, RemoteException {
651 Log.i(TAG, "SipService.createConference() thread running...");
652 callManagerJNI.removeConference(confID);
653 }
654 });
655
alision7f18fc82013-05-01 09:37:33 -0400656 }
657
658 @Override
alision43a9b362013-05-01 16:30:15 -0400659 public void joinParticipant(final String sel_callID, final String drag_callID) throws RemoteException {
660 getExecutor().execute(new SipRunnable() {
661 @Override
662 protected void doRun() throws SameThreadException, RemoteException {
663 Log.i(TAG, "SipService.joinParticipant() thread running...");
664 callManagerJNI.joinParticipant(sel_callID, drag_callID);
665 }
666 });
667
alision7f18fc82013-05-01 09:37:33 -0400668 }
669
670 @Override
alision43a9b362013-05-01 16:30:15 -0400671 public void createConfFromParticipantList(final List participants) throws RemoteException {
672 getExecutor().execute(new SipRunnable() {
673 @Override
674 protected void doRun() throws SameThreadException, RemoteException {
675 Log.i(TAG, "SipService.createConfFromParticipantList() thread running...");
676 // callManagerJNI.createConfFromParticipantList(participants);
677 }
678 });
679
alision7f18fc82013-05-01 09:37:33 -0400680 }
681
682 @Override
alision43a9b362013-05-01 16:30:15 -0400683 public void addParticipant(final String callID, final String confID) throws RemoteException {
684 getExecutor().execute(new SipRunnable() {
685 @Override
686 protected void doRun() throws SameThreadException, RemoteException {
687 Log.i(TAG, "SipService.addParticipant() thread running...");
688 callManagerJNI.addParticipant(callID, confID);
689 }
690 });
691
alision7f18fc82013-05-01 09:37:33 -0400692 }
693
694 @Override
alision43a9b362013-05-01 16:30:15 -0400695 public void addMainParticipant(final String confID) throws RemoteException {
696 getExecutor().execute(new SipRunnable() {
697 @Override
698 protected void doRun() throws SameThreadException, RemoteException {
699 Log.i(TAG, "SipService.addMainParticipant() thread running...");
700 callManagerJNI.addMainParticipant(confID);
701 }
702 });
703
alision7f18fc82013-05-01 09:37:33 -0400704 }
705
706 @Override
alision43a9b362013-05-01 16:30:15 -0400707 public void detachParticipant(final String callID) throws RemoteException {
708 getExecutor().execute(new SipRunnable() {
709 @Override
710 protected void doRun() throws SameThreadException, RemoteException {
711 Log.i(TAG, "SipService.detachParticipant() thread running...");
712 callManagerJNI.detachParticipant(callID);
713 }
714 });
715
alision7f18fc82013-05-01 09:37:33 -0400716 }
717
718 @Override
alision43a9b362013-05-01 16:30:15 -0400719 public void joinConference(final String sel_confID, final String drag_confID) throws RemoteException {
720 getExecutor().execute(new SipRunnable() {
721 @Override
722 protected void doRun() throws SameThreadException, RemoteException {
723 Log.i(TAG, "SipService.joinConference() thread running...");
724 callManagerJNI.joinConference(sel_confID, drag_confID);
725 }
726 });
727
alision7f18fc82013-05-01 09:37:33 -0400728 }
729
730 @Override
alision43a9b362013-05-01 16:30:15 -0400731 public void hangUpConference(final String confID) throws RemoteException {
732 getExecutor().execute(new SipRunnable() {
733 @Override
734 protected void doRun() throws SameThreadException, RemoteException {
735 Log.i(TAG, "SipService.joinConference() thread running...");
736 callManagerJNI.hangUpConference(confID);
737 }
738 });
739
alision7f18fc82013-05-01 09:37:33 -0400740 }
741
742 @Override
alision43a9b362013-05-01 16:30:15 -0400743 public void holdConference(final String confID) throws RemoteException {
744 getExecutor().execute(new SipRunnable() {
745 @Override
746 protected void doRun() throws SameThreadException, RemoteException {
747 Log.i(TAG, "SipService.holdConference() thread running...");
748 callManagerJNI.holdConference(confID);
749 }
750 });
751
alision7f18fc82013-05-01 09:37:33 -0400752 }
753
754 @Override
alision43a9b362013-05-01 16:30:15 -0400755 public void unholdConference(final String confID) throws RemoteException {
756 getExecutor().execute(new SipRunnable() {
757 @Override
758 protected void doRun() throws SameThreadException, RemoteException {
759 Log.i(TAG, "SipService.unholdConference() thread running...");
760 callManagerJNI.unholdConference(confID);
761 }
762 });
763
alision7f18fc82013-05-01 09:37:33 -0400764 }
765
766 @Override
767 public List getConferenceList() throws RemoteException {
alision4a0eb092013-05-07 13:52:03 -0400768 class ConfList extends SipRunnableWithReturn {
769 @Override
770 protected StringVect doRun() throws SameThreadException {
771 Log.i(TAG, "SipService.getAccountList() thread running...");
772 return callManagerJNI.getConferenceList();
773 }
774 }
775 ;
776 ConfList runInstance = new ConfList();
777 getExecutor().execute(runInstance);
778 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400779 // Log.w(TAG, "Waiting for getConferenceList");
alision4a0eb092013-05-07 13:52:03 -0400780 }
781 StringVect swigvect = (StringVect) runInstance.getVal();
782
783 ArrayList<String> nativelist = new ArrayList<String>();
784
785 for (int i = 0; i < swigvect.size(); i++)
786 nativelist.add(swigvect.get(i));
787
788 return nativelist;
alision7f18fc82013-05-01 09:37:33 -0400789 }
790
791 @Override
792 public List getParticipantList(String confID) throws RemoteException {
alision43a9b362013-05-01 16:30:15 -0400793 Log.e(TAG, "getConferenceList not implemented");
alision7f18fc82013-05-01 09:37:33 -0400794 return null;
795 }
796
797 @Override
798 public String getConferenceId(String callID) throws RemoteException {
alision43a9b362013-05-01 16:30:15 -0400799 Log.e(TAG, "getConferenceList not implemented");
alision7f18fc82013-05-01 09:37:33 -0400800 return null;
801 }
802
803 @Override
804 public Map getConferenceDetails(String callID) throws RemoteException {
alision43a9b362013-05-01 16:30:15 -0400805 Log.e(TAG, "getConferenceList not implemented");
alision7f18fc82013-05-01 09:37:33 -0400806 return null;
807 }
808
alision04a00182013-05-10 17:05:29 -0400809 @Override
810 public String getRecordPath() throws RemoteException {
811 class RecordPath extends SipRunnableWithReturn {
812
813 @Override
814 protected String doRun() throws SameThreadException {
815 Log.i(TAG, "SipService.getRecordPath() thread running...");
816 return configurationManagerJNI.getRecordPath();
817 }
818 }
819
820 RecordPath runInstance = new RecordPath();
821 getExecutor().execute(runInstance);
822 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400823 // Log.w(TAG, "Waiting for getRecordPath");
alision04a00182013-05-10 17:05:29 -0400824 }
825 String path = (String) runInstance.getVal();
826
827 return path;
828 }
829
830 @Override
831 public void setRecordingCall(final String id) throws RemoteException {
832 getExecutor().execute(new SipRunnable() {
833 @Override
834 protected void doRun() throws SameThreadException, RemoteException {
835 Log.i(TAG, "SipService.setRecordingCall() thread running...");
836 callManagerJNI.setRecordingCall(id);
837 }
838 });
839
840 }
841
842 @Override
843 public void setRecordPath(final String path) throws RemoteException {
844 getExecutor().execute(new SipRunnable() {
845 @Override
846 protected void doRun() throws SameThreadException, RemoteException {
847 Log.i(TAG, "SipService.setRecordingCall() thread running...");
848 configurationManagerJNI.setRecordPath(path);
849 }
850 });
851 }
852
853 @Override
854 public void sendTextMessage(final String callID, final String message, final String from) throws RemoteException {
855 getExecutor().execute(new SipRunnable() {
856 @Override
857 protected void doRun() throws SameThreadException, RemoteException {
858 Log.i(TAG, "SipService.sendTextMessage() thread running...");
859 callManagerJNI.sendTextMessage(callID, message, from);
860 }
861 });
862
863 }
864
alisiond295ec22013-05-17 10:12:13 -0400865 @Override
866 public List getAudioCodecList(String accountID) throws RemoteException {
867 class AudioCodecList extends SipRunnableWithReturn {
868
869 @Override
870 protected IntVect doRun() throws SameThreadException {
871 Log.i(TAG, "SipService.getAudioCodecList() thread running...");
872 return configurationManagerJNI.getAudioCodecList();
873 }
874 }
875
876 AudioCodecList runInstance = new AudioCodecList();
877 getExecutor().execute(runInstance);
878 while (!runInstance.isDone()) {
879 Log.w(TAG, "Waiting for getAudioCodecList");
880 }
881 IntVect swigmap = (IntVect) runInstance.getVal();
882
883 ArrayList<Integer> codecs = AudioHandler.convertSwigToNative(swigmap);
884
885 return codecs;
886 }
887
alision9f7a6ec2013-05-24 16:26:26 -0400888 @Override
alisionfde875f2013-05-28 17:01:54 -0400889 public HashMap<String, SipCall> getCallList() throws RemoteException {
alision85704182013-05-29 15:23:03 -0400890 // class CallList extends SipRunnableWithReturn {
891 //
892 // @Override
893 // protected StringVect doRun() throws SameThreadException {
894 // Log.i(TAG, "SipService.getCallList() thread running...");
895 // return callManagerJNI.getCallList();
896 // }
897 // }
898 //
899 // CallList runInstance = new CallList();
900 // getExecutor().execute(runInstance);
901 // while (!runInstance.isDone()) {
902 // Log.w(TAG, "Waiting for getAudioCodecList");
903 // }
904 // StringVect swigmap = (StringVect) runInstance.getVal();
905 //
906 // ArrayList<String> nativemap = new ArrayList<String>();
907 // for (int i = 0; i < swigmap.size(); ++i) {
908 //
909 // String t = swigmap.get(i);
910 // nativemap.add(t);
911 // }
alision9f7a6ec2013-05-24 16:26:26 -0400912
alision2cb99562013-05-30 17:02:20 -0400913 return getCurrent_calls();
alision9f7a6ec2013-05-24 16:26:26 -0400914 }
915
alision85704182013-05-29 15:23:03 -0400916 @Override
917 public SipCall getCall(String callID) throws RemoteException {
alision2cb99562013-05-30 17:02:20 -0400918 return getCurrent_calls().get(callID);
919 }
920
921 /***********************
922 * Notification API
923 ***********************/
924 @Override
925 public void createNotification() throws RemoteException {
926 makeNotification();
alisioncc7bb422013-06-06 15:31:39 -0400927
alision2cb99562013-05-30 17:02:20 -0400928 }
929
930 @Override
931 public void destroyNotification() throws RemoteException {
932 removeNotification();
alisioncc7bb422013-06-06 15:31:39 -0400933
alision2cb99562013-05-30 17:02:20 -0400934 }
alisioncc7bb422013-06-06 15:31:39 -0400935
alision2cb99562013-05-30 17:02:20 -0400936 private int NOTIFICATION_ID = new Random().nextInt(1000);
alisioncc7bb422013-06-06 15:31:39 -0400937
alision2cb99562013-05-30 17:02:20 -0400938 private void makeNotification() {
alisioncc7bb422013-06-06 15:31:39 -0400939 if (current_calls.size() == 0) {
alision2cb99562013-05-30 17:02:20 -0400940 return;
941 }
942 Intent notificationIntent = new Intent(getApplicationContext(), SFLPhoneHomeActivity.class);
alisioncc7bb422013-06-06 15:31:39 -0400943 PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 007, notificationIntent,
944 PendingIntent.FLAG_UPDATE_CURRENT);
alision2cb99562013-05-30 17:02:20 -0400945
946 NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
947
948 NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
alisioncc7bb422013-06-06 15:31:39 -0400949 //
950 // builder.setContent(view);
951 builder.setContentIntent(contentIntent).setOngoing(true).setSmallIcon(R.drawable.ic_launcher)
952 .setContentTitle(getCurrent_calls().size() + " ongoing calls").setTicker("Pending calls").setWhen(System.currentTimeMillis())
953 .setAutoCancel(false);
alision2cb99562013-05-30 17:02:20 -0400954 builder.setPriority(NotificationCompat.PRIORITY_MAX);
955 Notification n = builder.build();
956
957 nm.notify(NOTIFICATION_ID, n);
alisioncc7bb422013-06-06 15:31:39 -0400958
alision2cb99562013-05-30 17:02:20 -0400959 }
960
961 public void removeNotification() {
962 NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
963 nm.cancel(NOTIFICATION_ID);
alisioncc7bb422013-06-06 15:31:39 -0400964
alision85704182013-05-29 15:23:03 -0400965 }
966
Emeric Vigier6119d782012-09-21 18:04:14 -0400967 };
Emeric Vigiereaf2c492012-09-19 14:38:20 -0400968}