Home | History | Annotate | Download | only in jni
      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:
    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 
    148 int my_transportation::SendPacket(int channel,const void *data,int len)
    149 {
    150   netw->ReceivedRTPPacket(channel, data, len);
    151   return len;
    152 }
    153 
    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 
    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 
    195 ThreadTest::ThreadTest() :
    196     _thread(NULL)
    197 {
    198     _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority,
    199                                           "ThreadTest thread");
    200 }
    201 
    202 bool ThreadTest::Run(void* ptr)
    203 {
    204     return static_cast<ThreadTest*> (ptr)->Process();
    205 }
    206 
    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 
    281 int ThreadTest::RunTest()
    282 {
    283     if (_thread)
    284     {
    285         unsigned int id;
    286         _thread->Start(id);
    287     }
    288     return 0;
    289 }
    290 
    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 //
    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
    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 //
    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 //
    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 //
    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 //
    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 //
    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
    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
    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
    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
    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 //
    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
    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 //
    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 //
    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 //
    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 //
    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 //
    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
    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
    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 //
    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
    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 //
    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
    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
   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
   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
   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
   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
   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
   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
   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 //
   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 //
   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