• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include <android/log.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15 
16 #include "webrtc/voice_engine/test/android/android_test/jni/org_webrtc_voiceengine_test_AndroidTest.h"
17 
18 #include "webrtc/system_wrappers/interface/thread_wrapper.h"
19 
20 #include "webrtc/voice_engine/include/voe_audio_processing.h"
21 #include "webrtc/voice_engine/include/voe_base.h"
22 #include "webrtc/voice_engine/include/voe_codec.h"
23 #include "webrtc/voice_engine/include/voe_file.h"
24 #include "webrtc/voice_engine/include/voe_hardware.h"
25 #include "webrtc/voice_engine/include/voe_network.h"
26 #include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
27 #include "webrtc/voice_engine/include/voe_volume_control.h"
28 
29 #include "webrtc/voice_engine/test/auto_test/voe_test_interface.h"
30 
31 //#define INIT_FROM_THREAD
32 //#define START_CALL_FROM_THREAD
33 
34 #define WEBRTC_LOG_TAG "*WEBRTCN*" // As in WEBRTC Native...
35 #define VALIDATE_BASE_POINTER \
36     if (!veData1.base) \
37     { \
38         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
39                             "Base pointer doesn't exist"); \
40         return -1; \
41     }
42 #define VALIDATE_CODEC_POINTER \
43     if (!veData1.codec) \
44     { \
45         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
46                             "Codec pointer doesn't exist"); \
47         return -1; \
48     }
49 #define VALIDATE_FILE_POINTER \
50     if (!veData1.file) \
51     { \
52         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
53                             "File pointer doesn't exist"); \
54         return -1; \
55     }
56 #define VALIDATE_NETWORK_POINTER \
57     if (!veData1.netw) \
58     { \
59         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
60                             "Network pointer doesn't exist"); \
61         return -1; \
62     }
63 #define VALIDATE_APM_POINTER \
64     if (!veData1.codec) \
65     { \
66         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
67                             "Apm pointer doesn't exist"); \
68         return -1; \
69     }
70 #define VALIDATE_VOLUME_POINTER \
71     if (!veData1.volume) \
72     { \
73         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
74                             "Volume pointer doesn't exist"); \
75         return -1; \
76     }
77 #define VALIDATE_HARDWARE_POINTER \
78     if (!veData1.hardware) \
79     { \
80         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
81                             "Hardware pointer doesn't exist"); \
82         return -1; \
83     }
84 #define VALIDATE_RTP_RTCP_POINTER \
85     if (!veData1.rtp_rtcp) \
86     { \
87         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, \
88                             "RTP / RTCP pointer doesn't exist"); \
89         return -1; \
90     }
91 
92 // Register functions in JNI_OnLoad()
93 // How do we ensure that VoE is deleted? JNI_OnUnload?
94 // What happens if class is unloaded? When loaded again, NativeInit will be
95 // called again. Keep what we have?
96 // Should we do something in JNI_OnUnload?
97 // General design: create a class or keep global struct with "C" functions?
98 // Otherwise make sure symbols are as unique as possible.
99 
100 // TestType enumerator
101 enum TestType
102 {
103   Invalid = -1,
104   Standard = 0,
105   Extended = 1,
106   Stress   = 2,
107   Unit     = 3,
108   CPU      = 4
109 };
110 
111 using namespace webrtc;
112 
113 class my_transportation;
114 
115 // VoiceEngine data struct
116 typedef struct
117 {
118     // VoiceEngine
119     VoiceEngine* ve;
120     // Sub-APIs
121     VoEBase* base;
122     VoECodec* codec;
123     VoEFile* file;
124     VoENetwork* netw;
125     VoEAudioProcessing* apm;
126     VoEVolumeControl* volume;
127     VoEHardware* hardware;
128     VoERTP_RTCP* rtp_rtcp;
129     // Other
130     my_transportation* extTrans;
131     JavaVM* jvm;
132 } VoiceEngineData;
133 
134 // my_transportation is used when useExtTrans is enabled
135 class my_transportation : public Transport
136 {
137  public:
my_transportation(VoENetwork * network)138   my_transportation(VoENetwork * network) :
139       netw(network) {
140   }
141 
142   int SendPacket(int channel,const void *data,int len);
143   int SendRTCPPacket(int channel, const void *data, int len);
144  private:
145   VoENetwork * netw;
146 };
147 
SendPacket(int channel,const void * data,int len)148 int my_transportation::SendPacket(int channel,const void *data,int len)
149 {
150   netw->ReceivedRTPPacket(channel, data, len);
151   return len;
152 }
153 
SendRTCPPacket(int channel,const void * data,int len)154 int my_transportation::SendRTCPPacket(int channel, const void *data, int len)
155 {
156   netw->ReceivedRTCPPacket(channel, data, len);
157   return len;
158 }
159 
160 //Global variables visible in this file
161 static VoiceEngineData veData1;
162 static VoiceEngineData veData2;
163 
164 // "Local" functions (i.e. not Java accessible)
165 static bool GetSubApis(VoiceEngineData &veData);
166 static bool ReleaseSubApis(VoiceEngineData &veData);
167 
168 class ThreadTest
169 {
170 public:
171     ThreadTest();
172     ~ThreadTest();
173     int RunTest();
174     int CloseTest();
175 private:
176     static bool Run(void* ptr);
177     bool Process();
178 private:
179     ThreadWrapper* _thread;
180 };
181 
~ThreadTest()182 ThreadTest::~ThreadTest()
183 {
184     if (_thread)
185     {
186         _thread->SetNotAlive();
187         if (_thread->Stop())
188         {
189             delete _thread;
190             _thread = NULL;
191         }
192     }
193 }
194 
ThreadTest()195 ThreadTest::ThreadTest() :
196     _thread(NULL)
197 {
198     _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority,
199                                           "ThreadTest thread");
200 }
201 
Run(void * ptr)202 bool ThreadTest::Run(void* ptr)
203 {
204     return static_cast<ThreadTest*> (ptr)->Process();
205 }
206 
Process()207 bool ThreadTest::Process()
208 {
209     // Attach this thread to JVM
210     /*JNIEnv* env = NULL;
211      jint res = veData1.jvm->AttachCurrentThread(&env, NULL);
212      char msg[32];
213      sprintf(msg, "res=%d, env=%d", res, env);
214      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG, msg);*/
215 
216 #ifdef INIT_FROM_THREAD
217     VALIDATE_BASE_POINTER;
218     veData1.base->Init();
219 #endif
220 
221 #ifdef START_CALL_FROM_THREAD
222     // receiving instance
223     veData2.ve = VoiceEngine::Create();
224     GetSubApis(veData2);
225     veData2.base->Init();
226     veData2.base->CreateChannel();
227     if(veData2.base->SetLocalReceiver(0, 1234) < 0)
228     {
229         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
230                 "set local receiver 2 failed");
231     }
232     veData2.hardware->SetLoudspeakerStatus(false);
233     veData2.volume->SetSpeakerVolume(204);
234     veData2.base->StartReceive(0);
235     if(veData2.base->StartPlayout(0) < 0)
236     {
237         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
238                 "start playout failed");
239     }
240 
241     __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
242             "receiving instance started from thread");
243 
244     // sending instance
245     veData1.ve = VoiceEngine::Create();
246     GetSubApis(veData1);
247     veData1.base->Init();
248     if(veData1.base->CreateChannel() < 0)
249     {
250         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
251                 "create channel failed");
252     }
253     if(veData1.base->SetLocalReceiver(0, 1256) < 0)
254     {
255         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
256                 "set local receiver failed");
257     }
258     if(veData1.base->SetSendDestination(0, 1234, "127.0.0.1") < 0)
259     {
260         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
261                 "set send destination failed");
262     }
263     if(veData1.base->StartSend(0) < 0)
264     {
265         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
266                 "start send failed");
267     }
268 
269     __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
270             "sending instance started from thread");
271 #endif
272 
273     _thread->SetNotAlive();
274     _thread->Stop();
275 
276     //res = veData1.jvm->DetachCurrentThread();
277 
278     return true;
279 }
280 
RunTest()281 int ThreadTest::RunTest()
282 {
283     if (_thread)
284     {
285         unsigned int id;
286         _thread->Start(id);
287     }
288     return 0;
289 }
290 
CloseTest()291 int ThreadTest::CloseTest()
292 {
293     VALIDATE_BASE_POINTER
294 
295     veData1.base->DeleteChannel(0);
296     veData2.base->DeleteChannel(0);
297     veData1.base->Terminate();
298     veData2.base->Terminate();
299 
300     // Release sub-APIs
301     ReleaseSubApis(veData1);
302     ReleaseSubApis(veData2);
303 
304     // Delete
305     VoiceEngine::Delete(veData1.ve);
306     VoiceEngine::Delete(veData2.ve);
307     veData2.ve = NULL;
308     veData2.ve = NULL;
309 
310     return 0;
311 }
312 
313 ThreadTest threadTest;
314 
315 //////////////////////////////////////////////////////////////////
316 // General functions
317 //////////////////////////////////////////////////////////////////
318 
319 /////////////////////////////////////////////
320 // JNI_OnLoad
321 //
JNI_OnLoad(JavaVM * vm,void *)322 jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/)
323 {
324     if (!vm)
325     {
326         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
327                             "JNI_OnLoad did not receive a valid VM pointer");
328         return -1;
329     }
330 
331     // Get JNI
332     JNIEnv* env;
333     if (JNI_OK != vm->GetEnv(reinterpret_cast<void**> (&env),
334                              JNI_VERSION_1_4))
335     {
336         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
337                             "JNI_OnLoad could not get JNI env");
338         return -1;
339     }
340 
341     // Get class to register the native functions with
342     // jclass regClass = env->FindClass("webrtc/android/AndroidTest");
343     // if (!regClass) {
344     // return -1; // Exception thrown
345     // }
346 
347     // Register native functions
348     // JNINativeMethod methods[1];
349     // methods[0].name = NULL;
350     // methods[0].signature = NULL;
351     // methods[0].fnPtr = NULL;
352     // if (JNI_OK != env->RegisterNatives(regClass, methods, 1))
353     // {
354     // return -1;
355     // }
356 
357     // Init VoiceEngine data
358     memset(&veData1, 0, sizeof(veData1));
359     memset(&veData2, 0, sizeof(veData2));
360 
361     // Store the JVM
362     veData1.jvm = vm;
363     veData2.jvm = vm;
364 
365     return JNI_VERSION_1_4;
366 }
367 
368 /////////////////////////////////////////////
369 // Native initialization
370 //
371 JNIEXPORT jboolean JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_NativeInit(JNIEnv * env,jclass)372 Java_org_webrtc_voiceengine_test_AndroidTest_NativeInit(
373         JNIEnv * env,
374         jclass)
375 {
376     // Look up and cache any interesting class, field and method IDs for
377     // any used java class here
378 
379     return true;
380 }
381 
382 /////////////////////////////////////////////
383 // Run auto standard test
384 //
Java_org_webrtc_voiceengine_test_AndroidTest_RunAutoTest(JNIEnv * env,jobject context,jint testType,jint extendedSel)385 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_RunAutoTest(
386         JNIEnv *env,
387         jobject context,
388         jint testType,
389         jint extendedSel)
390 {
391     TestType tType(Invalid);
392 
393     switch (testType)
394     {
395         case 0:
396             return 0;
397         case 1:
398             tType = Standard;
399             break;
400         case 2:
401             tType = Extended;
402             break;
403         case 3:
404             tType = Stress;
405             break;
406         case 4:
407             tType = Unit;
408             break;
409         default:
410             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
411                                 "RunAutoTest - Invalid TestType");
412             return -1;
413     }
414 
415     // Set instance independent Java objects
416     VoiceEngine::SetAndroidObjects(veData1.jvm, env, context);
417 
418     // Call voe test interface function
419     // TODO(leozwang) add autotest setAndroidObjects(veData1.jvm, context);
420     // jint retVal = runAutoTest(tType);
421 
422     // Clear instance independent Java objects
423     VoiceEngine::SetAndroidObjects(NULL, NULL, NULL);
424 
425     return 0;
426 }
427 
428 //////////////////////////////////////////////////////////////////
429 // VoiceEngine API wrapper functions
430 //////////////////////////////////////////////////////////////////
431 
432 /////////////////////////////////////////////
433 // Create VoiceEngine instance
434 //
Java_org_webrtc_voiceengine_test_AndroidTest_Create(JNIEnv * env,jobject context)435 JNIEXPORT jboolean JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Create(
436         JNIEnv *env,
437         jobject context)
438 {
439     // Check if already created
440     if (veData1.ve)
441     {
442         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
443                             "VoE already created");
444         return false;
445     }
446 
447     // Set instance independent Java objects
448     VoiceEngine::SetAndroidObjects(veData1.jvm, env, context);
449 
450 #ifdef START_CALL_FROM_THREAD
451     threadTest.RunTest();
452 #else
453     // Create
454     veData1.ve = VoiceEngine::Create();
455     if (!veData1.ve)
456     {
457         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
458                             "Create VoE failed");
459         return false;
460     }
461 
462     // Get sub-APIs
463     if (!GetSubApis(veData1))
464     {
465         // If not OK, release all sub-APIs and delete VoE
466         ReleaseSubApis(veData1);
467         if (!VoiceEngine::Delete(veData1.ve))
468         {
469             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
470                                 "Delete VoE failed");
471         }
472         return false;
473     }
474 #endif
475 
476     return true;
477 }
478 
479 /////////////////////////////////////////////
480 // Delete VoiceEngine instance
481 //
Java_org_webrtc_voiceengine_test_AndroidTest_Delete(JNIEnv *,jobject)482 JNIEXPORT jboolean JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Delete(
483         JNIEnv *,
484         jobject)
485 {
486 #ifdef START_CALL_FROM_THREAD
487     threadTest.CloseTest();
488 #else
489     // Check if exists
490     if (!veData1.ve)
491     {
492         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
493                             "VoE does not exist");
494         return false;
495     }
496 
497     // Release sub-APIs
498     ReleaseSubApis(veData1);
499 
500     // Delete
501     if (!VoiceEngine::Delete(veData1.ve))
502     {
503         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
504                             "Delete VoE failed");
505         return false;
506     }
507 
508     veData1.ve = NULL;
509 #endif
510 
511     // Clear instance independent Java objects
512     VoiceEngine::SetAndroidObjects(NULL, NULL, NULL);
513 
514     return true;
515 }
516 
517 /////////////////////////////////////////////
518 // [Base] Initialize VoiceEngine
519 //
Java_org_webrtc_voiceengine_test_AndroidTest_Init(JNIEnv *,jobject,jboolean enableTrace,jboolean useExtTrans)520 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Init(
521         JNIEnv *,
522         jobject,
523         jboolean enableTrace,
524         jboolean useExtTrans)
525 {
526     VALIDATE_BASE_POINTER;
527 
528     if (enableTrace)
529     {
530         if (0 != VoiceEngine::SetTraceFile("/sdcard/trace.txt"))
531         {
532             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
533                                 "Could not enable trace");
534         }
535         if (0 != VoiceEngine::SetTraceFilter(kTraceAll))
536         {
537             __android_log_write(ANDROID_LOG_WARN, WEBRTC_LOG_TAG,
538                                 "Could not set trace filter");
539         }
540     }
541 
542     if (useExtTrans)
543     {
544         VALIDATE_NETWORK_POINTER;
545         veData1.extTrans = new my_transportation(veData1.netw);
546     }
547 
548     int retVal = 0;
549 #ifdef INIT_FROM_THREAD
550     threadTest.RunTest();
551     usleep(200000);
552 #else
553     retVal = veData1.base->Init();
554 #endif
555     return retVal;
556 }
557 
558 /////////////////////////////////////////////
559 // [Base] Terminate VoiceEngine
560 //
Java_org_webrtc_voiceengine_test_AndroidTest_Terminate(JNIEnv *,jobject)561 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_Terminate(
562         JNIEnv *,
563         jobject)
564 {
565     VALIDATE_BASE_POINTER;
566 
567     jint retVal = veData1.base->Terminate();
568 
569     delete veData1.extTrans;
570     veData1.extTrans = NULL;
571 
572     return retVal;
573 }
574 
575 /////////////////////////////////////////////
576 // [Base] Create channel
577 //
578 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_CreateChannel(JNIEnv *,jobject)579 Java_org_webrtc_voiceengine_test_AndroidTest_CreateChannel(
580         JNIEnv *,
581         jobject)
582 {
583     VALIDATE_BASE_POINTER;
584     jint channel = veData1.base->CreateChannel();
585 
586     if (veData1.extTrans)
587     {
588         VALIDATE_NETWORK_POINTER;
589         __android_log_print(ANDROID_LOG_DEBUG, WEBRTC_LOG_TAG,
590                             "Enabling external transport on channel %d",
591                             channel);
592         if (veData1.netw->RegisterExternalTransport(channel, *veData1.extTrans)
593                 < 0)
594         {
595             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
596                                 "Could not set external transport");
597             return -1;
598         }
599     }
600 
601     return channel;
602 }
603 
604 /////////////////////////////////////////////
605 // [Base] Delete channel
606 //
607 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_DeleteChannel(JNIEnv *,jobject,jint channel)608 Java_org_webrtc_voiceengine_test_AndroidTest_DeleteChannel(
609         JNIEnv *,
610         jobject,
611         jint channel)
612 {
613     VALIDATE_BASE_POINTER;
614     return veData1.base->DeleteChannel(channel);
615 }
616 
617 /////////////////////////////////////////////
618 // [Base] SetLocalReceiver
619 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetLocalReceiver(JNIEnv *,jobject,jint channel,jint port)620 Java_org_webrtc_voiceengine_test_AndroidTest_SetLocalReceiver(
621         JNIEnv *,
622         jobject,
623         jint channel,
624         jint port)
625 {
626     VALIDATE_BASE_POINTER;
627     return veData1.base->SetLocalReceiver(channel, port);
628 }
629 
630 /////////////////////////////////////////////
631 // [Base] SetSendDestination
632 //
633 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSendDestination(JNIEnv * env,jobject,jint channel,jint port,jstring ipaddr)634 Java_org_webrtc_voiceengine_test_AndroidTest_SetSendDestination(
635         JNIEnv *env,
636         jobject,
637         jint channel,
638         jint port,
639         jstring ipaddr)
640 {
641     VALIDATE_BASE_POINTER;
642 
643     const char* ipaddrNative = env->GetStringUTFChars(ipaddr, NULL);
644     if (!ipaddrNative)
645     {
646         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
647                             "Could not get UTF string");
648         return -1;
649     }
650 
651     jint retVal = veData1.base->SetSendDestination(channel, port, ipaddrNative);
652 
653     env->ReleaseStringUTFChars(ipaddr, ipaddrNative);
654 
655     return retVal;
656 }
657 
658 /////////////////////////////////////////////
659 // [Base] StartListen
660 //
Java_org_webrtc_voiceengine_test_AndroidTest_StartListen(JNIEnv *,jobject,jint channel)661 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StartListen(
662         JNIEnv *,
663         jobject,
664         jint channel)
665 {
666     VALIDATE_BASE_POINTER;
667     int retVal = veData1.base->StartReceive(channel);
668 
669     return retVal;
670 }
671 
672 /////////////////////////////////////////////
673 // [Base] Start playout
674 //
675 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayout(JNIEnv *,jobject,jint channel)676 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayout(
677         JNIEnv *,
678         jobject,
679         jint channel)
680 {
681     VALIDATE_BASE_POINTER;
682     int retVal = veData1.base->StartPlayout(channel);
683 
684     return retVal;
685 }
686 
687 /////////////////////////////////////////////
688 // [Base] Start send
689 //
Java_org_webrtc_voiceengine_test_AndroidTest_StartSend(JNIEnv *,jobject,jint channel)690 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StartSend(
691         JNIEnv *,
692         jobject,
693         jint channel)
694 {
695     /*    int dscp(0), serviceType(-1), overrideDscp(0), res(0);
696      bool gqosEnabled(false), useSetSockOpt(false);
697 
698      if (veData1.netw->SetSendTOS(channel, 13, useSetSockOpt) != 0)
699      {
700      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
701          "Failed to set TOS");
702      return -1;
703      }
704 
705      res = veData1.netw->GetSendTOS(channel, dscp, useSetSockOpt);
706      if (res != 0 || dscp != 13 || useSetSockOpt != true)
707      {
708      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
709          "Failed to get TOS");
710      return -1;
711      } */
712 
713     /* if (veData1.rtp_rtcp->SetREDStatus(channel, 1) != 0)
714      {
715      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
716          "Failed to enable RED");
717      return -1;
718      } */
719 
720     VALIDATE_BASE_POINTER;
721     int retVal = veData1.base->StartSend(channel);
722 
723     return retVal;
724 }
725 
726 /////////////////////////////////////////////
727 // [Base] Stop listen
728 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopListen(JNIEnv *,jobject,jint channel)729 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopListen(
730         JNIEnv *,
731         jobject,
732         jint channel)
733 {
734     VALIDATE_BASE_POINTER;
735     return veData1.base->StopReceive(channel);
736 }
737 
738 /////////////////////////////////////////////
739 // [Base] Stop playout
740 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayout(JNIEnv *,jobject,jint channel)741 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayout(
742         JNIEnv *,
743         jobject,
744         jint channel)
745 {
746     VALIDATE_BASE_POINTER;
747     return veData1.base->StopPlayout(channel);
748 }
749 
750 /////////////////////////////////////////////
751 // [Base] Stop send
752 //
Java_org_webrtc_voiceengine_test_AndroidTest_StopSend(JNIEnv *,jobject,jint channel)753 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_StopSend(
754         JNIEnv *,
755         jobject,
756         jint channel)
757 {
758     /* if (veData1.rtp_rtcp->SetREDStatus(channel, 0) != 0)
759      {
760      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
761          "Failed to disable RED");
762      return -1;
763      } */
764 
765     VALIDATE_BASE_POINTER;
766     return veData1.base->StopSend(channel);
767 }
768 
769 /////////////////////////////////////////////
770 // [codec] Number of codecs
771 //
Java_org_webrtc_voiceengine_test_AndroidTest_NumOfCodecs(JNIEnv *,jobject)772 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_NumOfCodecs(
773         JNIEnv *,
774         jobject)
775 {
776     VALIDATE_CODEC_POINTER;
777     return veData1.codec->NumOfCodecs();
778 }
779 
780 /////////////////////////////////////////////
781 // [codec] Set send codec
782 //
783 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSendCodec(JNIEnv *,jobject,jint channel,jint index)784 Java_org_webrtc_voiceengine_test_AndroidTest_SetSendCodec(
785         JNIEnv *,
786         jobject,
787         jint channel,
788         jint index)
789 {
790     VALIDATE_CODEC_POINTER;
791 
792     CodecInst codec;
793 
794     if (veData1.codec->GetCodec(index, codec) != 0)
795     {
796         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
797                             "Failed to get codec");
798         return -1;
799     }
800 
801     return veData1.codec->SetSendCodec(channel, codec);
802 }
803 
804 /////////////////////////////////////////////
805 // [codec] Set VAD status
806 //
807 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetVADStatus(JNIEnv *,jobject,jint channel,jboolean enable,jint mode)808 Java_org_webrtc_voiceengine_test_AndroidTest_SetVADStatus(
809         JNIEnv *,
810         jobject,
811         jint channel,
812         jboolean enable,
813         jint mode)
814 {
815     VALIDATE_CODEC_POINTER;
816 
817     VadModes VADmode = kVadConventional;
818 
819     switch (mode)
820     {
821         case 0:
822             break; // already set
823         case 1:
824             VADmode = kVadAggressiveLow;
825             break;
826         case 2:
827             VADmode = kVadAggressiveMid;
828             break;
829         case 3:
830             VADmode = kVadAggressiveHigh;
831             break;
832         default:
833             VADmode = (VadModes) 17; // force error
834             break;
835     }
836 
837     return veData1.codec->SetVADStatus(channel, enable, VADmode);
838 }
839 
840 /////////////////////////////////////////////
841 // [apm] SetNSStatus
842 //
Java_org_webrtc_voiceengine_test_AndroidTest_SetNSStatus(JNIEnv *,jobject,jboolean enable,jint mode)843 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_SetNSStatus(
844         JNIEnv *,
845         jobject,
846         jboolean enable,
847         jint mode)
848 {
849     VALIDATE_APM_POINTER;
850 
851     NsModes NSmode = kNsDefault;
852 
853     switch (mode)
854     {
855         case 0:
856             NSmode = kNsUnchanged;
857             break;
858         case 1:
859             break; // already set
860         case 2:
861             NSmode = kNsConference;
862             break;
863         case 3:
864             NSmode = kNsLowSuppression;
865             break;
866         case 4:
867             NSmode = kNsModerateSuppression;
868             break;
869         case 5:
870             NSmode = kNsHighSuppression;
871             break;
872         case 6:
873             NSmode = kNsVeryHighSuppression;
874             break;
875         default:
876             NSmode = (NsModes) 17; // force error
877             break;
878     }
879 
880     return veData1.apm->SetNsStatus(enable, NSmode);
881 }
882 
883 /////////////////////////////////////////////
884 // [apm] SetAGCStatus
885 //
886 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetAGCStatus(JNIEnv *,jobject,jboolean enable,jint mode)887 Java_org_webrtc_voiceengine_test_AndroidTest_SetAGCStatus(
888         JNIEnv *,
889         jobject,
890         jboolean enable,
891         jint mode)
892 {
893     VALIDATE_APM_POINTER;
894 
895     AgcModes AGCmode = kAgcDefault;
896 
897     switch (mode)
898     {
899         case 0:
900             AGCmode = kAgcUnchanged;
901             break;
902         case 1:
903             break; // already set
904         case 2:
905             AGCmode = kAgcAdaptiveAnalog;
906             break;
907         case 3:
908             AGCmode = kAgcAdaptiveDigital;
909             break;
910         case 4:
911             AGCmode = kAgcFixedDigital;
912             break;
913         default:
914             AGCmode = (AgcModes) 17; // force error
915             break;
916     }
917 
918     /* AgcConfig agcConfig;
919      agcConfig.targetLeveldBOv = 3;
920      agcConfig.digitalCompressionGaindB = 50;
921      agcConfig.limiterEnable = 0;
922 
923      if (veData1.apm->SetAGCConfig(agcConfig) != 0)
924      {
925      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
926          "Failed to set AGC config");
927      return -1;
928      } */
929 
930     return veData1.apm->SetAgcStatus(enable, AGCmode);
931 }
932 
933 /////////////////////////////////////////////
934 // [apm] SetECStatus
935 //
Java_org_webrtc_voiceengine_test_AndroidTest_SetECStatus(JNIEnv *,jobject,jboolean enable,jint mode)936 JNIEXPORT jint JNICALL Java_org_webrtc_voiceengine_test_AndroidTest_SetECStatus(
937         JNIEnv *,
938         jobject,
939         jboolean enable,
940         jint mode)
941 {
942     VALIDATE_APM_POINTER;
943 
944     EcModes ECmode = kEcDefault;
945 
946     switch (mode)
947     {
948         case 0:
949             ECmode = kEcDefault;
950             break;
951         case 1:
952             break; // already set
953         case 2:
954             ECmode = kEcConference;
955             break;
956         case 3:
957             ECmode = kEcAec;
958             break;
959         case 4:
960             ECmode = kEcAecm;
961             break;
962         default:
963             ECmode = (EcModes) 17; // force error
964             break;
965     }
966 
967     return veData1.apm->SetEcStatus(enable, ECmode);
968 }
969 
970 /////////////////////////////////////////////
971 // [File] Start play file locally
972 //
973 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileLocally(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean loop)974 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileLocally(
975         JNIEnv * env,
976         jobject,
977         jint channel,
978         jstring fileName,
979         jboolean loop)
980 {
981     VALIDATE_FILE_POINTER;
982 
983     const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
984     if (!fileNameNative)
985     {
986         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
987                             "Could not get UTF string");
988         return -1;
989     }
990 
991     jint retVal = veData1.file->StartPlayingFileLocally(channel,
992                                                         fileNameNative, loop);
993 
994     env->ReleaseStringUTFChars(fileName, fileNameNative);
995 
996     return retVal;
997 }
998 
999 /////////////////////////////////////////////
1000 // [File] Stop play file locally
1001 //
1002 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileLocally(JNIEnv *,jobject,jint channel)1003 Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileLocally(
1004         JNIEnv *,
1005         jobject,
1006         jint channel)
1007 {
1008     VALIDATE_FILE_POINTER;
1009     return veData1.file->StopPlayingFileLocally(channel);
1010 }
1011 
1012 /*
1013  * Class:     org_webrtc_voiceengine_test_AndroidTest
1014  * Method:    StartRecordingPlayout
1015  * Signature: (ILjava/lang/String;Z)I
1016  */
1017 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartRecordingPlayout(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean)1018 Java_org_webrtc_voiceengine_test_AndroidTest_StartRecordingPlayout(
1019         JNIEnv * env,
1020         jobject,
1021         jint channel,
1022         jstring fileName,
1023         jboolean)
1024 {
1025     VALIDATE_FILE_POINTER;
1026 
1027     const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
1028     if (!fileNameNative)
1029     {
1030         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1031                             "Could not get UTF string");
1032         return -1;
1033     }
1034 
1035     jint retVal = veData1.file->StartRecordingPlayout(channel, fileNameNative,
1036                                                       0);
1037 
1038     env->ReleaseStringUTFChars(fileName, fileNameNative);
1039 
1040     return retVal;
1041 }
1042 
1043 /////////////////////////////////////////////
1044 // [File] Stop Recording Playout
1045 //
1046 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopRecordingPlayout(JNIEnv *,jobject,jint channel)1047 Java_org_webrtc_voiceengine_test_AndroidTest_StopRecordingPlayout(
1048         JNIEnv *,
1049         jobject,
1050         jint channel)
1051 {
1052     VALIDATE_FILE_POINTER;
1053     return veData1.file->StopRecordingPlayout(channel);
1054 }
1055 
1056 /////////////////////////////////////////////
1057 // [File] Start playing file as microphone
1058 //
1059 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileAsMicrophone(JNIEnv * env,jobject,jint channel,jstring fileName,jboolean loop)1060 Java_org_webrtc_voiceengine_test_AndroidTest_StartPlayingFileAsMicrophone(
1061         JNIEnv *env,
1062         jobject,
1063         jint channel,
1064         jstring fileName,
1065         jboolean loop)
1066 {
1067     VALIDATE_FILE_POINTER;
1068 
1069     const char* fileNameNative = env->GetStringUTFChars(fileName, NULL);
1070     if (!fileNameNative)
1071     {
1072         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1073                             "Could not get UTF string");
1074         return -1;
1075     }
1076 
1077     jint retVal = veData1.file->StartPlayingFileAsMicrophone(channel,
1078                                                              fileNameNative,
1079                                                              loop);
1080 
1081     env->ReleaseStringUTFChars(fileName, fileNameNative);
1082 
1083     return retVal;
1084 }
1085 
1086 /////////////////////////////////////////////
1087 // [File] Stop playing file as microphone
1088 //
1089 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileAsMicrophone(JNIEnv *,jobject,jint channel)1090 Java_org_webrtc_voiceengine_test_AndroidTest_StopPlayingFileAsMicrophone(
1091         JNIEnv *,
1092         jobject,
1093         jint channel)
1094 {
1095     VALIDATE_FILE_POINTER;
1096     return veData1.file->StopPlayingFileAsMicrophone(channel);
1097 }
1098 
1099 /////////////////////////////////////////////
1100 // [Volume] Set speaker volume
1101 //
1102 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetSpeakerVolume(JNIEnv *,jobject,jint level)1103 Java_org_webrtc_voiceengine_test_AndroidTest_SetSpeakerVolume(
1104         JNIEnv *,
1105         jobject,
1106         jint level)
1107 {
1108     VALIDATE_VOLUME_POINTER;
1109     if (veData1.volume->SetSpeakerVolume(level) != 0)
1110     {
1111         return -1;
1112     }
1113 
1114     unsigned int storedVolume = 0;
1115     if (veData1.volume->GetSpeakerVolume(storedVolume) != 0)
1116     {
1117         return -1;
1118     }
1119 
1120     if (storedVolume != level)
1121     {
1122         return -1;
1123     }
1124 
1125     return 0;
1126 }
1127 
1128 /////////////////////////////////////////////
1129 // [Hardware] Set loudspeaker status
1130 //
1131 JNIEXPORT jint JNICALL
Java_org_webrtc_voiceengine_test_AndroidTest_SetLoudspeakerStatus(JNIEnv *,jobject,jboolean enable)1132 Java_org_webrtc_voiceengine_test_AndroidTest_SetLoudspeakerStatus(
1133         JNIEnv *,
1134         jobject,
1135         jboolean enable)
1136 {
1137     VALIDATE_HARDWARE_POINTER;
1138     if (veData1.hardware->SetLoudspeakerStatus(enable) != 0)
1139     {
1140         return -1;
1141     }
1142 
1143     /*VALIDATE_RTP_RTCP_POINTER;
1144 
1145      if (veData1.rtp_rtcp->SetREDStatus(0, enable, -1) != 0)
1146      {
1147      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1148          "Could not set RED");
1149      return -1;
1150      }
1151      else if(enable)
1152      {
1153      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1154          "Could enable RED");
1155      }
1156      else
1157      {
1158      __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1159          "Could disable RED");
1160      }*/
1161 
1162     return 0;
1163 }
1164 
1165 //////////////////////////////////////////////////////////////////
1166 // "Local" functions (i.e. not Java accessible)
1167 //////////////////////////////////////////////////////////////////
1168 
1169 /////////////////////////////////////////////
1170 // Get all sub-APIs
1171 //
GetSubApis(VoiceEngineData & veData)1172 bool GetSubApis(VoiceEngineData &veData)
1173 {
1174     bool getOK = true;
1175 
1176     // Base
1177     veData.base = VoEBase::GetInterface(veData.ve);
1178     if (!veData.base)
1179     {
1180         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1181                             "Get base sub-API failed");
1182         getOK = false;
1183     }
1184 
1185     // Codec
1186     veData.codec = VoECodec::GetInterface(veData.ve);
1187     if (!veData.codec)
1188     {
1189         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1190                             "Get codec sub-API failed");
1191         getOK = false;
1192     }
1193 
1194     // File
1195     veData.file = VoEFile::GetInterface(veData.ve);
1196     if (!veData.file)
1197     {
1198         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1199                             "Get file sub-API failed");
1200         getOK = false;
1201     }
1202 
1203     // Network
1204     veData.netw = VoENetwork::GetInterface(veData.ve);
1205     if (!veData.netw)
1206     {
1207         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1208                             "Get network sub-API failed");
1209         getOK = false;
1210     }
1211 
1212     // AudioProcessing module
1213     veData.apm = VoEAudioProcessing::GetInterface(veData.ve);
1214     if (!veData.apm)
1215     {
1216         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1217                             "Get apm sub-API failed");
1218         getOK = false;
1219     }
1220 
1221     // Volume
1222     veData.volume = VoEVolumeControl::GetInterface(veData.ve);
1223     if (!veData.volume)
1224     {
1225         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1226                             "Get volume sub-API failed");
1227         getOK = false;
1228     }
1229 
1230     // Hardware
1231     veData.hardware = VoEHardware::GetInterface(veData.ve);
1232     if (!veData.hardware)
1233     {
1234         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1235                             "Get hardware sub-API failed");
1236         getOK = false;
1237     }
1238 
1239     // RTP / RTCP
1240     veData.rtp_rtcp = VoERTP_RTCP::GetInterface(veData.ve);
1241     if (!veData.rtp_rtcp)
1242     {
1243         __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1244                             "Get rtp_rtcp sub-API failed");
1245         getOK = false;
1246     }
1247 
1248     return getOK;
1249 }
1250 
1251 /////////////////////////////////////////////
1252 // Release all sub-APIs
1253 //
ReleaseSubApis(VoiceEngineData & veData)1254 bool ReleaseSubApis(VoiceEngineData &veData)
1255 {
1256     bool releaseOK = true;
1257 
1258     // Base
1259     if (veData.base)
1260     {
1261         if (0 != veData.base->Release())
1262         {
1263             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1264                                 "Release base sub-API failed");
1265             releaseOK = false;
1266         }
1267         else
1268         {
1269             veData.base = NULL;
1270         }
1271     }
1272 
1273     // Codec
1274     if (veData.codec)
1275     {
1276         if (0 != veData.codec->Release())
1277         {
1278             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1279                                 "Release codec sub-API failed");
1280             releaseOK = false;
1281         }
1282         else
1283         {
1284             veData.codec = NULL;
1285         }
1286     }
1287 
1288     // File
1289     if (veData.file)
1290     {
1291         if (0 != veData.file->Release())
1292         {
1293             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1294                                 "Release file sub-API failed");
1295             releaseOK = false;
1296         }
1297         else
1298         {
1299             veData.file = NULL;
1300         }
1301     }
1302 
1303     // Network
1304     if (veData.netw)
1305     {
1306         if (0 != veData.netw->Release())
1307         {
1308             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1309                                 "Release network sub-API failed");
1310             releaseOK = false;
1311         }
1312         else
1313         {
1314             veData.netw = NULL;
1315         }
1316     }
1317 
1318     // apm
1319     if (veData.apm)
1320     {
1321         if (0 != veData.apm->Release())
1322         {
1323             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1324                                 "Release apm sub-API failed");
1325             releaseOK = false;
1326         }
1327         else
1328         {
1329             veData.apm = NULL;
1330         }
1331     }
1332 
1333     // Volume
1334     if (veData.volume)
1335     {
1336         if (0 != veData.volume->Release())
1337         {
1338             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1339                                 "Release volume sub-API failed");
1340             releaseOK = false;
1341         }
1342         else
1343         {
1344             veData.volume = NULL;
1345         }
1346     }
1347 
1348     // Hardware
1349     if (veData.hardware)
1350     {
1351         if (0 != veData.hardware->Release())
1352         {
1353             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1354                                 "Release hardware sub-API failed");
1355             releaseOK = false;
1356         }
1357         else
1358         {
1359             veData.hardware = NULL;
1360         }
1361     }
1362 
1363     // RTP RTCP
1364     if (veData.rtp_rtcp)
1365     {
1366         if (0 != veData.rtp_rtcp->Release())
1367         {
1368             __android_log_write(ANDROID_LOG_ERROR, WEBRTC_LOG_TAG,
1369                                 "Release rtp_rtcp sub-API failed");
1370             releaseOK = false;
1371         }
1372         else
1373         {
1374             veData.rtp_rtcp = NULL;
1375         }
1376     }
1377 
1378     return releaseOK;
1379 }
1380