blob: 9f1c1934c3b0385d73078e41618fad97d1eea7cb [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;
alision806e18e2013-06-21 15:30:17 -040033import java.util.Map.Entry;
alision2cb99562013-05-30 17:02:20 -040034import java.util.Random;
Emeric Vigier6119d782012-09-21 18:04:14 -040035
alision2cb99562013-05-30 17:02:20 -040036import android.app.Notification;
37import android.app.NotificationManager;
38import android.app.PendingIntent;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040039import android.app.Service;
alision17052d42013-04-22 10:39:38 -040040import android.content.Context;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040041import android.content.Intent;
alision17052d42013-04-22 10:39:38 -040042import android.content.IntentFilter;
alision7f18fc82013-05-01 09:37:33 -040043import android.os.Bundle;
Emeric Vigier6119d782012-09-21 18:04:14 -040044import android.os.Handler;
45import android.os.HandlerThread;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040046import android.os.IBinder;
Emeric Vigier6119d782012-09-21 18:04:14 -040047import android.os.Looper;
48import android.os.Message;
alision5f899632013-04-22 17:26:56 -040049import android.os.RemoteException;
alision2cb99562013-05-30 17:02:20 -040050import android.support.v4.app.NotificationCompat;
alision17052d42013-04-22 10:39:38 -040051import android.support.v4.content.LocalBroadcastManager;
Emeric Vigiereaf2c492012-09-19 14:38:20 -040052import android.util.Log;
53import android.widget.Toast;
54
alision2cb99562013-05-30 17:02:20 -040055import com.savoirfairelinux.sflphone.R;
alisionf76de3b2013-04-16 15:35:22 -040056import com.savoirfairelinux.sflphone.account.AccountDetailsHandler;
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;
alision806e18e2013-06-21 15:30:17 -040060import com.savoirfairelinux.sflphone.model.Conference;
alisionfde875f2013-05-28 17:01:54 -040061import com.savoirfairelinux.sflphone.model.SipCall;
alisioncc7bb422013-06-06 15:31:39 -040062import com.savoirfairelinux.sflphone.receivers.IncomingReceiver;
Alexandre Savard713a34d2012-09-26 15:50:41 -040063
Emeric Vigiereaf2c492012-09-19 14:38:20 -040064public class SipService extends Service {
65
66 static final String TAG = "SipService";
67 static final int DELAY = 5000; /* 5 sec */
68 private boolean runFlag = false;
69 private SipServiceThread sipServiceThread;
Emeric Vigier84e05da2012-09-20 14:53:05 -040070 private SFLphoneApplication sflphoneApp;
Emeric Vigier6119d782012-09-21 18:04:14 -040071 private SipServiceExecutor mExecutor;
72 private static HandlerThread executorThread;
73 private CallManagerJNI callManagerJNI;
Emeric Vigier0007dee2012-09-24 11:35:58 -040074 private CallManagerCallBack callManagerCallBack;
Alexandre Savardc1b08fe2012-09-25 16:24:47 -040075 private ConfigurationManagerJNI configurationManagerJNI;
Alexandre Savardfccd1dc2012-10-17 17:31:38 -040076 private ConfigurationManagerCallback configurationManagerCallback;
Emeric Vigier0007dee2012-09-24 11:35:58 -040077 private ManagerImpl managerImpl;
Emeric Vigier6119d782012-09-21 18:04:14 -040078 private boolean isPjSipStackStarted = false;
alisioncc7bb422013-06-06 15:31:39 -040079
alision2cb99562013-05-30 17:02:20 -040080 public static final String NOTIF_CREATION = "notif_creation";
81 public static final String NOTIF_DELETION = "notif_deletion";
alision04a00182013-05-10 17:05:29 -040082
alision2cb99562013-05-30 17:02:20 -040083 private HashMap<String, SipCall> current_calls = new HashMap<String, SipCall>();
alision806e18e2013-06-21 15:30:17 -040084 private HashMap<String, Conference> current_confs = new HashMap<String, Conference>();
85 private IncomingReceiver receiver;
Emeric Vigier6119d782012-09-21 18:04:14 -040086
alision806e18e2013-06-21 15:30:17 -040087 public HashMap<String, Conference> getCurrent_confs() {
88 return current_confs;
89 }
alision43a9b362013-05-01 16:30:15 -040090
91 @Override
92 public boolean onUnbind(Intent i) {
93 super.onUnbind(i);
94 Log.i(TAG, "onUnbind(intent)");
95 return false;
96
97 }
98
99 /* called once by startService() */
100 @Override
101 public void onCreate() {
102 Log.i(TAG, "onCreated");
103 super.onCreate();
104
105 sflphoneApp = (SFLphoneApplication) getApplication();
106 sipServiceThread = new SipServiceThread();
107
108 IntentFilter callFilter = new IntentFilter(CallManagerCallBack.CALL_STATE_CHANGED);
109 callFilter.addAction(CallManagerCallBack.INCOMING_CALL);
110 callFilter.addAction(CallManagerCallBack.NEW_CALL_CREATED);
alision4a0eb092013-05-07 13:52:03 -0400111 callFilter.addAction(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED);
112 callFilter.addAction(ConfigurationManagerCallback.ACCOUNTS_CHANGED);
alision04a00182013-05-10 17:05:29 -0400113 callFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
alision806e18e2013-06-21 15:30:17 -0400114 callFilter.addAction(CallManagerCallBack.CONF_CREATED);
115 callFilter.addAction(CallManagerCallBack.CONF_REMOVED);
116 callFilter.addAction(CallManagerCallBack.CONF_CHANGED);
117 receiver = new IncomingReceiver(this, mBinder);
alision2cb99562013-05-30 17:02:20 -0400118 LocalBroadcastManager.getInstance(this).registerReceiver(receiver, callFilter);
alision2cb99562013-05-30 17:02:20 -0400119
alisioncc7bb422013-06-06 15:31:39 -0400120 getExecutor().execute(new StartRunnable());
121
122 }
alision43a9b362013-05-01 16:30:15 -0400123
124 /* called for each startService() */
125 @Override
126 public int onStartCommand(Intent intent, int flags, int startId) {
127 Log.i(TAG, "onStarted");
128 super.onStartCommand(intent, flags, startId);
129
alision806e18e2013-06-21 15:30:17 -0400130 receiver = new IncomingReceiver(this, mBinder);
alision43a9b362013-05-01 16:30:15 -0400131 if (!runFlag) {
132 sipServiceThread.start();
133 runFlag = true;
134 sflphoneApp.setServiceRunning(true);
135 Toast.makeText(this, "Sflphone Service started", Toast.LENGTH_SHORT).show();
136 }
137
alision907bde72013-06-20 14:40:37 -0400138 return START_NOT_STICKY; /* started and stopped explicitly */
alision43a9b362013-05-01 16:30:15 -0400139 }
140
141 @Override
142 public void onDestroy() {
143 /* called once by stopService() */
144 sipServiceThread.interrupt();
145 sipServiceThread = null;
146 runFlag = false;
alision2cb99562013-05-30 17:02:20 -0400147 unregisterReceiver(receiver);
148
alision43a9b362013-05-01 16:30:15 -0400149 sflphoneApp.setServiceRunning(false);
150 Toast.makeText(this, "Sflphone Service stopped", Toast.LENGTH_SHORT).show();
151 super.onDestroy();
152
153 Log.i(TAG, "onDestroyed");
154 }
155
156 @Override
157 public IBinder onBind(Intent arg0) {
158 Log.i(TAG, "onBound");
159 return mBinder;
160 }
161
162 private static Looper createLooper() {
163 if (executorThread == null) {
164 Log.d(TAG, "Creating new handler thread");
165 // ADT gives a fake warning due to bad parse rule.
166 executorThread = new HandlerThread("SipService.Executor");
167 executorThread.start();
168 }
169 return executorThread.getLooper();
170 }
171
172 public SipServiceExecutor getExecutor() {
173 // create mExecutor lazily
174 if (mExecutor == null) {
175 mExecutor = new SipServiceExecutor(this);
176 }
177 return mExecutor;
178 }
179
180 // Executes immediate tasks in a single executorThread.
181 public static class SipServiceExecutor extends Handler {
182 WeakReference<SipService> handlerService;
183
184 SipServiceExecutor(SipService s) {
185 super(createLooper());
186 handlerService = new WeakReference<SipService>(s);
187 }
188
189 public void execute(Runnable task) {
190 // TODO: add wakelock
191 Message.obtain(this, 0/* don't care */, task).sendToTarget();
192 }
193
194 @Override
195 public void handleMessage(Message msg) {
196 if (msg.obj instanceof Runnable) {
197 executeInternal((Runnable) msg.obj);
198 } else {
199 Log.w(TAG, "can't handle msg: " + msg);
200 }
201 }
202
203 private void executeInternal(Runnable task) {
204 try {
205 task.run();
206 } catch (Throwable t) {
207 Log.e(TAG, "run task: " + task, t);
208 }
209 }
210 }
211
212 private void startPjSipStack() throws SameThreadException {
213 if (isPjSipStackStarted)
214 return;
215
216 try {
217 System.loadLibrary("gnustl_shared");
218 System.loadLibrary("expat");
219 System.loadLibrary("yaml");
220 System.loadLibrary("ccgnu2");
221 System.loadLibrary("crypto");
222 System.loadLibrary("ssl");
223 System.loadLibrary("ccrtp1");
224 System.loadLibrary("dbus");
225 System.loadLibrary("dbus-c++-1");
226 System.loadLibrary("samplerate");
227 System.loadLibrary("codec_ulaw");
228 System.loadLibrary("codec_alaw");
alisiond8c83882013-05-17 17:00:42 -0400229 System.loadLibrary("codec_g722");
alision43a9b362013-05-01 16:30:15 -0400230 System.loadLibrary("speexresampler");
231 System.loadLibrary("sflphone");
232 isPjSipStackStarted = true;
233 } catch (UnsatisfiedLinkError e) {
234 Log.e(TAG, "Problem with the current Pj stack...", e);
235 isPjSipStackStarted = false;
236 return;
237 } catch (Exception e) {
238 Log.e(TAG, "Problem with the current Pj stack...", e);
239 }
240
241 /* get unique instance of managerImpl */
242 managerImpl = SFLPhoneservice.instance();
243
244 /* set static AppPath before calling manager.init */
245 managerImpl.setPath(sflphoneApp.getAppPath());
246
247 callManagerJNI = new CallManagerJNI();
248 callManagerCallBack = new CallManagerCallBack(this);
249 SFLPhoneservice.setCallbackObject(callManagerCallBack);
250
251 configurationManagerJNI = new ConfigurationManagerJNI();
252 configurationManagerCallback = new ConfigurationManagerCallback(this);
253 SFLPhoneservice.setConfigurationCallbackObject(configurationManagerCallback);
254
255 managerImpl.init("");
256 return;
257 }
258
alision2cb99562013-05-30 17:02:20 -0400259 public HashMap<String, SipCall> getCurrent_calls() {
260 return current_calls;
261 }
262
alision43a9b362013-05-01 16:30:15 -0400263 // Enforce same thread contract to ensure we do not call from somewhere else
264 public class SameThreadException extends Exception {
265 private static final long serialVersionUID = -905639124232613768L;
266
267 public SameThreadException() {
268 super("Should be launched from a single worker thread");
269 }
270 }
271
272 public abstract static class SipRunnable implements Runnable {
273 protected abstract void doRun() throws SameThreadException, RemoteException;
274
275 public void run() {
276 try {
277 doRun();
278 } catch (SameThreadException e) {
279 Log.e(TAG, "Not done from same thread");
280 } catch (RemoteException e) {
281 Log.e(TAG, e.toString());
282 }
283 }
284 }
285
286 public abstract static class SipRunnableWithReturn implements Runnable {
287 Object obj = null;
288 boolean done = false;
289
290 protected abstract Object doRun() throws SameThreadException;
291
292 public Object getVal() {
293 return obj;
294 }
295
296 public boolean isDone() {
297 return done;
298 }
299
300 public void run() {
301 try {
302 obj = doRun();
303 done = true;
304 } catch (SameThreadException e) {
305 Log.e(TAG, "Not done from same thread");
306 }
307 }
308 }
309
310 class StartRunnable extends SipRunnable {
311 @Override
312 protected void doRun() throws SameThreadException {
313 startPjSipStack();
314 }
315 }
316
317 private class SipServiceThread extends Thread {
318
319 public SipServiceThread() {
320 super("sipServiceThread");
321 }
322
323 @Override
324 public void run() {
325 Log.i(TAG, "SipService thread running...");
326 SipService sipService = SipService.this;
327 while (sipService.runFlag) {
328 try {
329 Thread.sleep(DELAY);
330 } catch (InterruptedException e) {
331 sipService.runFlag = false;
332 Log.w(TAG, "service thread interrupted!");
333 }
334 }
335 }
336 }
337
338 /* ************************************
339 *
340 * Implement public interface for the service
341 *
342 *
343 * **********************************
344 */
Emeric Vigier6119d782012-09-21 18:04:14 -0400345 private final ISipService.Stub mBinder = new ISipService.Stub() {
346
347 @Override
alisionfde875f2013-05-28 17:01:54 -0400348 public void placeCall(final SipCall call) {
Emeric Vigier6119d782012-09-21 18:04:14 -0400349 getExecutor().execute(new SipRunnable() {
350 @Override
351 protected void doRun() throws SameThreadException {
352 Log.i(TAG, "SipService.placeCall() thread running...");
alision907bde72013-06-20 14:40:37 -0400353 callManagerJNI.placeCall(call.getAccountID(), call.getCallId(), call.getContact().getPhones().get(0).getNumber());
alision2cb99562013-05-30 17:02:20 -0400354 getCurrent_calls().put(call.getCallId(), call);
Emeric Vigier6119d782012-09-21 18:04:14 -0400355 }
356 });
357 }
358
359 @Override
360 public void refuse(final String callID) {
361 getExecutor().execute(new SipRunnable() {
362 @Override
363 protected void doRun() throws SameThreadException {
364 Log.i(TAG, "SipService.refuse() thread running...");
365 callManagerJNI.refuse(callID);
366 }
367 });
368 }
369
370 @Override
371 public void accept(final String callID) {
372 getExecutor().execute(new SipRunnable() {
373 @Override
374 protected void doRun() throws SameThreadException {
375 Log.i(TAG, "SipService.placeCall() thread running...");
376 callManagerJNI.accept(callID);
377 }
378 });
379 }
380
381 @Override
382 public void hangUp(final String callID) {
383 getExecutor().execute(new SipRunnable() {
384 @Override
385 protected void doRun() throws SameThreadException {
386 Log.i(TAG, "SipService.hangUp() thread running...");
387 callManagerJNI.hangUp(callID);
388 }
389 });
390 }
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400391
392 @Override
Alexandre Savarde9dc8992012-10-26 12:12:27 -0400393 public void hold(final String callID) {
394 getExecutor().execute(new SipRunnable() {
395 @Override
396 protected void doRun() throws SameThreadException {
397 Log.i(TAG, "SipService.hold() thread running...");
398 callManagerJNI.hold(callID);
399 }
400 });
401 }
402
403 @Override
404 public void unhold(final String callID) {
405 getExecutor().execute(new SipRunnable() {
406 @Override
407 protected void doRun() throws SameThreadException {
408 Log.i(TAG, "SipService.unhold() thread running...");
409 callManagerJNI.unhold(callID);
410 }
411 });
412 }
413
414 @Override
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400415 public void setAudioPlugin(final String audioPlugin) {
416 getExecutor().execute(new SipRunnable() {
alision371b77e2013-04-23 14:51:26 -0400417 @Override
418 protected void doRun() throws SameThreadException {
419 Log.i(TAG, "SipService.setAudioPlugin() thread running...");
420 configurationManagerJNI.setAudioPlugin(audioPlugin);
421 }
Alexandre Savard31d27c62012-10-04 16:05:08 -0400422 });
423 }
424
425 @Override
426 public String getCurrentAudioOutputPlugin() {
427 class CurrentAudioPlugin extends SipRunnableWithReturn {
428 @Override
429 protected String doRun() throws SameThreadException {
430 Log.i(TAG, "SipService.getCurrentAudioOutputPlugin() thread running...");
431 return configurationManagerJNI.getCurrentAudioOutputPlugin();
432 }
alision371b77e2013-04-23 14:51:26 -0400433 }
434 ;
Alexandre Savard31d27c62012-10-04 16:05:08 -0400435
436 CurrentAudioPlugin runInstance = new CurrentAudioPlugin();
437 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400438 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400439 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400440 }
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400441 return (String) runInstance.getVal();
Alexandre Savardc1b08fe2012-09-25 16:24:47 -0400442 }
Alexandre Savard713a34d2012-09-26 15:50:41 -0400443
444 @Override
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400445 public ArrayList<String> getAccountList() {
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400446 class AccountList extends SipRunnableWithReturn {
447 @Override
448 protected StringVect doRun() throws SameThreadException {
449 Log.i(TAG, "SipService.getAccountList() thread running...");
450 return configurationManagerJNI.getAccountList();
451 }
alision371b77e2013-04-23 14:51:26 -0400452 }
453 ;
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400454 AccountList runInstance = new AccountList();
455 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400456 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400457 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400458 }
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400459 StringVect swigvect = (StringVect) runInstance.getVal();
460
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400461 ArrayList<String> nativelist = new ArrayList<String>();
Alexandre Savard52a72522012-09-27 16:40:13 -0400462
alision371b77e2013-04-23 14:51:26 -0400463 for (int i = 0; i < swigvect.size(); i++)
464 nativelist.add(swigvect.get(i));
Alexandre Savard52a72522012-09-27 16:40:13 -0400465
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400466 return nativelist;
alision371b77e2013-04-23 14:51:26 -0400467 }
Alexandre Savard6b85e7e2012-09-27 15:43:14 -0400468
469 @Override
alision371b77e2013-04-23 14:51:26 -0400470 public HashMap<String, String> getAccountDetails(final String accountID) {
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400471 class AccountDetails extends SipRunnableWithReturn {
472 private String id;
alision371b77e2013-04-23 14:51:26 -0400473
474 AccountDetails(String accountId) {
475 id = accountId;
476 }
477
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400478 @Override
479 protected StringMap doRun() throws SameThreadException {
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400480 Log.i(TAG, "SipService.getAccountDetails() thread running...");
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400481 return configurationManagerJNI.getAccountDetails(id);
482 }
alision371b77e2013-04-23 14:51:26 -0400483 }
Alexandre Savard7a902bc2012-10-04 16:32:35 -0400484
485 AccountDetails runInstance = new AccountDetails(accountID);
486 getExecutor().execute(runInstance);
alisionfde875f2013-05-28 17:01:54 -0400487
alision371b77e2013-04-23 14:51:26 -0400488 while (!runInstance.isDone()) {
489 }
490 StringMap swigmap = (StringMap) runInstance.getVal();
Alexandre Savard713a34d2012-09-26 15:50:41 -0400491
Alexandre Savard3bbb4792012-10-05 11:30:01 -0400492 HashMap<String, String> nativemap = AccountDetailsHandler.convertSwigToNative(swigmap);
Alexandre Savard713a34d2012-09-26 15:50:41 -0400493
494 return nativemap;
495 }
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400496
497 @Override
alisioncc7bb422013-06-06 15:31:39 -0400498 public void setAccountDetails(final String accountId, final Map map) {
alision371b77e2013-04-23 14:51:26 -0400499 HashMap<String, String> nativemap = (HashMap<String, String>) map;
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400500
Alexandre Savard3bbb4792012-10-05 11:30:01 -0400501 final StringMap swigmap = AccountDetailsHandler.convertFromNativeToSwig(nativemap);
Alexandre Savard718d49f2012-10-02 15:17:13 -0400502
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400503 getExecutor().execute(new SipRunnable() {
504 @Override
505 protected void doRun() throws SameThreadException {
alisioncc7bb422013-06-06 15:31:39 -0400506
507 configurationManagerJNI.setCredentials(accountId, extractCredentials(map));
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400508 configurationManagerJNI.setAccountDetails(accountId, swigmap);
alisioncc7bb422013-06-06 15:31:39 -0400509
510 convertSwigToNative(configurationManagerJNI.getCredentials(accountId));
511 Log.i(TAG, "SipService.setAccountDetails() thread running...");
512 }
513
514 private VectMap extractCredentials(Map map) {
515 VectMap swigmap = new VectMap();
516 StringMap entry = new StringMap();
517 entry.set(ServiceConstants.CONFIG_ACCOUNT_USERNAME, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_USERNAME));
alision806e18e2013-06-21 15:30:17 -0400518 if ((String) map.get(ServiceConstants.CONFIG_ACCOUNT_REALM) != null)
alisioncc7bb422013-06-06 15:31:39 -0400519 entry.set(ServiceConstants.CONFIG_ACCOUNT_REALM, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_REALM));
520 else
521 entry.set(ServiceConstants.CONFIG_ACCOUNT_REALM, "*");
522 entry.set(ServiceConstants.CONFIG_ACCOUNT_PASSWORD, (String) map.get(ServiceConstants.CONFIG_ACCOUNT_PASSWORD));
523 swigmap.add(entry);
524 return swigmap;
525
Alexandre Savard7a2b2202012-10-04 17:07:33 -0400526 }
527 });
Alexandre Savard8b7d4332012-09-30 20:02:11 -0400528 }
529
alisioncc7bb422013-06-06 15:31:39 -0400530 public ArrayList<HashMap<String, String>> convertSwigToNative(VectMap swigmap) {
531
532 ArrayList<HashMap<String, String>> nativemap = new ArrayList<HashMap<String, String>>();
533 Log.i(TAG, "swigmap size " + swigmap.size());
534 for (int i = 0; i < swigmap.size(); ++i) {
535 Log.i(TAG, "Entry " + i);
536 StringMap tmp = swigmap.get(i);
537 Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_USERNAME));
alision806e18e2013-06-21 15:30:17 -0400538 // Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_REALM));
alisioncc7bb422013-06-06 15:31:39 -0400539 Log.i(TAG, tmp.get(ServiceConstants.CONFIG_ACCOUNT_PASSWORD));
540 }
541
542 return nativemap;
543 }
544
Alexandre Savard46036572012-10-05 13:56:49 -0400545 @Override
546 public String addAccount(Map map) {
547 class AddAccount extends SipRunnableWithReturn {
548 StringMap map;
alision371b77e2013-04-23 14:51:26 -0400549
550 AddAccount(StringMap m) {
551 map = m;
552 }
553
Alexandre Savard46036572012-10-05 13:56:49 -0400554 @Override
555 protected String doRun() throws SameThreadException {
556 Log.i(TAG, "SipService.getAccountDetails() thread running...");
557 return configurationManagerJNI.addAccount(map);
558 }
alision371b77e2013-04-23 14:51:26 -0400559 }
Alexandre Savard46036572012-10-05 13:56:49 -0400560
alision371b77e2013-04-23 14:51:26 -0400561 final StringMap swigmap = AccountDetailsHandler.convertFromNativeToSwig((HashMap<String, String>) map);
Alexandre Savard46036572012-10-05 13:56:49 -0400562
563 AddAccount runInstance = new AddAccount(swigmap);
564 getExecutor().execute(runInstance);
alision371b77e2013-04-23 14:51:26 -0400565 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400566 // Log.e(TAG, "Waiting for Nofing");
alision371b77e2013-04-23 14:51:26 -0400567 }
Alexandre Savard46036572012-10-05 13:56:49 -0400568 String accountId = (String) runInstance.getVal();
569
570 return accountId;
571 }
572
573 @Override
574 public void removeAccount(final String accountId) {
575 getExecutor().execute(new SipRunnable() {
576 @Override
577 protected void doRun() throws SameThreadException {
578 Log.i(TAG, "SipService.setAccountDetails() thread running...");
579 configurationManagerJNI.removeAccount(accountId);
580 }
581 });
582 }
alision5f899632013-04-22 17:26:56 -0400583
alisione2a38e12013-04-25 14:20:20 -0400584 @Override
585 public ArrayList<HashMap<String, String>> getHistory() throws RemoteException {
586 class History extends SipRunnableWithReturn {
587
588 @Override
589 protected VectMap doRun() throws SameThreadException {
590 Log.i(TAG, "SipService.getHistory() thread running...");
alision7f18fc82013-05-01 09:37:33 -0400591
alisione2a38e12013-04-25 14:20:20 -0400592 return configurationManagerJNI.getHistory();
593 }
594 }
595
596 History runInstance = new History();
597 getExecutor().execute(runInstance);
598 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400599 // Log.w(TAG, "Waiting for getHistory");
alisione2a38e12013-04-25 14:20:20 -0400600 }
alision1005ba12013-06-19 13:52:44 -0400601 Log.i(TAG, "SipService.getHistory() DONE");
alisione2a38e12013-04-25 14:20:20 -0400602 VectMap swigmap = (VectMap) runInstance.getVal();
603
604 ArrayList<HashMap<String, String>> nativemap = HistoryHandler.convertSwigToNative(swigmap);
605
606 return nativemap;
607 }
alision7f18fc82013-05-01 09:37:33 -0400608
alision43a9b362013-05-01 16:30:15 -0400609 /*************************
610 * Transfer related API
611 *************************/
612
alision7f18fc82013-05-01 09:37:33 -0400613 @Override
614 public void transfer(final String callID, final String to) throws RemoteException {
615 getExecutor().execute(new SipRunnable() {
616 @Override
617 protected void doRun() throws SameThreadException, RemoteException {
618 Log.i(TAG, "SipService.transfer() thread running...");
619 if (callManagerJNI.transfer(callID, to)) {
620 Bundle bundle = new Bundle();
621 bundle.putString("CallID", callID);
622 bundle.putString("State", "HUNGUP");
623 Intent intent = new Intent(CallManagerCallBack.CALL_STATE_CHANGED);
alision7f18fc82013-05-01 09:37:33 -0400624 intent.putExtra("com.savoirfairelinux.sflphone.service.newstate", bundle);
alision84813a12013-05-27 17:40:39 -0400625 sendBroadcast(intent);
alision7f18fc82013-05-01 09:37:33 -0400626 } else
627 Log.i(TAG, "NOT OK");
628 }
629 });
630
631 }
alision43a9b362013-05-01 16:30:15 -0400632
alision7f18fc82013-05-01 09:37:33 -0400633 @Override
634 public void attendedTransfer(final String transferID, final String targetID) throws RemoteException {
635 getExecutor().execute(new SipRunnable() {
636 @Override
637 protected void doRun() throws SameThreadException, RemoteException {
alision43a9b362013-05-01 16:30:15 -0400638 Log.i(TAG, "SipService.attendedTransfer() thread running...");
alision7f18fc82013-05-01 09:37:33 -0400639 if (callManagerJNI.attendedTransfer(transferID, targetID)) {
640 Log.i(TAG, "OK");
alision7f18fc82013-05-01 09:37:33 -0400641 } else
642 Log.i(TAG, "NOT OK");
643 }
644 });
alision43a9b362013-05-01 16:30:15 -0400645
646 }
647
648 /*************************
649 * Conference related API
650 *************************/
651
652 @Override
653 public void removeConference(final String confID) throws RemoteException {
654 getExecutor().execute(new SipRunnable() {
655 @Override
656 protected void doRun() throws SameThreadException, RemoteException {
657 Log.i(TAG, "SipService.createConference() thread running...");
658 callManagerJNI.removeConference(confID);
659 }
660 });
661
alision7f18fc82013-05-01 09:37:33 -0400662 }
663
664 @Override
alision43a9b362013-05-01 16:30:15 -0400665 public void joinParticipant(final String sel_callID, final String drag_callID) throws RemoteException {
666 getExecutor().execute(new SipRunnable() {
667 @Override
668 protected void doRun() throws SameThreadException, RemoteException {
669 Log.i(TAG, "SipService.joinParticipant() thread running...");
670 callManagerJNI.joinParticipant(sel_callID, drag_callID);
alision806e18e2013-06-21 15:30:17 -0400671 // Generate a CONF_CREATED callback
alision43a9b362013-05-01 16:30:15 -0400672 }
673 });
674
alision7f18fc82013-05-01 09:37:33 -0400675 }
676
alision7f18fc82013-05-01 09:37:33 -0400677 @Override
alision806e18e2013-06-21 15:30:17 -0400678 public void addParticipant(final SipCall call, final String confID) throws RemoteException {
alision43a9b362013-05-01 16:30:15 -0400679 getExecutor().execute(new SipRunnable() {
680 @Override
681 protected void doRun() throws SameThreadException, RemoteException {
682 Log.i(TAG, "SipService.addParticipant() thread running...");
alision806e18e2013-06-21 15:30:17 -0400683 callManagerJNI.addParticipant(call.getCallId(), confID);
684 current_confs.get(confID).getParticipants().add(call);
alision43a9b362013-05-01 16:30:15 -0400685 }
686 });
687
alision7f18fc82013-05-01 09:37:33 -0400688 }
689
690 @Override
alision43a9b362013-05-01 16:30:15 -0400691 public void addMainParticipant(final String confID) throws RemoteException {
692 getExecutor().execute(new SipRunnable() {
693 @Override
694 protected void doRun() throws SameThreadException, RemoteException {
695 Log.i(TAG, "SipService.addMainParticipant() thread running...");
696 callManagerJNI.addMainParticipant(confID);
697 }
698 });
699
alision7f18fc82013-05-01 09:37:33 -0400700 }
701
702 @Override
alision43a9b362013-05-01 16:30:15 -0400703 public void detachParticipant(final String callID) throws RemoteException {
704 getExecutor().execute(new SipRunnable() {
705 @Override
706 protected void doRun() throws SameThreadException, RemoteException {
707 Log.i(TAG, "SipService.detachParticipant() thread running...");
alision806e18e2013-06-21 15:30:17 -0400708 Log.i(TAG, "Detaching " + callID);
709 Iterator<Entry<String, Conference>> it = current_confs.entrySet().iterator();
710 Log.i(TAG, "current_confs size " + current_confs.size());
711 while (it.hasNext()) {
712 Conference tmp = it.next().getValue();
713 Log.i(TAG, "conf has " + tmp.getParticipants().size() + " participants");
714 if (tmp.contains(callID)) {
715 current_calls.put(callID, tmp.getCall(callID));
716 Log.i(TAG, "Call found and put in current_calls");
717 }
718 }
alision43a9b362013-05-01 16:30:15 -0400719 callManagerJNI.detachParticipant(callID);
720 }
721 });
722
alision7f18fc82013-05-01 09:37:33 -0400723 }
724
725 @Override
alision43a9b362013-05-01 16:30:15 -0400726 public void joinConference(final String sel_confID, final String drag_confID) throws RemoteException {
727 getExecutor().execute(new SipRunnable() {
728 @Override
729 protected void doRun() throws SameThreadException, RemoteException {
730 Log.i(TAG, "SipService.joinConference() thread running...");
731 callManagerJNI.joinConference(sel_confID, drag_confID);
732 }
733 });
734
alision7f18fc82013-05-01 09:37:33 -0400735 }
736
737 @Override
alision43a9b362013-05-01 16:30:15 -0400738 public void hangUpConference(final String confID) throws RemoteException {
739 getExecutor().execute(new SipRunnable() {
740 @Override
741 protected void doRun() throws SameThreadException, RemoteException {
742 Log.i(TAG, "SipService.joinConference() thread running...");
743 callManagerJNI.hangUpConference(confID);
744 }
745 });
746
alision7f18fc82013-05-01 09:37:33 -0400747 }
748
749 @Override
alision43a9b362013-05-01 16:30:15 -0400750 public void holdConference(final String confID) throws RemoteException {
751 getExecutor().execute(new SipRunnable() {
752 @Override
753 protected void doRun() throws SameThreadException, RemoteException {
754 Log.i(TAG, "SipService.holdConference() thread running...");
755 callManagerJNI.holdConference(confID);
756 }
757 });
758
alision7f18fc82013-05-01 09:37:33 -0400759 }
760
761 @Override
alision43a9b362013-05-01 16:30:15 -0400762 public void unholdConference(final String confID) throws RemoteException {
763 getExecutor().execute(new SipRunnable() {
764 @Override
765 protected void doRun() throws SameThreadException, RemoteException {
766 Log.i(TAG, "SipService.unholdConference() thread running...");
767 callManagerJNI.unholdConference(confID);
768 }
769 });
770
alision7f18fc82013-05-01 09:37:33 -0400771 }
772
773 @Override
774 public List getConferenceList() throws RemoteException {
alision4a0eb092013-05-07 13:52:03 -0400775 class ConfList extends SipRunnableWithReturn {
776 @Override
777 protected StringVect doRun() throws SameThreadException {
alision806e18e2013-06-21 15:30:17 -0400778 Log.i(TAG, "SipService.getConferenceList() thread running...");
alision4a0eb092013-05-07 13:52:03 -0400779 return callManagerJNI.getConferenceList();
780 }
781 }
782 ;
783 ConfList runInstance = new ConfList();
784 getExecutor().execute(runInstance);
785 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400786 // Log.w(TAG, "Waiting for getConferenceList");
alision4a0eb092013-05-07 13:52:03 -0400787 }
788 StringVect swigvect = (StringVect) runInstance.getVal();
789
790 ArrayList<String> nativelist = new ArrayList<String>();
791
792 for (int i = 0; i < swigvect.size(); i++)
793 nativelist.add(swigvect.get(i));
794
795 return nativelist;
alision7f18fc82013-05-01 09:37:33 -0400796 }
797
798 @Override
alision907bde72013-06-20 14:40:37 -0400799 public List getParticipantList(final String confID) throws RemoteException {
800 class PartList extends SipRunnableWithReturn {
801 @Override
802 protected StringVect doRun() throws SameThreadException {
803 Log.i(TAG, "SipService.getAccountList() thread running...");
804 return callManagerJNI.getParticipantList(confID);
805 }
806 }
807 ;
808 PartList runInstance = new PartList();
809 getExecutor().execute(runInstance);
810 while (!runInstance.isDone()) {
811 // Log.w(TAG, "Waiting for getConferenceList");
812 }
813 StringVect swigvect = (StringVect) runInstance.getVal();
814
815 ArrayList<String> nativelist = new ArrayList<String>();
816
817 for (int i = 0; i < swigvect.size(); i++)
818 nativelist.add(swigvect.get(i));
819
820 return nativelist;
alision7f18fc82013-05-01 09:37:33 -0400821 }
alision806e18e2013-06-21 15:30:17 -0400822
alision1005ba12013-06-19 13:52:44 -0400823 @Override
alision7f18fc82013-05-01 09:37:33 -0400824 public String getConferenceId(String callID) throws RemoteException {
alision43a9b362013-05-01 16:30:15 -0400825 Log.e(TAG, "getConferenceList not implemented");
alision7f18fc82013-05-01 09:37:33 -0400826 return null;
827 }
828
829 @Override
alision806e18e2013-06-21 15:30:17 -0400830 public String getConferenceDetails(final String callID) throws RemoteException {
831 class ConfDetails extends SipRunnableWithReturn {
832 @Override
833 protected StringMap doRun() throws SameThreadException {
834 Log.i(TAG, "SipService.getAccountList() thread running...");
835 return callManagerJNI.getConferenceDetails(callID);
836 }
837 }
838 ;
839 ConfDetails runInstance = new ConfDetails();
840 getExecutor().execute(runInstance);
841 while (!runInstance.isDone()) {
842 // Log.w(TAG, "Waiting for getConferenceList");
843 }
844 StringMap swigvect = (StringMap) runInstance.getVal();
845
846 return swigvect.get("CONF_STATE");
alision7f18fc82013-05-01 09:37:33 -0400847 }
848
alision04a00182013-05-10 17:05:29 -0400849 @Override
850 public String getRecordPath() throws RemoteException {
851 class RecordPath extends SipRunnableWithReturn {
852
853 @Override
854 protected String doRun() throws SameThreadException {
855 Log.i(TAG, "SipService.getRecordPath() thread running...");
856 return configurationManagerJNI.getRecordPath();
857 }
858 }
859
860 RecordPath runInstance = new RecordPath();
861 getExecutor().execute(runInstance);
862 while (!runInstance.isDone()) {
alision84813a12013-05-27 17:40:39 -0400863 // Log.w(TAG, "Waiting for getRecordPath");
alision04a00182013-05-10 17:05:29 -0400864 }
865 String path = (String) runInstance.getVal();
866
867 return path;
868 }
869
870 @Override
871 public void setRecordingCall(final String id) throws RemoteException {
872 getExecutor().execute(new SipRunnable() {
873 @Override
874 protected void doRun() throws SameThreadException, RemoteException {
875 Log.i(TAG, "SipService.setRecordingCall() thread running...");
876 callManagerJNI.setRecordingCall(id);
877 }
878 });
879
880 }
881
882 @Override
883 public void setRecordPath(final String path) throws RemoteException {
884 getExecutor().execute(new SipRunnable() {
885 @Override
886 protected void doRun() throws SameThreadException, RemoteException {
887 Log.i(TAG, "SipService.setRecordingCall() thread running...");
888 configurationManagerJNI.setRecordPath(path);
889 }
890 });
891 }
892
893 @Override
894 public void sendTextMessage(final String callID, final String message, final String from) throws RemoteException {
895 getExecutor().execute(new SipRunnable() {
896 @Override
897 protected void doRun() throws SameThreadException, RemoteException {
898 Log.i(TAG, "SipService.sendTextMessage() thread running...");
899 callManagerJNI.sendTextMessage(callID, message, from);
900 }
901 });
902
903 }
904
alisiond295ec22013-05-17 10:12:13 -0400905 @Override
906 public List getAudioCodecList(String accountID) throws RemoteException {
alision806e18e2013-06-21 15:30:17 -0400907 // class AudioCodecList extends SipRunnableWithReturn {
908 //
909 // @Override
910 // protected IntVect doRun() throws SameThreadException {
911 // Log.i(TAG, "SipService.getAudioCodecList() thread running...");
912 // return configurationManagerJNI.getAudioCodecList();
913 // }
914 // }
915 //
916 // AudioCodecList runInstance = new AudioCodecList();
917 // getExecutor().execute(runInstance);
918 // while (!runInstance.isDone()) {
919 // Log.w(TAG, "Waiting for getAudioCodecList");
920 // }
921 // IntVect swigmap = (IntVect) runInstance.getVal();
922 //
923 // ArrayList<Integer> codecs = AudioHandler.convertSwigToNative(swigmap);
924 //
925 // return codecs;
alision907bde72013-06-20 14:40:37 -0400926 return null;
alisiond295ec22013-05-17 10:12:13 -0400927 }
928
alision9f7a6ec2013-05-24 16:26:26 -0400929 @Override
alisionfde875f2013-05-28 17:01:54 -0400930 public HashMap<String, SipCall> getCallList() throws RemoteException {
alision85704182013-05-29 15:23:03 -0400931 // class CallList extends SipRunnableWithReturn {
932 //
933 // @Override
934 // protected StringVect doRun() throws SameThreadException {
935 // Log.i(TAG, "SipService.getCallList() thread running...");
936 // return callManagerJNI.getCallList();
937 // }
938 // }
939 //
940 // CallList runInstance = new CallList();
941 // getExecutor().execute(runInstance);
942 // while (!runInstance.isDone()) {
943 // Log.w(TAG, "Waiting for getAudioCodecList");
944 // }
945 // StringVect swigmap = (StringVect) runInstance.getVal();
946 //
947 // ArrayList<String> nativemap = new ArrayList<String>();
948 // for (int i = 0; i < swigmap.size(); ++i) {
949 //
950 // String t = swigmap.get(i);
951 // nativemap.add(t);
952 // }
alision9f7a6ec2013-05-24 16:26:26 -0400953
alision2cb99562013-05-30 17:02:20 -0400954 return getCurrent_calls();
alision9f7a6ec2013-05-24 16:26:26 -0400955 }
956
alision85704182013-05-29 15:23:03 -0400957 @Override
958 public SipCall getCall(String callID) throws RemoteException {
alision2cb99562013-05-30 17:02:20 -0400959 return getCurrent_calls().get(callID);
960 }
961
962 /***********************
963 * Notification API
964 ***********************/
965 @Override
966 public void createNotification() throws RemoteException {
967 makeNotification();
alisioncc7bb422013-06-06 15:31:39 -0400968
alision2cb99562013-05-30 17:02:20 -0400969 }
970
971 @Override
972 public void destroyNotification() throws RemoteException {
973 removeNotification();
alisioncc7bb422013-06-06 15:31:39 -0400974
alision2cb99562013-05-30 17:02:20 -0400975 }
alisioncc7bb422013-06-06 15:31:39 -0400976
alision2cb99562013-05-30 17:02:20 -0400977 private int NOTIFICATION_ID = new Random().nextInt(1000);
alisioncc7bb422013-06-06 15:31:39 -0400978
alision2cb99562013-05-30 17:02:20 -0400979 private void makeNotification() {
alisioncc7bb422013-06-06 15:31:39 -0400980 if (current_calls.size() == 0) {
alision2cb99562013-05-30 17:02:20 -0400981 return;
982 }
983 Intent notificationIntent = new Intent(getApplicationContext(), SFLPhoneHomeActivity.class);
alisioncc7bb422013-06-06 15:31:39 -0400984 PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 007, notificationIntent,
985 PendingIntent.FLAG_UPDATE_CURRENT);
alision2cb99562013-05-30 17:02:20 -0400986
987 NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
988
989 NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
alisioncc7bb422013-06-06 15:31:39 -0400990 //
991 // builder.setContent(view);
992 builder.setContentIntent(contentIntent).setOngoing(true).setSmallIcon(R.drawable.ic_launcher)
993 .setContentTitle(getCurrent_calls().size() + " ongoing calls").setTicker("Pending calls").setWhen(System.currentTimeMillis())
994 .setAutoCancel(false);
alision2cb99562013-05-30 17:02:20 -0400995 builder.setPriority(NotificationCompat.PRIORITY_MAX);
996 Notification n = builder.build();
997
998 nm.notify(NOTIFICATION_ID, n);
alisioncc7bb422013-06-06 15:31:39 -0400999
alision2cb99562013-05-30 17:02:20 -04001000 }
1001
1002 public void removeNotification() {
1003 NotificationManager nm = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
1004 nm.cancel(NOTIFICATION_ID);
alisioncc7bb422013-06-06 15:31:39 -04001005
alision85704182013-05-29 15:23:03 -04001006 }
1007
Emeric Vigier6119d782012-09-21 18:04:14 -04001008 };
Emeric Vigiereaf2c492012-09-19 14:38:20 -04001009}