Browse Source

[WallPadCall]
소스 업로드 (버전 2022.06.13.01)

jigsjjang 2 years ago
parent
commit
ec59c7c8d5
72 changed files with 23630 additions and 16 deletions
  1. 1 1
      WallPadCall/src/main/AndroidManifest.xml
  2. 105 0
      WallPadCall/src/main/java/bssoft/stack/sip/BSSVideo.java
  3. 3859 0
      WallPadCall/src/main/java/bssoft/stack/sip/CMCore.java
  4. 21 0
      WallPadCall/src/main/java/bssoft/stack/sip/Frequent.java
  5. 36 0
      WallPadCall/src/main/java/bssoft/stack/sip/GetIpDns.java
  6. 82 0
      WallPadCall/src/main/java/bssoft/stack/sip/History.java
  7. 95 0
      WallPadCall/src/main/java/bssoft/stack/sip/RFC2833.java
  8. 328 0
      WallPadCall/src/main/java/bssoft/stack/sip/RTPCore.java
  9. 316 0
      WallPadCall/src/main/java/bssoft/stack/sip/SDPMedia.java
  10. 138 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPAUTHENTICATEHeader.java
  11. 330 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPCONTACTHeader.java
  12. 2511 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPCall.java
  13. 362 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPG711.java
  14. 225 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPHeader.java
  15. 268 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPHeaderParty.java
  16. 135 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPROUTEHeader.java
  17. 204 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPRequestLine.java
  18. 248 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPSdp.java
  19. 785 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPStack.java
  20. 124 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPVIAHeader.java
  21. 38 0
      WallPadCall/src/main/java/bssoft/stack/sip/SIPmd5.java
  22. 294 0
      WallPadCall/src/main/java/bssoft/stack/sip/UPDATEHeaders.java
  23. 11 0
      WallPadCall/src/main/java/bssoft/stack/sip/UserDial.java
  24. 87 0
      WallPadCall/src/main/java/bssoft/stack/sip/stackKey.java
  25. 228 0
      WallPadCall/src/main/java/bssoft/stack/sip/videoEnc.java
  26. 190 0
      WallPadCall/src/main/java/ceres/api/AECParam.java
  27. 963 0
      WallPadCall/src/main/java/ceres/api/Configuration.java
  28. 127 0
      WallPadCall/src/main/java/ceres/api/SipConfigManager.java
  29. 425 0
      WallPadCall/src/main/java/ceres/api/SipManager.java
  30. 103 0
      WallPadCall/src/main/java/ceres/api/SpamList.java
  31. 0 0
      WallPadCall/src/main/java/ceres/api/UAStateReceiver.java
  32. 98 0
      WallPadCall/src/main/java/ceres/cminterface/CMAccStatus.java
  33. 80 0
      WallPadCall/src/main/java/ceres/cminterface/CMCallInfo.java
  34. 2552 0
      WallPadCall/src/main/java/ceres/cminterface/CMInterface.java
  35. 435 0
      WallPadCall/src/main/java/ceres/cminterface/DupCallInfo.java
  36. 130 0
      WallPadCall/src/main/java/ceres/cminterface/NPMetrics.java
  37. 113 0
      WallPadCall/src/main/java/ceres/cminterface/cnssipuaJNI.java
  38. 516 0
      WallPadCall/src/main/java/ceres/db/DBAdapter.java
  39. 1335 0
      WallPadCall/src/main/java/ceres/pcminterface/PCMInterface.java
  40. 149 0
      WallPadCall/src/main/java/ceres/security/Base64Utils.java
  41. 410 0
      WallPadCall/src/main/java/ceres/security/SeedAlg.java
  42. 178 0
      WallPadCall/src/main/java/ceres/service/MediaManager.java
  43. 113 0
      WallPadCall/src/main/java/ceres/service/MyTCPServer.java
  44. 187 0
      WallPadCall/src/main/java/ceres/service/SipNotifications.java
  45. 243 0
      WallPadCall/src/main/java/ceres/srinterface/AvcEncoder.java
  46. 285 0
      WallPadCall/src/main/java/ceres/srinterface/MediaDecoder.java
  47. 1414 0
      WallPadCall/src/main/java/ceres/srinterface/SRInterface.java
  48. 118 0
      WallPadCall/src/main/java/ceres/utils/CallLogHelper.java
  49. 177 0
      WallPadCall/src/main/java/ceres/utils/CollectLogs.java
  50. 424 0
      WallPadCall/src/main/java/ceres/utils/Compatibility.java
  51. 47 0
      WallPadCall/src/main/java/ceres/utils/CustomDistribution.java
  52. 164 0
      WallPadCall/src/main/java/ceres/utils/DialingFeedback.java
  53. 146 0
      WallPadCall/src/main/java/ceres/utils/IpAddress.java
  54. 941 0
      WallPadCall/src/main/java/ceres/utils/PreferencesWrapper.java
  55. 232 0
      WallPadCall/src/main/java/ceres/utils/Ringer.java
  56. 32 0
      WallPadCall/src/main/java/ceres/utils/Threading.java
  57. 151 0
      WallPadCall/src/main/java/ceres/utils/printlog.java
  58. 1 1
      WallPadCall/src/main/java/kr/co/icontrols/V40IFCCD/V40IFCCD.java
  59. 12 0
      WallPadCall/src/main/java/kr/co/icontrols/callengine/engine/SIPInterface.java
  60. 2 2
      WallPadCall/src/main/java/kr/co/icontrols/callengine/engine/VideoJNI.java
  61. 26 6
      WallPadCall/src/main/java/kr/co/icontrols/callengine/sip/SIPStun.java
  62. 2 2
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/declare/Global.java
  63. 191 0
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/popup/UpdateInfo.java
  64. 7 0
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/InquiryCallHistory.java
  65. 19 2
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkFront.java
  66. 44 2
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkGuard.java
  67. 11 0
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkLobby.java
  68. 6 0
      WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkResidence.java
  69. BIN
      WallPadCall/src/main/res/drawable-ldpi/bg_update_popup.png
  70. BIN
      WallPadCall/src/main/res/drawable-ldpi/btn_update_ok_normal.png
  71. BIN
      WallPadCall/src/main/res/drawable-ldpi/btn_update_ok_pressed.png
  72. BIN
      WallPadCall/src/main/res/drawable-ldpi/icon_update.png

+ 1 - 1
WallPadCall/src/main/AndroidManifest.xml

@@ -1,7 +1,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="kr.co.icontrols.wallpadcall"
     android:versionCode="17"
-    android:versionName="2022.02.04.01">
+    android:versionName="2022.06.13.01">
 
     <!--android:sharedUserId="android.uid.system"-->
     <!--<uses-sdk-->

+ 105 - 0
WallPadCall/src/main/java/bssoft/stack/sip/BSSVideo.java

@@ -0,0 +1,105 @@
+package bssoft.stack.sip;
+
+import java.util.Date;
+
+public class BSSVideo {
+    public static int HNS_SERVICE_NONE = 9;
+
+    public static int HNS_SERVICE_DOOR = 0;
+
+    public static int HNS_SERVICE_LOBBY = 1;
+
+    public static int HNS_SERVICE_GUARD = 2;
+
+    public static int HNS_SERVICE_NEIGHBOR = 3;
+
+    public static int HNS_SERVICE_TELEPHONE = 4;
+
+    public static int HNS_SERVICE_HISTORY = 5;
+
+    public static int HNS_SERVICE_PICTURE = 6;
+
+    public static int HNS_SERVICE_ORIGINATOR_SELECTED = HNS_SERVICE_NEIGHBOR;
+
+    public static int HNS_SERVICE_RECEIVER_SELECTED = HNS_SERVICE_NONE;
+
+    public static String HNS_PREFIX_LOBBY = "HNSLOBBY.";
+
+    public static String HNS_PREFIX_GUARD = "HNSGUARD.";
+
+    public static String HNS_PREFIX_NEIGHBOR = "HNSNEIGHBOR.";
+
+    public static String HNS_POSTFIX_LOBBY = ".HNSLOBBY";
+
+    public static String HNS_POSTFIX_GUARD = ".HNSGUARD";
+
+    public static String HNS_POSTFIX_NEIGHBOR = ".HNSNEIGHBOR";
+
+    public static int codec = 98;
+
+    public static int VIDEO_PTIME = 200;
+
+    public static boolean bInitializeMode = false;
+
+    public static int camera_width = 320;
+
+    public static int camera_height = 240;
+
+    public static int decode_width = 320;
+
+    public static int decode_height = 240;
+
+    public static int yuv_width = 320;
+
+    public static int yuv_height = 240;
+
+    public static int yuv_offset_x = 0;
+
+    public static int yuv_offset_y = 0;
+
+    public static int ENCODE_FRAME_RATE = 30;
+
+    public static int KEY_FRAME_RATE = 15;
+
+    public static int KEY_I_FRAME_INTERVAL = 5;
+
+    public static int KEY_BIT_RATE = 1440000;
+
+    public static boolean bService = false;
+
+    public static boolean bViewme = false;
+
+    public static int displaySizeType = 0;
+
+    public static boolean bSending = false;
+
+    public static boolean bFrameSet = false;
+
+    public static int iFrames = 0;
+
+    public static String remoteIp = null;
+
+    public static int remotePort = 3002;
+
+    public static int iRunmode = 0;
+
+    public static boolean bVideoEncoding = false;
+
+    public static boolean bVideoDecoding = false;
+
+    public static boolean bSurfaceoutput = true;
+
+    public static boolean bCover = true;
+
+    public static boolean bRemoteview = false;
+
+    public static Date dateVideoincoming = new Date();
+
+    public static int incurtenLength = 2000;
+
+    public static int outcurtenLength = 1000;
+
+    public static boolean bVideoMute = false;
+
+    public static boolean bProgressvideooffer = false;
+}

+ 3859 - 0
WallPadCall/src/main/java/bssoft/stack/sip/CMCore.java

@@ -0,0 +1,3859 @@
+package bssoft.stack.sip;
+
+import android.util.Log;
+
+import java.util.Date;
+import java.util.StringTokenizer;
+import java.util.Timer;
+
+public class CMCore {
+    String TAG = "CMCore";
+
+    public String commandLine = null;
+
+    public String viaH = null;
+
+    public String maxforwardH = null;
+
+    public String contactH = null;
+
+    public String toH = null;
+
+    public String fromH = null;
+
+    public String callidH = null;
+
+    public String cseqH = null;
+
+    public String expiresH = null;
+
+    public String allowH = null;
+
+    public String useragentH = null;
+
+    public String contentlengthH = null;
+
+    public String authorizationH = null;
+
+    public String serverIp = null;
+
+    public int serverPort = 5060;
+
+    public String serverDomain = null;
+
+    public String id = null;
+
+    public String cid = null;
+
+    public String authid = null;
+
+    public String authpassword = null;
+
+    public String localIp = null;
+
+    public String fromTag = null;
+
+    public String callId = null;
+
+    public int localPort = 5060;
+
+    public byte[] byteAddress = null;
+
+    public int CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_REGISTER;
+
+    public int regState = SIPStack.SIP_REGSTATE_IDLE;
+
+    public Date regTime = new Date();
+
+    public Date callTime = new Date();
+
+    public int expiresSeconds = 60;
+
+    public int repeatRegisterCount = 0;
+
+    public int registerNonceCount = 0;
+
+    public String ifIp = null;
+
+    public int ifPort = 5060;
+
+    public String previfIp = null;
+
+    public int previfPort = 5060;
+
+    public boolean bInterfaceChanged = false;
+
+    public String message = null;
+
+    public int serviceMode = SIPStack.SIP_SERVICEMODE_BASIC;
+
+    public boolean bRequestReadySet = false;
+
+    public Timer SIGNALCTRLTimer = null;
+
+    public Thread SIGNALCTRLThread = null;
+
+    public boolean SIGNALCTRLRunning = false;
+
+    public int ctrlIndex = 0;
+
+    public Date ctrlIntervalTimer = new Date();
+
+    public Date netcheckIntervalTimer = new Date();
+
+    public Date registStatusTimer = new Date();
+
+    public static Date pauseTime = new Date();
+
+    public static boolean bPausing = true;
+
+    public static final int BSSSIPStun_ICONTROLS_REGISTER = 1;
+
+    public static final int BSSSIPStun_ICONTROLS_UNREGISTER = 2;
+
+    public static final int BSSSIPStun_ICONTROLS_SET_INT_VALUE = 3;
+
+    public static final int BSSSIPStun_ICONTROLS_SET_STRING_VALUE = 4;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_UPDATESTATUS_TRUE = 10;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_UPDATESTATUS_FALSE = 11;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_VIDEOSET_TRUE = 12;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_VIDEOSET_FALSE = 13;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_INCOMINGCALL = 14;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLCONNECTED = 15;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_SHUTDOWNAPPLICATION = 16;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_BACKGROUNDINCOMINGCALL = 17;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_VIBRATOR_TRUE = 18;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_VIBRATOR_FALSE = 19;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_REGISTSTATUS_TRUE = 20;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_REGISTSTATUS_FALSE = 21;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_RINGBACKTONE_TRUE = 22;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_RINGBACKTONE_FALSE = 23;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLEND_TRUE = 24;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLEND_FALSE = 25;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_OUTBANDDTMF = 26;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_PADNUMBER = 27;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_PADTYPE = 28;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLNEIGHBOR = 29;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLGUARD = 30;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CALLTIME = 31;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_INCOMINGMULTICALL = 32;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_ENDMULTICALL = 33;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_NORMALIZEMULTICALL = 34;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_CANCELMULTICALL = 35;
+
+    public static final int BSSSIPStun_ICONTROLS_CM_OUTCALLFAIL = 36;
+
+    public static final int BSSSIPStun_ICONTROLS_DIALER_ACCEPTMULTICALL = 40;
+
+    public static final int BSSSIPStun_ICONTROLS_DIALER_REJECTMULTICALL = 41;
+
+    public static final int BSSSIPStun_ICONTROLS_DIALER_CANCELMULTICALL = 42;
+
+    public static final int BSSSIPStun_ICONTROLS_DIALER_COMMAND = 43;
+
+    public static final int BSSSIPStun_ICONTROLS_DIALER_FORWARD = 44;
+
+    public static final int BSSSIPStun_ICONTROLS_CONTACT_CALLNEIGHBOR = 50;
+
+    public static final int BSSSIPStun_ICONTROLS_CONTACT_CALLGUARD = 51;
+
+    public static final int BSSSIPStun_ICONTROLS_BLOCK_INVITE_MSG = 100;
+
+    public static final int BSSSIPStun_ICONTROLS_PAUSING_DURATION = 1000;
+
+    public static final int BSSSIPStun_ICONTROLS_UPDATE_BLOCK_STATUS = 2000;
+
+    public static boolean bDialerActive = false;
+
+    public CMCore() {
+        System.out.println("[CMCore] ========== START ==========");
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        this.commandLine = null;
+        this.viaH = null;
+        this.maxforwardH = null;
+        this.contactH = null;
+        this.toH = null;
+        this.fromH = null;
+        this.callidH = null;
+        this.cseqH = null;
+        this.expiresH = null;
+        this.allowH = null;
+        this.useragentH = null;
+        this.contentlengthH = null;
+        this.authorizationH = null;
+        this.serverIp = null;
+        this.serverPort = 5060;
+        this.serverDomain = null;
+        this.id = null;
+        this.cid = null;
+        this.authid = null;
+        this.authpassword = null;
+        this.localIp = null;
+        this.fromTag = null;
+        this.callId = null;
+        this.localPort = 5060;
+        this.byteAddress = null;
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_REGISTER;
+        this.regState = SIPStack.SIP_REGSTATE_IDLE;
+        this.regTime = new Date();
+        this.callTime = new Date();
+        this.expiresSeconds = 60;
+        this.repeatRegisterCount = 0;
+        this.registerNonceCount = 0;
+        this.ifIp = null;
+        this.ifPort = 5060;
+        this.previfIp = null;
+        this.previfPort = 5060;
+        this.bInterfaceChanged = false;
+        this.message = null;
+        this.serviceMode = SIPStack.SIP_SERVICEMODE_BASIC;
+        this.bRequestReadySet = false;
+        this.SIGNALCTRLTimer = null;
+        this.SIGNALCTRLThread = null;
+        this.SIGNALCTRLRunning = false;
+        this.ctrlIndex = 0;
+        this.ctrlIntervalTimer = new Date();
+        this.netcheckIntervalTimer = new Date();
+        this.registStatusTimer = new Date();
+    }
+
+    public void action_0(byte[] byteLocalip, int localport, byte[] byteServerip, int serverport, byte[] byteServerdomain, byte[] byteId, byte[] byteCid, byte[] byteAuthid, byte[] byteAuthpassword) {
+        this.byteAddress = this.byteAddress;
+        this.localIp = new String(byteLocalip, 0, 0, byteLocalip.length);
+        this.localPort = localport;
+        SIPStack.localSdpIp = new String(byteLocalip, 0, 0, byteLocalip.length);
+        if (SIPStack.usePrivateWiMax && (SIPStack.isInternetWiMax || SIPStack.isInternetMobile) && !SIPStack.isPrivateIp(SIPStack.localSdpIp))
+            SIPStack.localSdpIp = "192.168.10.2";
+        this.ifIp = new String(byteLocalip, 0, 0, byteLocalip.length);
+        this.ifPort = this.localPort;
+        this.serverIp = new String(byteServerip, 0, 0, byteServerip.length);
+        this.serverPort = serverport;
+        this.serverDomain = new String(byteServerdomain, 0, 0, byteServerdomain.length);
+        if (this.serverDomain == null || this.serverDomain.length() == 0)
+            this.serverDomain = new String(this.serverIp);
+        this.id = new String(byteId, 0, 0, byteId.length);
+        this.cid = new String(byteCid, 0, 0, byteCid.length);
+        if (this.cid.length() < 7 || this.cid.length() == 0)
+            this.cid = new String(this.id);
+        this.authid = new String(byteAuthid, 0, 0, byteAuthid.length);
+        this.authpassword = new String(byteAuthpassword, 0, 0, byteAuthpassword.length);
+        this.commandLine = "REGISTER sip:" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+        Date today = new Date();
+        this.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+        this.maxforwardH = "Max-Forwards: 70";
+        this.contactH = "Contact: <sip:" + this.id + "@" + this.localIp + ":" + this.localPort + ">";
+        this.toH = "To: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">";
+        this.fromTag = SIPStack.newTag();
+        this.fromH = "From: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">;tag=" + this.fromTag;
+        this.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+        this.callidH = "Call-ID: " + this.callId;
+        if (this.CSEQ_NUMBER > 65556)
+            this.CSEQ_NUMBER = 0;
+        SIPStack.SIP_SEQUENCE_REGISTER = this.CSEQ_NUMBER;
+        this.cseqH = "CSeq: " + this.CSEQ_NUMBER + " REGISTER";
+        this.expiresH = "Expires: " + this.expiresSeconds;
+        this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+        this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+        this.contentlengthH = "Content-Length: 0";
+        this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                this.viaH + SIPStack.SIP_LINE_END +
+                this.maxforwardH + SIPStack.SIP_LINE_END +
+                this.contactH + SIPStack.SIP_LINE_END +
+                this.fromH + SIPStack.SIP_LINE_END +
+                this.toH + SIPStack.SIP_LINE_END +
+                this.callidH + SIPStack.SIP_LINE_END +
+                this.cseqH + SIPStack.SIP_LINE_END +
+                this.expiresH + SIPStack.SIP_LINE_END +
+                this.allowH + SIPStack.SIP_LINE_END +
+                this.useragentH + SIPStack.SIP_LINE_END +
+                this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        if (SIPStack.bUseCtrlTimer) {
+            if (this.SIGNALCTRLTimer != null)
+                this.SIGNALCTRLTimer.cancel();
+        } else {
+            if (this.SIGNALCTRLThread != null)
+                this.SIGNALCTRLThread.interrupt();
+            this.SIGNALCTRLRunning = false;
+        }
+        this.SIGNALCTRLTimer = new Timer();
+    }
+
+    public void action_1(byte[] byteAddress, byte[] byteLocalip, int localport, String strServerHost, int serverport, String strServerDomain, byte[] byteId, byte[] byteCid, byte[] byteAuthid, byte[] byteAuthpassword) {
+        byteAddress = byteAddress;
+        this.localIp = new String(byteLocalip, 0, 0, byteLocalip.length);
+        this.localPort = localport;
+        SIPStack.localSdpIp = this.localIp;
+        this.ifIp = new String(byteLocalip, 0, 0, byteLocalip.length);
+        this.ifPort = this.localPort;
+        this.serverPort = serverport;
+        SIPStack.ipdns.bSipAddressResolved = false;
+        SIPStack.ipdns.sipServerHost = "";
+        this.serverDomain = "";
+        this.serverIp = "";
+        SIPStack.ipdns.sipTry = 0;
+        if (strServerDomain != null && strServerDomain.length() > 0)
+            this.serverDomain = new String(strServerDomain);
+        if (strServerHost != null && strServerHost.length() > 0) {
+            SIPStack.ipdns.sipServerHost = strServerHost;
+        } else {
+            SIPStack.ipdns.bSipAddressResolved = true;
+        }
+        this.id = new String(byteId, 0, 0, byteId.length);
+        this.cid = new String(byteCid, 0, 0, byteCid.length);
+        if (this.cid.length() < 7 || this.cid.length() == 0)
+            this.cid = new String(this.id);
+        this.authid = new String(byteAuthid, 0, 0, byteAuthid.length);
+        this.authpassword = new String(byteAuthpassword, 0, 0, byteAuthpassword.length);
+        this.commandLine = "REGISTER sip:" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+        Date today = new Date();
+        this.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+        this.maxforwardH = "Max-Forwards: 70";
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            this.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            this.contactH = "Contact: <sip:" + this.id + "@" + this.localIp + ":" + this.localPort + ">";
+        }
+        this.toH = "To: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">";
+        this.fromTag = SIPStack.newTag();
+        this.fromH = "From: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">;tag=" + this.fromTag;
+        this.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+        this.callidH = "Call-ID: " + this.callId;
+        if (this.CSEQ_NUMBER > 65556)
+            this.CSEQ_NUMBER = 0;
+        SIPStack.SIP_SEQUENCE_REGISTER = this.CSEQ_NUMBER;
+        this.cseqH = "CSeq: " + this.CSEQ_NUMBER + " REGISTER";
+        this.expiresH = "Expires: " + this.expiresSeconds;
+        this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+        this.useragentH = "User-Agent: " + SIPStack.USER_AGENT;
+        this.contentlengthH = "Content-Length: 0";
+        this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                this.viaH + SIPStack.SIP_LINE_END +
+                this.maxforwardH + SIPStack.SIP_LINE_END +
+                this.contactH + SIPStack.SIP_LINE_END +
+                this.fromH + SIPStack.SIP_LINE_END +
+                this.toH + SIPStack.SIP_LINE_END +
+                this.callidH + SIPStack.SIP_LINE_END +
+                this.cseqH + SIPStack.SIP_LINE_END +
+                this.expiresH + SIPStack.SIP_LINE_END +
+                this.allowH + SIPStack.SIP_LINE_END +
+                this.useragentH + SIPStack.SIP_LINE_END +
+                this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        if (SIPStack.bUseCtrlTimer) {
+            if (this.SIGNALCTRLTimer != null)
+                this.SIGNALCTRLTimer.cancel();
+        } else {
+            if (this.SIGNALCTRLThread != null)
+                this.SIGNALCTRLThread.interrupt();
+            this.SIGNALCTRLRunning = false;
+        }
+        this.SIGNALCTRLTimer = new Timer();
+    }
+
+    public void action_2(String strId, String strCid, String strAuthid, String strAuthpassword, String strServerHost, String strServerDomain, int serverport) {
+        this.serverIp = SIPStack.getIPV4(strServerHost);
+        if (this.serverIp == null)
+            this.serverIp = "";
+        if (strServerDomain == null || strServerDomain.length() == 0) {
+            this.serverDomain = new String(this.serverIp);
+        } else {
+            this.serverDomain = new String(strServerDomain);
+        }
+        this.serverPort = serverport;
+        this.id = new String(strId);
+        this.cid = new String(strCid);
+        this.authid = new String(strAuthid);
+        this.authpassword = new String(strAuthpassword);
+        this.regState = SIPStack.SIP_REGSTATE_REGISTERING;
+    }
+
+    public boolean action_net_0() {
+        try {
+            if (!SIPStack.ipdns.bSipAddressResolved &&
+                    SIPStack.ipdns.sipServerHost != null &&
+                    SIPStack.ipdns.sipServerHost.length() > 0) {
+                this.serverIp = SIPStack.getIPV4(SIPStack.ipdns.sipServerHost);
+                SIPStack.ipdns.sipTry++;
+                if (this.serverIp == null) {
+                    this.serverIp = "";
+                } else {
+                    SIPStack.ipdns.bSipAddressResolved = true;
+                }
+                if (this.serverDomain == null || this.serverDomain.length() == 0)
+                    this.serverDomain = new String(SIPStack.ipdns.sipServerHost);
+                if (this.serverIp != null && this.serverIp.length() > 0) {
+                    this.regState = SIPStack.SIP_REGSTATE_REGISTERING;
+                    return true;
+                }
+            }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public void action_net_1(String host) {
+        try {
+            if (host != null && host.length() > 0) {
+                String ip = SIPStack.getIPV4(host);
+                if (ip != null && ip.length() > 0)
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_AVAILABLE;
+                if (ip != null && ip.length() > 0 && ip.compareToIgnoreCase(this.localIp) != 0) {
+                    this.localIp = new String(ip);
+                    if (SIPStack.usePrivateWiMax && (
+                            SIPStack.isInternetWiMax || SIPStack.isInternetMobile) &&
+                            !SIPStack.isPrivateIp(ip)) {
+                        SIPStack.localSdpIp = "192.168.10.2";
+                    } else {
+                        SIPStack.localSdpIp = new String(ip);
+                    }
+                    if (this.ifIp == null || this.ifIp.length() == 0 || this.ifPort <= 0) {
+                        this.ifIp = new String(this.localIp);
+                        this.ifPort = SIPStack.SIP_LOCAL_PORT;
+                    }
+                } else if (ip == null || ip.length() == 0) {
+                    this.localIp = "127.0.0.1";
+                    SIPStack.localSdpIp = "127.0.0.1";
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+                }
+            } else if (host == null || host.length() == 0) {
+                this.localIp = "127.0.0.1";
+                SIPStack.localSdpIp = "127.0.0.1";
+                SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+            }
+        } catch (Exception exception) {}
+    }
+
+    public boolean action_net_2(String host) {
+        try {
+            if (host != null && host.length() > 0) {
+                String ip = SIPStack.getIPV4(host);
+                if (ip != null && ip.length() > 0)
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_AVAILABLE;
+                if (ip != null && ip.length() > 0 && ip.compareToIgnoreCase(this.localIp) != 0) {
+                    this.localIp = new String(ip);
+                    if (SIPStack.usePrivateWiMax && (
+                            SIPStack.isInternetWiMax || SIPStack.isInternetMobile) &&
+                            !SIPStack.isPrivateIp(ip)) {
+                        SIPStack.localSdpIp = "192.168.10.2";
+                    } else {
+                        SIPStack.localSdpIp = new String(ip);
+                    }
+                    this.ifIp = new String(this.localIp);
+                    this.ifPort = SIPStack.SIP_LOCAL_PORT;
+                    this.authorizationH = "";
+                    return true;
+                }
+                if (ip == null || ip.length() == 0) {
+                    this.localIp = "127.0.0.1";
+                    SIPStack.localSdpIp = "127.0.0.1";
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+                }
+            } else if (host == null || host.length() == 0) {
+                this.localIp = "127.0.0.1";
+                SIPStack.localSdpIp = "127.0.0.1";
+                SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+            }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean action_net_3(String host) {
+        try {
+            if (host != null && host.length() > 0) {
+                String ip = SIPStack.getIPV4(host);
+                if (ip != null && ip.length() > 0)
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_AVAILABLE;
+                if (ip != null && ip.length() > 0 && ip.compareToIgnoreCase(this.localIp) != 0) {
+                    this.localIp = new String(ip);
+                    if (SIPStack.usePrivateWiMax && (
+                            SIPStack.isInternetWiMax || SIPStack.isInternetMobile) &&
+                            !SIPStack.isPrivateIp(ip)) {
+                        SIPStack.localSdpIp = "192.168.10.2";
+                    } else {
+                        SIPStack.localSdpIp = new String(ip);
+                    }
+                    this.bInterfaceChanged = true;
+                    this.previfIp = this.ifIp;
+                    this.previfPort = this.ifPort;
+                    this.ifIp = new String(this.localIp);
+                    this.ifPort = SIPStack.SIP_LOCAL_PORT;
+                    return true;
+                }
+                if (ip == null || ip.length() == 0) {
+                    this.localIp = "127.0.0.1";
+                    SIPStack.localSdpIp = "127.0.0.1";
+                    SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+                }
+            } else if (host == null || host.length() == 0) {
+                this.localIp = "127.0.0.1";
+                SIPStack.localSdpIp = "127.0.0.1";
+                SIPStack.networkStatus = SIPStack.SIP_NETIF_UNAVAILABLE;
+            }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public SIPCONTACTHeader action_reg_0(String message) {
+        try {
+            String requestUri = "sip:" + this.id + "@" + this.localIp + ":" + this.localPort;
+            if (this.ifIp != null &&
+                    this.ifIp.length() > 0 &&
+                    this.ifPort > 0)
+                if (this.bInterfaceChanged) {
+                    requestUri = "sip:" + this.id + "@" + this.previfIp + ":" + this.previfPort;
+                } else {
+                    requestUri = "sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort;
+                }
+            return new SIPCONTACTHeader(message, requestUri);
+        } catch (Exception exception) {
+            return null;
+        }
+    }
+
+    public boolean action_reg_1(String message) {
+        try {
+            SIPVIAHeader viaHeader = new SIPVIAHeader(message);
+            if (viaHeader.flag && viaHeader.rportService &&
+                    viaHeader.rport > 0 && viaHeader.received.length() > 0)
+                if (this.ifIp == null ||
+                        this.ifIp.length() == 0 ||
+                        this.ifPort <= 0 ||
+                        this.ifIp.compareToIgnoreCase(viaHeader.received) != 0 ||
+                        this.ifPort != viaHeader.rport) {
+                    this.bInterfaceChanged = true;
+                    this.previfIp = this.ifIp;
+                    this.previfPort = this.ifPort;
+                    this.ifIp = new String(viaHeader.received);
+                    this.ifPort = viaHeader.getRport();
+                    return true;
+                }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean action_reg_2(String message) {
+        try {
+            this.authorizationH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE);
+            if (sipHeader == null || !sipHeader.flag)
+                sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE);
+            if (sipHeader != null && sipHeader.flag) {
+                SIPAUTHENTICATEHeader authHeader =
+                        new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE);
+                if (authHeader == null || !authHeader.flag)
+                    authHeader = new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE);
+                if (authHeader != null && authHeader.flag)
+                    if (authHeader.nonceValue.length() > 0 && authHeader.realmValue.length() > 0) {
+                        String qop = authHeader.qopValue;
+                        String uri = "sip:" + this.serverDomain + ":" + this.serverPort;
+                        this.authorizationH = getAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_REGISTER);
+                        return true;
+                    }
+            }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean action_reg_3(String message) {
+        try {
+            this.regState = SIPStack.SIP_REGSTATE_UNAUTHORIZED;
+            this.authorizationH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE);
+            if (sipHeader != null && sipHeader.flag) {
+                SIPAUTHENTICATEHeader authHeader =
+                        new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE);
+                if (authHeader != null && authHeader.flag)
+                    if (authHeader.nonceValue.length() > 0 && authHeader.realmValue.length() > 0) {
+                        String qop = authHeader.qopValue;
+                        String uri = "sip:" + this.serverDomain + ":" + this.serverPort;
+                        this.authorizationH = getProxyAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_REGISTER);
+                        return true;
+                    }
+            }
+            return false;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public void action_reg_4(String message) {
+        try {
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_MINEXPIRES);
+            if (sipHeader != null && sipHeader.flag)
+                this.expiresSeconds = Integer.parseInt(sipHeader.headerValue);
+            this.regState = SIPStack.SIP_REGSTATE_IDLE;
+        } catch (Exception exception) {}
+    }
+
+    public boolean action_bye_0(SIPCall sipCall, String message) {
+        try {
+            SIPRequestLine requestLine = new SIPRequestLine(message);
+            if (requestLine != null) {
+                SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                boolean bValidCall = false;
+                if (sipHeader != null && sipHeader.flag)
+                    if (sipHeader.headerValue != null &&
+                            sipHeader.headerValue.length() > 0 &&
+                            sipCall.callId != null &&
+                            sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                        bValidCall = true;
+                if (bValidCall) {
+                    sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                    if (sipHeader != null && sipHeader.flag) {
+                        int duration = 0;
+                        Date currentTime = new Date();
+                        if (sipCall.callTime_T4 != null)
+                            duration = (int)(currentTime.getTime() - sipCall.callTime_T4.getTime()) / 1000;
+                        sipCall.BYE_CSEQ = sipHeader.callSequenceNumber();
+                        sipCall.callState = 9;
+                        sipCall.callTime_T6 = new Date();
+                        return true;
+                    }
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean action_bye_1(SIPCall sipCall, String message) {
+        try {
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            boolean bValidCall = false;
+            if (sipHeader != null && sipHeader.flag)
+                if (sipHeader.headerValue != null &&
+                        sipHeader.headerValue.length() > 0 &&
+                        sipCall.callId != null &&
+                        sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                    bValidCall = true;
+            if (bValidCall) {
+                sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                if (sipHeader != null && sipHeader.flag) {
+                    sipCall.BYE_CSEQ = sipHeader.callSequenceNumber();
+                    sipCall.bByedisconnected = false;
+                    sipCall.resetCall();
+                    return true;
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean action_info_0(SIPCall sipCall, String message, int msgType) {
+        try {
+            if (msgType == SIPStack.SIP_MSGTYPE_REQUEST &&
+                    sipCall.flag &&
+                    sipCall.callState == 7) {
+                SIPRequestLine requestLine = new SIPRequestLine(message);
+                if (requestLine != null) {
+                    SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                    if (sipHeader != null && sipHeader.flag)
+                        if (sipHeader.headerValue != null &&
+                                sipHeader.headerValue.length() > 0 &&
+                                sipCall.callId != null &&
+                                sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                            return true;
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public String getAuthorizationHeader(String qop, String authid, String realmValue, String authpassword, String uri, String nonceValue, int methodType) {
+        String strHeader = null;
+        String finalDigest = null;
+        String step1Digest = SIPStack.BSSMD5Get(String.valueOf(authid) + ":" + realmValue + ":" + authpassword);
+        String step2Digest = null;
+        if (methodType == SIPStack.SIP_METHODTYPE_REGISTER) {
+            step2Digest = SIPStack.BSSMD5Get("REGISTER:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_INVITE) {
+            step2Digest = SIPStack.BSSMD5Get("INVITE:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_CANCEL) {
+            step2Digest = SIPStack.BSSMD5Get("CANCEL:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_ACK) {
+            step2Digest = SIPStack.BSSMD5Get("ACK:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_BYE) {
+            step2Digest = SIPStack.BSSMD5Get("BYE:" + uri);
+        }
+        this.registerNonceCount++;
+        if (qop.length() > 0) {
+            int nonceCount = 0;
+            String cnonce = SIPStack.BSSMD5Get("60cf184b29500b20" + this.registerNonceCount);
+            if (nonceValue.length() > 0)
+                nonceCount = 1;
+            finalDigest = SIPStack.BSSMD5Get(String.valueOf(step1Digest) + ":" + nonceValue + ":" + String.format("%08x", new Object[] { Integer.valueOf(nonceCount) }) + ":" + cnonce + ":" + qop + ":" + step2Digest);
+            strHeader = "Authorization: Digest username=\"" +
+                    authid + "\"," +
+                    " realm=\"" + realmValue + "\"," +
+                    " nonce=\"" + nonceValue + "\"," +
+                    " uri=\"" + uri + "\"," +
+                    " response=\"" + finalDigest + "\"," +
+                    " cnonce=\"" + cnonce + "\"," +
+                    " nc=" + String.format("%08x", new Object[] { Integer.valueOf(nonceCount) }) + "," +
+                    " qop=" + qop + "," +
+                    " algorithm=MD5";
+        } else {
+            finalDigest = SIPStack.BSSMD5Get(String.valueOf(step1Digest) + ":" + nonceValue + ":" + step2Digest);
+            strHeader = "Authorization: Digest username=\"" +
+                    authid + "\"," +
+                    " realm=\"" + realmValue + "\"," +
+                    " nonce=\"" + nonceValue + "\"," +
+                    " uri=\"" + uri + "\"," +
+                    " response=\"" + finalDigest + "\"," +
+                    " algorithm=MD5";
+        }
+        return strHeader;
+    }
+
+    public String getProxyAuthorizationHeader(String qop, String authid, String realmValue, String authpassword, String uri, String nonceValue, int methodType) {
+        String strHeader = null;
+        String finalDigest = null;
+        String step1Digest = SIPStack.BSSMD5Get(String.valueOf(authid) + ":" + realmValue + ":" + authpassword);
+        String step2Digest = null;
+        if (methodType == SIPStack.SIP_METHODTYPE_REGISTER) {
+            step2Digest = SIPStack.BSSMD5Get("REGISTER:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_INVITE) {
+            step2Digest = SIPStack.BSSMD5Get("INVITE:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_CANCEL) {
+            step2Digest = SIPStack.BSSMD5Get("CANCEL:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_ACK) {
+            step2Digest = SIPStack.BSSMD5Get("ACK:" + uri);
+        } else if (methodType == SIPStack.SIP_METHODTYPE_BYE) {
+            step2Digest = SIPStack.BSSMD5Get("BYE:" + uri);
+        }
+        this.registerNonceCount++;
+        if (qop.length() > 0) {
+            int nonceCount = 0;
+            String cnonce = SIPStack.BSSMD5Get("60cf184b29500b20" + this.registerNonceCount);
+            if (nonceValue.length() > 0)
+                nonceCount = 1;
+            finalDigest = SIPStack.BSSMD5Get(String.valueOf(step1Digest) + ":" + nonceValue + ":" + String.format("%08x", new Object[] { Integer.valueOf(nonceCount) }) + ":" + cnonce + ":" + qop + ":" + step2Digest);
+            strHeader = "Proxy-Authorization: Digest username=\"" +
+                    authid + "\"," +
+                    " realm=\"" + realmValue + "\"," +
+                    " nonce=\"" + nonceValue + "\"," +
+                    " uri=\"" + uri + "\"," +
+                    " response=\"" + finalDigest + "\"," +
+                    " cnonce=\"" + cnonce + "\"," +
+                    " nc=" + String.format("%08x", new Object[] { Integer.valueOf(nonceCount) }) + "," +
+                    " qop=" + qop + "," +
+                    " algorithm=MD5";
+        } else {
+            finalDigest = SIPStack.BSSMD5Get(String.valueOf(step1Digest) + ":" + nonceValue + ":" + step2Digest);
+            strHeader = "Proxy-Authorization: Digest username=\"" +
+                    authid + "\"," +
+                    " realm=\"" + realmValue + "\"," +
+                    " nonce=\"" + nonceValue + "\"," +
+                    " uri=\"" + uri + "\"," +
+                    " response=\"" + finalDigest + "\"," +
+                    " algorithm=MD5";
+        }
+        return strHeader;
+    }
+
+    public boolean makeRegister() {
+        try {
+            this.CSEQ_NUMBER++;
+            this.commandLine = "REGISTER sip:" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            Date today = new Date();
+            this.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+            this.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                this.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                this.contactH = "Contact: <sip:" + this.id + "@" + this.localIp + ":" + this.localPort + ">";
+            }
+            this.toH = "To: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">";
+            this.fromTag = SIPStack.newTag();
+            this.fromH = "From: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">;tag=" + this.fromTag;
+            if (this.callId == null || this.callId.length() == 0) {
+                this.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+                this.callidH = "Call-ID: " + this.callId;
+            }
+            if (this.CSEQ_NUMBER > 65556)
+                this.CSEQ_NUMBER = 0;
+            SIPStack.SIP_SEQUENCE_REGISTER = this.CSEQ_NUMBER;
+            this.cseqH = "CSeq: " + this.CSEQ_NUMBER + " REGISTER";
+            this.expiresH = "Expires: " + this.expiresSeconds;
+            this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            this.contentlengthH = "Content-Length: 0";
+            if (this.authorizationH != null && this.authorizationH.length() > 0) {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.authorizationH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeUNRegister() {
+        try {
+            this.CSEQ_NUMBER++;
+            this.commandLine = "REGISTER sip:" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            Date today = new Date();
+            this.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+            this.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                this.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">;expires=0";
+            } else {
+                this.contactH = "Contact: <sip:" + this.id + "@" + this.localIp + ":" + this.localPort + ">;expires=0";
+            }
+            this.toH = "To: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">";
+            this.fromTag = SIPStack.newTag();
+            this.fromH = "From: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">;tag=" + this.fromTag;
+            if (this.callId == null || this.callId.length() == 0) {
+                this.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+                this.callidH = "Call-ID: " + this.callId;
+            }
+            if (this.CSEQ_NUMBER > 65556)
+                this.CSEQ_NUMBER = 0;
+            SIPStack.SIP_SEQUENCE_REGISTER = this.CSEQ_NUMBER;
+            this.cseqH = "CSeq: " + this.CSEQ_NUMBER + " REGISTER";
+            this.expiresH = "Expires: 0";
+            this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            this.contentlengthH = "Content-Length: 0";
+            if (this.authorizationH != null && this.authorizationH.length() > 0) {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.authorizationH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeUNRegister(String contactip, int contactport) {
+        try {
+            this.CSEQ_NUMBER++;
+            this.commandLine = "REGISTER sip:" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            Date today = new Date();
+            this.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+            this.maxforwardH = "Max-Forwards: 70";
+            if (contactip != null && contactip.length() > 0 && contactport > 0) {
+                this.contactH = "Contact: <sip:" + this.id + "@" + contactip + ":" + contactport + ">";
+            } else {
+                return true;
+            }
+            this.toH = "To: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">";
+            this.fromTag = SIPStack.newTag();
+            this.fromH = "From: \"" + this.id + "\"<sip:" + this.id + "@" + this.serverDomain + ":" + this.serverPort + ">;tag=" + this.fromTag;
+            if (this.callId == null || this.callId.length() == 0) {
+                this.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+                this.callidH = "Call-ID: " + this.callId;
+            }
+            if (this.CSEQ_NUMBER > 65556)
+                this.CSEQ_NUMBER = 0;
+            SIPStack.SIP_SEQUENCE_REGISTER = this.CSEQ_NUMBER;
+            this.cseqH = "CSeq: " + this.CSEQ_NUMBER + " REGISTER";
+            this.expiresH = "Expires: 0";
+            this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            this.contentlengthH = "Content-Length: 0";
+            if (this.authorizationH != null && this.authorizationH.length() > 0) {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.authorizationH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                this.message = String.valueOf(this.commandLine) + SIPStack.SIP_LINE_END +
+                        this.viaH + SIPStack.SIP_LINE_END +
+                        this.maxforwardH + SIPStack.SIP_LINE_END +
+                        this.contactH + SIPStack.SIP_LINE_END +
+                        this.fromH + SIPStack.SIP_LINE_END +
+                        this.toH + SIPStack.SIP_LINE_END +
+                        this.callidH + SIPStack.SIP_LINE_END +
+                        this.cseqH + SIPStack.SIP_LINE_END +
+                        this.expiresH + SIPStack.SIP_LINE_END +
+                        this.allowH + SIPStack.SIP_LINE_END +
+                        this.useragentH + SIPStack.SIP_LINE_END +
+                        this.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeCancel(SIPCall sipCall) {
+        if (sipCall == null || !sipCall.flag)
+            return false;
+        sipCall.CANCEL_CSEQ = sipCall.CSEQ_NUMBER;
+        if (sipCall.callState != 1 &&
+                sipCall.callState != 3 &&
+                sipCall.callState != 4)
+            return false;
+        String commandLine = "CANCEL sip:" + sipCall.dnis + "@" + sipCall.dnis + " SIP/2.0";
+        String toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+        if (sipCall.viaH == null || sipCall.viaH.length() == 0) {
+            if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+        }
+        sipCall.cseqH = "CSeq: " + sipCall.CANCEL_CSEQ + " CANCEL";
+        sipCall.contentlengthH = "Content-Length: 0";
+        String routeString = "";
+        if (sipCall.routeArray != null &&
+                sipCall.routeArray.length() > 0)
+            routeString = sipCall.routeArray.toString();
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            sipCall.contactH = "Contact: <sip:" + sipCall.localIp + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+        }
+        if (sipCall.authorizationCANCELH != null && sipCall.authorizationCANCELH.length() > 0) {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.authorizationCANCELH + SIPStack.SIP_LINE_END +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        } else {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        }
+        return true;
+    }
+
+    public boolean makeRecancel(SIPCall sipCall) {
+        if (sipCall == null || !sipCall.flag)
+            return false;
+        sipCall.CANCEL_CSEQ = sipCall.CSEQ_NUMBER;
+        if (sipCall.callState != 11)
+            return false;
+        String commandLine = "CANCEL sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+        String toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+        if (sipCall.viaH == null || sipCall.viaH.length() == 0) {
+            if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+        }
+        sipCall.cseqH = "CSeq: " + sipCall.CANCEL_CSEQ + " CANCEL";
+        sipCall.contentlengthH = "Content-Length: 0";
+        String routeString = "";
+        if (sipCall.routeArray != null &&
+                sipCall.routeArray.length() > 0)
+            routeString = sipCall.routeArray.toString();
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+        }
+        if (sipCall.authorizationCANCELH != null && sipCall.authorizationCANCELH.length() > 0) {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.authorizationCANCELH + SIPStack.SIP_LINE_END +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        } else {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        }
+        return true;
+    }
+
+    public boolean makeBye(SIPCall sipCall) {
+        if (sipCall == null || !sipCall.flag)
+            return false;
+        if (sipCall.callState != 7 &&
+                sipCall.callState != 5 &&
+                sipCall.callState != 6)
+            return false;
+        String commandLine = null;
+        if (sipCall.remoteContactUri != null && sipCall.remoteContactUri.length() > 0) {
+            commandLine = "BYE " + sipCall.remoteContactUri + " SIP/2.0";
+        } else {
+            commandLine = "BYE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+        }
+        if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+            sipCall.viaBranch = SIPStack.getViaBranch();
+        String viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch;
+        String maxforwardH = "Max-Forwards: 70";
+        String contactH = null;
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+        }
+        String toH = null;
+        if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            if (sipCall.fromHeaderValue == null || sipCall.fromHeaderValue.length() == 0) {
+                toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            } else {
+                toH = "To: " + sipCall.fromHeaderValue;
+            }
+        } else {
+            toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.toTag;
+        }
+        String fromH = null;
+        if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            if (sipCall.toHeaderValue == null || sipCall.toHeaderValue.length() == 0) {
+                fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.toTag;
+            } else {
+                fromH = "From: " + sipCall.toHeaderValue;
+            }
+        } else {
+            fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+        }
+        sipCall.BYE_CSEQ = sipCall.CSEQ_NUMBER + 1;
+        String cseqH = "CSeq: " + sipCall.BYE_CSEQ + " BYE";
+        String contentlengthH = "Content-Length: 0";
+        String routeString = "";
+        if (sipCall.routeArray != null &&
+                sipCall.routeArray.length() > 0)
+            routeString = sipCall.routeArray.toString();
+        if (sipCall.authorizationBYEH != null && sipCall.authorizationBYEH.length() > 0) {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            maxforwardH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.authorizationBYEH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        } else {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            maxforwardH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        }
+        return true;
+    }
+
+    public boolean makeReBye(SIPCall sipCall) {
+        if (sipCall == null || !sipCall.flag)
+            return false;
+        if (sipCall.callState != 8 ||
+                !sipCall.bByedisconnected)
+            return false;
+        String commandLine = null;
+        if (sipCall.remoteContactUri != null && sipCall.remoteContactUri.length() > 0) {
+            commandLine = "BYE " + sipCall.remoteContactUri + " SIP/2.0";
+        } else {
+            commandLine = "BYE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+        }
+        if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+            sipCall.viaBranch = SIPStack.getViaBranch();
+        String viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch;
+        String maxforwardH = "Max-Forwards: 70";
+        String contactH = null;
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+        }
+        String toH = null;
+        if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            if (sipCall.fromHeaderValue == null || sipCall.fromHeaderValue.length() == 0) {
+                toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            } else {
+                toH = "To: " + sipCall.fromHeaderValue;
+            }
+        } else {
+            toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.toTag;
+        }
+        String fromH = null;
+        if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            if (sipCall.toHeaderValue == null || sipCall.toHeaderValue.length() == 0) {
+                fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.toTag;
+            } else {
+                fromH = "From: " + sipCall.toHeaderValue;
+            }
+        } else {
+            fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+        }
+        sipCall.BYE_CSEQ = sipCall.CSEQ_NUMBER + 1;
+        String cseqH = "CSeq: " + sipCall.BYE_CSEQ + " BYE";
+        String contentlengthH = "Content-Length: 0";
+        String routeString = "";
+        if (sipCall.routeArray != null &&
+                sipCall.routeArray.length() > 0)
+            routeString = sipCall.routeArray.toString();
+        if (sipCall.authorizationBYEH != null && sipCall.authorizationBYEH.length() > 0) {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            maxforwardH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            sipCall.authorizationBYEH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        } else {
+            sipCall.message =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            viaH + SIPStack.SIP_LINE_END +
+                            routeString +
+                            maxforwardH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+        }
+        return true;
+    }
+
+    public String getVideomediadescription(int port) {
+        String str = "m=video " + port + " RTP/AVP " + SIPStack.SIP_CODEC_H263 + SIPStack.SIP_LINE_END +
+                "a=rtpmap:" + SIPStack.SIP_CODEC_H263 + " H263/90000" + SIPStack.SIP_LINE_END +
+                "a=fmtp:" + SIPStack.SIP_CODEC_H263 + " packetization-mode=1;profile-level-id=2" + SIPStack.SIP_LINE_END +
+                "a=cliprect:0,0,288,352" + SIPStack.SIP_LINE_END +
+                "a=framesize:" + SIPStack.SIP_CODEC_H263 + " 352-288" + SIPStack.SIP_LINE_END;
+        //String str = "";
+        return str;
+    }
+
+    public boolean makeDirectcallMake(SIPCall sipCall, String number) {
+        String header = "";
+        if (sipCall == null || sipCall.flag)
+            return false;
+        sipCall.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        SIPStack.SIP_SEQUENCE_INVITE++;
+        if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+            SIPStack.SIP_SEQUENCE_INVITE = 1;
+        if (!sipCall.activeCallHandle(
+                this.id,
+                this.cid,
+                this.authid,
+                this.authpassword,
+                number,
+                sipCall.serverIp,
+                sipCall.serverPort,
+                sipCall.serverDomain,
+                this.localIp,
+                this.localPort))
+            return false;
+        if (number.length() <= 0)
+            return false;
+        sipCall.commandLine = "INVITE sip:" + number + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + " SIP/2.0";
+        Date today = new Date();
+        sipCall.viaBranch = SIPStack.getViaBranch();
+        sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+        sipCall.maxforwardH = "Max-Forwards: 70";
+        if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+            sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+        } else {
+            sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+        }
+        sipCall.toH = "To: \"" + number + "\"<sip:" + number + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+        sipCall.fromTag = SIPStack.newTag();
+        sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+        if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_LOBBY) {
+            String postFix = "";
+            if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+            } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+            } else {
+                postFix = BSSVideo.HNS_POSTFIX_LOBBY;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+            }
+            sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_LOBBY) + SIPStack.BSSMD5Get(this.viaH) +
+                    SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+            sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+            BSSVideo.bProgressvideooffer = true;
+        } else if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+            String postFix = "";
+            if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+            } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+            } else {
+                postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+            }
+            sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_GUARD) + SIPStack.BSSMD5Get(this.viaH) +
+                    SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+            sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_GUARD;
+            BSSVideo.bProgressvideooffer = true;
+        } else if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+            String postFix = "";
+            if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                BSSVideo.bProgressvideooffer = true;
+            } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                BSSVideo.bProgressvideooffer = true;
+            } else {
+                postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+                BSSVideo.bProgressvideooffer = false;
+            }
+            sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_NEIGHBOR) + SIPStack.BSSMD5Get(this.viaH) +
+                    SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+            sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+        } else {
+            sipCall.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+            sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+            sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+            BSSVideo.bProgressvideooffer = false;
+        }
+        sipCall.callidH = "Call-ID: " + sipCall.callId;
+        sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+        sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+        sipCall.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+        if (sipCall.cid != null && sipCall.cid.length() > 0) {
+            sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+        } else {
+            sipCall.passertedidentityH = null;
+            header = "";
+        }
+        int audioport = SIPStack.getFreeAudioRtpPort();
+        if (audioport > 0)
+            sipCall.constructSdp();
+        if (sipCall.sdp != null && sipCall.sdp.flag) {
+            sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+            if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+            } else {
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+            }
+            sipCall.sdp.setCodec(
+                    SIPStack.SIP_MEDIATYPE_AUDIO,
+                    RFC2833.payloadType,
+                    "telephone-event/8000");
+            sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+        }
+        String body = null;
+        sipCall.contenttypeH = "";
+        if (sipCall.sdp != null && sipCall.sdp.flag) {
+            sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+            if (SIPStack.bVideocommunication) {
+                body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(audioport + 2);
+            } else {
+                body = sipCall.sdp.getBodyString();
+            }
+            sipCall.contentlengthH = "Content-Length: " + body.length();
+        } else {
+            body = "";
+            sipCall.contentlengthH = "Content-Length: 0";
+        }
+        sipCall.callState = 1;
+        sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+        if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+            sipCall.message =
+                    String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            header +
+                            sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                            sipCall.contenttypeH +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                            body;
+        } else {
+            sipCall.message =
+                    String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            header +
+                            sipCall.contenttypeH +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                            body;
+        }
+        return true;
+    }
+
+    public boolean INVITEParser_action_0(SIPCall sipCall, String message) {
+        try {
+            SIPRequestLine requestLine = new SIPRequestLine(message);
+            if (requestLine != null &&
+                    sipCall != null &&
+                    sipCall.flag &&
+                    sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_OUT) {
+                SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                boolean bValidCall = false;
+                if (sipHeader != null && sipHeader.flag)
+                    if (sipHeader.headerValue != null &&
+                            sipHeader.headerValue.length() > 0 &&
+                            sipCall.callId != null &&
+                            sipHeader.headerValue.compareTo(sipCall.callId) == 0) {
+                        SIPHeader seqHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                        if (seqHeader != null && seqHeader.callSequenceNumber() == sipCall.CSEQ_NUMBER) {
+                            sipCall.responseCode = requestLine.code;
+                            //Log.e(TAG, "[INVITEParser] ============ requestLine.code ============ ");
+                            return true;
+                        }
+                    }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean ACKParser_action_0(SIPCall sipCall, String message) {
+        try {
+            if (sipCall.callState == 23 ||
+                    sipCall.callState == 24) {
+                SIPRequestLine requestLine = new SIPRequestLine(message);
+                if (requestLine != null) {
+                    SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                    boolean bValidCall = false;
+                    if (sipHeader != null && sipHeader.flag)
+                        if (sipHeader.headerValue != null &&
+                                sipHeader.headerValue.length() > 0 &&
+                                sipCall.callId != null &&
+                                sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                            bValidCall = true;
+                    if (bValidCall) {
+                        sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                        if (sipHeader != null && sipHeader.flag) {
+                            sipCall.ACK_CSEQ = sipHeader.callSequenceNumber();
+                            sipCall.callMode = SIPStack.SIP_CALLMODE_BASIC;
+                            sipCall.callState = 7;
+                            sipCall.resetUpdateheaders();
+                            return true;
+                        }
+                    }
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean ACKParser_action_1(SIPCall sipCall, String message) {
+        try {
+            SIPRequestLine requestLine = new SIPRequestLine(message);
+            if (requestLine != null) {
+                boolean bValidCall = false;
+                SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                if (sipHeader != null && sipHeader.flag)
+                    if (sipHeader.headerValue != null &&
+                            sipHeader.headerValue.length() > 0 &&
+                            sipCall.callId != null &&
+                            sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                        bValidCall = true;
+                if (bValidCall) {
+                    sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                    if (sipHeader != null && sipHeader.flag) {
+                        sipCall.ACK_CSEQ = sipHeader.callSequenceNumber();
+                        sipCall.callState = 7;
+                        return true;
+                    }
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean ACKParser_action_2(SIPCall sipCall, String message) {
+        try {
+            boolean bValidCall = false;
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag)
+                if (sipHeader.headerValue != null &&
+                        sipHeader.headerValue.length() > 0 &&
+                        sipCall.callId != null &&
+                        sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                    return true;
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean CANCELParser_action_0(SIPCall sipCall, String message) {
+        try {
+            SIPRequestLine requestLine = new SIPRequestLine(message);
+            if (requestLine != null) {
+                SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+                boolean bValidCall = false;
+                if (sipHeader != null && sipHeader.flag)
+                    if (sipHeader.headerValue != null &&
+                            sipHeader.headerValue.length() > 0 &&
+                            sipCall.callId != null &&
+                            sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                        bValidCall = true;
+                if (bValidCall) {
+                    sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+                    if (sipHeader != null && sipHeader.flag) {
+                        sipCall.CANCEL_CSEQ = sipHeader.callSequenceNumber();
+                        sipCall.callState = 12;
+                        return true;
+                    }
+                }
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public boolean CANCELParser_action_1(SIPCall sipCall, String message) {
+        try {
+            SIPRequestLine requestLine = new SIPRequestLine(message);
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            boolean bValidCall = false;
+            if (sipHeader != null && sipHeader.flag)
+                if (sipHeader.headerValue != null &&
+                        sipHeader.headerValue.length() > 0 &&
+                        sipCall.callId != null &&
+                        sipHeader.headerValue.compareTo(sipCall.callId) == 0)
+                    bValidCall = true;
+            if (bValidCall) {
+                if (requestLine.code != 401);
+                return true;
+            }
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public String makeAcceptCancelRequest(SIPCall sipCall, String message) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            sipCall.BYE_CSEQ = sipCall.ACK_CSEQ;
+            String commandLine = null;
+            String viaH = null;
+            String maxforwardH = null;
+            String contactH = null;
+            String toH = null;
+            String fromH = null;
+            String callidH = null;
+            String cseqH = null;
+            String expiresH = null;
+            String allowH = null;
+            String useragentH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 200 " + SIPStack.getResponseDescription(200) + SIPStack.SIP_LINE_END;
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_VIA);
+            if (sipHeader != null && sipHeader.flag) {
+                viaH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                viaH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipHeader != null && sipHeader.flag) {
+                fromH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                fromH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipHeader != null && sipHeader.flag) {
+                toH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+                if (toH.indexOf("tag=") < 0)
+                    toH = String.valueOf(sipHeader.header) + ";tag=" + SIPStack.newTag() + SIPStack.SIP_LINE_END;
+            } else {
+                toH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag) {
+                callidH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                callidH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipHeader != null && sipHeader.flag) {
+                sipCall.CANCEL_CSEQ = sipHeader.callSequenceNumber();
+                cseqH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                cseqH = "";
+            }
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaH +
+                            fromH +
+                            toH +
+                            callidH +
+                            cseqH +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendProgressingwithbody(SIPCall sipCall) {
+        try {
+            String commandLine = null;
+            String contactH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 183 " + SIPStack.getResponseDescription(183) + SIPStack.SIP_LINE_END;
+            String viaString = "";
+            if (sipCall.viaArray.length() > 0)
+                viaString = sipCall.viaArray.toString();
+            String routeString = "";
+            if (sipCall.recordrouteArray.length() > 0)
+                routeString = sipCall.recordrouteArray.toString();
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            String contenttypeString = "";
+            String bodyString = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                String body = "";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getFinalBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getFinalBodyString();
+                }
+                if (body != null && body.length() > 0) {
+                    bodyString = body;
+                    contenttypeString = "Content-Type: application/SDP\r\n";
+                }
+            }
+            contentlengthH = "Content-Length: " + bodyString.length() + SIPStack.SIP_LINE_END;
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaString +
+                            routeString +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            contenttypeString +
+                            contentlengthH + SIPStack.SIP_LINE_END +
+                            bodyString;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendProgressing(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            String commandLine = null;
+            String contactH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 180 " + SIPStack.getResponseDescription(180) + SIPStack.SIP_LINE_END;
+            String viaString = "";
+            if (sipCall.viaArray.length() > 0)
+                viaString = sipCall.viaArray.toString();
+            String routeString = "";
+            if (sipCall.recordrouteArray != null &&
+                    sipCall.recordrouteArray.length() > 0)
+                routeString = sipCall.recordrouteArray.toString();
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaString +
+                            routeString +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendProceeding(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            String commandLine = null;
+            String contactH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 100 " + SIPStack.getResponseDescription(100) + SIPStack.SIP_LINE_END;
+            String viaString = "";
+            if (sipCall.viaArray.length() > 0)
+                viaString = sipCall.viaArray.toString();
+            String routeString = "";
+            if (sipCall.recordrouteArray != null &&
+                    sipCall.recordrouteArray.length() > 0)
+                routeString = sipCall.recordrouteArray.toString();
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaString +
+                            routeString +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendAccept(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN &&
+                    sipCall.callState == 2) {
+                String commandLine = null;
+                String contactH = null;
+                String contentlengthH = null;
+                commandLine = "SIP/2.0 200 " + SIPStack.getResponseDescription(200) + SIPStack.SIP_LINE_END;
+                String viaString = "";
+                if (sipCall.viaArray.length() > 0)
+                    viaString = sipCall.viaArray.toString();
+                String routeString = "";
+                if (sipCall.recordrouteArray.length() > 0)
+                    routeString = sipCall.recordrouteArray.toString();
+                if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                    contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+                } else {
+                    contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                }
+                String contenttypeString = "";
+                String bodyString = "";
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    String body = "";
+                    if (SIPStack.bVideocommunication) {
+                        body = String.valueOf(sipCall.sdp.getFinalBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                    } else {
+                        body = sipCall.sdp.getFinalBodyString();
+                    }
+                    if (body != null && body.length() > 0) {
+                        bodyString = body;
+                        contenttypeString = "Content-Type: application/SDP\r\n";
+                    }
+                }
+                contentlengthH = "Content-Length: " + bodyString.length() + SIPStack.SIP_LINE_END;
+                String sendmessage =
+                        String.valueOf(commandLine) +
+                                viaString +
+                                routeString +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                contactH + SIPStack.SIP_LINE_END +
+                                contenttypeString +
+                                contentlengthH + SIPStack.SIP_LINE_END +
+                                bodyString;
+                return sendmessage;
+            }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public String makeDirectsendAccept(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN &&
+                    sipCall.callState == 2) {
+                String commandLine = null;
+                String contactH = null;
+                String contentlengthH = null;
+                commandLine = "SIP/2.0 200 " + SIPStack.getResponseDescription(200) + SIPStack.SIP_LINE_END;
+                String viaString = "";
+                if (sipCall.viaArray.length() > 0)
+                    viaString = sipCall.viaArray.toString();
+                String routeString = "";
+                if (sipCall.recordrouteArray.length() > 0)
+                    routeString = sipCall.recordrouteArray.toString();
+                if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                    contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+                } else {
+                    contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                }
+                String contenttypeString = "";
+                String bodyString = "";
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    String body = "";
+                    if (SIPStack.bVideocommunication) {
+                        body = String.valueOf(sipCall.sdp.getFinalBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                    } else {
+                        body = sipCall.sdp.getFinalBodyString();
+                    }
+                    if (body != null && body.length() > 0) {
+                        bodyString = body;
+                        contenttypeString = "Content-Type: application/SDP\r\n";
+                    }
+                }
+                contentlengthH = "Content-Length: " + bodyString.length() + SIPStack.SIP_LINE_END;
+                String sendmessage =
+                        String.valueOf(commandLine) +
+                                viaString +
+                                routeString +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                contactH + SIPStack.SIP_LINE_END +
+                                contenttypeString +
+                                contentlengthH + SIPStack.SIP_LINE_END +
+                                bodyString;
+                return sendmessage;
+            }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public boolean makeCallMake(SIPCall sipCall, String number) {
+        try {
+            String header = "";
+            if (sipCall == null || sipCall.flag)
+                return false;
+            sipCall.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+            SIPStack.SIP_SEQUENCE_INVITE++;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            if (!sipCall.activeCallHandle(
+                    this.id,
+                    this.cid,
+                    this.authid,
+                    this.authpassword,
+                    number,
+                    this.serverIp,
+                    this.serverPort,
+                    this.serverDomain,
+                    this.localIp,
+                    this.localPort))
+                return false;
+            if (number.length() <= 0)
+                return false;
+            sipCall.commandLine = "INVITE sip:" + number + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            Date today = new Date();
+            sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            sipCall.toH = "To: \"" + number + "\"<sip:" + number + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            sipCall.fromTag = SIPStack.newTag();
+            sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            sipCall.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+            sipCall.callidH = "Call-ID: " + sipCall.callId;
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            if (sipCall.cid != null && sipCall.cid.length() > 0) {
+                sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                sipCall.passertedidentityH = null;
+                header = "";
+            }
+            int audioport = SIPStack.getFreeAudioRtpPort();
+            if (audioport > 0)
+                sipCall.constructSdp();
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711U,
+                            "PCMU/8000");
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711A,
+                            "PCMA/8000");
+                } else {
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711A,
+                            "PCMA/8000");
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711U,
+                            "PCMU/8000");
+                }
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        RFC2833.payloadType,
+                        "telephone-event/8000");
+                sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 1;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+                return true;
+            }
+            sipCall.message =
+                    String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            header +
+                            sipCall.contenttypeH +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                            body;
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeSendReInvite(SIPCall sipCall) {
+        try {
+            String header = null;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.callState = 1;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            if (sipCall.cid != null && sipCall.cid.length() > 0) {
+                sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                sipCall.passertedidentityH = null;
+                header = "";
+            }
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+                return true;
+            }
+            sipCall.message =
+                    String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            header +
+                            sipCall.contenttypeH +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                            body;
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public String makeRejectCall(SIPCall sipCall, int code) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+
+
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN)
+                if (sipCall.callState == 2 ||
+                        sipCall.callState == 12) {
+                    String commandLine = null;
+                    String contactH = null;
+                    String contentlengthH = null;
+                    commandLine = "SIP/2.0 " + code + " " + SIPStack.getResponseDescription(code) + SIPStack.SIP_LINE_END;
+                    String viaString = "";
+                    if (sipCall.viaArray.length() > 0)
+                        viaString = sipCall.viaArray.toString();
+                    String routeString = "";
+                    if (sipCall.recordrouteArray.length() > 0)
+                        routeString = sipCall.recordrouteArray.toString();
+                    if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                        contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+                    } else {
+                        contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                    }
+                    contentlengthH = "Content-Length: 0" + SIPStack.SIP_LINE_END;
+                    String sendmessage =
+                            String.valueOf(commandLine) +
+                                    viaString +
+                                    routeString +
+                                    sipCall.fromH + SIPStack.SIP_LINE_END +
+                                    sipCall.toH + SIPStack.SIP_LINE_END +
+                                    sipCall.callidH + SIPStack.SIP_LINE_END +
+                                    sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                    contactH + SIPStack.SIP_LINE_END +
+                                    contentlengthH + SIPStack.SIP_LINE_END;
+                    return sendmessage;
+                }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public String makeRejectCall(SIPCall sipCall, int code, String contact) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN)
+                if (sipCall.callState == 2 ||
+                        sipCall.callState == 12) {
+                    String commandLine = null;
+                    String contactH = null;
+                    String contentlengthH = null;
+                    commandLine = "SIP/2.0 " + code + " " + SIPStack.getResponseDescription(code) + SIPStack.SIP_LINE_END;
+                    String viaString = "";
+                    if (sipCall.viaArray.length() > 0)
+                        viaString = sipCall.viaArray.toString();
+                    String routeString = "";
+                    if (sipCall.recordrouteArray.length() > 0)
+                        routeString = sipCall.recordrouteArray.toString();
+                    contactH = "Contact: <" + contact + ">";
+                    contentlengthH = "Content-Length: 0" + SIPStack.SIP_LINE_END;
+                    String sendmessage =
+                            String.valueOf(commandLine) +
+                                    viaString +
+                                    routeString +
+                                    sipCall.fromH + SIPStack.SIP_LINE_END +
+                                    sipCall.toH + SIPStack.SIP_LINE_END +
+                                    sipCall.callidH + SIPStack.SIP_LINE_END +
+                                    sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                    contactH + SIPStack.SIP_LINE_END +
+                                    contentlengthH + SIPStack.SIP_LINE_END;
+                    return sendmessage;
+                }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public String makeRejectCall(String message, int code, String localIp, int localPort, String remoteIp, int remotePort) {
+        try {
+            if (message == null || message.length() == 0 || remoteIp == null || remoteIp.length() == 0 ||
+                    remotePort <= 0)
+                return "";
+            String viaH = "";
+            StringBuffer viaArray = new StringBuffer();
+            String routeH = "";
+            StringBuffer routeArray = new StringBuffer();
+            String recordrouteH = "";
+            StringBuffer recordrouteArray = new StringBuffer();
+            String contactH = "";
+            String fromH = "";
+            String callidH = "";
+            String cseqH = "";
+            String contentlengthH = "";
+            StringTokenizer tokenArray = new StringTokenizer(message, SIPStack.SIP_LINE_END, true);
+            while (tokenArray.hasMoreTokens()) {
+                String token = tokenArray.nextToken().trim();
+                if (token.length() <= 0 ||
+                        token.compareTo("\r") == 0 ||
+                        token.compareTo("\n") == 0)
+                    continue;
+                if (token.startsWith("From: ")) {
+                    fromH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("f: ")) {
+                    fromH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("To: ")) {
+                    if (token.indexOf("tag=") < 0) {
+                        this.toH = String.valueOf(token) + ";tag=" + (new Date()).getTime() + SIPStack.SIP_LINE_END;
+                        continue;
+                    }
+                    this.toH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("t: ")) {
+                    if (token.indexOf("tag=") < 0) {
+                        this.toH = String.valueOf(token) + ";tag=" + (new Date()).getTime() + SIPStack.SIP_LINE_END;
+                        continue;
+                    }
+                    this.toH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("Via: ")) {
+                    if (viaH == null || viaH.length() == 0) {
+                        viaH = token;
+                        int iS = token.indexOf(";rport=");
+                        if (iS > 0 && token.indexOf(";received=") < 0) {
+                            String s1 = token.substring(0, iS);
+                            int iS_ = token.indexOf(";", iS + 1);
+                            String s2 = null;
+                            if (iS_ > 0) {
+                                s2 = token.substring(iS_ + 1);
+                                if (s1 != null && s2 != null) {
+                                    viaH = String.valueOf(s1) + ";" + s2;
+                                } else if (s1 != null) {
+                                    viaH = s1;
+                                }
+                            } else {
+                                viaH = s1;
+                            }
+                            if (viaH != null && viaH.length() > 0)
+                                viaH = String.valueOf(viaH) + ";received=" + remoteIp + ";rport=" + remotePort;
+                        }
+                        if (viaH != null && viaH.length() > 0)
+                            viaArray.append(String.valueOf(viaH) + SIPStack.SIP_LINE_END);
+                        continue;
+                    }
+                    viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                if (token.startsWith("v: ")) {
+                    if (viaH == null || viaH.length() == 0) {
+                        viaH = token;
+                        int iS = token.indexOf(";rport=");
+                        if (iS > 0 && token.indexOf(";received=") < 0) {
+                            String s1 = token.substring(0, iS);
+                            int iS_ = token.indexOf(";", iS + 1);
+                            String s2 = null;
+                            if (iS_ > 0) {
+                                s2 = token.substring(iS_ + 1);
+                                if (s1 != null && s2 != null) {
+                                    viaH = String.valueOf(s1) + ";" + s2;
+                                } else if (s1 != null) {
+                                    viaH = s1;
+                                }
+                            } else {
+                                viaH = s1;
+                            }
+                            if (viaH != null && viaH.length() > 0)
+                                viaH = String.valueOf(viaH) + ";received=" + remoteIp + ";rport=" + remotePort;
+                        }
+                        if (viaH != null && viaH.length() > 0)
+                            viaArray.append(String.valueOf(viaH) + SIPStack.SIP_LINE_END);
+                        continue;
+                    }
+                    viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                if (token.startsWith("Record-Route: ")) {
+                    if (recordrouteH == null || recordrouteH.length() == 0) {
+                        routeH = null;
+                        routeArray = new StringBuffer();
+                        recordrouteH = token;
+                        recordrouteArray.append(String.valueOf(recordrouteH) + SIPStack.SIP_LINE_END);
+                        routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                        continue;
+                    }
+                    recordrouteArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                    routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                if (token.startsWith("Call-ID: ")) {
+                    callidH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("i: ")) {
+                    callidH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("CSeq: ")) {
+                    cseqH = String.valueOf(token) + SIPStack.SIP_LINE_END;
+                    continue;
+                }
+                if (token.startsWith("Content-Length: ")) {
+                    contentlengthH = "Content-Length: 0\r\n";
+                    continue;
+                }
+                if (token.startsWith("l: "))
+                    contentlengthH = "Content-Length: 0\r\n";
+            }
+            String commandLine = "SIP/2.0 " + code + " " + SIPStack.getResponseDescription(code) + SIPStack.SIP_LINE_END;
+            String viaString = "";
+            if (viaArray.length() > 0)
+                viaString = viaArray.toString();
+            String routeString = "";
+            if (recordrouteArray.length() > 0)
+                routeString = recordrouteArray.toString();
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                contactH = "Contact: <sip:" + this.id + "@" + localIp + ":" + localPort + ">";
+            }
+            contentlengthH = "Content-Length: 0" + SIPStack.SIP_LINE_END;
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaString +
+                            routeString +
+                            fromH +
+                            this.toH +
+                            callidH +
+                            cseqH +
+                            contactH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendUpdateAccept(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN &&
+                    sipCall.callState == 23) {
+                String commandLine = null;
+                String contactH = null;
+                String contentlengthH = null;
+                commandLine = "SIP/2.0 200 " + SIPStack.getResponseDescription(200) + SIPStack.SIP_LINE_END;
+                String viaString = "";
+                if (sipCall.viaArray.length() > 0)
+                    viaString = sipCall.viaArray.toString();
+                String routeString = "";
+                if (sipCall.recordrouteArray.length() > 0)
+                    routeString = sipCall.recordrouteArray.toString();
+                if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                    sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+                } else {
+                    sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                }
+                String contenttypeString = "";
+                String bodyString = "";
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    String body = sipCall.sdp.getFinalBodyString();
+                    if (body != null && body.length() > 0) {
+                        bodyString = body;
+                        contenttypeString = "Content-Type: application/SDP\r\n";
+                    }
+                }
+                contentlengthH = "Content-Length: " + bodyString.length() + SIPStack.SIP_LINE_END;
+                String sendmessage =
+                        String.valueOf(commandLine) +
+                                viaString +
+                                routeString +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                contactH + SIPStack.SIP_LINE_END +
+                                contenttypeString +
+                                contentlengthH + SIPStack.SIP_LINE_END +
+                                bodyString;
+                return sendmessage;
+            }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public boolean makeSendRedirectCall(SIPCall sipCall, String message) {
+        try {
+            String header = null;
+            if (message == null || message.length() == 0)
+                return false;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            SIPCONTACTHeader contactHeader = new SIPCONTACTHeader(message);
+            if (contactHeader == null || !contactHeader.flag)
+                return false;
+            sipCall.initializeRedirectCall();
+            sipCall.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+            SIPStack.SIP_SEQUENCE_INVITE++;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            if (contactHeader != null && contactHeader.sipuri != null &&
+                    contactHeader.sipuri.length() > 0) {
+                sipCall.commandLine = "INVITE " + contactHeader.sipuri + " SIP/2.0";
+                sipCall.remoteIp = contactHeader.ip;
+                sipCall.remotePort = contactHeader.port;
+                sipCall.dnis = contactHeader.username;
+                sipCall.serverDomain = contactHeader.ip;
+                sipCall.serverPort = contactHeader.port;
+                BSSVideo.HNS_SERVICE_RECEIVER_SELECTED = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                if (contactHeader.username.startsWith("lobby")) {
+                    BSSVideo.HNS_SERVICE_RECEIVER_SELECTED = BSSVideo.HNS_SERVICE_LOBBY;
+                } else if (contactHeader.username.startsWith("office")) {
+                    BSSVideo.HNS_SERVICE_RECEIVER_SELECTED = BSSVideo.HNS_SERVICE_GUARD;
+                }
+            } else {
+                return false;
+            }
+            Date today = new Date();
+            sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            sipCall.toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            sipCall.fromTag = SIPStack.newTag();
+            sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_LOBBY) {
+                String postFix = "";
+                if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                    postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                    postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                } else {
+                    postFix = BSSVideo.HNS_POSTFIX_LOBBY;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+                }
+                sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_LOBBY) + SIPStack.BSSMD5Get(this.viaH) +
+                        SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+                sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+                BSSVideo.bProgressvideooffer = true;
+            } else if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                String postFix = "";
+                if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                    postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                    postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                } else {
+                    postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+                }
+                sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_GUARD) + SIPStack.BSSMD5Get(this.viaH) +
+                        SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+                sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                BSSVideo.bProgressvideooffer = true;
+            } else if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                String postFix = "";
+                if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
+                    postFix = BSSVideo.HNS_POSTFIX_GUARD;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                    BSSVideo.bProgressvideooffer = true;
+                } else if (BSSVideo.HNS_SERVICE_RECEIVER_SELECTED == BSSVideo.HNS_SERVICE_NEIGHBOR) {
+                    postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                    BSSVideo.bProgressvideooffer = true;
+                } else {
+                    postFix = BSSVideo.HNS_POSTFIX_NEIGHBOR;
+                    sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
+                    BSSVideo.bProgressvideooffer = false;
+                }
+                sipCall.callId = String.valueOf(BSSVideo.HNS_PREFIX_NEIGHBOR) + SIPStack.BSSMD5Get(this.viaH) +
+                        SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + "." + postFix;
+                sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+            } else {
+                sipCall.callId = String.valueOf(SIPStack.BSSMD5Get(this.viaH)) + SIPStack.BSSMD5Get("1198602188") + today.getSeconds() + ".";
+                sipCall.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+                sipCall.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                BSSVideo.bProgressvideooffer = false;
+            }
+            sipCall.callidH = "Call-ID: " + sipCall.callId;
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            if (sipCall.cid != null && sipCall.cid.length() > 0) {
+                sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                sipCall.passertedidentityH = null;
+                header = "";
+            }
+            int audioport = SIPStack.getFreeAudioRtpPort();
+            if (audioport > 0)
+                sipCall.constructSdp();
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711U,
+                            "PCMU/8000");
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711A,
+                            "PCMA/8000");
+                } else {
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711A,
+                            "PCMA/8000");
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711U,
+                            "PCMU/8000");
+                }
+                sipCall.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        RFC2833.payloadType,
+                        "telephone-event/8000");
+                sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 1;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            sipCall.message =
+                    String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                            sipCall.viaH + SIPStack.SIP_LINE_END +
+                            sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                            sipCall.contactH + SIPStack.SIP_LINE_END +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            sipCall.allowH + SIPStack.SIP_LINE_END +
+                            sipCall.useragentH + SIPStack.SIP_LINE_END +
+                            header +
+                            sipCall.contenttypeH +
+                            sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                            body;
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeReactionForWWWAUTHENTICATE(SIPCall sipCall, String message) {
+        try {
+            String header = null;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipCall.CSEQ_NUMBER = ++SIPStack.SIP_SEQUENCE_INVITE;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            sipCall.authorizationINVITEH = "";
+            sipCall.authorizationCANCELH = "";
+            sipCall.authorizationBYEH = "";
+            sipCall.authorizationACKH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE);
+            if (sipHeader == null || !sipHeader.flag)
+                sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE);
+            if (sipHeader != null && sipHeader.flag) {
+                SIPAUTHENTICATEHeader authHeader =
+                        new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE);
+                if (authHeader == null || !authHeader.flag)
+                    authHeader = new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE);
+                if (authHeader != null && authHeader.flag)
+                    if (authHeader.nonceValue.length() > 0 && authHeader.realmValue.length() > 0) {
+                        String qop = authHeader.qopValue;
+                        String uri = "sip:" + this.serverDomain + ":" + this.serverPort;
+                        sipCall.authorizationINVITEH = getAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_INVITE);
+                        sipCall.authorizationCANCELH = getAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_CANCEL);
+                        sipCall.authorizationBYEH = getAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_BYE);
+                        sipCall.authorizationACKH = getAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_ACK);
+                    }
+            }
+            sipCall.commandLine = "INVITE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            sipCall.toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            sipCall.fromTag = SIPStack.newTag();
+            sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            if (sipCall.cid != null && sipCall.cid.length() > 0) {
+                sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                sipCall.passertedidentityH = null;
+                header = "";
+            }
+            if (sipCall.sdp == null) {
+                int audioport = SIPStack.getFreeAudioRtpPort();
+                if (audioport > 0)
+                    sipCall.constructSdp();
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                    if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                    } else {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                    }
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            RFC2833.payloadType,
+                            "telephone-event/8000");
+                    sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+                }
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 1;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            sipCall.message = "";
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeReactionForPROXYAUTHENTICATE(SIPCall sipCall, String message) {
+        try {
+            String header = null;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipCall.CSEQ_NUMBER = ++SIPStack.SIP_SEQUENCE_INVITE;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            sipCall.authorizationINVITEH = "";
+            sipCall.authorizationCANCELH = "";
+            sipCall.authorizationBYEH = "";
+            sipCall.authorizationACKH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE);
+            if (sipHeader != null && sipHeader.flag) {
+                SIPAUTHENTICATEHeader authHeader =
+                        new SIPAUTHENTICATEHeader(sipHeader.header, SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE);
+                if (authHeader.flag)
+                    if (authHeader.nonceValue.length() > 0 && authHeader.realmValue.length() > 0) {
+                        String qop = authHeader.qopValue;
+                        String uri = "sip:" + this.serverDomain + ":" + this.serverPort;
+                        sipCall.authorizationINVITEH = getProxyAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_INVITE);
+                        sipCall.authorizationCANCELH = getProxyAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_CANCEL);
+                        sipCall.authorizationBYEH = getProxyAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_BYE);
+                        sipCall.authorizationACKH = getProxyAuthorizationHeader(
+                                qop,
+                                this.authid,
+                                authHeader.realmValue,
+                                this.authpassword, uri,
+                                authHeader.nonceValue,
+                                SIPStack.SIP_METHODTYPE_ACK);
+                    }
+            }
+            sipCall.commandLine = "INVITE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            sipCall.toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            sipCall.fromTag = SIPStack.newTag();
+            sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+            if (sipCall.cid != null && sipCall.cid.length() > 0) {
+                sipCall.passertedidentityH = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+                header = "P-Asserted-Identity: <sip:" + sipCall.cid + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                sipCall.passertedidentityH = null;
+                header = "";
+            }
+            if (sipCall.sdp == null) {
+                int audioport = SIPStack.getFreeAudioRtpPort();
+                if (audioport > 0)
+                    sipCall.constructSdp();
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                    if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                    } else {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                    }
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            RFC2833.payloadType,
+                            "telephone-event/8000");
+                    sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+                }
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 1;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                header +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public String makeRedirectIncomingCall(SIPCall sipCall, String redirectId) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (redirectId == null || redirectId.length() == 0)
+                return "";
+            if (sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN)
+                if (sipCall.callState == 2 ||
+                        sipCall.callState == 12) {
+                    String commandLine = null;
+                    String contactH = null;
+                    String contentlengthH = null;
+                    commandLine = "SIP/2.0 302 " + SIPStack.getResponseDescription(302) + SIPStack.SIP_LINE_END;
+                    String viaString = "";
+                    if (sipCall.viaArray.length() > 0)
+                        viaString = sipCall.viaArray.toString();
+                    String routeString = "";
+                    if (sipCall.recordrouteArray.length() > 0)
+                        routeString = sipCall.recordrouteArray.toString();
+                    contactH = "Contact: <sip:" + redirectId + "@" + this.serverIp + ":" + this.serverPort + ">";
+                    contentlengthH = "Content-Length: 0" + SIPStack.SIP_LINE_END;
+                    String sendmessage =
+                            String.valueOf(commandLine) +
+                                    viaString +
+                                    routeString +
+                                    sipCall.fromH + SIPStack.SIP_LINE_END +
+                                    sipCall.toH + SIPStack.SIP_LINE_END +
+                                    sipCall.callidH + SIPStack.SIP_LINE_END +
+                                    sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                    contactH + SIPStack.SIP_LINE_END +
+                                    contentlengthH + SIPStack.SIP_LINE_END;
+                    return sendmessage;
+                }
+        } catch (Exception exception) {}
+        return "";
+    }
+
+    public String makeSendProgressing(SIPCall sipCall, String body) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            if (body == null || body.length() <= 0)
+                return "";
+            String commandLine = null;
+            String contactH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 183 " + SIPStack.getResponseDescription(183) + SIPStack.SIP_LINE_END;
+            String viaString = "";
+            if (sipCall.viaArray.length() > 0)
+                viaString = sipCall.viaArray.toString();
+            SIPHeader sipHeader = new SIPHeader(this.message, SIPStack.SIP_HEADERTYPE_VIA);
+            if (sipHeader != null && sipHeader.flag) {
+                this.viaH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                this.viaH = "";
+            }
+            String routeString = "";
+            if (sipCall.recordrouteArray != null &&
+                    sipCall.recordrouteArray.length() > 0)
+                routeString = sipCall.recordrouteArray.toString();
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            contentlengthH = "Content-Length: " + body.length() + SIPStack.SIP_LINE_END;
+            String contenttypeH = "";
+            if (body != null && body.length() > 0)
+                contenttypeH = "Content-Type: application/SDP" + SIPStack.SIP_LINE_END;
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaString +
+                            routeString +
+                            sipCall.fromH + SIPStack.SIP_LINE_END +
+                            sipCall.toH + SIPStack.SIP_LINE_END +
+                            sipCall.callidH + SIPStack.SIP_LINE_END +
+                            sipCall.cseqH + SIPStack.SIP_LINE_END +
+                            contactH + SIPStack.SIP_LINE_END +
+                            contenttypeH +
+                            contentlengthH +
+                            SIPStack.SIP_LINE_END +
+                            body;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public boolean makeSendAck(SIPCall sipCall, String message) {
+        try {
+            sipCall.routeIp = "";
+            sipCall.routePort = 5060;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipCall.ACK_CSEQ = sipCall.CSEQ_NUMBER;
+            sipCall.reverseRecordRoute(message);
+            if (sipCall.remoteContactUri != null && sipCall.remoteContactUri.length() > 0) {
+                sipCall.commandLine = "ACK " + sipCall.remoteContactUri + " SIP/2.0";
+            } else {
+                sipCall.commandLine = "ACK sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            }
+            if (sipCall.viaH == null || sipCall.viaH.length() == 0) {
+                if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                    sipCall.viaBranch = SIPStack.getViaBranch();
+                sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            }
+            sipCall.cseqH = "CSeq: " + sipCall.ACK_CSEQ + " ACK";
+            sipCall.contentlengthH = "Content-Length: 0";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            String routeString = "";
+            if (sipCall.routeArray != null &&
+                    sipCall.routeArray.length() > 0) {
+                routeString = sipCall.routeArray.toString();
+                if (sipCall.routeH != null && sipCall.routeH.length() > 0) {
+                    SIPROUTEHeader header = new SIPROUTEHeader(sipCall.routeH);
+                    if (header != null && header.flag) {
+                        sipCall.routeIp = header.getIp();
+                        sipCall.routePort = header.getPort();
+                    }
+                }
+            }
+            if (sipCall.authorizationACKH != null && sipCall.authorizationACKH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.authorizationACKH + SIPStack.SIP_LINE_END +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeSendFinalAck(SIPCall sipCall, String message) {
+        try {
+            String fromH = null;
+            String toH = null;
+            String callidH = null;
+            String viaH = null;
+            String commandLine = null;
+            String contentlengthH = null;
+            String cseqH = null;
+            SIPHeader sipheader = null;
+            sipCall.routeIp = "";
+            sipCall.routePort = 5060;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                fromH = new String(sipheader.header);
+            } else {
+                return false;
+            }
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                toH = new String(sipheader.header);
+            } else {
+                return false;
+            }
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                callidH = new String(sipheader.header);
+            } else {
+                return false;
+            }
+            int ACK_CSEQ = sipCall.CSEQ_NUMBER;
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipheader != null && sipheader.flag && sipheader.callSequenceNumber() >= 0)
+                ACK_CSEQ = sipheader.callSequenceNumber();
+            sipCall.reverseRecordRoute(message);
+            if (sipCall.remoteContactUri != null && sipCall.remoteContactUri.length() > 0) {
+                commandLine = "ACK " + sipCall.remoteContactUri + " SIP/2.0";
+            } else {
+                commandLine = "ACK sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            }
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_VIA);
+            if (sipheader != null && sipheader.flag) {
+                viaH = new String(sipheader.header);
+                if (viaH != null && viaH.length() > 0) {
+                    String branch = "";
+                    int index = viaH.indexOf(";branch=");
+                    if (index > 0)
+                        branch = viaH.substring(index + 1);
+                    index = branch.indexOf(";");
+                    if (index > 0)
+                        branch = branch.substring(0, index);
+                    index = viaH.indexOf(";received=");
+                    if (index > 0)
+                        viaH = viaH.substring(0, index);
+                    index = viaH.indexOf(";rport=");
+                    if (index > 0)
+                        viaH = viaH.substring(0, index);
+                    viaH = String.valueOf(viaH) + ";" + branch;
+                }
+            }
+            if (viaH == null || viaH.length() == 0)
+                viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+            cseqH = "CSeq: " + ACK_CSEQ + " ACK";
+            contentlengthH = "Content-Length: 0";
+            String routeString = "";
+            if (sipCall.routeArray != null &&
+                    sipCall.routeArray.length() > 0) {
+                routeString = sipCall.routeArray.toString();
+                if (sipCall.routeH != null && sipCall.routeH.length() > 0) {
+                    SIPROUTEHeader header = new SIPROUTEHeader(sipCall.routeH);
+                    if (header != null && header.flag) {
+                        sipCall.routeIp = header.getIp();
+                        sipCall.routePort = header.getPort();
+                    }
+                }
+            }
+            if (sipCall.authorizationACKH != null && sipCall.authorizationACKH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                                fromH + SIPStack.SIP_LINE_END +
+                                toH + SIPStack.SIP_LINE_END +
+                                viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                callidH + SIPStack.SIP_LINE_END +
+                                cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.authorizationACKH + SIPStack.SIP_LINE_END +
+                                contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                sipCall.message =
+                        String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                                fromH + SIPStack.SIP_LINE_END +
+                                toH + SIPStack.SIP_LINE_END +
+                                viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                callidH + SIPStack.SIP_LINE_END +
+                                cseqH + SIPStack.SIP_LINE_END +
+                                contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public String makeSendFinalAck(SIPCall sipCall, String message, String remoteIp, int remotePort) {
+        try {
+            String fromH = null;
+            String toH = null;
+            String callidH = null;
+            String viaH = null;
+            String commandLine = null;
+            String contentlengthH = null;
+            String cseqH = null;
+            SIPHeader sipheader = null;
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                fromH = new String(sipheader.header);
+            } else {
+                return "";
+            }
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                toH = new String(sipheader.header);
+            } else {
+                return "";
+            }
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipheader != null && sipheader.flag && sipheader.header != null && sipheader.header.length() > 0) {
+                callidH = new String(sipheader.header);
+            } else {
+                return "";
+            }
+            int ACK_CSEQ = 0;
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipheader != null && sipheader.flag && sipheader.callSequenceNumber() >= 0)
+                ACK_CSEQ = sipheader.callSequenceNumber();
+            commandLine = "ACK sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            sipheader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_VIA);
+            if (sipheader != null && sipheader.flag) {
+                viaH = new String(sipheader.header);
+                if (viaH != null && viaH.length() > 0) {
+                    String branch = "";
+                    int index = viaH.indexOf(";branch=");
+                    if (index > 0)
+                        branch = viaH.substring(index + 1);
+                    index = branch.indexOf(";");
+                    if (index > 0)
+                        branch = branch.substring(0, index);
+                    index = viaH.indexOf(";received=");
+                    if (index > 0)
+                        viaH = viaH.substring(0, index);
+                    index = viaH.indexOf(";rport=");
+                    if (index > 0)
+                        viaH = viaH.substring(0, index);
+                    viaH = String.valueOf(viaH) + ";" + branch;
+                }
+            }
+            if (viaH == null || viaH.length() == 0)
+                viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + SIPStack.getViaBranch() + ";rport";
+            cseqH = "CSeq: " + ACK_CSEQ + " ACK";
+            contentlengthH = "Content-Length: 0";
+            String sendmessage =
+                    String.valueOf(commandLine) + SIPStack.SIP_LINE_END +
+                            fromH + SIPStack.SIP_LINE_END +
+                            toH + SIPStack.SIP_LINE_END +
+                            viaH + SIPStack.SIP_LINE_END +
+                            callidH + SIPStack.SIP_LINE_END +
+                            cseqH + SIPStack.SIP_LINE_END +
+                            contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public boolean makeSendRedirectFinalAck(SIPCall sipCall, String message) {
+        try {
+            sipCall.routeIp = "";
+            sipCall.routePort = 5060;
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            sipCall.ACK_CSEQ = sipCall.CSEQ_NUMBER;
+            sipCall.reverseRecordRoute(message);
+            sipCall.commandLine = "ACK sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            if (sipCall.viaH == null || sipCall.viaH.length() == 0) {
+                if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                    sipCall.viaBranch = SIPStack.getViaBranch();
+                sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            }
+            sipCall.cseqH = "CSeq: " + sipCall.ACK_CSEQ + " ACK";
+            sipCall.contentlengthH = "Content-Length: 0";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            String routeString = "";
+            if (sipCall.routeArray != null &&
+                    sipCall.routeArray.length() > 0) {
+                routeString = sipCall.routeArray.toString();
+                if (sipCall.routeH != null && sipCall.routeH.length() > 0) {
+                    SIPROUTEHeader header = new SIPROUTEHeader(sipCall.routeH);
+                    if (header != null && header.flag) {
+                        sipCall.routeIp = header.getIp();
+                        sipCall.routePort = header.getPort();
+                    }
+                }
+            }
+            if (sipCall.authorizationACKH != null && sipCall.authorizationACKH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.authorizationACKH + SIPStack.SIP_LINE_END +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                routeString +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public String makeSendByeResponse(SIPCall sipCall, String message) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            sipCall.BYE_CSEQ = sipCall.ACK_CSEQ;
+            String commandLine = null;
+            String viaH = null;
+            String toH = null;
+            String fromH = null;
+            String callidH = null;
+            String cseqH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 200 " + SIPStack.getResponseDescription(200) + SIPStack.SIP_LINE_END;
+            viaH = sipCall.getViaArray(message);
+            if (viaH == null || viaH.length() == 0)
+                viaH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipHeader != null && sipHeader.flag) {
+                fromH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                fromH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipHeader != null && sipHeader.flag) {
+                toH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+                if (toH.indexOf("tag=") < 0)
+                    toH = String.valueOf(sipHeader.header) + ";tag=" + SIPStack.newTag() + SIPStack.SIP_LINE_END;
+            } else {
+                toH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag) {
+                callidH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                callidH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipHeader != null && sipHeader.flag) {
+                sipCall.BYE_CSEQ = sipHeader.callSequenceNumber();
+                cseqH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                cseqH = "";
+            }
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaH +
+                            fromH +
+                            toH +
+                            callidH +
+                            cseqH +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendOptionsResponse(SIPCall sipCall, String message, int code) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return "";
+            String commandLine = null;
+            String viaH = null;
+            String toH = null;
+            String fromH = null;
+            String callidH = null;
+            String cseqH = null;
+            String allowH = null;
+            String useragentH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 " + code + " " + SIPStack.getResponseDescription(code) + SIPStack.SIP_LINE_END;
+            viaH = sipCall.getViaArray(message);
+            if (viaH == null || viaH.length() == 0)
+                viaH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipHeader != null && sipHeader.flag) {
+                fromH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                fromH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipHeader != null && sipHeader.flag) {
+                toH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+                if (toH.indexOf("tag=") < 0)
+                    toH = String.valueOf(sipHeader.header) + ";tag=" + SIPStack.newTag() + SIPStack.SIP_LINE_END;
+            } else {
+                toH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag) {
+                callidH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                callidH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipHeader != null && sipHeader.flag) {
+                cseqH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                cseqH = "";
+            }
+            allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO" + SIPStack.SIP_LINE_END;
+            useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o" + SIPStack.SIP_LINE_END;
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaH +
+                            fromH +
+                            toH +
+                            callidH +
+                            cseqH +
+                            allowH +
+                            useragentH +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public String makeSendInfoResponse(SIPCall sipCall, String message, int code) {
+        if (sipCall == null || !sipCall.flag)
+            return "";
+        try {
+            String commandLine = null;
+            String viaH = null;
+            String toH = null;
+            String fromH = null;
+            String callidH = null;
+            String cseqH = null;
+            String allowH = null;
+            String useragentH = null;
+            String contentlengthH = null;
+            commandLine = "SIP/2.0 " + code + " " + SIPStack.getResponseDescription(code) + SIPStack.SIP_LINE_END;
+            viaH = sipCall.getViaArray(message);
+            if (viaH == null || viaH.length() == 0)
+                viaH = "";
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_FROM);
+            if (sipHeader != null && sipHeader.flag) {
+                fromH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                fromH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);
+            if (sipHeader != null && sipHeader.flag) {
+                toH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+                if (toH.indexOf("tag=") < 0)
+                    toH = String.valueOf(sipHeader.header) + ";tag=" + SIPStack.newTag() + SIPStack.SIP_LINE_END;
+            } else {
+                toH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag) {
+                callidH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                callidH = "";
+            }
+            sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
+            if (sipHeader != null && sipHeader.flag) {
+                cseqH = String.valueOf(sipHeader.header) + SIPStack.SIP_LINE_END;
+            } else {
+                cseqH = "";
+            }
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                this.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">" + SIPStack.SIP_LINE_END;
+            } else {
+                this.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">" + SIPStack.SIP_LINE_END;
+            }
+            allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO" + SIPStack.SIP_LINE_END;
+            useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o" + SIPStack.SIP_LINE_END;
+            contentlengthH = "Content-Length: 0\r\n";
+            String sendmessage =
+                    String.valueOf(commandLine) +
+                            viaH +
+                            fromH +
+                            toH +
+                            callidH +
+                            cseqH +
+                            this.contactH +
+                            allowH +
+                            useragentH +
+                            contentlengthH + SIPStack.SIP_LINE_END;
+            return sendmessage;
+        } catch (Exception exception) {
+            return "";
+        }
+    }
+
+    public boolean makeSendUpdate(SIPCall sipCall) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            String viaBranch = sipCall.viaBranch;
+            sipCall.setUpdateheaders("sendonly");
+            sipCall.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+            SIPStack.SIP_SEQUENCE_INVITE++;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            sipCall.commandLine = "INVITE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            sipCall.viaBranch = viaBranch;
+            if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            if (sipCall.toH == null || sipCall.toH.length() == 0)
+                sipCall.toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            if (sipCall.fromH == null || sipCall.fromH.length() == 0) {
+                sipCall.fromTag = SIPStack.newTag();
+                sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            }
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: " + SIPStack.USER_AGENT;
+            if (sipCall.sdp == null) {
+                int audioport = SIPStack.getFreeAudioRtpPort();
+                if (audioport > 0)
+                    sipCall.constructSdp();
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                    if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                    } else {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                    }
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            RFC2833.payloadType,
+                            "telephone-event/8000");
+                    sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+                }
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 20;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public boolean makeSendUpdate(SIPCall sipCall, String flow) {
+        try {
+            if (sipCall == null || !sipCall.flag)
+                return false;
+            String viaBranch = sipCall.viaBranch;
+            sipCall.setUpdateheaders(flow);
+            sipCall.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+            SIPStack.SIP_SEQUENCE_INVITE++;
+            if (SIPStack.SIP_SEQUENCE_INVITE > 65556)
+                SIPStack.SIP_SEQUENCE_INVITE = 1;
+            sipCall.commandLine = "INVITE sip:" + sipCall.dnis + "@" + this.serverDomain + ":" + this.serverPort + " SIP/2.0";
+            sipCall.viaBranch = viaBranch;
+            if (sipCall.viaBranch == null || sipCall.viaBranch.length() == 0)
+                sipCall.viaBranch = SIPStack.getViaBranch();
+            sipCall.viaH = "Via: SIP/2.0/UDP " + this.localIp + ":" + this.localPort + ";branch=" + sipCall.viaBranch + ";rport";
+            sipCall.maxforwardH = "Max-Forwards: 70";
+            if (this.ifIp != null && this.ifIp.length() > 0 && this.ifPort > 0) {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + this.ifIp + ":" + this.ifPort + ">";
+            } else {
+                sipCall.contactH = "Contact: <sip:" + this.id + "@" + sipCall.localIp + ":" + sipCall.localPort + ">";
+            }
+            if (sipCall.toH == null || sipCall.toH.length() == 0)
+                sipCall.toH = "To: \"" + sipCall.dnis + "\"<sip:" + sipCall.dnis + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">";
+            if (sipCall.fromH == null || sipCall.fromH.length() == 0) {
+                sipCall.fromTag = SIPStack.newTag();
+                sipCall.fromH = "From: \"" + sipCall.id + "\"<sip:" + sipCall.id + "@" + sipCall.serverDomain + ":" + sipCall.serverPort + ">;tag=" + sipCall.fromTag;
+            }
+            sipCall.cseqH = "CSeq: " + sipCall.CSEQ_NUMBER + " INVITE";
+            sipCall.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+            sipCall.useragentH = "User-Agent: " + SIPStack.USER_AGENT;
+            if (sipCall.sdp == null) {
+                int audioport = SIPStack.getFreeAudioRtpPort();
+                if (audioport > 0)
+                    sipCall.constructSdp();
+                if (sipCall.sdp != null && sipCall.sdp.flag) {
+                    sipCall.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+                    if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                    } else {
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711A,
+                                "PCMA/8000");
+                        sipCall.sdp.setCodec(
+                                SIPStack.SIP_MEDIATYPE_AUDIO,
+                                SIPStack.SIP_CODEC_G711U,
+                                "PCMU/8000");
+                    }
+                    sipCall.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            RFC2833.payloadType,
+                            "telephone-event/8000");
+                    sipCall.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+                }
+            }
+            String body = null;
+            sipCall.contenttypeH = "";
+            if (sipCall.sdp != null && sipCall.sdp.flag) {
+                sipCall.contenttypeH = "Content-Type: application/SDP\r\n";
+                if (SIPStack.bVideocommunication) {
+                    body = String.valueOf(sipCall.sdp.getBodyString()) + getVideomediadescription(sipCall.sdp.audioM.mediaPort + 2);
+                } else {
+                    body = sipCall.sdp.getBodyString();
+                }
+                sipCall.contentlengthH = "Content-Length: " + body.length();
+            } else {
+                body = "";
+                sipCall.contentlengthH = "Content-Length: 0";
+            }
+            sipCall.callState = 20;
+            sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
+            if (sipCall.authorizationINVITEH != null && sipCall.authorizationINVITEH.length() > 0) {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.authorizationINVITEH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            } else {
+                sipCall.message =
+                        String.valueOf(sipCall.commandLine) + SIPStack.SIP_LINE_END +
+                                sipCall.viaH + SIPStack.SIP_LINE_END +
+                                sipCall.maxforwardH + SIPStack.SIP_LINE_END +
+                                sipCall.contactH + SIPStack.SIP_LINE_END +
+                                sipCall.fromH + SIPStack.SIP_LINE_END +
+                                sipCall.toH + SIPStack.SIP_LINE_END +
+                                sipCall.callidH + SIPStack.SIP_LINE_END +
+                                sipCall.cseqH + SIPStack.SIP_LINE_END +
+                                sipCall.allowH + SIPStack.SIP_LINE_END +
+                                sipCall.useragentH + SIPStack.SIP_LINE_END +
+                                sipCall.contenttypeH +
+                                sipCall.contentlengthH + SIPStack.SIP_LINE_DOUBLEEND +
+                                body;
+            }
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public static String getCallfailReason(int finalCode) {
+        String desc = "";
+        switch (finalCode) {
+            case 200:
+                desc = "통화";
+                break;
+            case 300:
+                desc = "거절";
+                break;
+            case 301:
+                desc = "거절";
+                break;
+            case 302:
+                desc = "거절";
+                break;
+            case 305:
+                desc = "거절";
+                break;
+            case 380:
+                desc = "거절";
+                break;
+            case 400:
+                desc = "거절";
+                break;
+            case 401:
+                desc = "거절";
+                break;
+            case 402:
+                desc = "거절";
+                break;
+            case 403:
+                desc = "거절";
+                break;
+            case 404:
+                desc = "거절";
+                break;
+            case 405:
+                desc = "거절";
+                break;
+            case 406:
+                desc = "거절";
+                break;
+            case 407:
+                desc = "거절";
+                break;
+            case 408:
+                desc = "거절";
+                break;
+            case 409:
+                desc = "거절";
+                break;
+            case 410:
+                desc = "거절";
+                break;
+            case 411:
+                desc = "거절";
+                break;
+            case 413:
+                desc = "거절";
+                break;
+            case 414:
+                desc = "거절";
+                break;
+            case 415:
+                desc = "거절";
+                break;
+            case 420:
+                desc = "거절";
+                break;
+            case 421:
+                desc = "거절";
+                break;
+            case 423:
+                desc = "거절";
+                break;
+            case 480:
+                desc = "거절";
+                break;
+            case 481:
+                desc = "거절";
+                break;
+            case 482:
+                desc = "거절";
+                break;
+            case 483:
+                desc = "거절";
+                break;
+            case 484:
+                desc = "거절";
+                break;
+            case 485:
+                desc = "거절";
+                break;
+            case 486:
+                desc = "거절";
+                break;
+            case 487:
+                desc = "통화중";
+                break;
+            case 488:
+                desc = "거절";
+                break;
+            case 500:
+                desc = "거절";
+                break;
+            case 501:
+                desc = "거절";
+                break;
+            case 502:
+                desc = "거절";
+                break;
+            case 503:
+                desc = "거절";
+                break;
+            case 504:
+                desc = "거절";
+                break;
+            case 505:
+                desc = "거절";
+                break;
+            case 600:
+                desc = "거절";
+                break;
+            case 603:
+                desc = "거절";
+                break;
+            case 604:
+                desc = "거절";
+                break;
+            case 606:
+                desc = "거절";
+                break;
+            case 700:
+                desc = "통화종료";
+                break;
+        }
+        return desc;
+    }
+}

+ 21 - 0
WallPadCall/src/main/java/bssoft/stack/sip/Frequent.java

@@ -0,0 +1,21 @@
+package bssoft.stack.sip;
+
+public class Frequent {
+    public int _id;
+
+    public String phone;
+
+    public String name;
+
+    public Frequent() {
+        this._id = 0;
+        this.phone = "";
+        this.name = "";
+    }
+
+    public Frequent(int id, String phone, String name) {
+        this._id = id;
+        this.phone = phone;
+        this.name = name;
+    }
+}

+ 36 - 0
WallPadCall/src/main/java/bssoft/stack/sip/GetIpDns.java

@@ -0,0 +1,36 @@
+package bssoft.stack.sip;
+
+public class GetIpDns {
+    public String sipServerHost = "";
+
+    public String strId = "";
+
+    public String strCid = "";
+
+    public String strAuthid = "";
+
+    public String strAuthpassword = "";
+
+    public String strServerHost = "";
+
+    public String strServerDomain = "";
+
+    public int serverPort = 5060;
+
+    public boolean bSipAddressResolved = false;
+
+    public int sipTry = 0;
+
+    public GetIpDns() {
+        this.sipServerHost = "";
+        this.bSipAddressResolved = false;
+        this.sipTry = 0;
+        this.strId = "";
+        this.strCid = "";
+        this.strAuthid = "";
+        this.strAuthpassword = "";
+        this.strServerHost = "";
+        this.strServerDomain = "";
+        this.serverPort = 5060;
+    }
+}

+ 82 - 0
WallPadCall/src/main/java/bssoft/stack/sip/History.java

@@ -0,0 +1,82 @@
+package bssoft.stack.sip;
+
+public class History {
+    public int _id;
+
+    public String phone;
+
+    public String ani;
+
+    public String dnis;
+
+    public String name;
+
+    public String date;
+
+    public String direction;
+
+    public String code;
+
+    public String duration;
+
+    public String calltype;
+
+    public String callhandle;
+
+    public String check;
+
+    public String view;
+
+    public int count;
+
+    public History() {
+        this._id = 0;
+        this.phone = "";
+        this.ani = "";
+        this.dnis = "";
+        this.name = "";
+        this.date = "";
+        this.direction = "";
+        this.code = "";
+        this.duration = "";
+        this.calltype = "";
+        this.callhandle = "";
+        this.count = 0;
+        this.check = "0";
+        this.view = "0";
+    }
+
+    public History(int id, String phone, String ani, String dnis, String name, String date, String direction, String code, String duration, String calltype, String callhandle) {
+        this._id = id;
+        this.phone = phone;
+        this.ani = ani;
+        this.dnis = dnis;
+        this.name = name;
+        this.date = date;
+        this.direction = direction;
+        this.code = code;
+        this.duration = duration;
+        this.calltype = calltype;
+        this.callhandle = callhandle;
+        this.check = "0";
+        this.view = "0";
+        this.count = 1;
+    }
+
+    public History(int id, String phone, String ani, String dnis, String name, String date, String direction, String code, String duration, String calltype, String callhandle, String check, String view) {
+        this._id = id;
+        this.phone = phone;
+        this.ani = ani;
+        this.dnis = dnis;
+        this.name = name;
+        this.date = date;
+        this.direction = direction;
+        this.code = code;
+        this.duration = duration;
+        this.calltype = calltype;
+        this.callhandle = callhandle;
+        this.check = check;
+        this.view = view;
+        this.count = 1;
+    }
+}

+ 95 - 0
WallPadCall/src/main/java/bssoft/stack/sip/RFC2833.java

@@ -0,0 +1,95 @@
+package bssoft.stack.sip;
+
+public class RFC2833 {
+    public boolean bStart = false;
+
+    public boolean bEnd = false;
+
+    public static int payloadType = 101;
+
+    public int event = 0;
+
+    public int volume = 0;
+
+    public int reserved = 0;
+
+    public int edge = 0;
+
+    public int duration = 0;
+
+    public int exceedDuration = 0;
+
+    public boolean bActive;
+
+    public boolean flag;
+
+    public byte[] rfcdata = new byte[4];
+
+    public RFC2833() {
+        this.bActive = false;
+        this.flag = true;
+    }
+
+    public boolean setDtmf(int event, int volume, int reserved, int duration) {
+        System.out.println("DTMF SET :" + event + ":" + volume + ":" + reserved + ":" + duration);
+        this.bStart = true;
+        this.bEnd = false;
+        this.event = event;
+        this.volume = volume;
+        this.reserved = reserved;
+        this.edge = 0;
+        this.duration = duration;
+        this.bActive = true;
+        return true;
+    }
+
+    public boolean resetDtmf() {
+        this.bStart = false;
+        this.bEnd = false;
+        this.event = 0;
+        this.volume = 0;
+        this.reserved = 0;
+        this.edge = 0;
+        this.duration = 0;
+        this.exceedDuration = 0;
+        this.bActive = false;
+        return true;
+    }
+
+    public byte[] constructDtmfPacket() {
+        int field = 0;
+        field = this.event;
+        this.rfcdata[0] = (byte)(field << 24 >> 24);
+        field = 0;
+        field = this.volume << 26 >> 26 & 0x3F;
+        field |= this.edge << 31 >> 24 & 0x80;
+        this.rfcdata[1] = (byte)(field << 24 >> 24);
+        field = this.duration;
+        this.rfcdata[2] = (byte)(field << 16 >> 24);
+        this.rfcdata[3] = (byte)(field << 24 >> 24);
+        return this.rfcdata;
+    }
+
+    public byte[] constructDtmfPacket(int consumeduration) {
+        if (this.exceedDuration >= this.duration)
+            return null;
+        if (this.exceedDuration > 0)
+            this.bStart = false;
+        this.exceedDuration += consumeduration;
+        if (this.exceedDuration >= this.duration) {
+            this.edge = 1;
+            this.bEnd = true;
+        }
+        int field = 0;
+        field = this.event;
+        this.rfcdata[0] = (byte)(field << 24 >> 24);
+        field = 0;
+        field = this.volume << 26 >> 26 & 0x3F;
+        field |= this.edge << 31 >> 24 & 0x80;
+        this.rfcdata[1] = (byte)(field << 24 >> 24);
+        field = this.duration;
+        this.rfcdata[2] = (byte)(field << 16 >> 24);
+        this.rfcdata[3] = (byte)(field << 24 >> 24);
+        return this.rfcdata;
+    }
+}

+ 328 - 0
WallPadCall/src/main/java/bssoft/stack/sip/RTPCore.java

@@ -0,0 +1,328 @@
+package bssoft.stack.sip;
+
+import java.net.DatagramPacket;
+import java.util.Date;
+
+public class RTPCore {
+    public int RTP_PORT = 0;
+
+    public int mediaType = SIPStack.SIP_MEDIATYPE_NONE;
+
+    public byte[] buffer = null;
+
+    public byte[] pcmLinearBuffer = null;
+
+    public boolean bRTPlooping = false;
+
+    public boolean bRTPparsing = false;
+
+    public boolean bActive = false;
+
+    public int RTPversion = 0;
+
+    public int RTPpadding = 0;
+
+    public int RTPextension = 0;
+
+    public int RTPcsrc = 0;
+
+    public int RTPmark = 0;
+
+    public int RTPpayload = 0;
+
+    public int RTPsequence = 0;
+
+    public int RTPtimestamp = 0;
+
+    public int RTPssrc = 0;
+
+    public byte[] rtpPacketBuffer = null;
+
+    public byte[] rtpBulkBuffer = null;
+
+    public byte[] fieldBytes = null;
+
+    public byte[] rtpfieldBytes = null;
+
+    public boolean running = false;
+
+    public int remotePayloadType = SIPStack.SIP_CODEC_NONE;
+
+    public String remoteMediaIp = null;
+
+    public int remoteMediaPort = 0;
+
+    public boolean bDtmfDetected = false;
+
+    public int detectedDtmf = 0;
+
+    public Date rtpArrivalTime = null;
+
+    public int packetSize = 0;
+
+    public int PARSEversion = 0;
+
+    public int PARSEpadding = 0;
+
+    public int PARSEextension = 0;
+
+    public int PARSEcsrc = 0;
+
+    public int PARSEmark = 0;
+
+    public int PARSEpayload = 0;
+
+    public int PARSEsequence = 0;
+
+    public int PARSEtimestamp = 0;
+
+    public int PARSEssrc = 0;
+
+    public int PARSERFCdtmf = 0;
+
+    public int PARSERFCedge = 0;
+
+    public int PARSERFCvolume = 0;
+
+    public int PARSERFCduration = 0;
+
+    public RTPCore(int port, int mediaType) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        this.RTP_PORT = port;
+        this.pcmLinearBuffer = new byte[1024];
+        this.rtpPacketBuffer = new byte[512];
+        this.rtpBulkBuffer = new byte[512];
+        this.fieldBytes = new byte[4];
+        this.rtpfieldBytes = new byte[4];
+        this.RTPversion = 2;
+        this.RTPpadding = 0;
+        this.RTPextension = 0;
+        this.RTPcsrc = 0;
+        this.RTPmark = 0;
+        this.RTPpayload = 0;
+        this.RTPsequence = 0;
+        Date date = new Date();
+        this.RTPtimestamp = (int)date.getTime();
+        this.RTPssrc = (int)date.getTime();
+        this.mediaType = mediaType;
+        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            this.buffer = new byte[SIPStack.RTP_AUDIO_SIZE];
+        } else if (mediaType == SIPStack.SIP_MEDIATYPE_VIDEO) {
+            this.buffer = new byte[65507];
+        } else {
+            this.buffer = new byte[65507];
+        }
+        this.bActive = false;
+        this.bDtmfDetected = false;
+        this.detectedDtmf = 0;
+        this.rtpArrivalTime = new Date();
+    }
+
+    public boolean encodeRtpHeader(byte[] header, int version, int padding, int extension, int csrc, int mark, int payload, int sequence, int timestamp, int ssrc) {
+        if (header == null || header.length < 12)
+            return false;
+        int iField = 0;
+        int iAppend = 0;
+        iField = version << 6 & 0xC0;
+        iAppend = padding << 5 & 0x20;
+        iField |= iAppend;
+        iAppend = extension << 4 & 0x10;
+        iField |= iAppend;
+        iAppend = csrc & 0xF;
+        iField |= iAppend;
+        header[0] = (byte)iField;
+        iField = 0;
+        iField = mark << 7 & 0x80;
+        iAppend = payload & 0x7F;
+        iField |= iAppend;
+        header[1] = (byte)iField;
+        iField = 0;
+        header[2] = (byte)(sequence << 16 >> 24);
+        header[3] = (byte)(sequence << 24 >> 24);
+        header[4] = (byte)(timestamp >> 24);
+        header[5] = (byte)(timestamp << 8 >> 24);
+        header[6] = (byte)(timestamp << 16 >> 24);
+        header[7] = (byte)(timestamp << 24 >> 24);
+        header[8] = (byte)(ssrc >> 24);
+        header[9] = (byte)(ssrc << 8 >> 24);
+        header[10] = (byte)(ssrc << 16 >> 24);
+        header[11] = (byte)(ssrc << 24 >> 24);
+        return true;
+    }
+
+    public boolean encodeRtpHeader(int payload) {
+        if (this.rtpPacketBuffer == null || this.rtpPacketBuffer.length < 12)
+            return false;
+        int iField = 0;
+        int iAppend = 0;
+        iField = this.RTPversion << 6 & 0xC0;
+        iAppend = this.RTPpadding << 5 & 0x20;
+        iField |= iAppend;
+        iAppend = this.RTPextension << 4 & 0x10;
+        iField |= iAppend;
+        iAppend = this.RTPcsrc & 0xF;
+        iField |= iAppend;
+        this.rtpPacketBuffer[0] = (byte)iField;
+        iField = 0;
+        iField = this.RTPmark << 7 & 0x80;
+        iAppend = payload & 0x7F;
+        iField |= iAppend;
+        this.rtpPacketBuffer[1] = (byte)iField;
+        iField = 0;
+        this.rtpPacketBuffer[2] = (byte)(this.RTPsequence << 16 >> 24);
+        this.rtpPacketBuffer[3] = (byte)(this.RTPsequence << 24 >> 24);
+        this.rtpPacketBuffer[4] = (byte)(this.RTPtimestamp >> 24);
+        this.rtpPacketBuffer[5] = (byte)(this.RTPtimestamp << 8 >> 24);
+        this.rtpPacketBuffer[6] = (byte)(this.RTPtimestamp << 16 >> 24);
+        this.rtpPacketBuffer[7] = (byte)(this.RTPtimestamp << 24 >> 24);
+        this.rtpPacketBuffer[8] = (byte)(this.RTPssrc >> 24);
+        this.rtpPacketBuffer[9] = (byte)(this.RTPssrc << 8 >> 24);
+        this.rtpPacketBuffer[10] = (byte)(this.RTPssrc << 16 >> 24);
+        this.rtpPacketBuffer[11] = (byte)(this.RTPssrc << 24 >> 24);
+        return true;
+    }
+
+    public int getBytesToInt(byte[] bytes) {
+        int newValue = 0;
+        newValue |= bytes[0] << 24 & 0xFF000000;
+        newValue |= bytes[1] << 16 & 0xFF0000;
+        newValue |= bytes[2] << 8 & 0xFF00;
+        newValue |= bytes[3] & 0xFF;
+        return newValue;
+    }
+
+    public byte[] getIntToBytes(int iValue) {
+        byte[] newbytes = new byte[4];
+        newbytes[0] = (byte)(iValue >> 24);
+        newbytes[1] = (byte)(iValue << 8 >> 24);
+        newbytes[2] = (byte)(iValue << 16 >> 24);
+        newbytes[3] = (byte)(iValue << 24 >> 24);
+        return newbytes;
+    }
+
+    public boolean setRTPPort(int port) {
+        if (port <= 0)
+            return false;
+        this.RTP_PORT = port;
+        return true;
+    }
+
+    public void setRemoteMediaInfo(int payloadtype, String mediaIp, int mediaPort) {
+        this.remotePayloadType = payloadtype;
+        this.remoteMediaIp = mediaIp;
+        this.remoteMediaPort = mediaPort;
+    }
+
+    public void parseRtpHeader(byte[] buffer) {
+        if (buffer == null || buffer.length < 12)
+            return;
+        this.fieldBytes[0] = buffer[0];
+        int version = this.fieldBytes[0] >> 6 & 0x3;
+        System.out.println("VERSION:" + version);
+        this.fieldBytes[0] = buffer[1];
+        int payloadType = this.fieldBytes[0] & Byte.MAX_VALUE;
+        System.out.println("Payload:" + payloadType);
+        this.fieldBytes[0] = 0;
+        this.fieldBytes[1] = 0;
+        this.fieldBytes[2] = buffer[2];
+        this.fieldBytes[3] = buffer[3];
+        int sequencNumber = getBytesToInt(this.fieldBytes);
+        System.out.println("SEQUENCE NUMBER:" + sequencNumber);
+        this.fieldBytes[0] = buffer[4];
+        this.fieldBytes[1] = buffer[5];
+        this.fieldBytes[2] = buffer[6];
+        this.fieldBytes[3] = buffer[7];
+        int timeStamp = getBytesToInt(this.fieldBytes);
+        System.out.println("TIMESTAMP:" + timeStamp);
+        this.fieldBytes[0] = buffer[8];
+        this.fieldBytes[1] = buffer[9];
+        this.fieldBytes[2] = buffer[10];
+        this.fieldBytes[3] = buffer[11];
+        int ssrc = getBytesToInt(this.fieldBytes);
+        System.out.println("SSRC:" + ssrc);
+    }
+
+    public void init() {
+        this.RTPversion = 2;
+        this.RTPpadding = 0;
+        this.RTPextension = 0;
+        this.RTPcsrc = 0;
+        this.RTPmark = 0;
+        this.RTPpayload = 0;
+        this.RTPsequence = 0;
+        Date date = new Date();
+        this.RTPtimestamp = (int)date.getTime();
+        this.RTPssrc = (int)date.getTime();
+        this.bDtmfDetected = false;
+        this.detectedDtmf = 0;
+        this.bActive = false;
+        this.rtpArrivalTime = new Date();
+    }
+
+    public boolean parseRTPHeader() {
+        try {
+            this.PARSEversion = 0;
+            this.PARSEpadding = 0;
+            this.PARSEextension = 0;
+            this.PARSEcsrc = 0;
+            this.PARSEmark = 0;
+            this.PARSEpayload = 0;
+            this.PARSEsequence = 0;
+            this.PARSEtimestamp = 0;
+            this.PARSEssrc = 0;
+            this.rtpfieldBytes[0] = this.buffer[1];
+            this.PARSEmark = this.rtpfieldBytes[0] >> 7 & 0x1;
+            this.PARSEpayload = this.rtpfieldBytes[0] & Byte.MAX_VALUE;
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    public String getRemotAddress(DatagramPacket dp) {
+        String strIp = "0.0.0.0:0";
+        try {
+            byte[] address = dp.getAddress().getAddress();
+            if (address.length == 4) {
+                int unsignedByte1 = (address[0] < 0) ? (address[0] + 256) : address[0];
+                int unsignedByte2 = (address[1] < 0) ? (address[1] + 256) : address[1];
+                int unsignedByte3 = (address[2] < 0) ? (address[2] + 256) : address[2];
+                int unsignedByte4 = (address[3] < 0) ? (address[3] + 256) : address[3];
+                strIp = String.valueOf(unsignedByte1) + "." + unsignedByte2 + "." + unsignedByte3 + "." + unsignedByte4 + ":" + dp.getPort();
+            }
+        } catch (Exception exception) {}
+        return strIp;
+    }
+
+    public boolean parseRFC2833() {
+        this.PARSERFCdtmf = 0;
+        this.PARSERFCedge = 0;
+        this.PARSERFCvolume = 0;
+        this.PARSERFCduration = 0;
+        try {
+            int field = 0;
+            this.PARSERFCdtmf = this.buffer[12];
+            field = this.buffer[13];
+            this.PARSERFCedge = (field & 0x80) >> 7;
+            this.PARSERFCvolume = field & 0x3F;
+            this.PARSERFCduration = this.buffer[14] << 24 >> 16 & 0xFF00;
+            this.PARSERFCduration |= this.buffer[15] << 24 >> 24 & 0xFF;
+            return true;
+        } catch (Exception exception) {
+            return false;
+        }
+    }
+
+    public String getVideomediadescription() {
+        int port = this.RTP_PORT + 2;
+        String str = "m=video " + port + " RTP/AVP " + SIPStack.SIP_CODEC_H264 + SIPStack.SIP_LINE_END +
+                "a=rtpmap:" + SIPStack.SIP_CODEC_H264 + " H264/90000" + SIPStack.SIP_LINE_END +
+                "a=fmtp:" + SIPStack.SIP_CODEC_H264 + " packetization-mode=1;profile-level-id=2" + SIPStack.SIP_LINE_END +
+                "a=cliprect:0,0,240,320" + SIPStack.SIP_LINE_END +
+                "a=framesize:" + SIPStack.SIP_CODEC_H264 + " 320-240" + SIPStack.SIP_LINE_END;
+        return str;
+    }
+}

+ 316 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SDPMedia.java

@@ -0,0 +1,316 @@
+package bssoft.stack.sip;
+
+import java.util.StringTokenizer;
+
+public class SDPMedia {
+    public int mediaType = SIPStack.SIP_MEDIATYPE_NONE;
+
+    public String mediaIp = null;
+
+    public int mediaPort = 0;
+
+    public int flowIndicator = SIPStack.SIP_MEDIAFLOW_NONE;
+
+    public StringBuffer rtpmapBuffer = null;
+
+    public StringBuffer fmtpBuffer = null;
+
+    public String flow = "sendrecv";
+
+    public StringBuffer codecS = null;
+
+    public int commonCodec = -1;
+
+    public boolean flag = false;
+
+    public String mediaString = null;
+
+    public SDPMedia(int mediatype) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        this.mediaType = mediatype;
+        this.mediaIp = null;
+        this.mediaPort = 0;
+        this.rtpmapBuffer = new StringBuffer();
+        this.fmtpBuffer = new StringBuffer();
+        this.flow = "sendrecv";
+        this.codecS = new StringBuffer();
+        this.commonCodec = -1;
+        this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
+        this.flag = true;
+    }
+
+    public SDPMedia(String mediadescribe, String platformIp) {
+        this.mediaType = SIPStack.SIP_MEDIATYPE_NONE;
+        this.mediaIp = platformIp;
+        this.mediaPort = 0;
+        this.rtpmapBuffer = new StringBuffer();
+        this.fmtpBuffer = new StringBuffer();
+        this.flow = "sendrecv";
+        this.codecS = new StringBuffer();
+        this.commonCodec = -1;
+        this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
+        boolean bContinueParse = true;
+        if (mediadescribe != null && mediadescribe.length() > 0) {
+            int iS = 0;
+            int iE = 0;
+            String header = null;
+            if (mediadescribe.startsWith("m=audio ")) {
+                this.mediaType = SIPStack.SIP_MEDIATYPE_AUDIO;
+            } else if (mediadescribe.startsWith("m=video ")) {
+                this.mediaType = SIPStack.SIP_MEDIATYPE_VIDEO;
+            } else {
+                bContinueParse = false;
+            }
+            if (bContinueParse) {
+                iE = mediadescribe.indexOf(SIPStack.SIP_LINE_END);
+                if (iE > 0) {
+                    header = mediadescribe.substring(0, iE);
+                    StringTokenizer st = new StringTokenizer(header, " ", true);
+                    int fieldCount = 0;
+                    while (st.hasMoreTokens()) {
+                        String str = st.nextToken().trim();
+                        if (str.length() > 0 && str.compareTo(" ") != 0) {
+                            if (fieldCount == 0) {
+                                if (str.compareTo("m=audio") != 0) {
+                                    bContinueParse = false;
+                                    break;
+                                }
+                            } else if (fieldCount == 1) {
+                                this.mediaPort = Integer.parseInt(str);
+                            } else if (fieldCount == 2) {
+                                if (str.compareTo("RTP/AVP") != 0) {
+                                    bContinueParse = false;
+                                    break;
+                                }
+                            } else if (fieldCount > 2) {
+                                if (this.codecS.length() > 0) {
+                                    this.codecS.append(" " + str);
+                                } else {
+                                    this.codecS.append(str);
+                                }
+                            }
+                            fieldCount++;
+                        }
+                    }
+                } else {
+                    bContinueParse = false;
+                }
+            }
+            if (bContinueParse) {
+                StringTokenizer st = new StringTokenizer(mediadescribe, "\n", true);
+                while (st.hasMoreTokens()) {
+                    String str = st.nextToken().trim();
+                    if (str.length() > 0 && str.startsWith("a=")) {
+                        if (str.startsWith("a=rtpmap:")) {
+                            this.rtpmapBuffer.append(String.valueOf(str) + "\n");
+                            continue;
+                        }
+                        if (str.startsWith("a=fmtp:")) {
+                            this.fmtpBuffer.append(String.valueOf(str) + "\n");
+                            continue;
+                        }
+                        if (str.startsWith("a=sendrecv")) {
+                            this.flow = "sendrecv";
+                            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
+                            continue;
+                        }
+                        if (str.startsWith("a=sendonly")) {
+                            this.flow = "sendonly";
+                            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDONLY;
+                            continue;
+                        }
+                        if (str.startsWith("a=recvonly")) {
+                            this.flow = "recvonly";
+                            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_RECVONLY;
+                        }
+                    }
+                }
+            }
+            if (bContinueParse && mediadescribe.indexOf("\nc=IN IP4 ") > 0) {
+                iS = 0;
+                iE = 0;
+                iS = mediadescribe.indexOf("c=");
+                if (iS >= 0) {
+                    iE = mediadescribe.indexOf(SIPStack.SIP_LINE_END, iS);
+                    header = "";
+                    if (iS >= 0 && iE > iS) {
+                        header = mediadescribe.substring(iS, iE + 2);
+                        iE = header.indexOf(SIPStack.SIP_LINE_END);
+                        this.mediaIp = header.substring("c=IN IP4 ".length(), iE);
+                    }
+                }
+            }
+        }
+        if (!bContinueParse)
+            resetMedia();
+        this.flag = true;
+    }
+
+    public void resetMedia() {
+        this.mediaType = SIPStack.SIP_MEDIATYPE_NONE;
+        this.mediaIp = null;
+        this.mediaPort = 0;
+        this.rtpmapBuffer = null;
+        this.fmtpBuffer = null;
+        this.flow = "sendrecv";
+        this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
+        this.codecS = null;
+        this.commonCodec = -1;
+        this.flag = false;
+        this.mediaString = null;
+    }
+
+    public String getMediaString() {
+        if (!this.flag)
+            return null;
+        String mString = "";
+        String aString = "";
+        String fmtpString = "";
+        String flowString = "a=" + this.flow + SIPStack.SIP_LINE_END;
+        if (this.mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            mString = "m=audio " + this.mediaPort + " RTP/AVP " + this.codecS.toString() + SIPStack.SIP_LINE_END;
+        } else if (this.mediaType != SIPStack.SIP_MEDIATYPE_VIDEO) {
+            return null;
+        }
+        if (this.rtpmapBuffer.length() > 0)
+            aString = this.rtpmapBuffer.toString();
+        if (this.fmtpBuffer.length() > 0)
+            fmtpString = this.fmtpBuffer.toString();
+        this.mediaString = String.valueOf(mString) +
+                aString +
+                fmtpString +
+                flowString;
+        return this.mediaString;
+    }
+
+    public String getFinalMediaString() {
+        if (!this.flag)
+            return null;
+        if (this.commonCodec < 0)
+            return null;
+        String mString = "";
+        String aString = "";
+        String flowString = "a=" + this.flow + SIPStack.SIP_LINE_END;
+        if (this.mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            mString = "m=audio " + this.mediaPort + " RTP/AVP " + this.commonCodec + SIPStack.SIP_LINE_END;
+        } else if (this.mediaType != SIPStack.SIP_MEDIATYPE_VIDEO) {
+            return null;
+        }
+        if (this.commonCodec == 0) {
+            aString = "a=rtpmap:0 PCMU/8000" + SIPStack.SIP_LINE_END;
+        } else if (this.commonCodec == 8) {
+            aString = "a=rtpmap:8 PCMA/8000" + SIPStack.SIP_LINE_END;
+        } else if (this.commonCodec == 18) {
+            aString = "a=rtpmap:18 G729/8000" + SIPStack.SIP_LINE_END;
+        }
+        this.mediaString = String.valueOf(mString) +
+                aString +
+                flowString;
+        return this.mediaString;
+    }
+
+    public boolean setMediaAddress(String ip, int port) {
+        if (!this.flag)
+            return false;
+        if (port < 0 || port > 65556)
+            return false;
+        this.mediaIp = ip;
+        this.mediaPort = port;
+        return true;
+    }
+
+    public boolean setCodec(int codec) {
+        if (!this.flag)
+            return false;
+        if (this.codecS.length() > 0) {
+            this.codecS.append(" " + codec);
+        } else {
+            this.codecS.append(codec);
+        }
+        return true;
+    }
+
+    public boolean setCodec(int codec, String describe) {
+        if (!this.flag)
+            return false;
+        setCodec(codec);
+        this.rtpmapBuffer.append("a=rtpmap:" + codec + " " + describe + SIPStack.SIP_LINE_END);
+        return true;
+    }
+
+    public boolean setFmtpDescribe(int codec, String describe) {
+        if (!this.flag)
+            return false;
+        this.fmtpBuffer.append("a=fmtp:" + codec + " " + describe + SIPStack.SIP_LINE_END);
+        return true;
+    }
+
+    public boolean setCommonCodec(int codec) {
+        if (!this.flag)
+            return false;
+        this.commonCodec = codec;
+        return true;
+    }
+
+    public boolean setFlow(String flow) {
+        if (flow == null)
+            return false;
+        if (!this.flag)
+            return false;
+        this.flow = flow;
+        if (flow.compareTo("sendrecv") == 0) {
+            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
+        } else if (flow.compareTo("sendonly") == 0) {
+            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDONLY;
+        } else if (flow.compareTo("recvonly") == 0) {
+            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_RECVONLY;
+        } else {
+            this.flowIndicator = SIPStack.SIP_MEDIAFLOW_NONE;
+        }
+        return true;
+    }
+
+    public int negotiateAudioCodec(String sideCodecs) {
+        if (this.codecS == null || this.codecS.length() <= 0)
+            return -1;
+        String myCodecs = this.codecS.toString();
+        myCodecs.trim();
+        if (myCodecs == null || myCodecs.length() <= 0)
+            return -1;
+        sideCodecs.trim();
+        if (sideCodecs == null || sideCodecs.length() <= 0)
+            return -1;
+        StringTokenizer my_st = new StringTokenizer(myCodecs, " ", true);
+        String str = null;
+        int codec = -1;
+        while (my_st.hasMoreTokens()) {
+            str = my_st.nextToken().trim();
+            if (str == null || str.length() == 0)
+                continue;
+            codec = Integer.parseInt(str);
+            if (codec >= 0 && codec < 100) {
+                StringTokenizer side_st = new StringTokenizer(sideCodecs, " ", true);
+                int sidecodec = -1;
+                boolean bDecided = false;
+                while (side_st.hasMoreTokens()) {
+                    str = side_st.nextToken().trim();
+                    if (str == null || str.length() == 0)
+                        continue;
+                    sidecodec = Integer.parseInt(str);
+                    if (str.length() > 0 && sidecodec >= 0 && codec < 100)
+                        if (sidecodec == codec) {
+                            bDecided = true;
+                            this.commonCodec = codec;
+                            break;
+                        }
+                }
+                if (bDecided)
+                    return this.commonCodec;
+            }
+        }
+        return -1;
+    }
+}

+ 138 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPAUTHENTICATEHeader.java

@@ -0,0 +1,138 @@
+package bssoft.stack.sip;
+
+public class SIPAUTHENTICATEHeader {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public String realmValue = null;
+
+    public String nonceValue = null;
+
+    public String qopValue = null;
+
+    public String strStale = null;
+
+    public String strAlgorithm = null;
+
+    public int headerType = SIPStack.SIP_HEADERTYPE_NONE;
+
+    public boolean flag = false;
+
+    public SIPAUTHENTICATEHeader(String header, int headerType) {
+        if (header != null) {
+            String keyWord;
+            if (headerType == SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE) {
+                keyWord = "WWW-Authenticate: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE) {
+                keyWord = "Www-Authenticate: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE) {
+                keyWord = "Proxy-Authenticate: ";
+            } else {
+                keyWord = null;
+            }
+            if (keyWord != null)
+                if (header.startsWith(keyWord)) {
+                    this.headerType = headerType;
+                    this.header = header;
+                    this.flag = true;
+                    int iS = 0;
+                    int iE = 0;
+                    String strRealm = null;
+                    iS = header.indexOf("realm=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = header.indexOf(",", iS);
+                        if (iE > 0) {
+                            strRealm = header.substring(iS, iE);
+                        } else if (iE < 0) {
+                            strRealm = header.substring(iS);
+                        }
+                        if (strRealm.length() > 0) {
+                            iS = strRealm.indexOf("=");
+                            String strValue = strRealm.substring(iS + 1);
+                            strValue = strValue.trim();
+                            if (strValue.indexOf("\"") == 0)
+                                iS = 1;
+                            if (iS > 0)
+                                iE = strValue.indexOf("\"", iS);
+                            this.realmValue = strValue.substring(iS, iE);
+                        }
+                    } else {
+                        this.realmValue = "";
+                    }
+                    String strQop = null;
+                    iS = header.indexOf("qop=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = header.indexOf(",", iS);
+                        if (iE > 0) {
+                            strQop = header.substring(iS, iE);
+                        } else if (iE < 0) {
+                            strQop = header.substring(iS);
+                        }
+                        this.qopValue = "";
+                        if (strQop.length() > 0) {
+                            iS = strQop.indexOf("=");
+                            String strValue = strQop.substring(iS + 1);
+                            strValue = strValue.trim();
+                            if (strValue.indexOf("\"") == 0)
+                                iS = 1;
+                            if (iS > 0)
+                                iE = strValue.indexOf("\"", iS);
+                            this.qopValue = strValue.substring(iS, iE);
+                        }
+                    } else {
+                        this.qopValue = "";
+                    }
+                    String strNonce = null;
+                    iS = header.indexOf("nonce=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = header.indexOf(",", iS);
+                        if (iE > 0) {
+                            strNonce = header.substring(iS, iE);
+                        } else if (iE < 0) {
+                            strNonce = header.substring(iS);
+                        }
+                        if (strNonce.length() > 0) {
+                            iS = strNonce.indexOf("=");
+                            String strValue = strNonce.substring(iS + 1);
+                            strValue = strValue.trim();
+                            if (strValue.indexOf("\"") == 0)
+                                iS = 1;
+                            if (iS > 0)
+                                iE = strValue.indexOf("\"", iS);
+                            this.nonceValue = strValue.substring(iS, iE);
+                        }
+                    } else {
+                        this.nonceValue = "";
+                    }
+                    iS = header.indexOf("stale=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = header.indexOf(",", iS);
+                        if (iE > 0) {
+                            this.strStale = header.substring(iS + 6, iE);
+                        } else if (iE < 0) {
+                            this.strStale = header.substring(iS + 6);
+                        }
+                    } else {
+                        this.strStale = "";
+                    }
+                    iS = header.indexOf("algorithm=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = header.indexOf(",", iS);
+                        if (iE > 0) {
+                            this.strAlgorithm = header.substring(iS + 10, iE);
+                        } else if (iE < 0) {
+                            this.strAlgorithm = header.substring(iS + 10);
+                        }
+                    } else {
+                        this.strAlgorithm = "";
+                    }
+                }
+        }
+    }
+}

+ 330 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPCONTACTHeader.java

@@ -0,0 +1,330 @@
+package bssoft.stack.sip;
+
+public class SIPCONTACTHeader {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public int expires = -1;
+
+    public String display = null;
+
+    public String username = null;
+
+    public String sipuri = null;
+
+    public String uriusertag = null;
+
+    public String ip = null;
+
+    public int port = 0;
+
+    public String tag = null;
+
+    public boolean flag = false;
+
+    public SIPCONTACTHeader(String message) {
+        if (message != null && message.length() > 0) {
+            int iS = message.indexOf("Contact: ");
+            int iE = 0;
+            if (iS < 0) {
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "m: ");
+                if (iS >= 0)
+                    iS += 2;
+            }
+            if (iS >= 0) {
+                iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                if (iE > 0) {
+                    this.header = message.substring(iS, iE);
+                    if (this.header.startsWith("Contact: ")) {
+                        this.headerValue = this.header.substring(9);
+                    } else if (this.header.startsWith("m: ")) {
+                        this.headerValue = this.header.substring(3);
+                    }
+                    String strExpires = null;
+                    iS = this.headerValue.indexOf(";expires=");
+                    iE = 0;
+                    if (iS >= 0) {
+                        iE = this.headerValue.indexOf(";", iS + 1);
+                        int iE_ = this.headerValue.indexOf(",", iS + 1);
+                        if (iE_ > 0 && iE_ < iE)
+                            iE = iE_;
+                        if (iE > 0) {
+                            strExpires = this.headerValue.substring(iS, iE);
+                        } else if (iE < 0) {
+                            strExpires = this.headerValue.substring(iS);
+                        }
+                        if (strExpires != null && strExpires.length() > 0)
+                            this.expires = Integer.parseInt(strExpires.substring(9).trim());
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            if (this.headerValue != null && this.headerValue.length() > 0) {
+                iE = this.headerValue.indexOf("<sip:");
+                if (iE > 0) {
+                    String str = null;
+                    str = this.headerValue.substring(0, iE).trim();
+                    if (str != null && str.length() > 1 &&
+                            str.startsWith("\"") &&
+                            str.endsWith("\"")) {
+                        this.display = str.substring(1, str.length() - 1);
+                    } else if (str != null && str.length() > 0) {
+                        this.display = str;
+                    }
+                }
+                iS = this.headerValue.indexOf("sip:");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(">", iS + 4);
+                    if (iE < 0)
+                        iE = this.headerValue.indexOf(";", iS + 4);
+                    if (iE > 0) {
+                        str = this.headerValue.substring(iS, iE);
+                    } else {
+                        str = this.headerValue.substring(iS);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.sipuri = str.trim();
+                }
+                if (this.sipuri != null && this.sipuri.length() > 0) {
+                    iS = this.sipuri.indexOf("@", 4);
+                    if (iS > 0)
+                        this.username = this.sipuri.substring(4, iS).trim();
+                }
+                if (this.sipuri != null && this.sipuri.length() > 0) {
+                    iS = this.sipuri.indexOf("@", 4);
+                    iE = this.sipuri.indexOf(";", 4);
+                    String str = null;
+                    if (iS >= 0 && iE >= 0) {
+                        str = this.sipuri.substring(iS + 1, iE).trim();
+                    } else if (iS >= 0) {
+                        str = this.sipuri.substring(iS + 1).trim();
+                    } else if (iE >= 0) {
+                        str = this.sipuri.substring(4, iE).trim();
+                    } else {
+                        str = this.sipuri.substring(4).trim();
+                    }
+                    this.port = 5060;
+                    if (str != null && str.length() > 0) {
+                        iS = str.indexOf(":");
+                        if (iS > 0) {
+                            this.port = Integer.parseInt(str.substring(iS + 1).trim());
+                            this.ip = str.substring(0, iS);
+                        } else {
+                            this.ip = str;
+                        }
+                    }
+                }
+                iS = this.headerValue.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.headerValue.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.headerValue.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.tag = str.trim();
+                }
+                iS = this.headerValue.indexOf("sip:");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(">", iS + 4);
+                    if (iE > 0)
+                        str = this.headerValue.substring(iS, iE);
+                    if (str != null && str.length() > 0) {
+                        iS = str.indexOf(";user=", iS + 4);
+                        if (iS > 0) {
+                            this.uriusertag = str.substring(iS + 6);
+                            if (this.uriusertag != null && this.uriusertag.length() > 0 && this.uriusertag.indexOf(";") >= 0)
+                                if (this.uriusertag.indexOf(";") == 0) {
+                                    this.uriusertag = null;
+                                } else {
+                                    this.uriusertag = this.uriusertag.substring(0, this.uriusertag.indexOf(";")).trim();
+                                }
+                        }
+                    }
+                }
+                this.flag = true;
+            }
+        }
+    }
+
+    public SIPCONTACTHeader(String message, String requesturi) {
+        if (message != null && message.length() > 0) {
+            int iS = message.indexOf("Contact: ");
+            int iE = 0;
+            if (iS < 0) {
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "m: ");
+                if (iS >= 0)
+                    iS += 2;
+            }
+            if (iS >= 0) {
+                iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                if (iE > 0) {
+                    this.header = message.substring(iS, iE);
+                    if (this.header.startsWith("Contact: ")) {
+                        this.headerValue = this.header.substring(9);
+                    } else if (this.header.startsWith("m: ")) {
+                        this.headerValue = this.header.substring(3);
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            if (this.headerValue != null && this.headerValue.length() > 0) {
+                this.display = "";
+                String tempValue = this.headerValue;
+                iS = tempValue.indexOf("sip:");
+                String str = "";
+                boolean bFound = false;
+                while (iS >= 0) {
+                    tempValue = tempValue.substring(iS);
+                    iE = tempValue.indexOf(">", 4);
+                    if (iE < 0)
+                        iE = tempValue.indexOf(";", 4);
+                    if (iE > 0) {
+                        str = tempValue.substring(0, iE);
+                    } else {
+                        str = tempValue;
+                    }
+                    if (str != null && str.length() > 0)
+                        this.sipuri = str.trim();
+                    if (str != null &&
+                            str.length() > 0 &&
+                            requesturi != null &&
+                            requesturi.length() > 0 &&
+                            str.trim().compareTo(requesturi) == 0) {
+                        bFound = true;
+                        this.sipuri = str.trim();
+                        String strExpires = null;
+                        iS = tempValue.indexOf(";expires=");
+                        iE = 0;
+                        if (iS >= 0) {
+                            iE = tempValue.indexOf(";", iS + 1);
+                            int iE_ = tempValue.indexOf(",", iS + 1);
+                            if (iE_ > 0 && iE_ < iE)
+                                iE = iE_;
+                            if (iE > 0) {
+                                strExpires = tempValue.substring(iS, iE);
+                            } else if (iE < 0) {
+                                strExpires = tempValue.substring(iS);
+                            }
+                            if (strExpires != null && strExpires.length() > 0)
+                                this.expires = Integer.parseInt(strExpires.substring(9).trim());
+                        }
+                        break;
+                    }
+                    tempValue = tempValue.substring(iE + 1).trim();
+                    iS = tempValue.indexOf("sip:");
+                }
+                if (bFound) {
+                    if (this.sipuri != null && this.sipuri.length() > 0) {
+                        iS = this.sipuri.indexOf("@", 4);
+                        if (iS > 0)
+                            this.username = this.sipuri.substring(4, iS).trim();
+                    }
+                    if (this.sipuri != null && this.sipuri.length() > 0) {
+                        iS = this.sipuri.indexOf("@", 4);
+                        iE = this.sipuri.indexOf(";", 4);
+                        if (iS >= 0 && iE >= 0) {
+                            str = this.sipuri.substring(iS + 1, iE).trim();
+                        } else if (iS >= 0) {
+                            str = this.sipuri.substring(iS + 1).trim();
+                        } else if (iE >= 0) {
+                            str = this.sipuri.substring(4, iE).trim();
+                        } else {
+                            str = this.sipuri.substring(4).trim();
+                        }
+                        this.port = 5060;
+                        if (str != null && str.length() > 0) {
+                            iS = str.indexOf(":");
+                            if (iS > 0) {
+                                this.port = Integer.parseInt(str.substring(iS + 1).trim());
+                                this.ip = str.substring(0, iS);
+                            } else {
+                                this.ip = str;
+                            }
+                        }
+                    }
+                    iS = this.headerValue.indexOf(";tag=");
+                    if (iS > 0) {
+                        iE = this.headerValue.indexOf(";", iS + 5);
+                        if (iE >= 0) {
+                            if (iE > iS + 5) {
+                                str = this.headerValue.substring(iS + 5, iE);
+                            } else {
+                                str = "";
+                            }
+                        } else {
+                            str = this.headerValue.substring(iS + 5);
+                        }
+                        if (str != null && str.length() > 0) {
+                            this.tag = str.trim();
+                        } else {
+                            this.tag = "";
+                        }
+                    }
+                    iS = this.headerValue.indexOf("sip:");
+                    if (iS > 0) {
+                        iE = this.headerValue.indexOf(">", iS + 4);
+                        if (iE > 0)
+                            str = this.headerValue.substring(iS, iE);
+                        if (str != null && str.length() > 0) {
+                            iS = str.indexOf(";user=", iS + 4);
+                            if (iS > 0) {
+                                this.uriusertag = str.substring(iS + 6);
+                                if (this.uriusertag != null && this.uriusertag.length() > 0 && this.uriusertag.indexOf(";") >= 0)
+                                    if (this.uriusertag.indexOf(";") == 0) {
+                                        this.uriusertag = null;
+                                    } else {
+                                        this.uriusertag = this.uriusertag.substring(0, this.uriusertag.indexOf(";")).trim();
+                                    }
+                            }
+                        }
+                    }
+                    this.flag = true;
+                }
+            }
+        }
+    }
+
+    public String getDisplay() {
+        return this.display;
+    }
+
+    public String getUsername() {
+        return this.username;
+    }
+
+    public String getSipuri() {
+        return this.sipuri;
+    }
+
+    public String getSipuriusertag() {
+        return this.uriusertag;
+    }
+
+    public String getIp() {
+        return this.ip;
+    }
+
+    public int getPort() {
+        return this.port;
+    }
+
+    public String getTag() {
+        return this.tag;
+    }
+
+    public int getExpires() {
+        return this.expires;
+    }
+}

+ 2511 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPCall.java

@@ -0,0 +1,2511 @@
+package bssoft.stack.sip;
+
+import java.util.Date;
+import java.util.StringTokenizer;
+
+public class SIPCall {
+    public String commandLine = null;
+
+    public String viaH = null;
+
+    public StringBuffer viaArray = new StringBuffer();
+
+    public String routeH = null;
+
+    public StringBuffer routeArray = new StringBuffer();
+
+    public String recordrouteH = null;
+
+    public StringBuffer recordrouteArray = new StringBuffer();
+
+    public String maxforwardH = null;
+
+    public String contactH = null;
+
+    public String toH = null;
+
+    public String fromH = null;
+
+    public String callidH = null;
+
+    public String cseqH = null;
+
+    public String expiresH = null;
+
+    public String allowH = null;
+
+    public String useragentH = null;
+
+    public String remoteuseragentH = null;
+
+    public String contentlengthH = null;
+
+    public String contenttypeH = null;
+
+    public String authorizationINVITEH = null;
+
+    public String authorizationCANCELH = null;
+
+    public String authorizationBYEH = null;
+
+    public String authorizationACKH = null;
+
+    public String passertedidentityH = null;
+
+    public String serverIp = null;
+
+    public int serverPort = 5060;
+
+    public String serverDomain = null;
+
+    public String remoteIp = null;
+
+    public int remotePort = 5060;
+
+    public String remoteContactIp = null;
+
+    public int remoteContactPort = 5060;
+
+    public String routeIp = null;
+
+    public int routePort = 5060;
+
+    public String remoteContactUri = null;
+
+    public String localIp = null;
+
+    public int localPort = 5060;
+
+    public String id = null;
+
+    public String cid = null;
+
+    public String authid = null;
+
+    public String authpassword = null;
+
+    public String fromTag = null;
+
+    public String toTag = null;
+
+    public String fromHeaderValue = null;
+
+    public String toHeaderValue = null;
+
+    public String callId = null;
+
+    public String dnis = null;
+
+    public String viaBranch = null;
+
+    public int CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+
+    public int INVITE_CSEQ = 0;
+
+    public int CANCEL_CSEQ = 0;
+
+    public int ACK_CSEQ = 0;
+
+    public int BYE_CSEQ = 0;
+
+    public int callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+
+    public int responseCode = 0;
+
+    public int callState = 0;
+
+    public int callMode = SIPStack.SIP_CALLMODE_NONE;
+
+    public Date callTime_TI = null;
+
+    public Date callTime_T0 = null;
+
+    public Date callTime_T00 = null;
+
+    public int invitingTimes = 0;
+
+    public Date callTime_T1 = null;
+
+    public Date callTime_T2 = null;
+
+    public Date callTime_T3 = null;
+
+    public Date callTime_T4 = null;
+
+    public Date callTime_T40 = null;
+
+    public Date callTime_T5 = null;
+
+    public Date callTime_T6 = null;
+
+    public Date callTime_T7 = null;
+
+    public Date callTime_T8 = null;
+
+    public Date callTime_T9 = null;
+
+    public int expiresTI = 0;
+
+    public int expiresT0 = 0;
+
+    public int expiresT00 = 0;
+
+    public int expiresT1 = 0;
+
+    public int expiresT2 = 0;
+
+    public int expiresT3 = 0;
+
+    public int expiresT4 = 0;
+
+    public int expiresT5 = 0;
+
+    public int expiresT6 = 0;
+
+    public int expiresT7 = 0;
+
+    public int expiresT8 = 0;
+
+    public int expiresT9 = 0;
+
+    public SIPSdp sdp = null;
+
+    public SIPSdp remoteSdp = null;
+
+    public String message = null;
+
+    public boolean flag;
+
+    public UPDATEHeaders updateHeaders = null;
+
+    public boolean bHolding = false;
+
+    public boolean bPending = false;
+
+    public boolean bDtmfdetected = false;
+
+    public int detectedDtmf = 0;
+
+    public int dtmfDuration = 0;
+
+    public boolean bCancelRequest = false;
+
+    public boolean bRejectRequest = false;
+
+    public boolean bNewcallRequest = false;
+
+    public boolean bUpdateRequest = false;
+
+    public boolean bAsMaster = false;
+
+    public boolean bForwardRequest = false;
+
+    public boolean bByedisconnected = false;
+
+    public String number = "";
+
+    public String dong_number = "";
+
+    public String ho_number = "";
+
+    public boolean bDirectcall = false;
+
+    public boolean bResponsebackgroundcall = false;
+
+    public boolean bResponsebackgroundcallReady = false;
+
+    public Date responsebackgroundcallTimer = new Date();
+
+    public int hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+
+    public int hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+
+    public SIPCall() {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("call handle created.");
+        this.updateHeaders = new UPDATEHeaders();
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_BASIC;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.bHolding = false;
+        this.bPending = false;
+        this.bCancelRequest = false;
+        this.bRejectRequest = false;
+        this.bNewcallRequest = false;
+        this.bUpdateRequest = false;
+        this.bAsMaster = false;
+        this.bForwardRequest = false;
+        this.bByedisconnected = false;
+        this.number = "";
+        this.viaBranch = null;
+        this.bResponsebackgroundcall = false;
+        this.bResponsebackgroundcallReady = false;
+        this.responsebackgroundcallTimer = new Date();
+        this.callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+        this.bDirectcall = SIPStack.bDirectCall;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+        this.flag = false;
+    }
+
+    public SIPCall(boolean bPending) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("call handle created.");
+        this.updateHeaders = new UPDATEHeaders();
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_BASIC;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.bHolding = false;
+        this.bCancelRequest = false;
+        this.bRejectRequest = false;
+        this.bNewcallRequest = false;
+        this.bUpdateRequest = false;
+        this.bAsMaster = false;
+        this.bForwardRequest = false;
+        this.bByedisconnected = false;
+        this.bResponsebackgroundcall = false;
+        this.bResponsebackgroundcallReady = false;
+        this.responsebackgroundcallTimer = new Date();
+        this.number = "";
+        this.viaBranch = null;
+        bPending = bPending;
+        this.bDirectcall = SIPStack.bDirectCall;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+        this.flag = false;
+    }
+
+    public void resetCall() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG) {
+            System.out.println("call handle reset.");
+            SIPStack.printAudioRtpPortInfo();
+        }
+        this.commandLine = null;
+        this.viaH = null;
+        this.viaArray = null;
+        this.routeH = null;
+        this.routeArray = null;
+        this.recordrouteH = null;
+        this.recordrouteArray = null;
+        this.maxforwardH = null;
+        this.contactH = null;
+        this.toH = null;
+        this.fromH = null;
+        this.callidH = null;
+        this.cseqH = null;
+        this.expiresH = null;
+        this.allowH = null;
+        this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+        this.remoteuseragentH = null;
+        this.contentlengthH = null;
+        this.contenttypeH = null;
+        this.authorizationINVITEH = null;
+        this.authorizationCANCELH = null;
+        this.authorizationBYEH = null;
+        this.authorizationACKH = null;
+        this.passertedidentityH = null;
+        this.serverIp = null;
+        this.serverPort = 5060;
+        this.serverDomain = null;
+        this.remoteIp = null;
+        this.remotePort = 5060;
+        this.remoteContactIp = null;
+        this.remoteContactPort = 5060;
+        this.remoteContactUri = null;
+        this.localIp = null;
+        this.localPort = 5060;
+        this.id = null;
+        this.cid = null;
+        this.authid = null;
+        this.authpassword = null;
+        this.fromTag = null;
+        this.toTag = null;
+        this.fromHeaderValue = null;
+        this.toHeaderValue = null;
+        this.callId = null;
+        this.dnis = null;
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_BASIC;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        if (this.sdp != null && this.sdp.flag && this.sdp.audioM != null)
+            SIPStack.freeAudioRtpPort(this.sdp.audioM.mediaPort);
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.message = null;
+        this.bHolding = false;
+        this.bPending = false;
+        this.bCancelRequest = false;
+        this.bRejectRequest = false;
+        this.bNewcallRequest = false;
+        this.bUpdateRequest = false;
+        this.bAsMaster = false;
+        this.bForwardRequest = false;
+        this.bByedisconnected = false;
+        this.bResponsebackgroundcall = false;
+        this.bResponsebackgroundcallReady = false;
+        this.responsebackgroundcallTimer = new Date();
+        this.number = "";
+        this.viaBranch = null;
+        this.callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+        this.bDirectcall = SIPStack.bDirectCall;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+        this.flag = false;
+        SIPStack.exceptionCountAtCurrentCall = 0;
+        System.gc();
+    }
+
+    public void initializeRedirectCall() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("redirect call handle initialize.");
+        this.viaH = null;
+        this.viaArray = null;
+        this.routeH = null;
+        this.routeArray = null;
+        this.recordrouteH = null;
+        this.recordrouteArray = null;
+        this.remoteContactIp = null;
+        this.remoteContactPort = 5060;
+        this.remoteContactUri = null;
+        this.callId = null;
+        this.authorizationINVITEH = null;
+        this.authorizationCANCELH = null;
+        this.authorizationBYEH = null;
+        this.authorizationACKH = null;
+        this.viaBranch = null;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_BASIC;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        if (this.sdp != null && this.sdp.flag && this.sdp.audioM != null)
+            SIPStack.freeAudioRtpPort(this.sdp.audioM.mediaPort);
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.message = null;
+        this.bHolding = false;
+        this.bPending = false;
+        this.bCancelRequest = false;
+        this.bRejectRequest = false;
+        this.bNewcallRequest = false;
+        this.bUpdateRequest = false;
+        this.bAsMaster = false;
+        this.bForwardRequest = false;
+        this.bByedisconnected = false;
+        this.bResponsebackgroundcall = false;
+        this.bResponsebackgroundcallReady = false;
+        this.responsebackgroundcallTimer = new Date();
+        this.number = "";
+        this.viaBranch = null;
+        this.callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+        this.bDirectcall = SIPStack.bDirectCall;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+    }
+
+    public boolean activeCallHandle(String id, String cid, String authid, String authpassword, String number, String serverIp, int serverPort, String serverDomain, String localIp, int localPort) {
+        if (this.flag)
+            return false;
+        resetCall();
+        this.flag = true;
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("call handle activated.");
+        this.id = localIp;
+        this.cid = localIp;
+        this.authid = authid;
+        this.authpassword = authpassword;
+        this.dnis = number;
+        this.serverIp = serverIp;
+        this.serverPort = serverPort;
+        this.serverDomain = serverDomain;
+        this.remoteIp = serverIp;
+        this.remotePort = serverPort;
+        this.localIp = localIp;
+        this.localPort = localPort;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+        return true;
+    }
+
+    public boolean activePendingCallHandle(String id, String cid, String authid, String authpassword, String number, String serverIp, int serverPort, String serverDomain, String localIp, int localPort) {
+        if (this.flag)
+            return false;
+        resetCall();
+        this.flag = true;
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("conference call activated.");
+        this.id = id;
+        this.cid = cid;
+        this.authid = authid;
+        this.authpassword = authpassword;
+        this.dnis = number;
+        this.serverIp = serverIp;
+        this.serverPort = serverPort;
+        this.serverDomain = serverDomain;
+        this.remoteIp = serverIp;
+        this.remotePort = serverPort;
+        this.localIp = localIp;
+        this.localPort = localPort;
+        this.bPending = true;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+        BSSVideo.bProgressvideooffer = false;
+        BSSVideo.bCover = true;
+        return true;
+    }
+
+    public boolean constructHeaders(String message, String remoteIp, int remotePort) {
+        if (message == null || message.length() == 0)
+            return false;
+        this.viaH = null;
+        this.viaArray = new StringBuffer();
+        this.routeH = null;
+        this.routeArray = new StringBuffer();
+        this.recordrouteH = null;
+        this.recordrouteArray = new StringBuffer();
+        this.message = message;
+        StringTokenizer tokenArray = new StringTokenizer(message, SIPStack.SIP_LINE_END, true);
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken().trim();
+            if (token.length() <= 0 ||
+                    token.compareTo("\r") == 0 ||
+                    token.compareTo("\n") == 0)
+                continue;
+            if (token.startsWith("From: ")) {
+                this.fromH = token;
+                this.fromHeaderValue = token.substring(6);
+                continue;
+            }
+            if (token.startsWith("f: ")) {
+                this.fromH = token;
+                this.fromHeaderValue = token.substring(3);
+                continue;
+            }
+            if (token.startsWith("To: ")) {
+                this.toH = token;
+                if (this.toH.indexOf("tag=") < 0) {
+                    this.toTag = Long.toString((new Date()).getTime());
+                    this.toH = String.valueOf(token) + ";tag=" + this.toTag;
+                    this.toHeaderValue = String.valueOf(token.substring(4)) + ";tag=" + this.toTag;
+                    continue;
+                }
+                this.toHeaderValue = token.substring(4);
+                continue;
+            }
+            if (token.startsWith("t: ")) {
+                this.toH = token;
+                if (this.toH.indexOf("tag=") < 0) {
+                    this.toTag = Long.toString((new Date()).getTime());
+                    this.toH = String.valueOf(token) + ";tag=" + this.toTag;
+                    this.toHeaderValue = String.valueOf(token.substring(3)) + ";tag=" + this.toTag;
+                    continue;
+                }
+                this.toHeaderValue = token.substring(3);
+                continue;
+            }
+            if (token.startsWith("Via: ")) {
+                if (this.viaH == null) {
+                    this.viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = "";
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            this.viaH = token.substring(0, index);
+                        } else {
+                            this.viaH = token;
+                        }
+                        index = this.viaH.indexOf(";rport=");
+                        if (index > 0)
+                            this.viaH = this.viaH.substring(0, index);
+                        this.viaH = String.valueOf(this.viaH) + ";received=" + remoteIp + ";rport=" + remotePort + ";branch=" + this.viaBranch;
+                    }
+                    this.viaArray.append(String.valueOf(this.viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("v: ")) {
+                if (this.viaH == null) {
+                    this.viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = branch;
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            this.viaH = token.substring(0, index);
+                        } else {
+                            this.viaH = token;
+                        }
+                        index = this.viaH.indexOf(";rport=");
+                        if (index > 0)
+                            this.viaH = this.viaH.substring(0, index);
+                        this.viaH = String.valueOf(this.viaH) + ";received=" + remoteIp + ";rport=" + remotePort + ";branch=" + this.viaBranch;
+                    }
+                    this.viaArray.append(String.valueOf(this.viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("Record-Route: ")) {
+                if (this.recordrouteH == null) {
+                    this.routeH = null;
+                    this.routeArray = new StringBuffer();
+                    this.recordrouteH = token;
+                    this.recordrouteArray.append(String.valueOf(this.recordrouteH) + SIPStack.SIP_LINE_END);
+                    this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.recordrouteArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("Contact: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("m: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("Call-ID: ")) {
+                this.callidH = token;
+                this.callId = token.substring(9).trim();
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_LOBBY)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_GUARD)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_LOBBY)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_NEIGHBOR)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = false;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+                this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                BSSVideo.bProgressvideooffer = false;
+                continue;
+            }
+            if (token.startsWith("i: ")) {
+                this.callidH = token;
+                this.callId = token.substring(3).trim();
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_LOBBY)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_GUARD)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_LOBBY)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_LOBBY;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                if (this.callId.startsWith(BSSVideo.HNS_PREFIX_NEIGHBOR)) {
+                    this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_GUARD)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_GUARD;
+                        BSSVideo.bProgressvideooffer = true;
+                        continue;
+                    }
+                    if (this.callId.endsWith(BSSVideo.HNS_POSTFIX_NEIGHBOR)) {
+                        this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NEIGHBOR;
+                        BSSVideo.bProgressvideooffer = false;
+                        continue;
+                    }
+                    this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                    BSSVideo.bProgressvideooffer = false;
+                    continue;
+                }
+                this.hnsOriginatorServiceType = BSSVideo.HNS_SERVICE_NONE;
+                this.hnsReceiverServiceType = BSSVideo.HNS_SERVICE_NONE;
+                BSSVideo.bProgressvideooffer = false;
+                continue;
+            }
+            if (token.startsWith("CSeq: ")) {
+                this.cseqH = token;
+                StringTokenizer fieldArray = new StringTokenizer(token, " ", true);
+                int tokenCount = 0;
+                while (fieldArray.hasMoreTokens()) {
+                    String fieldtoken = fieldArray.nextToken();
+                    if (fieldtoken.length() > 0 && fieldtoken.compareTo(" ") != 0) {
+                        tokenCount++;
+                        if (tokenCount == 2) {
+                            this.CSEQ_NUMBER = Integer.parseInt(fieldtoken);
+                            break;
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("Content-Type: ")) {
+                this.contenttypeH = token;
+                continue;
+            }
+            if (token.startsWith("c: ")) {
+                this.contenttypeH = token;
+                continue;
+            }
+            if (token.startsWith("Content-Length: ")) {
+                this.contentlengthH = token;
+                continue;
+            }
+            if (token.startsWith("l: ")) {
+                this.contentlengthH = token;
+                continue;
+            }
+            if (token.startsWith("User-Agent: ")) {
+                this.remoteuseragentH = token;
+                this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+                continue;
+            }
+            if (token.startsWith("P-Asserted-Identity: "))
+                this.passertedidentityH = token;
+        }
+        this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+        this.maxforwardH = "Max-Forwards: 70";
+        int audioport = SIPStack.getFreeAudioRtpPort();
+        if (audioport > 0)
+            constructSdp();
+        if (this.sdp != null && this.sdp.flag) {
+            this.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+            if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+            } else {
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+            }
+            this.sdp.setCodec(
+                    SIPStack.SIP_MEDIATYPE_AUDIO,
+                    RFC2833.payloadType,
+                    "telephone-event/8000");
+            this.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+        }
+        if (parseRemoteSdp(message))
+            if (this.remoteSdp != null &&
+                    this.remoteSdp.flag)
+                if (this.remoteSdp.audioM != null &&
+                        this.sdp != null && this.sdp.flag && this.sdp.audioM != null &&
+                        this.remoteSdp.audioM.flow != null &&
+                        this.remoteSdp.audioM.flow.length() > 0)
+                    if (this.remoteSdp.audioM.flow.compareTo("sendrecv") == 0) {
+                        this.sdp.audioM.setFlow("sendrecv");
+                    } else if (this.remoteSdp.audioM.flow.compareTo("sendonly") == 0) {
+                        this.sdp.audioM.setFlow("recvonly");
+                    } else if (this.remoteSdp.audioM.flow.compareTo("recvonly") == 0) {
+                        this.sdp.audioM.setFlow("sendonly");
+                    }
+        negotiateAudioCodec();
+        return true;
+    }
+
+    public boolean constructUPDATEHeaders(String message, String remoteIp, int remotePort) {
+        if (message == null || message.length() == 0)
+            return false;
+        resetUpdateheaders();
+        setUpdateheaders();
+        this.viaH = null;
+        this.viaArray = new StringBuffer();
+        this.routeH = null;
+        this.routeArray = new StringBuffer();
+        this.recordrouteH = null;
+        this.recordrouteArray = new StringBuffer();
+        this.message = message;
+        StringTokenizer tokenArray = new StringTokenizer(message, SIPStack.SIP_LINE_END, true);
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken().trim();
+            if (token.length() <= 0 ||
+                    token.compareTo("\r") == 0 ||
+                    token.compareTo("\n") == 0)
+                continue;
+            if (token.startsWith("From: ")) {
+                this.fromH = token;
+                int iS = this.fromH.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    int iE = this.fromH.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.fromH.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.fromH.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.fromTag = str.trim();
+                }
+                this.fromHeaderValue = token.substring(6);
+                System.out.println("FROM TAG:" + this.fromTag);
+                continue;
+            }
+            if (token.startsWith("f: ")) {
+                this.fromH = token;
+                int iS = this.fromH.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    int iE = this.fromH.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.fromH.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.fromH.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.fromTag = str.trim();
+                }
+                this.fromHeaderValue = token.substring(3);
+                System.out.println("FROM TAG:" + this.fromTag);
+                continue;
+            }
+            if (token.startsWith("To: ")) {
+                this.toH = token;
+                int iS = this.toH.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    int iE = this.toH.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.toH.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.toH.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.toTag = str.trim();
+                }
+                this.toHeaderValue = token.substring(4);
+                System.out.println("TO TAG:" + this.toTag);
+                continue;
+            }
+            if (token.startsWith("To: ")) {
+                this.toH = token;
+                int iS = this.toH.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    int iE = this.toH.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.toH.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.toH.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.toTag = str.trim();
+                }
+                this.toHeaderValue = token.substring(3);
+                System.out.println("TO TAG:" + this.toTag);
+                continue;
+            }
+            if (token.startsWith("Via: ")) {
+                if (this.viaH == null) {
+                    this.viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = "";
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            this.viaH = token.substring(0, index);
+                        } else {
+                            this.viaH = token;
+                        }
+                        index = this.viaH.indexOf(";rport=");
+                        if (index > 0)
+                            this.viaH = this.viaH.substring(0, index);
+                        this.viaH = String.valueOf(this.viaH) + ";received=" + remoteIp + ";rport=" + remotePort + ";branch=" + this.viaBranch;
+                    }
+                    this.viaArray.append(String.valueOf(this.viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("v: ")) {
+                if (this.viaH == null) {
+                    this.viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = branch;
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            this.viaH = token.substring(0, index);
+                        } else {
+                            this.viaH = token;
+                        }
+                        index = this.viaH.indexOf(";rport=");
+                        if (index > 0)
+                            this.viaH = this.viaH.substring(0, index);
+                        this.viaH = String.valueOf(this.viaH) + ";received=" + remoteIp + ";rport=" + remotePort + ";branch=" + this.viaBranch;
+                    }
+                    this.viaArray.append(String.valueOf(this.viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("Record-Route: ")) {
+                if (this.recordrouteH == null) {
+                    this.routeH = null;
+                    this.routeArray = new StringBuffer();
+                    this.recordrouteH = token;
+                    this.recordrouteArray.append(String.valueOf(this.recordrouteH) + SIPStack.SIP_LINE_END);
+                    this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                this.recordrouteArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("Contact: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("m: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("Call-ID: ")) {
+                this.callidH = token;
+                this.callId = token.substring(9).trim();
+                continue;
+            }
+            if (token.startsWith("i: ")) {
+                this.callidH = token;
+                this.callId = token.substring(3).trim();
+                continue;
+            }
+            if (token.startsWith("CSeq: ")) {
+                this.cseqH = token;
+                StringTokenizer fieldArray = new StringTokenizer(token, " ", true);
+                int tokenCount = 0;
+                while (fieldArray.hasMoreTokens()) {
+                    String fieldtoken = fieldArray.nextToken();
+                    if (fieldtoken.length() > 0 && fieldtoken.compareTo(" ") != 0) {
+                        tokenCount++;
+                        if (tokenCount == 2) {
+                            this.CSEQ_NUMBER = Integer.parseInt(fieldtoken);
+                            break;
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("Content-Type: ")) {
+                this.contenttypeH = token;
+                continue;
+            }
+            if (token.startsWith("c: ")) {
+                this.contenttypeH = token;
+                continue;
+            }
+            if (token.startsWith("Content-Length: ")) {
+                this.contentlengthH = token;
+                continue;
+            }
+            if (token.startsWith("l: ")) {
+                this.contentlengthH = token;
+                continue;
+            }
+            if (token.startsWith("User-Agent: ")) {
+                this.remoteuseragentH = token;
+                this.useragentH = "User-Agent: KwangHaeSoft SmartSip release 0100o";
+                continue;
+            }
+            if (token.startsWith("P-Asserted-Identity: "))
+                this.passertedidentityH = token;
+        }
+        this.allowH = "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO";
+        this.maxforwardH = "Max-Forwards: 70";
+        int audioport = this.updateHeaders.sdp.audioM.mediaPort;
+        if (audioport > 0)
+            constructSdp();
+        if (this.sdp != null && this.sdp.flag) {
+            this.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+            if (SIPStack.PRIMARY_CODEC_AUDIO == SIPStack.SIP_CODEC_G711U) {
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+            } else {
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711A,
+                        "PCMA/8000");
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        SIPStack.SIP_CODEC_G711U,
+                        "PCMU/8000");
+            }
+            this.sdp.setCodec(
+                    SIPStack.SIP_MEDIATYPE_AUDIO,
+                    RFC2833.payloadType,
+                    "telephone-event/8000");
+            this.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+        }
+        if (parseRemoteSdp(message))
+            if (this.remoteSdp != null &&
+                    this.remoteSdp.flag)
+                if (this.remoteSdp.audioM != null &&
+                        this.sdp != null && this.sdp.flag && this.sdp.audioM != null &&
+                        this.remoteSdp.audioM.flow != null &&
+                        this.remoteSdp.audioM.flow.length() > 0)
+                    if (this.remoteSdp.audioM.flow.compareTo("sendrecv") == 0) {
+                        this.sdp.audioM.setFlow("sendrecv");
+                    } else if (this.remoteSdp.audioM.flow.compareTo("sendonly") == 0) {
+                        this.sdp.audioM.setFlow("recvonly");
+                    } else if (this.remoteSdp.audioM.flow.compareTo("recvonly") == 0) {
+                        this.sdp.audioM.setFlow("sendonly");
+                    }
+        negotiateAudioCodec();
+        return true;
+    }
+
+    public void reverseRecordRoute(String message) {
+        if (message == null || message.length() == 0)
+            return;
+        this.recordrouteArray = null;
+        this.routeH = null;
+        StringTokenizer tokenArray = new StringTokenizer(message, SIPStack.SIP_LINE_END, true);
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken().trim();
+            if (token.length() <= 0 ||
+                    token.compareTo("\r") == 0 ||
+                    token.compareTo("\n") == 0)
+                continue;
+            if (token.startsWith("Record-Route: ")) {
+                this.routeH = token.substring(7).trim();
+                if (this.routeArray == null) {
+                    this.routeArray = new StringBuffer();
+                    this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                if (this.routeArray != null && this.routeArray.length() > 0) {
+                    this.routeArray.insert(0, String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                if (this.routeArray != null)
+                    this.routeArray.append(String.valueOf(token.substring(7)) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("Contact: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (token.startsWith("m: ")) {
+                this.contactH = token;
+                if (token.length() > 0) {
+                    int iS = 0;
+                    iS = token.indexOf("sip:");
+                    if (iS > 0) {
+                        String str = null;
+                        int iE = 0;
+                        iE = token.indexOf(">", iS);
+                        if (iE > 0) {
+                            str = token.substring(iS, iE);
+                        } else {
+                            str = token.substring(iS);
+                        }
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(";");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        iE = str.indexOf(" ");
+                        if (iE > 0)
+                            str = str.substring(0, iE);
+                        if (str.length() > 0)
+                            this.remoteContactUri = str;
+                        if (str.length() > 0) {
+                            iS = str.indexOf("@");
+                            if (iS > 0) {
+                                str = str.substring(iS + 1);
+                            } else {
+                                str = str.substring(4);
+                            }
+                            int iM = str.indexOf(":", iS);
+                            if (iM < 0) {
+                                this.remoteContactIp = str;
+                                this.remoteContactPort = 5060;
+                                continue;
+                            }
+                            this.remoteContactIp = str.substring(0, iM).trim();
+                            this.remoteContactPort = Integer.parseInt(str.substring(iM + 1).trim());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public String getViaArray(String message) {
+        if (message == null || message.length() == 0)
+            return null;
+        StringBuffer viaArray = new StringBuffer();
+        String viaH = null;
+        StringTokenizer tokenArray = new StringTokenizer(message, SIPStack.SIP_LINE_END, true);
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken().trim();
+            if (token.length() <= 0 ||
+                    token.compareTo("\r") == 0 ||
+                    token.compareTo("\n") == 0)
+                continue;
+            if (token.startsWith("Via: ")) {
+                if (viaH == null) {
+                    viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = "";
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            viaH = token.substring(0, index);
+                        } else {
+                            viaH = token;
+                        }
+                        index = viaH.indexOf(";rport=");
+                        if (index > 0)
+                            viaH = viaH.substring(0, index);
+                        viaH = String.valueOf(viaH) + ";received=" + this.remoteIp + ";rport=" + this.remotePort + ";branch=" + this.viaBranch;
+                    }
+                    viaArray.append(String.valueOf(viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+                continue;
+            }
+            if (token.startsWith("v: ")) {
+                if (viaH == null) {
+                    viaH = token;
+                    if (token.indexOf(";received=") < 0) {
+                        String branch = "";
+                        int index = token.indexOf(";branch=");
+                        if (index > 0)
+                            branch = token.substring(index + 8);
+                        if (branch != null && branch.length() > 0) {
+                            index = branch.indexOf(";");
+                            if (index > 0) {
+                                this.viaBranch = branch.substring(0, index);
+                            } else {
+                                this.viaBranch = branch;
+                            }
+                        } else {
+                            this.viaBranch = branch;
+                        }
+                        index = token.indexOf(";branch=");
+                        if (index > 0) {
+                            viaH = token.substring(0, index);
+                        } else {
+                            viaH = token;
+                        }
+                        index = viaH.indexOf(";rport=");
+                        if (index > 0)
+                            viaH = viaH.substring(0, index);
+                        viaH = String.valueOf(viaH) + ";received=" + this.remoteIp + ";rport=" + this.remotePort + ";branch=" + this.viaBranch;
+                    }
+                    viaArray.append(String.valueOf(viaH) + SIPStack.SIP_LINE_END);
+                    continue;
+                }
+                viaArray.append(String.valueOf(token) + SIPStack.SIP_LINE_END);
+            }
+        }
+        return viaArray.toString();
+    }
+
+    public boolean constructSdp() {
+        if (this.sdp != null && this.sdp.flag)
+            return false;
+        if (SIPStack.localSdpIp != null && SIPStack.localSdpIp.length() > 0 && SIPStack.usePrivateWiMax) {
+            this.sdp = new SIPSdp(this.dnis, this.localIp, SIPStack.localSdpIp);
+        } else {
+            this.sdp = new SIPSdp(this.dnis, this.localIp);
+        }
+        if (this.sdp != null && this.sdp.flag)
+            return true;
+        return false;
+    }
+
+    public boolean parseRemoteSdp(String message) {
+        if (message == null || message.length() == 0)
+            return false;
+        boolean bContinueParsing = true;
+        int iS = 0;
+        int iE = 0;
+        String header = null;
+        if (bContinueParsing) {
+            bContinueParsing = false;
+            iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Type: ");
+            if (iS > 0) {
+                iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                if (iS > 0 && iE > 0) {
+                    header = message.substring(iS + 2, iE);
+                    String headerValue = null;
+                    if (header != null && header.length() > 0)
+                        headerValue = header.substring(14);
+                    if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/sdp") == 0)
+                        bContinueParsing = true;
+                }
+            } else {
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "c: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(3);
+                        if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/sdp") == 0)
+                            bContinueParsing = true;
+                    }
+                }
+            }
+        }
+        iS = 0;
+        iE = 0;
+        header = null;
+        int contentLength = 0;
+        if (bContinueParsing) {
+            bContinueParsing = false;
+            iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Length: ");
+            if (iS > 0) {
+                iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                if (iS > 0 && iE > 0) {
+                    header = message.substring(iS + 2, iE);
+                    String headerValue = null;
+                    if (header != null && header.length() > 0)
+                        headerValue = header.substring(16);
+                    if (headerValue != null && headerValue.length() > 0) {
+                        contentLength = Integer.parseInt(headerValue);
+                        bContinueParsing = true;
+                    }
+                }
+            } else {
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "l: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(3);
+                        if (headerValue != null && headerValue.length() > 0) {
+                            contentLength = Integer.parseInt(headerValue);
+                            bContinueParsing = true;
+                        }
+                    }
+                }
+            }
+        }
+        iS = 0;
+        iE = 0;
+        header = null;
+        String body = null;
+        if (bContinueParsing) {
+            bContinueParsing = false;
+            iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_DOUBLEEND) + "v=0" + SIPStack.SIP_LINE_END);
+            if (iS > 0) {
+                body = message.substring(iS + 4);
+                if (body != null && body.length() >= contentLength)
+                    bContinueParsing = true;
+            }
+        }
+        if (bContinueParsing) {
+            this.remoteSdp = new SIPSdp(body);
+            if (this.remoteSdp != null && this.remoteSdp.flag)
+                return true;
+        }
+        return false;
+    }
+
+    public boolean parseDtmfSdp(String message, int dtmftype) {
+        if (message == null || message.length() == 0)
+            return false;
+        boolean bContinueParsing = true;
+        int iS = 0;
+        int iE = 0;
+        int dtmf = 0;
+        this.bDtmfdetected = false;
+        String header = null;
+        if (dtmftype == SIPStack.SIP_DTMFINFO_DTMFRELAY) {
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Type: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(14);
+                        if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/dtmf-relay") == 0)
+                            bContinueParsing = true;
+                    }
+                } else {
+                    iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "c: ");
+                    if (iS > 0) {
+                        iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                        if (iS > 0 && iE > 0) {
+                            header = message.substring(iS + 2, iE);
+                            String headerValue = null;
+                            if (header != null && header.length() > 0)
+                                headerValue = header.substring(3);
+                            if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/dtmf-relay") == 0)
+                                bContinueParsing = true;
+                        }
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            header = null;
+            int contentLength = 0;
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Length: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(16);
+                        if (headerValue != null && headerValue.length() > 0) {
+                            contentLength = Integer.parseInt(headerValue);
+                            bContinueParsing = true;
+                        }
+                    }
+                } else {
+                    iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "l: ");
+                    if (iS > 0) {
+                        iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                        if (iS > 0 && iE > 0) {
+                            header = message.substring(iS + 2, iE);
+                            String headerValue = null;
+                            if (header != null && header.length() > 0)
+                                headerValue = header.substring(3);
+                            if (headerValue != null && headerValue.length() > 0) {
+                                contentLength = Integer.parseInt(headerValue);
+                                bContinueParsing = true;
+                            }
+                        }
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            header = null;
+            String body = null;
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_DOUBLEEND) + "Signal=");
+                if (iS > 0) {
+                    body = message.substring(iS + 4);
+                    if (body != null && body.length() >= contentLength)
+                        bContinueParsing = true;
+                }
+            }
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                String sH = null;
+                iS = body.indexOf("Signal=");
+                if (iS >= 0)
+                    iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+                if (iS >= 0 && iE > iS) {
+                    sH = body.substring(iS + 7, iE).trim();
+                    dtmf = Integer.parseInt(sH);
+                    if (dtmf >= 0 && dtmf < 12) {
+                        bContinueParsing = true;
+                        this.detectedDtmf = dtmf;
+                        this.bDtmfdetected = true;
+                        this.dtmfDuration = 0;
+                    }
+                }
+                if (bContinueParsing) {
+                    iS = body.indexOf("Duration=");
+                    if (iS >= 0)
+                        iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+                    if (iS >= 0 && iE > iS) {
+                        sH = body.substring(iS + 9, iE).trim();
+                        this.dtmfDuration = Integer.parseInt(sH);
+                    }
+                }
+            }
+            return this.bDtmfdetected;
+        }
+        if (dtmftype == SIPStack.SIP_DTMFINFO_DTMF) {
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Type: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(14);
+                        if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/dtmf") == 0)
+                            bContinueParsing = true;
+                    }
+                } else {
+                    iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "c: ");
+                    if (iS > 0) {
+                        iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                        if (iS > 0 && iE > 0) {
+                            header = message.substring(iS + 2, iE);
+                            String headerValue = null;
+                            if (header != null && header.length() > 0)
+                                headerValue = header.substring(3);
+                            if (headerValue != null && headerValue.length() > 0 && headerValue.toLowerCase().compareTo("application/dtmf") == 0)
+                                bContinueParsing = true;
+                        }
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            header = null;
+            int contentLength = 0;
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "Content-Length: ");
+                if (iS > 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                    if (iS > 0 && iE > 0) {
+                        header = message.substring(iS + 2, iE);
+                        String headerValue = null;
+                        if (header != null && header.length() > 0)
+                            headerValue = header.substring(16);
+                        if (headerValue != null && headerValue.length() > 0) {
+                            contentLength = Integer.parseInt(headerValue);
+                            bContinueParsing = true;
+                        }
+                    }
+                } else {
+                    iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "l: ");
+                    if (iS > 0) {
+                        iE = message.indexOf(SIPStack.SIP_LINE_END, iS + 2);
+                        if (iS > 0 && iE > 0) {
+                            header = message.substring(iS + 2, iE);
+                            String headerValue = null;
+                            if (header != null && header.length() > 0)
+                                headerValue = header.substring(3);
+                            if (headerValue != null && headerValue.length() > 0) {
+                                contentLength = Integer.parseInt(headerValue);
+                                bContinueParsing = true;
+                            }
+                        }
+                    }
+                }
+            }
+            iS = 0;
+            iE = 0;
+            header = null;
+            String body = null;
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                iS = message.indexOf(SIPStack.SIP_LINE_DOUBLEEND);
+                if (iS > 0) {
+                    body = message.substring(iS + 4);
+                    if (body != null && body.length() >= contentLength)
+                        bContinueParsing = true;
+                }
+            }
+            if (bContinueParsing) {
+                bContinueParsing = false;
+                String sH = null;
+                iS = 0;
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+                if (iE > iS) {
+                    sH = body.substring(iS, iE).trim();
+                    dtmf = Integer.parseInt(sH);
+                    if (dtmf >= 0 && dtmf < 12) {
+                        bContinueParsing = true;
+                        this.detectedDtmf = dtmf;
+                        this.bDtmfdetected = true;
+                        this.dtmfDuration = 0;
+                    }
+                }
+            }
+            return this.bDtmfdetected;
+        }
+        return false;
+    }
+
+    public boolean negotiateAudioCodec() {
+        if (this.sdp != null && this.sdp.flag && this.sdp.audioM != null && this.sdp.audioM.flag &&
+                this.remoteSdp != null && this.remoteSdp.flag && this.remoteSdp.audioM != null &&
+                this.remoteSdp.audioM.flag)
+            if (this.callDirection == SIPStack.SIP_CALLDIRECTION_OUT) {
+                int finalCodec = this.remoteSdp.audioM.negotiateAudioCodec(this.sdp.audioM.codecS.toString());
+                if (finalCodec >= 0) {
+                    this.sdp.audioM.setCommonCodec(finalCodec);
+                    return true;
+                }
+            } else if (this.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+                int finalCodec = this.sdp.audioM.negotiateAudioCodec(this.remoteSdp.audioM.codecS.toString());
+                if (finalCodec >= 0) {
+                    this.remoteSdp.audioM.setCommonCodec(finalCodec);
+                    return true;
+                }
+            }
+        return false;
+    }
+
+    public boolean negotiateVideoCodec() {
+        return true;
+    }
+
+    public void exceptionTI() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("IDLE CALL EXCEPTION occurred.");
+        resetCall();
+    }
+
+    public void exceptionT0() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("INVITING CALL EXCEPTION occurred.");
+        resetCall();
+    }
+
+    public void exceptionT1() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("PROCEEDING CALL EXCEPTION occurred.");
+    }
+
+    public void exceptionT2() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("PROGRESSING CALL EXCEPTION occurred.");
+    }
+
+    public void exceptionT3() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("ACCEPTED CALL EXCEPTION occurred.");
+    }
+
+    public void exceptionT4() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("CONNECTED CALL EXCEPTION occurred.");
+    }
+
+    public void exceptionT5() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("DISCONNECTING CALL EXCEPTION occurred.");
+        resetCall();
+    }
+
+    public void exceptionT6() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("TERMINATING CALL EXCEPTION occurred.");
+        resetCall();
+    }
+
+    public void exceptionT7() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("OFFERRED CALL EXCEPTION occurred.");
+    }
+
+    public void exceptionT8() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("CANCELLING CALL EXCEPTION occurred.");
+        resetCall();
+    }
+
+    public void setUpdateheaders() {
+        if (this.updateHeaders == null)
+            return;
+        this.updateHeaders.commandLine = this.commandLine;
+        this.updateHeaders.viaH = this.viaH;
+        this.updateHeaders.viaArray = this.viaArray;
+        this.updateHeaders.routeH = this.routeH;
+        this.updateHeaders.routeArray = this.routeArray;
+        this.updateHeaders.recordrouteH = this.recordrouteH;
+        this.updateHeaders.recordrouteArray = this.recordrouteArray;
+        this.updateHeaders.maxforwardH = this.maxforwardH;
+        this.updateHeaders.contactH = this.contactH;
+        this.updateHeaders.toH = this.toH;
+        this.updateHeaders.fromH = this.fromH;
+        this.updateHeaders.callidH = this.callidH;
+        this.updateHeaders.cseqH = this.cseqH;
+        this.updateHeaders.expiresH = this.expiresH;
+        this.updateHeaders.allowH = this.allowH;
+        this.updateHeaders.useragentH = this.useragentH;
+        this.updateHeaders.remoteuseragentH = this.remoteuseragentH;
+        this.updateHeaders.contentlengthH = this.contentlengthH;
+        this.updateHeaders.contenttypeH = this.contenttypeH;
+        this.updateHeaders.authorizationINVITEH = this.authorizationINVITEH;
+        this.updateHeaders.authorizationCANCELH = this.authorizationCANCELH;
+        this.updateHeaders.authorizationBYEH = this.authorizationBYEH;
+        this.updateHeaders.authorizationACKH = this.authorizationACKH;
+        this.updateHeaders.passertedidentityH = this.passertedidentityH;
+        this.updateHeaders.serverIp = this.serverIp;
+        this.updateHeaders.serverPort = this.serverPort;
+        this.updateHeaders.serverDomain = this.serverDomain;
+        this.updateHeaders.remoteIp = this.remoteIp;
+        this.updateHeaders.remotePort = this.remotePort;
+        this.updateHeaders.remoteContactIp = this.remoteContactIp;
+        this.updateHeaders.remoteContactPort = this.remoteContactPort;
+        this.updateHeaders.remoteContactUri = this.remoteContactUri;
+        this.updateHeaders.localIp = this.localIp;
+        this.updateHeaders.localPort = this.localPort;
+        this.updateHeaders.id = this.id;
+        this.updateHeaders.cid = this.cid;
+        this.updateHeaders.authid = this.authid;
+        this.updateHeaders.authpassword = this.authpassword;
+        this.updateHeaders.fromTag = this.fromTag;
+        this.updateHeaders.toTag = this.toTag;
+        this.updateHeaders.fromHeaderValue = this.fromHeaderValue;
+        this.updateHeaders.toHeaderValue = this.toHeaderValue;
+        this.updateHeaders.callId = this.callId;
+        this.updateHeaders.dnis = this.dnis;
+        this.updateHeaders.CSEQ_NUMBER = this.CSEQ_NUMBER;
+        this.updateHeaders.INVITE_CSEQ = this.INVITE_CSEQ;
+        this.updateHeaders.CANCEL_CSEQ = this.CANCEL_CSEQ;
+        this.updateHeaders.ACK_CSEQ = this.ACK_CSEQ;
+        this.updateHeaders.BYE_CSEQ = this.BYE_CSEQ;
+        this.updateHeaders.callDirection = this.callDirection;
+        this.updateHeaders.viaBranch = this.viaBranch;
+        this.updateHeaders.callState = this.callState;
+        this.updateHeaders.callMode = this.callMode;
+        this.updateHeaders.callTime_TI = this.callTime_TI;
+        this.updateHeaders.callTime_T0 = this.callTime_T0;
+        this.updateHeaders.callTime_T00 = this.callTime_T00;
+        this.updateHeaders.invitingTimes = this.invitingTimes;
+        this.updateHeaders.callTime_T1 = this.callTime_T1;
+        this.updateHeaders.callTime_T2 = this.callTime_T2;
+        this.updateHeaders.callTime_T3 = this.callTime_T3;
+        this.updateHeaders.callTime_T4 = this.callTime_T4;
+        this.updateHeaders.callTime_T40 = this.callTime_T40;
+        this.updateHeaders.callTime_T5 = this.callTime_T5;
+        this.updateHeaders.callTime_T6 = this.callTime_T6;
+        this.updateHeaders.callTime_T7 = this.callTime_T7;
+        this.updateHeaders.callTime_T8 = this.callTime_T8;
+        this.updateHeaders.callTime_T9 = this.callTime_T9;
+        this.updateHeaders.expiresTI = this.expiresTI;
+        this.updateHeaders.expiresT0 = this.expiresT0;
+        this.updateHeaders.expiresT1 = this.expiresT1;
+        this.updateHeaders.expiresT2 = this.expiresT2;
+        this.updateHeaders.expiresT3 = this.expiresT3;
+        this.updateHeaders.expiresT4 = this.expiresT4;
+        this.updateHeaders.expiresT5 = this.expiresT5;
+        this.updateHeaders.expiresT6 = this.expiresT6;
+        this.updateHeaders.expiresT7 = this.expiresT7;
+        this.updateHeaders.expiresT8 = this.expiresT8;
+        this.updateHeaders.expiresT9 = this.expiresT9;
+        this.updateHeaders.sdp = this.sdp;
+        this.updateHeaders.remoteSdp = this.remoteSdp;
+        this.updateHeaders.message = this.message;
+        this.commandLine = null;
+        this.viaH = null;
+        this.viaArray = null;
+        this.routeH = null;
+        this.routeArray = null;
+        this.recordrouteH = null;
+        this.recordrouteArray = null;
+        this.maxforwardH = null;
+        this.contactH = null;
+        this.toH = null;
+        this.fromH = null;
+        this.callidH = null;
+        this.cseqH = null;
+        this.expiresH = null;
+        this.allowH = null;
+        this.useragentH = null;
+        this.remoteuseragentH = null;
+        this.contentlengthH = null;
+        this.contenttypeH = null;
+        this.authorizationINVITEH = null;
+        this.authorizationCANCELH = null;
+        this.authorizationBYEH = null;
+        this.authorizationACKH = null;
+        this.passertedidentityH = null;
+        this.fromTag = null;
+        this.toTag = null;
+        this.callId = null;
+        this.viaBranch = null;
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.message = null;
+        this.updateHeaders.flag = true;
+    }
+
+    public void setUpdateheaders(String flow) {
+        if (this.updateHeaders == null)
+            return;
+        this.updateHeaders.commandLine = this.commandLine;
+        this.updateHeaders.viaH = this.viaH;
+        this.updateHeaders.viaArray = this.viaArray;
+        this.updateHeaders.routeH = this.routeH;
+        this.updateHeaders.routeArray = this.routeArray;
+        this.updateHeaders.recordrouteH = this.recordrouteH;
+        this.updateHeaders.recordrouteArray = this.recordrouteArray;
+        this.updateHeaders.maxforwardH = this.maxforwardH;
+        this.updateHeaders.contactH = this.contactH;
+        this.updateHeaders.toH = this.toH;
+        this.updateHeaders.fromH = this.fromH;
+        this.updateHeaders.callidH = this.callidH;
+        this.updateHeaders.cseqH = this.cseqH;
+        this.updateHeaders.expiresH = this.expiresH;
+        this.updateHeaders.allowH = this.allowH;
+        this.updateHeaders.useragentH = this.useragentH;
+        this.updateHeaders.remoteuseragentH = this.remoteuseragentH;
+        this.updateHeaders.contentlengthH = this.contentlengthH;
+        this.updateHeaders.contenttypeH = this.contenttypeH;
+        this.updateHeaders.authorizationINVITEH = this.authorizationINVITEH;
+        this.updateHeaders.authorizationCANCELH = this.authorizationCANCELH;
+        this.updateHeaders.authorizationBYEH = this.authorizationBYEH;
+        this.updateHeaders.authorizationACKH = this.authorizationACKH;
+        this.updateHeaders.passertedidentityH = this.passertedidentityH;
+        this.updateHeaders.serverIp = this.serverIp;
+        this.updateHeaders.serverPort = this.serverPort;
+        this.updateHeaders.serverDomain = this.serverDomain;
+        this.updateHeaders.remoteIp = this.remoteIp;
+        this.updateHeaders.remotePort = this.remotePort;
+        this.updateHeaders.remoteContactIp = this.remoteContactIp;
+        this.updateHeaders.remoteContactPort = this.remoteContactPort;
+        this.updateHeaders.remoteContactUri = this.remoteContactUri;
+        this.updateHeaders.localIp = this.localIp;
+        this.updateHeaders.localPort = this.localPort;
+        this.updateHeaders.id = this.id;
+        this.updateHeaders.cid = this.cid;
+        this.updateHeaders.authid = this.authid;
+        this.updateHeaders.authpassword = this.authpassword;
+        this.updateHeaders.fromTag = this.fromTag;
+        this.updateHeaders.toTag = this.toTag;
+        this.updateHeaders.fromHeaderValue = this.fromHeaderValue;
+        this.updateHeaders.toHeaderValue = this.toHeaderValue;
+        this.updateHeaders.callId = this.callId;
+        this.updateHeaders.dnis = this.dnis;
+        this.updateHeaders.CSEQ_NUMBER = this.CSEQ_NUMBER;
+        this.updateHeaders.INVITE_CSEQ = this.INVITE_CSEQ;
+        this.updateHeaders.CANCEL_CSEQ = this.CANCEL_CSEQ;
+        this.updateHeaders.ACK_CSEQ = this.ACK_CSEQ;
+        this.updateHeaders.BYE_CSEQ = this.BYE_CSEQ;
+        this.updateHeaders.callDirection = this.callDirection;
+        this.updateHeaders.viaBranch = this.viaBranch;
+        this.updateHeaders.callState = this.callState;
+        this.updateHeaders.callMode = this.callMode;
+        this.updateHeaders.callTime_TI = this.callTime_TI;
+        this.updateHeaders.callTime_T0 = this.callTime_T0;
+        this.updateHeaders.callTime_T00 = this.callTime_T00;
+        this.updateHeaders.invitingTimes = this.invitingTimes;
+        this.updateHeaders.callTime_T1 = this.callTime_T1;
+        this.updateHeaders.callTime_T2 = this.callTime_T2;
+        this.updateHeaders.callTime_T3 = this.callTime_T3;
+        this.updateHeaders.callTime_T4 = this.callTime_T4;
+        this.updateHeaders.callTime_T40 = this.callTime_T40;
+        this.updateHeaders.callTime_T5 = this.callTime_T5;
+        this.updateHeaders.callTime_T6 = this.callTime_T6;
+        this.updateHeaders.callTime_T7 = this.callTime_T7;
+        this.updateHeaders.callTime_T8 = this.callTime_T8;
+        this.updateHeaders.callTime_T9 = this.callTime_T9;
+        this.updateHeaders.expiresTI = this.expiresTI;
+        this.updateHeaders.expiresT0 = this.expiresT0;
+        this.updateHeaders.expiresT1 = this.expiresT1;
+        this.updateHeaders.expiresT2 = this.expiresT2;
+        this.updateHeaders.expiresT3 = this.expiresT3;
+        this.updateHeaders.expiresT4 = this.expiresT4;
+        this.updateHeaders.expiresT5 = this.expiresT5;
+        this.updateHeaders.expiresT6 = this.expiresT6;
+        this.updateHeaders.expiresT7 = this.expiresT7;
+        this.updateHeaders.expiresT8 = this.expiresT8;
+        this.updateHeaders.expiresT9 = this.expiresT9;
+        this.updateHeaders.sdp = this.sdp;
+        this.updateHeaders.remoteSdp = this.remoteSdp;
+        this.updateHeaders.message = this.message;
+        this.commandLine = null;
+        this.viaH = null;
+        this.viaArray = null;
+        this.recordrouteH = null;
+        this.recordrouteArray = null;
+        this.maxforwardH = null;
+        this.contactH = null;
+        if (this.updateHeaders.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            if (this.updateHeaders.fromH != null && this.updateHeaders.fromH.length() > 5)
+                if (this.updateHeaders.fromH.startsWith("f: ")) {
+                    this.toH = "t:" + this.updateHeaders.fromH.substring(2);
+                } else {
+                    this.toH = "To:" + this.updateHeaders.fromH.substring(5);
+                }
+            if (this.updateHeaders.toH != null && this.updateHeaders.toH.length() > 3)
+                if (this.updateHeaders.toH.startsWith("t: ")) {
+                    this.fromH = "From:" + this.updateHeaders.toH.substring(2);
+                } else {
+                    this.fromH = "From:" + this.updateHeaders.toH.substring(3);
+                }
+            this.fromTag = this.updateHeaders.toTag;
+            this.toTag = this.updateHeaders.fromTag;
+        }
+        this.cseqH = null;
+        this.expiresH = null;
+        this.allowH = null;
+        this.useragentH = null;
+        this.remoteuseragentH = null;
+        this.contentlengthH = null;
+        this.contenttypeH = null;
+        this.viaBranch = null;
+        if (this.updateHeaders.callDirection == SIPStack.SIP_CALLDIRECTION_IN) {
+            this.authorizationINVITEH = null;
+            this.authorizationCANCELH = null;
+            this.authorizationBYEH = null;
+            this.authorizationACKH = null;
+        }
+        this.passertedidentityH = null;
+        this.callState = 20;
+        this.callMode = SIPStack.SIP_CALLMODE_HOLD;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.sdp = null;
+        this.remoteSdp = null;
+        int audioport = this.updateHeaders.sdp.audioM.mediaPort;
+        if (audioport > 0)
+            constructSdp();
+        if (this.sdp != null && this.sdp.flag) {
+            this.sdp.setMediaPort(SIPStack.SIP_MEDIATYPE_AUDIO, audioport);
+            if (this.sdp.audioM != null) {
+                if (this.updateHeaders.sdp.audioM.commonCodec == SIPStack.SIP_CODEC_G711U) {
+                    this.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711U,
+                            "PCMU/8000");
+                } else if (this.updateHeaders.sdp.audioM.commonCodec == SIPStack.SIP_CODEC_G711A) {
+                    this.sdp.setCodec(
+                            SIPStack.SIP_MEDIATYPE_AUDIO,
+                            SIPStack.SIP_CODEC_G711A,
+                            "PCMA/8000");
+                }
+                this.sdp.setCodec(
+                        SIPStack.SIP_MEDIATYPE_AUDIO,
+                        RFC2833.payloadType,
+                        "telephone-event/8000");
+                this.sdp.setFmtpDescribe(SIPStack.SIP_MEDIATYPE_AUDIO, RFC2833.payloadType, "0-15");
+                this.sdp.audioM.setFlow(flow);
+            }
+        }
+        this.message = null;
+        this.updateHeaders.flag = true;
+    }
+
+    public void restoreUpdateheaders() {
+        if (this.updateHeaders == null || !this.updateHeaders.flag)
+            return;
+        this.commandLine = this.updateHeaders.commandLine;
+        this.viaH = this.updateHeaders.viaH;
+        this.viaArray = this.updateHeaders.viaArray;
+        this.routeH = this.updateHeaders.routeH;
+        this.routeArray = this.updateHeaders.routeArray;
+        this.recordrouteH = this.updateHeaders.recordrouteH;
+        this.recordrouteArray = this.updateHeaders.recordrouteArray;
+        this.maxforwardH = this.updateHeaders.maxforwardH;
+        this.contactH = this.updateHeaders.contactH;
+        this.toH = this.updateHeaders.toH;
+        this.fromH = this.updateHeaders.fromH;
+        this.callidH = this.updateHeaders.callidH;
+        this.cseqH = this.updateHeaders.cseqH;
+        this.expiresH = this.updateHeaders.expiresH;
+        this.allowH = this.updateHeaders.allowH;
+        this.useragentH = this.updateHeaders.useragentH;
+        this.remoteuseragentH = this.updateHeaders.remoteuseragentH;
+        this.contentlengthH = this.updateHeaders.contentlengthH;
+        this.contenttypeH = this.updateHeaders.contenttypeH;
+        this.authorizationINVITEH = this.updateHeaders.authorizationINVITEH;
+        this.authorizationCANCELH = this.updateHeaders.authorizationCANCELH;
+        this.authorizationBYEH = this.updateHeaders.authorizationBYEH;
+        this.authorizationACKH = this.updateHeaders.authorizationACKH;
+        this.passertedidentityH = this.updateHeaders.passertedidentityH;
+        this.serverIp = this.updateHeaders.serverIp;
+        this.serverPort = this.updateHeaders.serverPort;
+        this.serverDomain = this.updateHeaders.serverDomain;
+        this.remoteIp = this.updateHeaders.remoteIp;
+        this.remotePort = this.updateHeaders.remotePort;
+        this.remoteContactIp = this.updateHeaders.remoteContactIp;
+        this.remoteContactPort = this.updateHeaders.remoteContactPort;
+        this.remoteContactUri = this.updateHeaders.remoteContactUri;
+        this.localIp = this.updateHeaders.localIp;
+        this.localPort = this.updateHeaders.localPort;
+        this.id = this.updateHeaders.id;
+        this.cid = this.updateHeaders.cid;
+        this.authid = this.updateHeaders.authid;
+        this.authpassword = this.updateHeaders.authpassword;
+        this.fromTag = this.updateHeaders.fromTag;
+        this.toTag = this.updateHeaders.toTag;
+        this.fromHeaderValue = this.updateHeaders.fromHeaderValue;
+        this.toHeaderValue = this.updateHeaders.toHeaderValue;
+        this.callId = this.updateHeaders.callId;
+        this.dnis = this.updateHeaders.dnis;
+        this.CSEQ_NUMBER = this.updateHeaders.CSEQ_NUMBER;
+        this.INVITE_CSEQ = this.updateHeaders.INVITE_CSEQ;
+        this.CANCEL_CSEQ = this.updateHeaders.CANCEL_CSEQ;
+        this.ACK_CSEQ = this.updateHeaders.ACK_CSEQ;
+        this.BYE_CSEQ = this.updateHeaders.BYE_CSEQ;
+        this.callDirection = this.updateHeaders.callDirection;
+        this.viaBranch = this.updateHeaders.viaBranch;
+        this.callState = this.updateHeaders.callState;
+        this.callMode = this.updateHeaders.callMode;
+        this.callTime_TI = this.updateHeaders.callTime_TI;
+        this.callTime_T0 = this.updateHeaders.callTime_T0;
+        this.callTime_T00 = this.updateHeaders.callTime_T00;
+        this.invitingTimes = this.updateHeaders.invitingTimes;
+        this.callTime_T1 = this.updateHeaders.callTime_T1;
+        this.callTime_T2 = this.updateHeaders.callTime_T2;
+        this.callTime_T3 = this.updateHeaders.callTime_T3;
+        this.callTime_T4 = this.updateHeaders.callTime_T4;
+        this.callTime_T40 = this.updateHeaders.callTime_T40;
+        this.callTime_T5 = this.updateHeaders.callTime_T5;
+        this.callTime_T6 = this.updateHeaders.callTime_T6;
+        this.callTime_T7 = this.updateHeaders.callTime_T7;
+        this.callTime_T8 = this.updateHeaders.callTime_T8;
+        this.callTime_T9 = this.updateHeaders.callTime_T9;
+        this.expiresTI = this.updateHeaders.expiresTI;
+        this.expiresT0 = this.updateHeaders.expiresT0;
+        this.expiresT1 = this.updateHeaders.expiresT1;
+        this.expiresT2 = this.updateHeaders.expiresT2;
+        this.expiresT3 = this.updateHeaders.expiresT3;
+        this.expiresT4 = this.updateHeaders.expiresT4;
+        this.expiresT5 = this.updateHeaders.expiresT5;
+        this.expiresT6 = this.updateHeaders.expiresT6;
+        this.expiresT7 = this.updateHeaders.expiresT7;
+        this.expiresT8 = this.updateHeaders.expiresT8;
+        this.expiresT9 = this.updateHeaders.expiresT9;
+        this.sdp = this.updateHeaders.sdp;
+        this.remoteSdp = this.updateHeaders.remoteSdp;
+        this.message = this.updateHeaders.message;
+        this.updateHeaders.flag = false;
+    }
+
+    public void resetUpdateheaders() {
+        if (this.updateHeaders == null || !this.updateHeaders.flag)
+            return;
+        this.updateHeaders.reset();
+    }
+
+    public boolean isCurrentCall(String message) {
+        try {
+            SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
+            if (sipHeader != null && sipHeader.flag)
+                if (sipHeader.headerValue != null &&
+                        sipHeader.headerValue.length() > 0 &&
+                        this.callId != null &&
+                        sipHeader.headerValue.compareTo(this.callId) == 0)
+                    return true;
+        } catch (Exception exception) {}
+        return false;
+    }
+
+    public String getCallState() {
+        switch (this.callState) {
+            case 0:
+                return "Idle";
+            case 1:
+                return "Inviting";
+            case 2:
+                return "Offerred";
+            case 3:
+                return "Proceeding";
+            case 4:
+                return "Progressing";
+            case 5:
+                return "Accepted";
+            case 6:
+                return "Remoteaccepted";
+            case 7:
+                return "Connected";
+            case 8:
+                return "Disconnecting";
+            case 9:
+                return "Terminating";
+            case 10:
+                return "Unauthorized";
+            case 11:
+                return "Cancelling";
+            case 13:
+                return "Recancelling";
+            case 14:
+                return "Cancelremoteaccepted";
+            case 12:
+                return "Cancelled";
+            case 15:
+                return "Rejected";
+            case 16:
+                return "Redirected";
+            case 20:
+                return "Updating";
+            case 21:
+                return "Updateproceeding";
+            case 22:
+                return "Updateprogressing";
+            case 23:
+                return "Updateofferred";
+            case 24:
+                return "Updateaccepted";
+            case 25:
+                return "Updaterejected";
+            case 26:
+                return "Updateremoteaccepted";
+            case 27:
+                return "Updateremoterejected";
+            case 28:
+                return "Updateunauthorized";
+            case 29:
+                return "Updateredirected";
+        }
+        return "Undefined";
+    }
+}

+ 362 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPG711.java

@@ -0,0 +1,362 @@
+package bssoft.stack.sip;
+
+public class SIPG711 {
+    static final int SIGN_BIT = 128;
+
+    static final int QUANT_MASK = 15;
+
+    static final int NSEGS = 8;
+
+    static final int SEG_SHIFT = 4;
+
+    static final int SEG_MASK = 112;
+
+    static final int[] seg_end = new int[] { 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 };
+
+    static final int[] _u2a = new int[] {
+            1, 1, 2, 2, 3, 3, 4, 4,
+
+            5, 5,
+            6, 6, 7, 7, 8, 8,
+
+            9, 10, 11, 12,
+            13, 14, 15, 16,
+
+            17, 18, 19, 20, 21, 22,
+            23, 24,
+
+            25, 27, 29, 31, 33, 34, 35, 36,
+            37, 38, 39, 40, 41, 42, 43, 44,
+
+            46, 48,
+            49, 50, 51, 52, 53, 54,
+
+            55, 56, 57, 58,
+            59, 60, 61, 62,
+
+            64, 65, 66, 67, 68, 69,
+            70, 71,
+
+            72, 73, 74, 75, 76, 77, 78, 79,
+            81, 82, 83, 84, 85, 86, 87, 88,
+
+            89, 90,
+            91, 92, 93, 94, 95, 96,
+
+            97, 98, 99, 100,
+            101, 102, 103, 104,
+
+            105, 106, 107, 108, 109, 110,
+            111, 112,
+
+            113, 114, 115, 116, 117, 118, 119, 120,
+            121, 122, 123, 124, 125, 126, 127, 128 };
+
+    static final int[] _a2u = new int[] {
+            1, 3, 5, 7, 9, 11, 13, 15,
+
+            16, 17,
+            18, 19, 20, 21, 22, 23,
+
+            24, 25, 26, 27,
+            28, 29, 30, 31,
+
+            32, 32, 33, 33, 34, 34,
+            35, 35,
+
+            36, 37, 38, 39, 40, 41, 42, 43,
+            44, 45, 46, 47, 48, 48, 49, 49,
+
+            50, 51,
+            52, 53, 54, 55, 56, 57,
+
+            58, 59, 60, 61,
+            62, 63, 64, 64,
+
+            65, 66, 67, 68, 69, 70,
+            71, 72,
+
+            73, 74, 75, 76, 77, 78, 79, 79,
+            80, 81, 82, 83, 84, 85, 86, 87,
+
+            88, 89,
+            90, 91, 92, 93, 94, 95,
+
+            96, 97, 98, 99,
+            100, 101, 102, 103,
+
+            104, 105, 106, 107, 108, 109,
+            110, 111,
+
+            112, 113, 114, 115, 116, 117, 118, 119,
+            120, 121, 122, 123, 124, 125, 126, 127 };
+
+    public static final int BIAS = 132;
+
+    static int search(int val, int[] table) {
+        for (int i = 0; i < table.length; ) {
+            if (val <= table[i])
+                return i;
+            i++;
+        }
+        return table.length;
+    }
+
+    public static int linear2alaw(int pcm_val) {
+        int mask;
+        if (pcm_val >= 0) {
+            mask = 213;
+        } else {
+            mask = 85;
+            pcm_val = -pcm_val - 8;
+        }
+        int seg = search(pcm_val, seg_end);
+        if (seg >= 8)
+            return 0x7F ^ mask;
+        int aval = seg << 4;
+        if (seg < 2) {
+            aval |= pcm_val >> 4 & 0xF;
+        } else {
+            aval |= pcm_val >> seg + 3 & 0xF;
+        }
+        return aval ^ mask;
+    }
+
+    public static int alaw2linear(int a_val) {
+        a_val ^= 0x55;
+        int t = (a_val & 0xF) << 4;
+        int seg = (a_val & 0x70) >> 4;
+        switch (seg) {
+            case 0:
+                t += 8;
+                break;
+            case 1:
+                t += 264;
+                break;
+            default:
+                t += 264;
+                t <<= seg - 1;
+                break;
+        }
+        return ((a_val & 0x80) != 0) ? t : -t;
+    }
+
+    public static int linear2ulaw(int pcm_val) {
+        int mask;
+        if (pcm_val < 0) {
+            pcm_val = 132 - pcm_val;
+            mask = 127;
+        } else {
+            pcm_val += 132;
+            mask = 255;
+        }
+        int seg = search(pcm_val, seg_end);
+        if (seg >= 8)
+            return 0x7F ^ mask;
+        int uval = seg << 4 | pcm_val >> seg + 3 & 0xF;
+        return uval ^ mask;
+    }
+
+    public static int ulaw2linear(int u_val) {
+        u_val ^= 0xFFFFFFFF;
+        int t = ((u_val & 0xF) << 3) + 132;
+        t <<= (u_val & 0x70) >> 4;
+        return ((u_val & 0x80) != 0) ? (132 - t) : (t - 132);
+    }
+
+    public static int alaw2ulaw(int aval) {
+        aval &= 0xFF;
+        return ((aval & 0x80) != 0) ? (0xFF ^ _a2u[aval ^ 0xD5]) : (0x7F ^ _a2u[aval ^ 0x55]);
+    }
+
+    public static int ulaw2alaw(int uval) {
+        uval &= 0xFF;
+        return ((uval & 0x80) != 0) ? (0xD5 ^ _u2a[0xFF ^ uval] - 1) : (0x55 ^ _u2a[0x7F ^ uval] - 1);
+    }
+
+    public static int encode2ULaw(short[] src, int srcsize, byte[] dest, int start) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return 0;
+        int encsize = srcsize;
+        for (int i = 0; i < encsize; i++)
+            dest[start + i] = (byte)linear2ulaw(src[i]);
+        return encsize + start;
+    }
+
+    public static int encode2ULawExt(byte[] src, int srcsize, byte[] dest, int start) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return 0;
+        int encsize = srcsize / 2;
+        int val = 0;
+        int val_ = 0;
+        for (int i = 0; i < encsize; i++) {
+            val = src[2 * i + 1];
+            val_ = src[2 * i];
+            val = val << 8 & 0xFFFFFF00;
+            val_ &= 0xFF;
+            val |= val_;
+            dest[start + i] = (byte)linear2ulaw(val);
+        }
+        return encsize + start;
+    }
+
+    public static int encode2ALaw(short[] src, int srcsize, byte[] dest, int start) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return 0;
+        int encsize = srcsize;
+        for (int i = 0; i < encsize; i++)
+            dest[start + i] = (byte)linear2alaw(src[i]);
+        return encsize + start;
+    }
+
+    public static int encode2ALawExt(byte[] src, int srcsize, byte[] dest, int start) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return 0;
+        int encsize = srcsize / 2;
+        int val = 0;
+        int val_ = 0;
+        for (int i = 0; i < encsize; i++) {
+            val = src[2 * i + 1];
+            val_ = src[2 * i];
+            val = val << 8 & 0xFFFFFF00;
+            val_ &= 0xFF;
+            val |= val_;
+            dest[start + i] = (byte)linear2alaw(val);
+        }
+        return encsize + start;
+    }
+
+    public static short[] decodeULaw(byte[] src, int start, int srcsize) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return null;
+        short[] decbuffer = new short[srcsize];
+        for (int i = 0; i < srcsize; i++)
+            decbuffer[i] = (short)ulaw2linear(src[i + start] & 0xFF);
+        return decbuffer;
+    }
+
+    public static byte[] decodeULawExt(byte[] src, int start, int srcsize) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return null;
+        byte[] decbuffer = new byte[srcsize * 2];
+        int val = 0;
+        for (int i = 0; i < srcsize; i++) {
+            val = ulaw2linear(src[i + start] & 0xFF);
+            decbuffer[2 * i + 1] = (byte)(val >> 8);
+            decbuffer[2 * i] = (byte)(val << 24 >> 24);
+        }
+        return decbuffer;
+    }
+
+    public static boolean decodeULawExt(byte[] src, int start, int srcsize, byte[] decbuffer) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return false;
+        int val = 0;
+        for (int i = 0; i < srcsize; i++) {
+            val = ulaw2linear(src[i + start] & 0xFF);
+            decbuffer[2 * i + 1] = (byte)(val >> 8);
+            decbuffer[2 * i] = (byte)(val << 24 >> 24);
+        }
+        return true;
+    }
+
+    public static short[] decodeALaw(byte[] src, int start, int srcsize) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return null;
+        short[] decbuffer = new short[srcsize];
+        for (int i = 0; i < srcsize; i++)
+            decbuffer[i] = (short)alaw2linear(src[i + start] & 0xFF);
+        return decbuffer;
+    }
+
+    public static byte[] decodeALawExt(byte[] src, int start, int srcsize) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return null;
+        byte[] decbuffer = new byte[srcsize * 2];
+        int val = 0;
+        for (int i = 0; i < srcsize; i++) {
+            val = alaw2linear(src[i + start] & 0xFF);
+            decbuffer[2 * i + 1] = (byte)(val >> 8);
+            decbuffer[2 * i] = (byte)(val << 24 >> 24);
+        }
+        return decbuffer;
+    }
+
+    public static boolean decodeALawExt(byte[] src, int start, int srcsize, byte[] decbuffer) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return false;
+        int val = 0;
+        for (int i = 0; i < srcsize; i++) {
+            val = alaw2linear(src[i + start] & 0xFF);
+            decbuffer[2 * i + 1] = (byte)(val >> 8);
+            decbuffer[2 * i] = (byte)(val << 24 >> 24);
+        }
+        return true;
+    }
+
+    public static boolean mixPCMLinear(byte[] src1, byte[] src2, int srcsize, byte[] dest) {
+        if (srcsize <= 0 || src1 == null || src1.length < srcsize ||
+                src2 == null || src2.length < srcsize)
+            return false;
+        int encsize = srcsize / 2;
+        int val = 0;
+        int val_ = 0;
+        int val_final = 0;
+        for (int i = 0; i < encsize; i++) {
+            val = src1[2 * i + 1];
+            val_ = src1[2 * i];
+            val = val << 8 & 0xFFFFFF00;
+            val_ &= 0xFF;
+            val |= val_;
+            val_final = val;
+            val = 0;
+            val_ = 0;
+            val = src2[2 * i + 1];
+            val_ = src2[2 * i];
+            val = val << 8 & 0xFFFFFF00;
+            val_ &= 0xFF;
+            val |= val_;
+            val_final = (int)((val + val_final) / 2.0F);
+            dest[2 * i + 1] = (byte)(val_final >> 8);
+            dest[2 * i] = (byte)(val_final << 24 >> 24);
+        }
+        return true;
+    }
+
+    public static boolean amplitudePCMLinear(byte[] src, int srcsize, int rate) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return false;
+        int encsize = srcsize / 2;
+        int val = 0;
+        int val_ = 0;
+        int val_final = 0;
+        for (int i = 0; i < encsize; i++) {
+            val = src[2 * i + 1];
+            val_ = src[2 * i];
+            val = val << 8 & 0xFFFFFF00;
+            val_ &= 0xFF;
+            val |= val_;
+            val_final = val / 10 * rate;
+            src[2 * i + 1] = (byte)(val_final >> 8);
+            src[2 * i] = (byte)(val_final << 24 >> 24);
+        }
+        return true;
+    }
+
+    public static boolean getPCMLinearComportableNoise(byte[] src, int srcsize) {
+        if (srcsize <= 0 || src == null || src.length < srcsize)
+            return false;
+        int encsize = srcsize / 2;
+        int val_final = 0;
+        int val = 0;
+        for (int i = 0; i < encsize; i++) {
+            val = 1;
+            val_final = Math.abs(val) % 10;
+            if (i % 2 == 1)
+                val_final *= -1;
+            src[2 * i + 1] = (byte)(val_final >> 8);
+            src[2 * i] = (byte)(val_final << 24 >> 24);
+        }
+        return true;
+    }
+}

+ 225 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPHeader.java

@@ -0,0 +1,225 @@
+package bssoft.stack.sip;
+
+import java.util.StringTokenizer;
+
+public class SIPHeader {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public int headerType = SIPStack.SIP_HEADERTYPE_NONE;
+
+    public boolean flag = false;
+
+    public SIPHeader(String message, int headerType) {
+        String compactKeyWord = null;
+        if (message != null) {
+            String keyWord;
+            if (headerType == SIPStack.SIP_HEADERTYPE_ACCEPT) {
+                keyWord = "Accept: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ACCEPTENCODING) {
+                keyWord = "Accept-Encoding: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ACCEPTLANGUAGE) {
+                keyWord = "Accept-Language: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ALERTINFO) {
+                keyWord = "Alert-Info: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ALLOW) {
+                keyWord = "Allow: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ALLOWEVENTS) {
+                keyWord = "Allow-Events: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_AUTHENTICATIONINFO) {
+                keyWord = "Authentication-Info: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_AUTHORIZATION) {
+                keyWord = "Authorization: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CALLID) {
+                keyWord = "Call-ID: ";
+                compactKeyWord = "i: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CALLINFO) {
+                keyWord = "Call-Info: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTACT) {
+                keyWord = "Contact: ";
+                compactKeyWord = "m: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTENTDISPOSITION) {
+                keyWord = "Content-Disposition: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTENTENCODING) {
+                keyWord = "Content-Encoding: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTENTLANGUAGE) {
+                keyWord = "Content-Language: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTENTLENGTH) {
+                keyWord = "Content-Length: ";
+                compactKeyWord = "l: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CONTENTTYPE) {
+                keyWord = "Content-Type: ";
+                compactKeyWord = "c: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_CSEQ) {
+                keyWord = "CSeq: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_DATE) {
+                keyWord = "Date: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_EVENT) {
+                keyWord = "Event: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ERRORINFO) {
+                keyWord = "Error-Info: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_EXPIRES) {
+                keyWord = "Expires: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_FROM) {
+                keyWord = "From: ";
+                compactKeyWord = "f: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_INREPLYTO) {
+                keyWord = "In-Reply-To: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_MAXFORWARDS) {
+                keyWord = "Max-Forwards: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_MINEXPIRES) {
+                keyWord = "Min-Expires: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_MIMEVERSION) {
+                keyWord = "MIME-Version: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ORGANIZATION) {
+                keyWord = "Organization: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PRIORITY) {
+                keyWord = "Priority: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PROXYAUTHENTICATE) {
+                keyWord = "Proxy-Authenticate: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PROXYAUTHORIZATION) {
+                keyWord = "Proxy-Authorization: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PROXYREQUIRE) {
+                keyWord = "Proxy-Require: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_PASSERTEDIDENTITY) {
+                keyWord = "P-Asserted-Identity: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_RECORDROUTE) {
+                keyWord = "Record-Route: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_REPLYTO) {
+                keyWord = "Reply-To: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_REQUIRE) {
+                keyWord = "Require: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_RETRYAFTER) {
+                keyWord = "Retry-After: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_ROUTE) {
+                keyWord = "Route: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_SERVER) {
+                keyWord = "Server: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_SUBJECT) {
+                keyWord = "Subject: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_SUPPORTED) {
+                keyWord = "Supported: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_TIMESTAMP) {
+                keyWord = "Timestamp: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_TO) {
+                keyWord = "To: ";
+                compactKeyWord = "t: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_UNSUPPORTED) {
+                keyWord = "Unsupported: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_USERAGENT) {
+                keyWord = "User-Agent: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_VIA) {
+                keyWord = "Via: ";
+                compactKeyWord = "v: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_WARNING) {
+                keyWord = "Warning: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_WWWAUTHENTICATE) {
+                keyWord = "WWW-Authenticate: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_WwwAUTHENTICATE) {
+                keyWord = "Www-Authenticate: ";
+            } else {
+                keyWord = null;
+            }
+            if (keyWord != null) {
+                int iS = message.indexOf(keyWord);
+                int iE = 0;
+                if (iS >= 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                    if (iE > 0) {
+                        this.header = message.substring(iS, iE);
+                        this.headerValue = message.substring(iS + keyWord.length(), iE);
+                        this.headerType = headerType;
+                        this.flag = true;
+                    }
+                } else {
+                    this.flag = false;
+                }
+            }
+            if (!this.flag && compactKeyWord != null) {
+                int iS = message.indexOf(compactKeyWord);
+                int iE = 0;
+                if (iS >= 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                    if (iE > 0) {
+                        this.header = message.substring(iS, iE);
+                        this.headerValue = message.substring(iS + compactKeyWord.length(), iE);
+                        this.headerType = headerType;
+                        this.flag = true;
+                    }
+                } else {
+                    this.flag = false;
+                }
+            }
+        }
+    }
+
+    public int callSequenceNumber() {
+        int seqCode = 0;
+        if (this.headerType == SIPStack.SIP_HEADERTYPE_CSEQ && this.header != null && this.header.length() > 0) {
+            StringTokenizer tokenArray = new StringTokenizer(this.header, " ", true);
+            int tokenCount = 0;
+            while (tokenArray.hasMoreTokens()) {
+                String token = tokenArray.nextToken();
+                if (token.length() > 0 && token.compareTo(" ") != 0) {
+                    tokenCount++;
+                    if (tokenCount == 2) {
+                        seqCode = Integer.parseInt(token);
+                        break;
+                    }
+                }
+            }
+        }
+        return seqCode;
+    }
+
+    public String getTag() {
+        String tag = null;
+        if ((this.headerType == SIPStack.SIP_HEADERTYPE_FROM || this.headerType == SIPStack.SIP_HEADERTYPE_TO) &&
+                this.header != null && this.header.length() > 0) {
+            StringTokenizer tokenArray = new StringTokenizer(this.header, ";", true);
+            while (tokenArray.hasMoreTokens()) {
+                String token = tokenArray.nextToken();
+                if (token.length() > 0 && token.startsWith("tag=")) {
+                    tag = token.substring(4);
+                    break;
+                }
+            }
+        }
+        return tag;
+    }
+
+    public String getId() {
+        String id = "";
+        if ((this.headerType == SIPStack.SIP_HEADERTYPE_FROM || this.headerType == SIPStack.SIP_HEADERTYPE_TO) &&
+                this.header != null && this.header.length() > 0) {
+            int iS = 0;
+            int iE = 0;
+            iS = this.header.indexOf("sip:");
+            if (iS > 0) {
+                iE = this.header.indexOf("@", iS);
+                if (iE > 0)
+                    id = this.header.substring(iS + 4, iE).trim();
+            }
+        }
+        return id;
+    }
+
+    public String getFieldValue(String fieldName) {
+        if (this.headerValue == null || this.headerValue.length() <= 0)
+            return null;
+        if (fieldName == null || fieldName.length() <= 0)
+            return null;
+        StringTokenizer tokenArray = new StringTokenizer(this.headerValue, ";><", true);
+        String keyWord = String.valueOf(fieldName) + "=";
+        String fieldValue = null;
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken().trim();
+            if (token.length() > 0 && token.startsWith(keyWord)) {
+                fieldValue = token.substring(keyWord.length());
+                break;
+            }
+        }
+        return fieldValue;
+    }
+}

+ 268 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPHeaderParty.java

@@ -0,0 +1,268 @@
+package bssoft.stack.sip;
+
+public class SIPHeaderParty {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public String display = null;
+
+    public String username = null;
+
+    public String sipuri = null;
+
+    public String uriusertag = null;
+
+    public String ip = null;
+
+    public int port = 0;
+
+    public String tag = null;
+
+    public int headerType = SIPStack.SIP_HEADERTYPE_NONE;
+
+    public boolean flag = false;
+
+    public SIPHeaderParty(String message, int headerType) {
+        String compactKeyWord = null;
+        if (message != null) {
+            String keyWord;
+            if (headerType == SIPStack.SIP_HEADERTYPE_FROM) {
+                keyWord = "From: ";
+                compactKeyWord = "f: ";
+            } else if (headerType == SIPStack.SIP_HEADERTYPE_TO) {
+                keyWord = "To: ";
+                compactKeyWord = "t: ";
+            } else {
+                keyWord = null;
+            }
+            if (keyWord != null) {
+                int iS = message.indexOf(keyWord);
+                int iE = 0;
+                if (iS >= 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                    if (iE > 0) {
+                        this.header = message.substring(iS, iE);
+                        this.headerValue = message.substring(iS + keyWord.length(), iE);
+                        this.headerType = headerType;
+                        iE = this.headerValue.indexOf("<sip:");
+                        if (iE > 0) {
+                            String str = null;
+                            str = this.headerValue.substring(0, iE).trim();
+                            if (str != null && str.length() > 1 &&
+                                    str.startsWith("\"") &&
+                                    str.endsWith("\"")) {
+                                this.display = str.substring(1, str.length() - 1);
+                            } else if (str != null && str.length() > 0) {
+                                this.display = str;
+                            }
+                        }
+                        iS = this.headerValue.indexOf("sip:");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(">", iS + 4);
+                            if (iE < 0)
+                                iE = this.headerValue.indexOf(";", iS + 4);
+                            if (iE > 0) {
+                                str = this.headerValue.substring(iS, iE);
+                            } else {
+                                str = this.headerValue.substring(iS);
+                            }
+                            if (str != null && str.length() > 0)
+                                this.sipuri = str.trim();
+                        }
+                        if (this.sipuri != null && this.sipuri.length() > 0) {
+                            iS = this.sipuri.indexOf("@", 4);
+                            if (iS > 0)
+                                this.username = this.sipuri.substring(4, iS).trim();
+                        }
+                        if (this.sipuri != null && this.sipuri.length() > 0) {
+                            iS = this.sipuri.indexOf("@", 4);
+                            String str = null;
+                            if (iS >= 0) {
+                                str = this.sipuri.substring(iS + 1).trim();
+                            } else {
+                                str = this.sipuri.substring(4).trim();
+                            }
+                            this.port = 5060;
+                            if (str != null && str.length() > 0) {
+                                iS = str.indexOf(":");
+                                if (iS > 0) {
+                                    this.port = Integer.parseInt(str.substring(iS + 1).trim());
+                                    this.ip = str.substring(0, iS);
+                                } else {
+                                    this.ip = str;
+                                }
+                            }
+                        }
+                        iS = this.headerValue.indexOf(";tag=");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(";", iS + 5);
+                            if (iE >= 0) {
+                                if (iE > iS + 5) {
+                                    str = this.headerValue.substring(iS + 5, iE);
+                                } else {
+                                    str = "";
+                                }
+                            } else {
+                                str = this.headerValue.substring(iS + 5);
+                            }
+                            if (str != null && str.length() > 0)
+                                this.tag = str.trim();
+                        } else {
+                            this.tag = "";
+                        }
+                        iS = this.headerValue.indexOf("sip:");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(">", iS + 4);
+                            if (iE > 0)
+                                str = this.headerValue.substring(iS, iE);
+                            if (str != null && str.length() > 0) {
+                                iS = str.indexOf(";user=", iS + 4);
+                                if (iS > 0) {
+                                    this.uriusertag = str.substring(iS + 6);
+                                    if (this.uriusertag != null && this.uriusertag.length() > 0 && this.uriusertag.indexOf(";") >= 0)
+                                        if (this.uriusertag.indexOf(";") == 0) {
+                                            this.uriusertag = null;
+                                        } else {
+                                            this.uriusertag = this.uriusertag.substring(0, this.uriusertag.indexOf(";")).trim();
+                                        }
+                                }
+                            }
+                        }
+                        this.flag = true;
+                    }
+                }
+            } else if (compactKeyWord != null) {
+                int iS = message.indexOf(compactKeyWord);
+                int iE = 0;
+                if (iS >= 0) {
+                    iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                    if (iE > 0) {
+                        this.header = message.substring(iS, iE);
+                        this.headerValue = message.substring(iS + compactKeyWord.length(), iE);
+                        this.headerType = headerType;
+                        iE = this.headerValue.indexOf("<sip:");
+                        if (iE > 0) {
+                            String str = null;
+                            str = this.headerValue.substring(0, iE).trim();
+                            if (str != null && str.length() > 1 &&
+                                    str.startsWith("\"") &&
+                                    str.endsWith("\"")) {
+                                this.display = str.substring(1, str.length() - 1);
+                            } else if (str != null && str.length() > 0) {
+                                this.display = str;
+                            }
+                        }
+                        iS = this.headerValue.indexOf("sip:");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(">", iS + 4);
+                            if (iE < 0)
+                                iE = this.headerValue.indexOf(";", iS + 4);
+                            if (iE > 0) {
+                                str = this.headerValue.substring(iS, iE);
+                            } else {
+                                str = this.headerValue.substring(iS);
+                            }
+                            if (str != null && str.length() > 0)
+                                this.sipuri = str.trim();
+                        }
+                        if (this.sipuri != null && this.sipuri.length() > 0) {
+                            iS = this.sipuri.indexOf("@", 4);
+                            if (iS > 0)
+                                this.username = this.sipuri.substring(4, iS).trim();
+                        }
+                        if (this.sipuri != null && this.sipuri.length() > 0) {
+                            iS = this.sipuri.indexOf("@", 4);
+                            String str = null;
+                            if (iS >= 0) {
+                                str = this.sipuri.substring(iS + 1).trim();
+                            } else {
+                                str = this.sipuri.substring(4).trim();
+                            }
+                            this.port = 5060;
+                            if (str != null && str.length() > 0) {
+                                iS = str.indexOf(":");
+                                if (iS > 0) {
+                                    this.port = Integer.parseInt(str.substring(iS + 1).trim());
+                                    this.ip = str.substring(0, iS);
+                                } else {
+                                    this.ip = str;
+                                }
+                            }
+                        }
+                        iS = this.headerValue.indexOf(";tag=");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(";", iS + 5);
+                            if (iE >= 0) {
+                                if (iE > iS + 5) {
+                                    str = this.headerValue.substring(iS + 5, iE);
+                                } else {
+                                    str = "";
+                                }
+                            } else {
+                                str = this.headerValue.substring(iS + 5);
+                            }
+                            if (str != null && str.length() > 0)
+                                this.tag = str.trim();
+                        } else {
+                            this.tag = "";
+                        }
+                        iS = this.headerValue.indexOf("sip:");
+                        if (iS > 0) {
+                            String str = null;
+                            iE = this.headerValue.indexOf(">", iS + 4);
+                            if (iE > 0)
+                                str = this.headerValue.substring(iS, iE);
+                            if (str != null && str.length() > 0) {
+                                iS = str.indexOf(";user=", iS + 4);
+                                if (iS > 0) {
+                                    this.uriusertag = str.substring(iS + 6);
+                                    if (this.uriusertag != null && this.uriusertag.length() > 0 && this.uriusertag.indexOf(";") >= 0)
+                                        if (this.uriusertag.indexOf(";") == 0) {
+                                            this.uriusertag = null;
+                                        } else {
+                                            this.uriusertag = this.uriusertag.substring(0, this.uriusertag.indexOf(";")).trim();
+                                        }
+                                }
+                            }
+                        }
+                        this.flag = true;
+                    }
+                }
+            }
+        }
+    }
+
+    public String getDisplay() {
+        return this.display;
+    }
+
+    public String getUsername() {
+        return this.username;
+    }
+
+    public String getSipuri() {
+        return this.sipuri;
+    }
+
+    public String getSipuriusertag() {
+        return this.uriusertag;
+    }
+
+    public String getIp() {
+        return this.ip;
+    }
+
+    public int getPort() {
+        return this.port;
+    }
+
+    public String getTag() {
+        return this.tag;
+    }
+}

+ 135 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPROUTEHeader.java

@@ -0,0 +1,135 @@
+package bssoft.stack.sip;
+
+public class SIPROUTEHeader {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public String username = null;
+
+    public String sipuri = null;
+
+    public String uriusertag = null;
+
+    public String ip = null;
+
+    public int port = 0;
+
+    public String tag = null;
+
+    public boolean flag = false;
+
+    public SIPROUTEHeader(String header) {
+        int iS = 0;
+        int iE = 0;
+        if (header != null && header.length() > 0 && header.startsWith("Route: ")) {
+            this.header = header;
+            this.headerValue = header.substring(7).trim();
+            if (this.headerValue != null && this.headerValue.length() > 0) {
+                iS = this.headerValue.indexOf("sip:");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(">", iS + 4);
+                    if (iE < 0)
+                        iE = this.headerValue.indexOf(";", iS + 4);
+                    if (iE > 0) {
+                        str = this.headerValue.substring(iS, iE);
+                    } else {
+                        str = this.headerValue.substring(iS);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.sipuri = str.trim();
+                }
+                if (this.sipuri != null && this.sipuri.length() > 0) {
+                    iS = this.sipuri.indexOf("@", 4);
+                    if (iS > 0)
+                        this.username = this.sipuri.substring(4, iS).trim();
+                }
+                if (this.sipuri != null && this.sipuri.length() > 0) {
+                    iS = this.sipuri.indexOf("@", 4);
+                    iE = this.sipuri.indexOf(";", 4);
+                    String str = null;
+                    if (iS >= 0 && iE >= 0) {
+                        str = this.sipuri.substring(iS + 1, iE).trim();
+                    } else if (iS >= 0) {
+                        str = this.sipuri.substring(iS + 1).trim();
+                    } else if (iE >= 0) {
+                        str = this.sipuri.substring(4, iE).trim();
+                    } else {
+                        str = this.sipuri.substring(4).trim();
+                    }
+                    this.port = 5060;
+                    if (str != null && str.length() > 0) {
+                        iS = str.indexOf(":");
+                        if (iS > 0) {
+                            this.port = Integer.parseInt(str.substring(iS + 1).trim());
+                            this.ip = str.substring(0, iS);
+                        } else {
+                            this.ip = str;
+                        }
+                    }
+                }
+                iS = this.headerValue.indexOf(";tag=");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(";", iS + 5);
+                    if (iE >= 0) {
+                        if (iE > iS + 5) {
+                            str = this.headerValue.substring(iS + 5, iE);
+                        } else {
+                            str = "";
+                        }
+                    } else {
+                        str = this.headerValue.substring(iS + 5);
+                    }
+                    if (str != null && str.length() > 0)
+                        this.tag = str.trim();
+                }
+                iS = this.headerValue.indexOf("sip:");
+                if (iS > 0) {
+                    String str = null;
+                    iE = this.headerValue.indexOf(">", iS + 4);
+                    if (iE > 0)
+                        str = this.headerValue.substring(iS, iE);
+                    if (str != null && str.length() > 0) {
+                        iS = str.indexOf(";user=", iS + 4);
+                        if (iS > 0) {
+                            this.uriusertag = str.substring(iS + 6);
+                            if (this.uriusertag != null && this.uriusertag.length() > 0 && this.uriusertag.indexOf(";") >= 0)
+                                if (this.uriusertag.indexOf(";") == 0) {
+                                    this.uriusertag = null;
+                                } else {
+                                    this.uriusertag = this.uriusertag.substring(0, this.uriusertag.indexOf(";")).trim();
+                                }
+                        }
+                    }
+                }
+                this.flag = true;
+            }
+        }
+    }
+
+    public String getUsername() {
+        return this.username;
+    }
+
+    public String getSipuri() {
+        return this.sipuri;
+    }
+
+    public String getSipuriusertag() {
+        return this.uriusertag;
+    }
+
+    public String getIp() {
+        return this.ip;
+    }
+
+    public int getPort() {
+        return this.port;
+    }
+
+    public String getTag() {
+        return this.tag;
+    }
+}

+ 204 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPRequestLine.java

@@ -0,0 +1,204 @@
+package bssoft.stack.sip;
+
+import android.util.Log;
+
+import java.util.StringTokenizer;
+
+public class SIPRequestLine {
+    public String header = null;
+
+    public int iMethodType = SIPStack.SIP_METHODTYPE_NONE;
+
+    public String uri = null;
+
+    public int version = 2;
+
+    public int revision = 0;
+
+    public int code = 0;
+
+    public int iMessageType = SIPStack.SIP_MSGTYPE_NONE;
+
+    public boolean flag = false;
+
+    public SIPRequestLine(String message) {
+        if (message != null) {
+            StringTokenizer st = new StringTokenizer(message, "\n", true);
+            int headerCount = 0;
+            while (st.hasMoreTokens()) {
+                this.header = st.nextToken();
+                if (this.header.length() > 1) {
+                    if (headerCount == 0 && this.header.startsWith("INVITE") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_INVITE;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("BYE") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_BYE;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("ACK") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_ACK;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("CANCEL") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_CANCEL;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("OPTIONS") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_OPTIONS;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("INFO") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_INFO;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("PRACK") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_PRACK;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("MESSAGE") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_MESSAGE;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("SUBSCRIBE") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_SUBSCRIBE;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("REFER") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_REFER;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("NOTIFY") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_NOTIFY;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("PUBLISH") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_PUBLISH;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("REGISTER") && this.header.endsWith("SIP/2.0\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_REGISTER;
+                        this.flag = true;
+                        break;
+                    }
+                    if (headerCount == 0 && this.header.startsWith("SIP/2.0") && this.header.endsWith("\r")) {
+                        this.iMessageType = SIPStack.SIP_MSGTYPE_RESPONSE;
+                        this.iMethodType = SIPStack.SIP_METHODTYPE_NONE;
+                        StringTokenizer tokenArray = new StringTokenizer(this.header, " ", true);
+                        int tokenCount = 0;
+                        //Log.e("INVITEParser", "[INVITEParser] ============ token ============ " + this.header);
+                        String[] strSplit = this.header.split(" ");
+                        this.code = Integer.parseInt(strSplit[1]);
+                        while (tokenArray.hasMoreTokens()) {
+                            String token = tokenArray.nextToken();
+                            //Log.e("INVITEParser", "[INVITEParser] ============ token ============ " + token);
+                            tokenCount++;
+                            if (token.compareTo(" ") != 0 && tokenCount == 2)
+                            //if (tokenCount == 2)
+                                this.code = Integer.parseInt(token);
+                        }
+                        //Log.e("INVITEParser", "[INVITEParser] ============ token  this.code ============ " + this.code);
+                        int iS = message.indexOf("CSeq: ");
+                        int iE = 0;
+                        if (iS >= 0) {
+                            iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                            if (iE <= 0)
+                                break;
+                            String strCSEQ = message.substring(iS, iE);
+                            tokenArray = new StringTokenizer(strCSEQ, " ", true);
+                            tokenCount = 0;
+                            while (tokenArray.hasMoreTokens()) {
+                                String token = tokenArray.nextToken();
+                                if (token.length() > 0 && token.compareTo(" ") != 0) {
+                                    tokenCount++;
+                                    if (tokenCount == 3) {
+                                        if (token.compareTo("REGISTER") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_REGISTER;
+                                        } else if (token.compareTo("INVITE") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_INVITE;
+                                        } else if (token.compareTo("CANCEL") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_CANCEL;
+                                        } else if (token.compareTo("BYE") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_BYE;
+                                        } else if (token.compareTo("INFO") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_INFO;
+                                        } else if (token.compareTo("OPTIONS") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_OPTIONS;
+                                        } else if (token.compareTo("ACK") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_ACK;
+                                        } else if (token.compareTo("REFER") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_REFER;
+                                        } else if (token.compareTo("NOTIFY") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_NOTIFY;
+                                        } else if (token.compareTo("PUBLISH") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_PUBLISH;
+                                        } else if (token.compareTo("MESSAGE") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_MESSAGE;
+                                        } else if (token.compareTo("SUBSCRIBE") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_SUBSCRIBE;
+                                        } else if (token.compareTo("PRACK") == 0) {
+                                            this.iMethodType = SIPStack.SIP_METHODTYPE_PRACK;
+                                        }
+                                        if (this.iMethodType != SIPStack.SIP_METHODTYPE_NONE)
+                                            this.flag = true;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            if (this.flag && this.iMessageType == SIPStack.SIP_MSGTYPE_REQUEST && this.header != null) {
+                StringTokenizer tokenArray = new StringTokenizer(this.header, " ", true);
+                int tokenCount = 0;
+                while (tokenArray.hasMoreTokens()) {
+                    String token = tokenArray.nextToken();
+                    if (token.compareTo(" ") == 0)
+                        continue;
+                    tokenCount++;
+                    if (tokenCount == 2)
+                        this.uri = token;
+                }
+            }
+        }
+        //print();
+    }
+
+    public void print() {
+        System.out.println("=====================================================");
+        System.out.println("HEADER:");
+        System.out.println(this.header);
+        System.out.println(".....................................................");
+        System.out.println("flag\t\t:" + this.flag);
+        System.out.println("iMethodType\t:" + this.iMethodType);
+        System.out.println("uri\t\t\t:" + this.uri);
+        System.out.println("code\t\t:" + this.code);
+        System.out.println("version\t\t:" + this.version);
+        System.out.println("revision\t:" + this.revision);
+        System.out.println("iMessageType:" + this.iMessageType);
+        System.out.println("=====================================================");
+    }
+}

+ 248 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPSdp.java

@@ -0,0 +1,248 @@
+package bssoft.stack.sip;
+
+import java.util.Date;
+
+public class SIPSdp {
+    public String vH = null;
+
+    public String oH = null;
+
+    public String sH = null;
+
+    public String cH = null;
+
+    public String tH = null;
+
+    public SDPMedia audioM = null;
+
+    public SDPMedia videoM = null;
+
+    public String body = null;
+
+    public String dn = null;
+
+    public String platformIp = null;
+
+    public String audioDescription = null;
+
+    public String videoDescription = null;
+
+    public boolean flag;
+
+    public SIPSdp(String dn, String localIp) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        this.dn = dn;
+        this.platformIp = localIp;
+        long ltime = (new Date()).getTime();
+        this.vH = "v=0" + SIPStack.SIP_LINE_END;
+        this.oH = "o=" + dn + " " + ltime + " " + (ltime + 1L) + " IN IP4 " + this.platformIp + SIPStack.SIP_LINE_END;
+        this.sH = "s=Smart Android call" + SIPStack.SIP_LINE_END;
+        this.cH = "c=IN IP4 " + this.platformIp + SIPStack.SIP_LINE_END;
+        this.tH = "t=0 0" + SIPStack.SIP_LINE_END;
+        this.audioDescription = "";
+        this.videoDescription = "";
+        this.flag = true;
+    }
+
+    public SIPSdp(String dn, String localIp, String localSdpIp) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        this.dn = dn;
+        this.platformIp = localIp;
+        long ltime = (new Date()).getTime();
+        this.vH = "v=0" + SIPStack.SIP_LINE_END;
+        this.oH = "o=" + dn + " " + ltime + " " + (ltime + 1L) + " IN IP4 " + localSdpIp + SIPStack.SIP_LINE_END;
+        this.sH = "s=Smart Android call" + SIPStack.SIP_LINE_END;
+        this.cH = "c=IN IP4 " + localSdpIp + SIPStack.SIP_LINE_END;
+        this.tH = "t=0 0" + SIPStack.SIP_LINE_END;
+        this.audioDescription = "";
+        this.videoDescription = "";
+        this.flag = true;
+    }
+
+    public SIPSdp(String body) {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    //System.exit(0);
+        }
+        if (body != null && body.length() > 0) {
+            this.body = body;
+            int iS = 0;
+            int iE = 0;
+            iS = body.indexOf("v=");
+            if (iS >= 0)
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+            if (iS >= 0 && iE > iS)
+                this.vH = body.substring(iS, iE + 2);
+            iS = 0;
+            iE = 0;
+            iS = body.indexOf("o=");
+            if (iS >= 0)
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+            if (iS >= 0 && iE > iS)
+                this.oH = body.substring(iS, iE + 2);
+            iS = 0;
+            iE = 0;
+            iS = body.indexOf("s=");
+            if (iS >= 0)
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+            if (iS >= 0 && iE > iS)
+                this.sH = body.substring(iS, iE + 2);
+            iS = 0;
+            iE = 0;
+            iS = body.indexOf("c=");
+            if (iS >= 0)
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+            if (iS >= 0 && iE > iS)
+                this.cH = body.substring(iS, iE + 2);
+            iS = 0;
+            iE = 0;
+            iS = body.indexOf("t=");
+            if (iS >= 0)
+                iE = body.indexOf(SIPStack.SIP_LINE_END, iS);
+            if (iS >= 0 && iE > iS)
+                this.tH = body.substring(iS, iE + 2);
+            if (this.vH != null && this.vH.length() > 0 &&
+                    this.oH != null && this.oH.length() > 0 &&
+                    this.tH != null && this.tH.length() > 0) {
+                this.platformIp = "0.0.0.0";
+                if (this.cH != null && this.cH.length() > 0 && this.cH.startsWith("c=IN IP4 ")) {
+                    iE = this.cH.indexOf(SIPStack.SIP_LINE_END);
+                    this.platformIp = this.cH.substring("c=IN IP4 ".length(), iE);
+                }
+                iS = body.indexOf("m=audio ");
+                if (iS > 0) {
+                    iE = body.indexOf("m=", iS + 8);
+                    if (iE > 0 && iE > iS) {
+                        this.audioM = new SDPMedia(body.substring(iS, iE), this.platformIp);
+                    } else if (iE < 0) {
+                        this.audioM = new SDPMedia(body.substring(iS), this.platformIp);
+                    }
+                }
+                iS = body.indexOf("m=video ");
+                if (iS > 0) {
+                    iE = body.indexOf("m=", iS + 8);
+                    if (iE > 0 && iE > iS) {
+                        this.videoM = new SDPMedia(body.substring(iS, iE), this.platformIp);
+                    } else if (iE < 0) {
+                        this.videoM = new SDPMedia(body.substring(iS), this.platformIp);
+                    }
+                }
+            }
+            this.flag = true;
+        }
+    }
+
+    public boolean setMediaPort(int mediaType, int port) {
+        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            if (this.audioM == null) {
+                this.audioM = new SDPMedia(mediaType);
+                if (this.audioM != null && this.audioM.flag)
+                    return this.audioM.setMediaAddress(this.platformIp, port);
+            }
+        } else if (mediaType == SIPStack.SIP_MEDIATYPE_VIDEO) {
+            if (this.videoM == null) {
+                this.videoM = new SDPMedia(mediaType);
+                if (this.videoM != null && this.videoM.flag)
+                    return this.videoM.setMediaAddress(this.platformIp, port);
+            }
+        }
+        return false;
+    }
+
+    public boolean setCodec(int mediaType, int codec) {
+        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            if (this.audioM != null && this.audioM.flag)
+                return this.audioM.setCodec(codec);
+        } else if (mediaType == SIPStack.SIP_MEDIATYPE_VIDEO) {
+            if (this.videoM != null && this.videoM.flag)
+                return this.videoM.setCodec(codec);
+        }
+        return false;
+    }
+
+    public boolean setCodec(int mediaType, int codec, String describe) {
+        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            if (this.audioM != null && this.audioM.flag)
+                return this.audioM.setCodec(codec, describe);
+        } else if (mediaType == SIPStack.SIP_MEDIATYPE_VIDEO) {
+            if (this.videoM != null && this.videoM.flag)
+                return this.videoM.setCodec(codec, describe);
+        }
+        return false;
+    }
+
+    public boolean setFmtpDescribe(int mediaType, int codec, String describe) {
+        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
+            if (this.audioM != null && this.audioM.flag)
+                return this.audioM.setFmtpDescribe(codec, describe);
+        } else if (mediaType == SIPStack.SIP_MEDIATYPE_VIDEO) {
+            if (this.videoM != null && this.videoM.flag)
+                return this.videoM.setFmtpDescribe(codec, describe);
+        }
+        return false;
+    }
+
+    public void resetSdp() {
+        this.flag = false;
+    }
+
+    public String getBodyString() {
+        this.audioDescription = "";
+        this.videoDescription = "";
+        if (!this.flag)
+            return null;
+        if (this.audioM != null && this.audioM.flag) {
+            this.audioDescription = this.audioM.getMediaString();
+            if (this.audioDescription == null)
+                this.audioDescription = "";
+        }
+        if (this.videoM != null && this.videoM.flag) {
+            this.videoDescription = this.videoM.getMediaString();
+            if (this.videoDescription == null)
+                this.videoDescription = "";
+        }
+        this.body = String.valueOf(this.vH) +
+                this.oH +
+                this.sH +
+                this.cH +
+                this.tH +
+                this.audioDescription +
+                this.videoDescription;
+        return this.body;
+    }
+
+    public String getFinalBodyString() {
+        this.audioDescription = "";
+        this.videoDescription = "";
+        if (!this.flag)
+            return null;
+        if (this.audioM != null && this.audioM.flag) {
+            this.audioDescription = this.audioM.getFinalMediaString();
+            if (this.audioDescription == null)
+                this.audioDescription = "";
+        }
+        if (this.videoM != null && this.videoM.flag) {
+            this.videoDescription = this.videoM.getFinalMediaString();
+            if (this.videoDescription == null)
+                this.videoDescription = "";
+        }
+        this.body = String.valueOf(this.vH) +
+                this.oH +
+                this.sH +
+                this.cH +
+                this.tH +
+                this.audioDescription +
+                this.videoDescription;
+        return this.body;
+    }
+
+    public boolean update(String body) {
+        return true;
+    }
+}

+ 785 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPStack.java

@@ -0,0 +1,785 @@
+package bssoft.stack.sip;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+public class SIPStack {
+    public static int SIP_LOCAL_PORT = 5060;
+
+    public static int SIP_SIGNAL_PORT = 5060;
+
+    public static int MAX_SIGNAL_PORTS = 100;
+
+    public static int SIP_METHODTYPE_NONE = 0;
+
+    public static int SIP_METHODTYPE_REGISTER = 1;
+
+    public static int SIP_METHODTYPE_INVITE = 2;
+
+    public static int SIP_METHODTYPE_CANCEL = 3;
+
+    public static int SIP_METHODTYPE_BYE = 4;
+
+    public static int SIP_METHODTYPE_INFO = 5;
+
+    public static int SIP_METHODTYPE_OPTIONS = 6;
+
+    public static int SIP_METHODTYPE_ACK = 7;
+
+    public static int SIP_METHODTYPE_REFER = 8;
+
+    public static int SIP_METHODTYPE_NOTIFY = 9;
+
+    public static int SIP_METHODTYPE_MESSAGE = 10;
+
+    public static int SIP_METHODTYPE_SUBSCRIBE = 11;
+
+    public static int SIP_METHODTYPE_PRACK = 12;
+
+    public static int SIP_METHODTYPE_PUBLISH = 13;
+
+    public static int SIP_METHODTYPE_RESPONSE = 14;
+
+    public static int SIP_HEADERTYPE_NONE = 0;
+
+    public static int SIP_HEADERTYPE_ACCEPT = 1;
+
+    public static int SIP_HEADERTYPE_ACCEPTENCODING = 2;
+
+    public static int SIP_HEADERTYPE_ACCEPTLANGUAGE = 3;
+
+    public static int SIP_HEADERTYPE_ALERTINFO = 4;
+
+    public static int SIP_HEADERTYPE_ALLOW = 5;
+
+    public static int SIP_HEADERTYPE_ALLOWEVENTS = 6;
+
+    public static int SIP_HEADERTYPE_AUTHENTICATIONINFO = 7;
+
+    public static int SIP_HEADERTYPE_AUTHORIZATION = 8;
+
+    public static int SIP_HEADERTYPE_CALLID = 9;
+
+    public static int SIP_HEADERTYPE_CALLINFO = 10;
+
+    public static int SIP_HEADERTYPE_CONTACT = 11;
+
+    public static int SIP_HEADERTYPE_CONTENTDISPOSITION = 12;
+
+    public static int SIP_HEADERTYPE_CONTENTENCODING = 13;
+
+    public static int SIP_HEADERTYPE_CONTENTLANGUAGE = 14;
+
+    public static int SIP_HEADERTYPE_CONTENTLENGTH = 15;
+
+    public static int SIP_HEADERTYPE_CONTENTTYPE = 16;
+
+    public static int SIP_HEADERTYPE_CSEQ = 17;
+
+    public static int SIP_HEADERTYPE_DATE = 18;
+
+    public static int SIP_HEADERTYPE_EVENT = 19;
+
+    public static int SIP_HEADERTYPE_ERRORINFO = 20;
+
+    public static int SIP_HEADERTYPE_EXPIRES = 21;
+
+    public static int SIP_HEADERTYPE_FROM = 22;
+
+    public static int SIP_HEADERTYPE_INREPLYTO = 23;
+
+    public static int SIP_HEADERTYPE_MAXFORWARDS = 24;
+
+    public static int SIP_HEADERTYPE_MINEXPIRES = 25;
+
+    public static int SIP_HEADERTYPE_MIMEVERSION = 26;
+
+    public static int SIP_HEADERTYPE_ORGANIZATION = 27;
+
+    public static int SIP_HEADERTYPE_PRIORITY = 28;
+
+    public static int SIP_HEADERTYPE_PROXYAUTHENTICATE = 29;
+
+    public static int SIP_HEADERTYPE_PROXYAUTHORIZATION = 30;
+
+    public static int SIP_HEADERTYPE_PROXYREQUIRE = 31;
+
+    public static int SIP_HEADERTYPE_PASSERTEDIDENTITY = 32;
+
+    public static int SIP_HEADERTYPE_RECORDROUTE = 33;
+
+    public static int SIP_HEADERTYPE_REPLYTO = 34;
+
+    public static int SIP_HEADERTYPE_REQUIRE = 35;
+
+    public static int SIP_HEADERTYPE_RETRYAFTER = 36;
+
+    public static int SIP_HEADERTYPE_ROUTE = 37;
+
+    public static int SIP_HEADERTYPE_SERVER = 38;
+
+    public static int SIP_HEADERTYPE_SUBJECT = 39;
+
+    public static int SIP_HEADERTYPE_SUPPORTED = 40;
+
+    public static int SIP_HEADERTYPE_TIMESTAMP = 41;
+
+    public static int SIP_HEADERTYPE_TO = 42;
+
+    public static int SIP_HEADERTYPE_UNSUPPORTED = 43;
+
+    public static int SIP_HEADERTYPE_USERAGENT = 44;
+
+    public static int SIP_HEADERTYPE_VIA = 45;
+
+    public static int SIP_HEADERTYPE_WARNING = 46;
+
+    public static int SIP_HEADERTYPE_WWWAUTHENTICATE = 47;
+
+    public static int SIP_HEADERTYPE_WwwAUTHENTICATE = 48;
+
+    public static String SIP_LINE_END = "\r\n";
+
+    public static String SIP_LINE_DOUBLEEND = "\r\n\r\n";
+
+    public static String SIP_LINE_END_SINGLE = "\n";
+
+    public static String USER_AGENT = "BSSHns release 0100o";
+
+    public static int SIP_MSGTYPE_NONE = 0;
+
+    public static int SIP_MSGTYPE_REQUEST = 1;
+
+    public static int SIP_MSGTYPE_RESPONSE = 2;
+
+    public static int SIP_REGSTATE_IDLE = 0;
+
+    public static int SIP_REGSTATE_REGISTERING = 1;
+
+    public static int SIP_REGSTATE_REGISTERED = 2;
+
+    public static int SIP_REGSTATE_UNREGISTERING = 3;
+
+    public static int SIP_REGSTATE_AUTHORIZING = 4;
+
+    public static int SIP_REGSTATE_UNAUTHORIZED = 5;
+
+    public static int SIP_REGSTATE_UNAVAILABLE = 6;
+
+    public static final int SIP_CALLSTATE_IDLE = 0;
+
+    public static final int SIP_CALLSTATE_INVITING = 1;
+
+    public static final int SIP_CALLSTATE_OFFERRED = 2;
+
+    public static final int SIP_CALLSTATE_PROCEEDING = 3;
+
+    public static final int SIP_CALLSTATE_PROGRESSING = 4;
+
+    public static final int SIP_CALLSTATE_ACCEPTED = 5;
+
+    public static final int SIP_CALLSTATE_REMOTEACCEPTED = 6;
+
+    public static final int SIP_CALLSTATE_CONNECTED = 7;
+
+    public static final int SIP_CALLSTATE_DISCONNECTING = 8;
+
+    public static final int SIP_CALLSTATE_TERMINATING = 9;
+
+    public static final int SIP_CALLSTATE_UNAUTHORIZED = 10;
+
+    public static final int SIP_CALLSTATE_CANCELLING = 11;
+
+    public static final int SIP_CALLSTATE_CANCELLED = 12;
+
+    public static final int SIP_CALLSTATE_RECANCELLING = 13;
+
+    public static final int SIP_CALLSTATE_CANCELREMOTEACCEPTED = 14;
+
+    public static final int SIP_CALLSTATE_REJECTED = 15;
+
+    public static final int SIP_CALLSTATE_REDIRECTED = 16;
+
+    public static final int SIP_CALLSTATE_UPDATING = 20;
+
+    public static final int SIP_CALLSTATE_UPDATEPROCEEDING = 21;
+
+    public static final int SIP_CALLSTATE_UPDATEPROGRESSING = 22;
+
+    public static final int SIP_CALLSTATE_UPDATEOFFERRED = 23;
+
+    public static final int SIP_CALLSTATE_UPDATEACCEPTED = 24;
+
+    public static final int SIP_CALLSTATE_UPDATEREJECTED = 25;
+
+    public static final int SIP_CALLSTATE_UPDATEREMOTEACCEPTED = 26;
+
+    public static final int SIP_CALLSTATE_UPDATEREMOTEREJECTED = 27;
+
+    public static final int SIP_CALLSTATE_UPDATEUNAUTHORIZED = 28;
+
+    public static final int SIP_CALLSTATE_UPDATEREDIRECTED = 29;
+
+    public static int SIP_CALLMODE_NONE = 0;
+
+    public static int SIP_CALLMODE_BASIC = 1;
+
+    public static int SIP_CALLMODE_HOLD = 2;
+
+    public static int SIP_SERVICEMODE_BASIC = 0;
+
+    public static int SIP_SERVICEMODE_CONFERENCE = 1;
+
+    public static int SIP_CALLDIRECTION_NONE = 0;
+
+    public static int SIP_CALLDIRECTION_IN = 1;
+
+    public static int SIP_CALLDIRECTION_OUT = 2;
+
+    public static int SIP_MEDIATYPE_NONE = 0;
+
+    public static int SIP_MEDIATYPE_AUDIO = 1;
+
+    public static int SIP_MEDIATYPE_VIDEO = 2;
+
+    public static int SIP_CODEC_NONE = -1;
+
+    public static int SIP_CODEC_G711U = 0;
+
+    public static int SIP_CODEC_G711A = 8;
+
+    public static int SIP_CODEC_G7231 = 4;
+
+    public static int SIP_CODEC_G729 = 18;
+
+    public static int SIP_CODEC_H263 = 34;
+
+    public static int SIP_CODEC_H264 = 98;
+
+    public static int PRIMARY_CODEC_AUDIO = SIP_CODEC_G711U;
+
+    public static int PRIMARY_CODEC_VIDEO = SIP_CODEC_H263;
+
+    public static int SIP_DTMFINFO_DTMFRELAY = 0;
+
+    public static int SIP_DTMFINFO_DTMF = 1;
+
+    public static int SIP_SEQUENCE_INVITE = 1;
+
+    public static int SIP_SEQUENCE_REGISTER = 1;
+
+    public static int SIP_MEDIA_INITPORT = 3000;
+
+    public static int SIP_MEDIA_PORTS = 5;
+
+    public static int SIP_MEDIAFLOW_NONE = 0;
+
+    public static int SIP_MEDIAFLOW_SENDRECV = 1;
+
+    public static int SIP_MEDIAFLOW_SENDONLY = 2;
+
+    public static int SIP_MEDIAFLOW_RECVONLY = 3;
+
+    public static int RTP_AUDIO_SIZE = 1024;
+
+    public static int RTP_VIDEO_SIZE = 30000;
+
+    public static boolean[] SIP_MEDIA_PORTFLAG = new boolean[SIP_MEDIA_PORTS];
+
+    public static int CS_TIMEOUT_TI = 3;
+
+    public static int CS_TIMEOUT_T0 = 15;
+
+    public static int CS_TIMEOUT_T00 = 10;
+
+    public static int CS_TIMEOUT_T000 = 5;
+
+    public static int CS_TIMEOUT_T1 = 30;
+
+    public static int CS_TIMEOUT_T2 = 120;
+
+    public static int CS_TIMEOUT_T3 = 7;
+
+    public static int CS_TIMEOUT_T4 = 7200;
+
+    public static int CS_TIMEOUT_T5 = 7;
+
+    public static int CS_TIMEOUT_T6 = 0;
+
+    public static int CS_TIMEOUT_T7 = 30;
+
+    public static int CS_TIMEOUT_T8 = 7;
+
+    public static int CS_TIMEOUT_T80 = 2;
+
+    public static int CS_TIMEOUT_RESPONSE = 1;
+
+    public static int NETWORKIF_CHECK_TIME = 5;
+
+    public static int TEARDOWN_CODE_NORMAL = 0;
+
+    public static int TEARDOWN_CODE_EEREJECT = 1;
+
+    public static int TEARDOWN_CODE_ERREJECT = 2;
+
+    public static int TEARDOWN_CODE_NOTFOUND = 3;
+
+    public static int TEARDOWN_CODE_ERROR = 4;
+
+    public static int SIP_NETIF_UNAVAILABLE = 0;
+
+    public static int SIP_NETIF_AVAILABLE = 1;
+
+    public static int SIP_NETIF_UNREACHABLE = 2;
+
+    public static int REPEAT_SENDCOUNT = 3;
+
+    public static int SIP_MAXMESSAGE_SIZE = 2500;
+
+    public static boolean SIP_MESSAGE_DEBUG = false;
+
+    public static boolean SIP_CALLHANDLE_DEBUG = false;
+
+    public static Date bootTime = new Date();
+
+    public static int exceptionCountAtCurrentCall = 0;
+
+    public static boolean ventureCall = true;
+
+    public static boolean bLimitedUse = false;
+
+    public static int BACKGROUNDIDLE_MAX_SECONDS = 28800;
+
+    public static int networkStatus = SIP_NETIF_UNAVAILABLE;
+
+    public static String generalPhoneNumber = "";
+
+    public static String hwModelName = "";
+
+    public static String hwId = "";
+
+    public static String firmVersion = "";
+
+    public static String hwImsi = "";
+
+    public static String hwImei = "";
+
+    public static String gcmRegistId = "";
+
+    public static boolean bGCMRegistSend = false;
+
+    public static String ANDROID_API_KEY = "AIzaSyDZcNyOPs5iTQ9kGZaF56Ngf4eCQDzMEl0";
+
+    public static boolean isInternetWiMax = false;
+
+    public static boolean isInternetWiFi = false;
+
+    public static boolean isInternetMobile = false;
+
+    public static String localSdpIp = "0.0.0.0";
+
+    public static boolean usePrivateWiMax = true;
+
+    public static boolean bShutdownApplication = false;
+
+    public static boolean bOuttraffic = false;
+
+    public static boolean bIntraffic = false;
+
+    public static String macAddress = "";
+
+    public static boolean bTtsservice = false;
+
+    public static boolean bSupportTts = false;
+
+    public static int WIFI_CALL_SIGNAL_MIN = 3;
+
+    public static Date networkInfoCheckTime = new Date();
+
+    public static int WIFI_SIGNAL_VALUE = 0;
+
+    public static String mobileLanguage = "ko";
+
+    public static boolean bActive = false;
+
+    public static boolean bVibrator = true;
+
+    public static boolean bVibrating = false;
+
+    public static int iVibrator = 0;
+
+    public static GetIpDns ipdns = new GetIpDns();
+
+    public static boolean bNetworkActive = false;
+
+    public static int antenaOnStep = 0;
+
+    public static boolean bProximityOn = false;
+
+    public static int localPort = SIP_LOCAL_PORT;
+
+    public static String strLocalip = null;
+
+    public static boolean bBackgroundRunning = false;
+
+    public static boolean bGeneralPhoneDetected = false;
+
+    public static stackKey stackkey = new stackKey();
+
+    public static Date backgroundEnteredTime = new Date();
+
+    public static boolean bdialContextActive = false;
+
+    public static UserDial userDial = new UserDial();
+
+    public static int SIPCTRL_INTERVAL = 40;
+
+    public static boolean bVideocommunication = true;
+
+    public static boolean bDirectCall = true;
+
+    protected static boolean bStackLicensed = false;
+
+    public static boolean bUseSendTimer = false;
+
+    public static boolean bUseCtrlTimer = false;
+
+    public static int getCSeqMethod(String s) {
+        int iMethodType = SIP_METHODTYPE_NONE;
+        int iS = s.indexOf("CSeq: ");
+        int iE = 0;
+        if (iS >= 0)
+            iE = s.indexOf(SIP_LINE_END, iS);
+        if (iE <= 0)
+            return iMethodType;
+        String strCSEQ = s.substring(iS, iE);
+        StringTokenizer tokenArray = new StringTokenizer(strCSEQ, " ", true);
+        int tokenCount = 0;
+        while (tokenArray.hasMoreTokens()) {
+            String token = tokenArray.nextToken();
+            if (token.length() > 0 && token.compareTo(" ") != 0) {
+                tokenCount++;
+                if (tokenCount == 3) {
+                    if (token.compareTo("REGISTER") == 0) {
+                        iMethodType = SIP_METHODTYPE_REGISTER;
+                        break;
+                    }
+                    if (token.compareTo("INVITE") == 0) {
+                        iMethodType = SIP_METHODTYPE_INVITE;
+                        break;
+                    }
+                    if (token.compareTo("CANCEL") == 0) {
+                        iMethodType = SIP_METHODTYPE_CANCEL;
+                        break;
+                    }
+                    if (token.compareTo("BYE") == 0) {
+                        iMethodType = SIP_METHODTYPE_BYE;
+                        break;
+                    }
+                    if (token.compareTo("INFO") == 0) {
+                        iMethodType = SIP_METHODTYPE_INFO;
+                        break;
+                    }
+                    if (token.compareTo("OPTIONS") == 0) {
+                        iMethodType = SIP_METHODTYPE_OPTIONS;
+                        break;
+                    }
+                    if (token.compareTo("ACK") == 0) {
+                        iMethodType = SIP_METHODTYPE_ACK;
+                        break;
+                    }
+                    if (token.compareTo("REFER") == 0) {
+                        iMethodType = SIP_METHODTYPE_REFER;
+                        break;
+                    }
+                    if (token.compareTo("NOTIFY") == 0) {
+                        iMethodType = SIP_METHODTYPE_NOTIFY;
+                        break;
+                    }
+                    if (token.compareTo("MESSAGE") == 0) {
+                        iMethodType = SIP_METHODTYPE_MESSAGE;
+                        break;
+                    }
+                    if (token.compareTo("SUBSCRIBE") == 0) {
+                        iMethodType = SIP_METHODTYPE_SUBSCRIBE;
+                        break;
+                    }
+                    if (token.compareTo("PRACK") == 0)
+                        iMethodType = SIP_METHODTYPE_PRACK;
+                    break;
+                }
+            }
+        }
+        return iMethodType;
+    }
+
+    public static int getRequestlineMethod(String str) {
+        int iMethodType = SIP_METHODTYPE_NONE;
+        if (str.startsWith("INVITE") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_INVITE;
+        } else if (str.startsWith("BYE") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_BYE;
+        } else if (str.startsWith("ACK") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_ACK;
+        } else if (str.startsWith("CANCEL") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_CANCEL;
+        } else if (str.startsWith("OPTIONS") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_OPTIONS;
+        } else if (str.startsWith("INFO") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_INFO;
+        } else if (str.startsWith("PRACK") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_PRACK;
+        } else if (str.startsWith("MESSAGE") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_MESSAGE;
+        } else if (str.startsWith("SUBSCRIBE") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_SUBSCRIBE;
+        } else if (str.startsWith("REFER") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_REFER;
+        } else if (str.startsWith("NOTIFY") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_NOTIFY;
+        } else if (str.startsWith("REGISTER") && str.endsWith("SIP/2.0\r")) {
+            iMethodType = SIP_METHODTYPE_REGISTER;
+        } else if (str.startsWith("SIP/2.0") && str.endsWith("\r")) {
+            iMethodType = SIP_METHODTYPE_RESPONSE;
+        }
+        return iMethodType;
+    }
+
+    public static void setLicense(String strLicense) {
+        if (bLimitedUse) {
+            Date currentDate = new Date();
+            int month = currentDate.getMonth() + 1;
+            int day = currentDate.getDate();
+            int year = currentDate.getYear() + 1900;
+            if (year != 2014 || month > 12) {
+                System.out.println("사용기간 종료되었습니다.");
+                        bStackLicensed = false;
+                System.exit(0);
+            }
+        }
+        String license = "주식회사아이콘트롤스 200701243005451";
+        if (strLicense.compareTo(license) == 0) {
+            bStackLicensed = true;
+        } else {
+            System.out.println("SIP 라이슨스가 맞지 않습니다.");
+                    bStackLicensed = false;
+        }
+        System.out.println(
+                "이 스택은 아이콘트롤스 홈네트워크용입니다.");
+    }
+
+    public static String getResponseDescription(int code) {
+        switch (code) {
+            case 100:
+                return "Trying";
+            case 180:
+                return "Ringing";
+            case 181:
+                return "Call Is Being Forwarded";
+            case 182:
+                return "Call Queued";
+            case 183:
+                return "Session Progress";
+            case 200:
+                return "OK";
+            case 300:
+                return "Multiple Choices";
+            case 301:
+                return "Moved Permanently";
+            case 302:
+                return "Moved Temporarily";
+            case 305:
+                return "Use Proxy";
+            case 380:
+                return "Alternative Service";
+            case 400:
+                return "Bad Request";
+            case 401:
+                return "Unauthorized";
+            case 402:
+                return "Payment Required";
+            case 403:
+                return "Forbidden";
+            case 404:
+                return "Not Found";
+            case 405:
+                return "Method Not Allowed";
+            case 406:
+                return "Not Acceptable";
+            case 407:
+                return "Proxy Authentication Required";
+            case 408:
+                return "Request Timeout";
+            case 409:
+                return "Conflict";
+            case 410:
+                return "Gone";
+            case 411:
+                return "Length Required";
+            case 413:
+                return "Request Entity Too Large";
+            case 414:
+                return "Request-URI Too Long";
+            case 415:
+                return "Unsupported Media Type";
+            case 420:
+                return "Bad Extension";
+            case 421:
+                return "Extension Required";
+            case 423:
+                return "Interval Too Brief";
+            case 480:
+                return "Temporarily Unavailable";
+            case 481:
+                return "Call Leg Does Not Exist";
+            case 482:
+                return "Loop Detected";
+            case 483:
+                return "Two Many Hops";
+            case 484:
+                return "Address Incomplete";
+            case 485:
+                return "Ambiguous";
+            case 486:
+                return "Busy Here";
+            case 487:
+                return "Request Canceled";
+            case 488:
+                return "Not Acceptable Here";
+            case 500:
+                return "Server Internal Error";
+            case 501:
+                return "Not Implemented";
+            case 502:
+                return "Bad Gateway";
+            case 503:
+                return "Service Unavailable";
+            case 504:
+                return "Gateway Timeout";
+            case 505:
+                return "Version Not Supported";
+            case 600:
+                return "Busy Everywhere";
+            case 603:
+                return "Decline";
+            case 604:
+                return "Does Not Exist Anywhere";
+            case 606:
+                return "Not Acceptable";
+        }
+        return "";
+    }
+
+    public static String BSSMD5Get(String data) {
+        if (data == null || data.length() <= 0)
+            return null;
+        try {
+            SIPmd5 md = SIPmd5.getInstance();
+            return md.hashData(data.getBytes());
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace(System.out);
+            exceptionCountAtCurrentCall++;
+            return null;
+        }
+    }
+
+    public static String getViaBranch() {
+        Date today = new Date();
+        return "z9hG4bK-" + today.getTime() + "-" + ((int)today.getTime() % 7);
+    }
+
+    public static String newTag(String prefix) {
+        Date today = new Date();
+        return String.valueOf(prefix) + today.getTime() + "-" + today.hashCode();
+    }
+
+    public static String newTag() {
+        Date today = new Date();
+        return String.valueOf(today.getTime()) + "." + today.hashCode();
+    }
+
+    public static int getFreeAudioRtpPort() {
+        for (int i = 0; i < SIP_MEDIA_PORTS; i++) {
+            if (!SIP_MEDIA_PORTFLAG[i]) {
+                SIP_MEDIA_PORTFLAG[i] = true;
+                return SIP_MEDIA_INITPORT + i * 2;
+            }
+        }
+        return 0;
+    }
+
+    public static boolean freeAudioRtpPort(int port) {
+        int index = (port - SIP_MEDIA_INITPORT) / 2;
+        if (index >= 0 && index < SIP_MEDIA_PORTS) {
+            SIP_MEDIA_PORTFLAG[index] = false;
+            return true;
+        }
+        return false;
+    }
+
+    public static void printAudioRtpPortInfo() {
+        System.out.print(">>>> RTP PORT STATUS  ");
+        for (int i = 0; i < SIP_MEDIA_PORTS; i++)
+            System.out.print("  " + SIP_MEDIA_PORTFLAG[i]);
+        System.out.println("  ");
+    }
+
+    public static String getIPV4(String host) {
+        if (host == null || host.length() == 0)
+            return null;
+        String ip = null;
+        try {
+            InetAddress ia = InetAddress.getByName(host);
+            byte[] address = ia.getAddress();
+            if (address.length == 4) {
+                int unsignedByte1 = (address[0] < 0) ? (address[0] + 256) : address[0];
+                int unsignedByte2 = (address[1] < 0) ? (address[1] + 256) : address[1];
+                int unsignedByte3 = (address[2] < 0) ? (address[2] + 256) : address[2];
+                int unsignedByte4 = (address[3] < 0) ? (address[3] + 256) : address[3];
+                ip = String.valueOf(unsignedByte1) + "." + unsignedByte2 + "." + unsignedByte3 + "." + unsignedByte4;
+            }
+        } catch (UnknownHostException uhe) {
+            System.err.println(uhe);
+            exceptionCountAtCurrentCall++;
+        } catch (Exception e) {
+            System.err.println(e);
+        }
+        return ip;
+    }
+
+    public static boolean isPrivateIp(String ip) {
+        if (ip == null || ip.length() < 7)
+            return false;
+        boolean bPrivate = false;
+        StringTokenizer st = new StringTokenizer(ip, ".", true);
+        int tokenCount = 0;
+        String token = null;
+        int ipdigit_0 = 0;
+        int ipdigit_1 = 0;
+        while (st.hasMoreTokens()) {
+            token = st.nextToken().trim();
+            if (token != null && token.length() > 0 &&
+                    token.length() <= 3 &&
+                    token.compareTo(".") != 0) {
+                if (tokenCount == 0) {
+                    ipdigit_0 = Integer.parseInt(token.trim());
+                } else if (tokenCount == 1) {
+                    ipdigit_1 = Integer.parseInt(token.trim());
+                }
+                tokenCount++;
+            }
+        }
+        if (tokenCount == 4)
+            bPrivate = !(ipdigit_0 != 10 && (
+                    ipdigit_0 != 172 || ipdigit_1 < 16 || ipdigit_1 > 31) && (
+                    ipdigit_0 != 192 || ipdigit_1 != 168));
+        return bPrivate;
+    }
+
+    public static boolean getLicensed() {
+        return bStackLicensed;
+    }
+}

+ 124 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPVIAHeader.java

@@ -0,0 +1,124 @@
+package bssoft.stack.sip;
+
+import java.util.StringTokenizer;
+
+public class SIPVIAHeader {
+    public String header = null;
+
+    public String headerValue = null;
+
+    public String branch = null;
+
+    public String received = null;
+
+    public int rport = -1;
+
+    public String ip = null;
+
+    public int port = 0;
+
+    public String tag = null;
+
+    public boolean rportService = false;
+
+    public boolean flag = false;
+
+    public SIPVIAHeader(String message) {
+        if (message != null && message.length() > 0) {
+            this.rport = 0;
+            this.received = null;
+            int iS = message.indexOf("Via: ");
+            int iE = 0;
+            if (iS < 0) {
+                iS = message.indexOf(String.valueOf(SIPStack.SIP_LINE_END) + "v: ");
+                if (iS >= 0)
+                    iS += 2;
+            }
+            if (iS >= 0) {
+                iE = message.indexOf(SIPStack.SIP_LINE_END, iS);
+                if (iE > 0) {
+                    this.header = message.substring(iS, iE);
+                    if (this.header.startsWith("Via: ")) {
+                        this.headerValue = this.header.substring(5);
+                    } else if (this.header.startsWith("v: ")) {
+                        this.headerValue = this.header.substring(3);
+                    }
+                }
+            }
+            if (this.headerValue != null && this.headerValue.length() > 0) {
+                StringTokenizer st = new StringTokenizer(this.headerValue, ";", true);
+                int tokenCount = 0;
+                String token = null;
+                while (st.hasMoreTokens()) {
+                    token = st.nextToken().trim();
+                    if (token != null && token.length() > 0 && token.compareTo(";") != 0) {
+                        tokenCount++;
+                        if (tokenCount == 1 && token.startsWith("SIP/")) {
+                            StringTokenizer tokenArray = new StringTokenizer(token, " ", true);
+                            int fieldCount = 0;
+                            while (tokenArray.hasMoreTokens()) {
+                                String field = tokenArray.nextToken().trim();
+                                if (field != null && field.length() > 0 && field.compareTo(" ") != 0) {
+                                    fieldCount++;
+                                    if (fieldCount == 2) {
+                                        iS = field.indexOf(":");
+                                        if (iS > 0) {
+                                            this.port = Integer.parseInt(field.substring(iS + 1));
+                                            this.ip = field.substring(0, iS);
+                                            continue;
+                                        }
+                                        this.port = 5060;
+                                        this.ip = field;
+                                    }
+                                }
+                            }
+                            continue;
+                        }
+                        if (tokenCount != 1 && token.startsWith("branch=")) {
+                            this.branch = token.substring(7);
+                            continue;
+                        }
+                        if (tokenCount != 1 && token.compareTo("rport") == 0) {
+                            this.rportService = true;
+                            continue;
+                        }
+                        if (tokenCount != 1 && token.startsWith("rport=")) {
+                            this.rportService = true;
+                            this.rport = Integer.parseInt(token.substring(6).trim());
+                            continue;
+                        }
+                        if (tokenCount != 1 && token.startsWith("received=")) {
+                            this.rportService = true;
+                            this.received = token.substring(9).trim();
+                        }
+                    }
+                }
+                this.flag = true;
+            }
+        }
+    }
+
+    public String getReceived() {
+        return this.received;
+    }
+
+    public int getRport() {
+        return this.rport;
+    }
+
+    public String getAddress() {
+        return String.valueOf(this.ip) + ":" + this.port;
+    }
+
+    public String getIp() {
+        return this.ip;
+    }
+
+    public int getPort() {
+        return this.port;
+    }
+
+    public String getBranch() {
+        return this.branch;
+    }
+}

+ 38 - 0
WallPadCall/src/main/java/bssoft/stack/sip/SIPmd5.java

@@ -0,0 +1,38 @@
+package bssoft.stack.sip;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class SIPmd5 {
+    public MessageDigest md = null;
+
+    public static SIPmd5 md5 = null;
+
+    public SIPmd5() throws NoSuchAlgorithmException {
+        this.md = MessageDigest.getInstance("MD5");
+    }
+
+    public static SIPmd5 getInstance() throws NoSuchAlgorithmException {
+        if (md5 == null)
+            md5 = new SIPmd5();
+        return md5;
+    }
+
+    public String hashData(byte[] dataToHash) {
+        return hexStringFromBytes(calculateHash(dataToHash));
+    }
+
+    public byte[] calculateHash(byte[] dataToHash) {
+        this.md.update(dataToHash, 0, dataToHash.length);
+        return this.md.digest();
+    }
+
+    public String hexStringFromBytes(byte[] b) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < b.length; i++) {
+            String md5Char = String.format("%02x", new Object[] { Integer.valueOf(0xFF & (char)b[i]) });
+            sb.append(md5Char);
+        }
+        return sb.toString();
+    }
+}

+ 294 - 0
WallPadCall/src/main/java/bssoft/stack/sip/UPDATEHeaders.java

@@ -0,0 +1,294 @@
+package bssoft.stack.sip;
+
+import java.util.Date;
+
+public class UPDATEHeaders {
+    public String commandLine = null;
+
+    public String viaH = null;
+
+    public StringBuffer viaArray = null;
+
+    public String routeH = null;
+
+    public StringBuffer routeArray = null;
+
+    public String recordrouteH = null;
+
+    public StringBuffer recordrouteArray = null;
+
+    public String maxforwardH = null;
+
+    public String contactH = null;
+
+    public String toH = null;
+
+    public String fromH = null;
+
+    public String callidH = null;
+
+    public String cseqH = null;
+
+    public String expiresH = null;
+
+    public String allowH = null;
+
+    public String useragentH = null;
+
+    public String remoteuseragentH = null;
+
+    public String contentlengthH = null;
+
+    public String contenttypeH = null;
+
+    public String authorizationINVITEH = null;
+
+    public String authorizationCANCELH = null;
+
+    public String authorizationBYEH = null;
+
+    public String authorizationACKH = null;
+
+    public String passertedidentityH = null;
+
+    public String serverIp = null;
+
+    public int serverPort = 5060;
+
+    public String serverDomain = null;
+
+    public String remoteIp = null;
+
+    public int remotePort = 5060;
+
+    public String remoteContactIp = null;
+
+    public int remoteContactPort = 5060;
+
+    public String remoteContactUri = null;
+
+    public String localIp = null;
+
+    public int localPort = 5060;
+
+    public String id = null;
+
+    public String cid = null;
+
+    public String authid = null;
+
+    public String authpassword = null;
+
+    public String fromTag = null;
+
+    public String toTag = null;
+
+    public String fromHeaderValue = null;
+
+    public String toHeaderValue = null;
+
+    public String callId = null;
+
+    public String dnis = null;
+
+    public String viaBranch = null;
+
+    public int CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+
+    public int INVITE_CSEQ = 0;
+
+    public int CANCEL_CSEQ = 0;
+
+    public int ACK_CSEQ = 0;
+
+    public int BYE_CSEQ = 0;
+
+    public int callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+
+    public int callState = 0;
+
+    public int callMode = SIPStack.SIP_CALLMODE_NONE;
+
+    public Date callTime_TI = null;
+
+    public Date callTime_T0 = null;
+
+    public Date callTime_T00 = null;
+
+    public int invitingTimes = 0;
+
+    public Date callTime_T1 = null;
+
+    public Date callTime_T2 = null;
+
+    public Date callTime_T3 = null;
+
+    public Date callTime_T4 = null;
+
+    public Date callTime_T40 = null;
+
+    public Date callTime_T5 = null;
+
+    public Date callTime_T6 = null;
+
+    public Date callTime_T7 = null;
+
+    public Date callTime_T8 = null;
+
+    public Date callTime_T9 = null;
+
+    public int expiresTI = 0;
+
+    public int expiresT0 = 0;
+
+    public int expiresT00 = 0;
+
+    public int expiresT1 = 0;
+
+    public int expiresT2 = 0;
+
+    public int expiresT3 = 0;
+
+    public int expiresT4 = 0;
+
+    public int expiresT5 = 0;
+
+    public int expiresT6 = 0;
+
+    public int expiresT7 = 0;
+
+    public int expiresT8 = 0;
+
+    public int expiresT9 = 0;
+
+    public SIPSdp sdp = null;
+
+    public SIPSdp remoteSdp = null;
+
+    public String message = null;
+
+    public boolean flag;
+
+    public UPDATEHeaders() {
+        if (SIPStack.SIP_CALLHANDLE_DEBUG)
+            System.out.println("call handle created.");
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_BASIC;
+        this.callTime_TI = new Date();
+        this.callTime_T0 = new Date();
+        this.callTime_T00 = new Date();
+        this.invitingTimes = 0;
+        this.callTime_T1 = new Date();
+        this.callTime_T2 = new Date();
+        this.callTime_T3 = new Date();
+        this.callTime_T4 = new Date();
+        this.callTime_T40 = new Date();
+        this.callTime_T5 = new Date();
+        this.callTime_T6 = new Date();
+        this.callTime_T7 = new Date();
+        this.callTime_T8 = new Date();
+        this.callTime_T9 = new Date();
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.flag = false;
+    }
+
+    public void reset() {
+        this.commandLine = null;
+        this.viaH = null;
+        this.viaArray = null;
+        this.routeH = null;
+        this.routeArray = null;
+        this.recordrouteH = null;
+        this.recordrouteArray = null;
+        this.maxforwardH = null;
+        this.contactH = null;
+        this.toH = null;
+        this.fromH = null;
+        this.callidH = null;
+        this.cseqH = null;
+        this.expiresH = null;
+        this.allowH = null;
+        this.useragentH = null;
+        this.remoteuseragentH = null;
+        this.contentlengthH = null;
+        this.contenttypeH = null;
+        this.authorizationINVITEH = null;
+        this.authorizationCANCELH = null;
+        this.authorizationBYEH = null;
+        this.authorizationACKH = null;
+        this.passertedidentityH = null;
+        this.serverIp = null;
+        this.serverPort = 5060;
+        this.serverDomain = null;
+        this.remoteIp = null;
+        this.remotePort = 5060;
+        this.remoteContactIp = null;
+        this.remoteContactPort = 5060;
+        this.remoteContactUri = null;
+        this.localIp = null;
+        this.localPort = 5060;
+        this.id = null;
+        this.cid = null;
+        this.authid = null;
+        this.authpassword = null;
+        this.fromTag = null;
+        this.toTag = null;
+        this.fromHeaderValue = null;
+        this.toHeaderValue = null;
+        this.callId = null;
+        this.dnis = null;
+        this.viaBranch = null;
+        this.CSEQ_NUMBER = SIPStack.SIP_SEQUENCE_INVITE;
+        this.INVITE_CSEQ = 0;
+        this.CANCEL_CSEQ = 0;
+        this.ACK_CSEQ = 0;
+        this.BYE_CSEQ = 0;
+        this.callDirection = SIPStack.SIP_CALLDIRECTION_NONE;
+        this.callState = 0;
+        this.callMode = SIPStack.SIP_CALLMODE_NONE;
+        this.callTime_TI = null;
+        this.callTime_T0 = null;
+        this.callTime_T00 = null;
+        this.invitingTimes = 0;
+        this.callTime_T1 = null;
+        this.callTime_T2 = null;
+        this.callTime_T3 = null;
+        this.callTime_T4 = null;
+        this.callTime_T40 = null;
+        this.callTime_T5 = null;
+        this.callTime_T6 = null;
+        this.callTime_T7 = null;
+        this.callTime_T8 = null;
+        this.callTime_T9 = null;
+        this.expiresTI = 0;
+        this.expiresT0 = 0;
+        this.expiresT00 = 0;
+        this.expiresT1 = 0;
+        this.expiresT2 = 0;
+        this.expiresT3 = 0;
+        this.expiresT4 = 0;
+        this.expiresT5 = 0;
+        this.expiresT6 = 0;
+        this.expiresT7 = 0;
+        this.expiresT8 = 0;
+        this.expiresT9 = 0;
+        this.sdp = null;
+        this.remoteSdp = null;
+        this.message = null;
+        this.flag = false;
+    }
+}

+ 11 - 0
WallPadCall/src/main/java/bssoft/stack/sip/UserDial.java

@@ -0,0 +1,11 @@
+package bssoft.stack.sip;
+
+public class UserDial {
+    public String dial = "";
+
+    public String dong = "";
+
+    public String ho = "";
+
+    public String latestDial = "";
+}

+ 87 - 0
WallPadCall/src/main/java/bssoft/stack/sip/stackKey.java

@@ -0,0 +1,87 @@
+package bssoft.stack.sip;
+
+public class stackKey {
+    public String KEY_BSS_SMARTINFO;
+
+    public String KEY_BSS_ID;
+
+    public String KEY_BSS_AUTHID;
+
+    public String KEY_BSS_PASSWORD;
+
+    public String KEY_BSS_CID;
+
+    public String KEY_BSS_SERVERIP;
+
+    public String KEY_BSS_SERVERDOMAIN;
+
+    public String KEY_BSS_SERVERPORT;
+
+    public String KEY_BSS_PMPSET;
+
+    public String KEY_BSS_IMSI;
+
+    public String KEY_BSS_GENERALPHONE;
+
+    public String KEY_BSS_WEBID;
+
+    public String KEY_BSS_WEBPWD;
+
+    public String KEY_BSS_LATESTDIAL;
+
+    public String KEY_BSS_FORWARD;
+
+    public String strId = "";
+
+    public String strCid = "";
+
+    public String strAuthid = "";
+
+    public String strAuthpassword = "";
+
+    public String strServerHost = "";
+
+    public String strServerDomain = "";
+
+    public String strImsi = "";
+
+    public String strGeneralPhone = "";
+
+    public String strWebId = "";
+
+    public String strWebPwd = "";
+
+    public int serverPort = 5060;
+
+    public String strForward = "";
+
+    public stackKey() {
+        this.KEY_BSS_SMARTINFO = "bss_smartinfo";
+        this.KEY_BSS_ID = "bss_id";
+        this.KEY_BSS_AUTHID = "bss_authid";
+        this.KEY_BSS_PASSWORD = "bss_password";
+        this.KEY_BSS_CID = "bss_cid";
+        this.KEY_BSS_SERVERIP = "bss_serverip";
+        this.KEY_BSS_SERVERDOMAIN = "bss_serverdomain";
+        this.KEY_BSS_SERVERPORT = "bss_serverport";
+        this.KEY_BSS_PMPSET = "bss_pmpset";
+        this.KEY_BSS_IMSI = "bss_imsi";
+        this.KEY_BSS_GENERALPHONE = "bss_generalphone";
+        this.KEY_BSS_WEBID = "bss_webid";
+        this.KEY_BSS_WEBPWD = "bss_webpwd";
+        this.KEY_BSS_LATESTDIAL = "bss_latestdial";
+        this.KEY_BSS_FORWARD = "bss_forward";
+        this.strId = "";
+        this.strCid = "";
+        this.strAuthid = "";
+        this.strAuthpassword = "";
+        this.strServerHost = "";
+        this.strServerDomain = "";
+        this.strImsi = "";
+        this.strGeneralPhone = "";
+        this.strWebId = "";
+        this.strWebPwd = "";
+        this.serverPort = 5060;
+        this.strForward = "";
+    }
+}

+ 228 - 0
WallPadCall/src/main/java/bssoft/stack/sip/videoEnc.java

@@ -0,0 +1,228 @@
+package bssoft.stack.sip;
+
+public class videoEnc {
+    public boolean bReceiveRunning = false;
+
+    public byte[] buffer = null;
+
+    public byte[] rtpVideoBuffer = null;
+
+    public byte[] data = null;
+
+    public int RTP_VIDEO_SIZE = 70000;
+
+    public int RTPversion = 0;
+
+    public int RTPpadding = 0;
+
+    public int RTPextension = 0;
+
+    public int RTPcsrc = 0;
+
+    public int RTPmark = 0;
+
+    public int RTPpayload = 0;
+
+    public int RTPsequence = 0;
+
+    public int RTPtimestamp = 0;
+
+    public int RTPssrc = 0;
+
+    public boolean bService = false;
+
+    public String remoteIp = "127.0.0.1";
+
+    public int remotePort = 3002;
+
+    public byte[] rtpfieldBytes = null;
+
+    public boolean bIframeset = false;
+
+    public boolean bIframedoubleset = false;
+
+    public boolean bView = false;
+
+    public int PARSEversion = 0;
+
+    public int PARSEpadding = 0;
+
+    public int PARSEextension = 0;
+
+    public int PARSEcsrc = 0;
+
+    public int PARSEmark = 0;
+
+    public int PARSEpayload = 0;
+
+    public int PARSEsequence = 0;
+
+    public int PARSEtimestamp = 0;
+
+    public int PARSEssrc = 0;
+
+    public int PARSEview = 0;
+
+    public videoEnc() {
+        if (!SIPStack.bStackLicensed) {
+            System.out.println("라이슨스키를 설정하세요.");
+                    System.exit(0);
+        }
+        this.buffer = new byte[this.RTP_VIDEO_SIZE];
+        this.rtpVideoBuffer = new byte[this.RTP_VIDEO_SIZE];
+        this.data = new byte[this.RTP_VIDEO_SIZE];
+        this.RTPversion = 0;
+        this.RTPpadding = 0;
+        this.RTPextension = 0;
+        this.RTPcsrc = 0;
+        this.RTPmark = 0;
+        this.RTPpayload = 0;
+        this.RTPsequence = 0;
+        this.RTPtimestamp = 0;
+        this.RTPssrc = 0;
+        this.bService = false;
+        this.remoteIp = "127.0.0.1";
+        this.remotePort = 3002;
+        this.rtpfieldBytes = new byte[4];
+        this.bIframeset = false;
+        this.bIframedoubleset = false;
+        this.bView = false;
+    }
+
+    public void init() {
+        this.RTPversion = 0;
+        this.RTPpadding = 0;
+        this.RTPextension = 0;
+        this.RTPcsrc = 0;
+        this.RTPmark = 0;
+        this.RTPpayload = 0;
+        this.RTPsequence = 0;
+        this.RTPtimestamp = 0;
+        this.RTPssrc = 0;
+        this.bService = false;
+        this.remoteIp = "127.0.0.1";
+        this.remotePort = 3002;
+        this.bIframeset = false;
+        this.bIframedoubleset = false;
+        this.bView = false;
+    }
+
+    public boolean encodeRtpHeader(int payload) {
+        if (this.rtpVideoBuffer == null || this.rtpVideoBuffer.length < 12)
+            return false;
+        int iField = 0;
+        int iAppend = 0;
+        iField = this.RTPversion << 6 & 0xC0;
+        iAppend = this.RTPpadding << 5 & 0x20;
+        iField |= iAppend;
+        iAppend = this.RTPextension << 4 & 0x10;
+        iField |= iAppend;
+        iAppend = this.RTPcsrc & 0xF;
+        iField |= iAppend;
+        this.rtpVideoBuffer[0] = (byte)iField;
+        iField = 0;
+        iField = this.RTPmark << 7 & 0x80;
+        iAppend = payload & 0x7F;
+        iField |= iAppend;
+        this.rtpVideoBuffer[1] = (byte)iField;
+        iField = 0;
+        this.rtpVideoBuffer[2] = (byte)(this.RTPsequence << 16 >> 24);
+        this.rtpVideoBuffer[3] = (byte)(this.RTPsequence << 24 >> 24);
+        this.rtpVideoBuffer[4] = (byte)(this.RTPtimestamp >> 24);
+        this.rtpVideoBuffer[5] = (byte)(this.RTPtimestamp << 8 >> 24);
+        this.rtpVideoBuffer[6] = (byte)(this.RTPtimestamp << 16 >> 24);
+        this.rtpVideoBuffer[7] = (byte)(this.RTPtimestamp << 24 >> 24);
+        this.rtpVideoBuffer[8] = (byte)(this.RTPssrc >> 24);
+        this.rtpVideoBuffer[9] = (byte)(this.RTPssrc << 8 >> 24);
+        this.rtpVideoBuffer[10] = (byte)(this.RTPssrc << 16 >> 24);
+        this.rtpVideoBuffer[11] = (byte)(this.RTPssrc << 24 >> 24);
+        return true;
+    }
+
+    public boolean encodeHNSRtpHeader(int payload, boolean bView) {
+        if (this.rtpVideoBuffer == null || this.rtpVideoBuffer.length < 12)
+            return false;
+        int iField = 0;
+        int iAppend = 0;
+        iField = this.RTPversion << 6 & 0xC0;
+        iAppend = this.RTPpadding << 5 & 0x20;
+        iField |= iAppend;
+        iAppend = this.RTPextension << 4 & 0x10;
+        iField |= iAppend;
+        iAppend = this.RTPcsrc & 0xF;
+        iField |= iAppend;
+        this.rtpVideoBuffer[0] = (byte)iField;
+        iField = 0;
+        iField = this.RTPmark << 7 & 0x80;
+        iAppend = payload & 0x7F;
+        iField |= iAppend;
+        this.rtpVideoBuffer[1] = (byte)iField;
+        iField = 0;
+        this.rtpVideoBuffer[2] = (byte)(this.RTPsequence << 16 >> 24);
+        this.rtpVideoBuffer[3] = (byte)(this.RTPsequence << 24 >> 24);
+        this.rtpVideoBuffer[4] = (byte)(this.RTPtimestamp >> 24);
+        this.rtpVideoBuffer[5] = (byte)(this.RTPtimestamp << 8 >> 24);
+        this.rtpVideoBuffer[6] = (byte)(this.RTPtimestamp << 16 >> 24);
+        this.rtpVideoBuffer[7] = (byte)(this.RTPtimestamp << 24 >> 24);
+        this.rtpVideoBuffer[8] = (byte)(this.RTPssrc >> 24);
+        this.rtpVideoBuffer[9] = (byte)(this.RTPssrc << 8 >> 24);
+        this.rtpVideoBuffer[10] = (byte)(this.RTPssrc << 16 >> 24);
+        this.rtpVideoBuffer[11] = (byte)(this.RTPssrc << 24 >> 24);
+        if (bView) {
+            iField = 1;
+        } else {
+            iField = 0;
+        }
+        this.rtpVideoBuffer[12] = (byte)iField;
+        return true;
+    }
+
+    public boolean parseRTPHeader() {
+        try {
+            this.PARSEversion = 0;
+            this.PARSEpadding = 0;
+            this.PARSEextension = 0;
+            this.PARSEcsrc = 0;
+            this.PARSEmark = 0;
+            this.PARSEpayload = 0;
+            this.PARSEsequence = 0;
+            this.PARSEtimestamp = 0;
+            this.PARSEssrc = 0;
+            this.PARSEview = 0;
+            this.rtpfieldBytes[0] = this.buffer[1];
+            this.PARSEmark = this.rtpfieldBytes[0] >> 7 & 0x1;
+            this.PARSEpayload = this.rtpfieldBytes[0] & Byte.MAX_VALUE;
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean parseHNSRTPHeader() {
+        try {
+            this.PARSEversion = 0;
+            this.PARSEpadding = 0;
+            this.PARSEextension = 0;
+            this.PARSEcsrc = 0;
+            this.PARSEmark = 0;
+            this.PARSEpayload = 0;
+            this.PARSEsequence = 0;
+            this.PARSEtimestamp = 0;
+            this.PARSEssrc = 0;
+            this.PARSEview = 0;
+            this.rtpfieldBytes[0] = this.buffer[1];
+            this.PARSEmark = this.rtpfieldBytes[0] >> 7 & 0x1;
+            this.PARSEpayload = this.rtpfieldBytes[0] & Byte.MAX_VALUE;
+            this.rtpfieldBytes[0] = this.buffer[12];
+            this.PARSEview = this.rtpfieldBytes[0] & 0x1;
+            if (this.PARSEview == 1) {
+                this.bView = true;
+            } else {
+                this.bView = false;
+            }
+        } catch (Exception e) {
+            return false;
+        }
+        return true;
+    }
+}

+ 190 - 0
WallPadCall/src/main/java/ceres/api/AECParam.java

@@ -0,0 +1,190 @@
+package ceres.api;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import ceres.utils.printlog;
+
+
+public class AECParam implements Parcelable {
+	
+	private static final String THIS_FILE = "AECParam";
+
+	//Constants
+	public final static int INVALID_ID = -1;	
+		
+	// Fields for table 
+	// -- AEC Tuning param.
+	public static final String FIELD_ID 			= "_id";
+	public static final String MEMO 				= "memo";
+	public static final String DELAY 				= "delay";
+	public static final String TIME_SPAN			= "time_span";
+	public static final String ERL 				    = "erl";
+	public static final String DYNAMIC_VOL_MIC		= "dynamic_vol_mic";
+	public static final String DYNAMIC_VOL_MIC_MIN  = "dynamic_vol_mic_min";
+	public static final String UPDATE_SPEED 		= "update_speed";
+	public static final String WEIGHT_MAX_INDEX 	= "weight_max_index";
+	public static final String WEIGHT_SCALE			= "weight_scale";
+	public static final String DATE					= "date";
+	
+	public final static String[] full_projection = {
+		FIELD_ID,
+		// Application relative fields
+		MEMO, DELAY, TIME_SPAN, ERL, DYNAMIC_VOL_MIC, DYNAMIC_VOL_MIC,
+		DYNAMIC_VOL_MIC_MIN, UPDATE_SPEED, WEIGHT_MAX_INDEX, WEIGHT_SCALE,
+		DATE
+		};
+	
+	//Properties
+	public int 	  PrimaryKey 			= -1;
+	public int 	  _id 		 			= INVALID_ID;
+	public String memo 					= "";
+	public String delay 				= "";
+	public String time_span				= "";
+	public String erl					= "";
+	public String dynamic_vol_mic 	 	= "";	// dynamic_vol_factor
+	public String dynamic_vol_mic_min   = "";	// dynamic_vol_min
+	public String update_speed    		= "";
+	public String weight_max_index 		= "";
+	public String weight_scale 			= "";
+	public long   date					= 0;
+	
+	public AECParam(){
+		printlog.i(THIS_FILE, "new AECParam()");
+	}
+	
+	public AECParam(Parcel in) {
+		PrimaryKey 			= in.readInt();
+		_id 				= in.readInt();
+		memo				= in.readString();
+		delay 				= in.readString();
+		time_span			= in.readString();
+		erl 				= in.readString();
+		dynamic_vol_mic 	= in.readString();
+		dynamic_vol_mic_min = in.readString();
+		update_speed 		= in.readString();
+		weight_max_index 	= in.readString();
+		weight_scale 		= in.readString();
+		date				= in.readLong();
+	}
+	
+	@Override
+	public int describeContents() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+	
+	@Override
+	public void writeToParcel(Parcel dest, int flags) {
+		// TODO Auto-generated method stub
+		dest.writeInt(PrimaryKey);
+		dest.writeInt(_id);
+		dest.writeString(memo);
+		dest.writeString(delay);
+		dest.writeString(time_span);
+		dest.writeString(erl);
+		dest.writeString(dynamic_vol_mic);
+		dest.writeString(dynamic_vol_mic_min);
+		dest.writeString(update_speed);
+		dest.writeString(weight_max_index);
+		dest.writeString(weight_scale);					
+		dest.writeLong(date);
+	}
+	
+	public static final Creator<AECParam> CREATOR = new Creator<AECParam>() {
+		public AECParam createFromParcel(Parcel in) {
+			return new AECParam(in);
+		}
+
+		public AECParam[] newArray(int size) {
+			return new AECParam[size];
+		}
+	};
+	
+	/** 
+	 * Fill account object from cursor
+	 * @param c cursor on the database 
+	 */		
+	public void createFromDb(Cursor c) {
+		ContentValues args = new ContentValues();
+		DatabaseUtils.cursorRowToContentValues(c, args);
+		Integer tmp_i;
+		String tmp_s;
+		long tmp_l;
+
+		// Application specific settings
+		tmp_i = args.getAsInteger(FIELD_ID);
+		if (tmp_i != null) {
+			_id = tmp_i;
+		}
+		tmp_s = args.getAsString(MEMO);
+		if (tmp_s != null) {
+			memo = tmp_s;
+		}
+		tmp_s = args.getAsString(DELAY);
+		if (tmp_s != null) {
+			delay = tmp_s;
+		}
+		tmp_s = args.getAsString(TIME_SPAN);
+		if (tmp_s != null) {
+			time_span = tmp_s;
+		}
+		tmp_s = args.getAsString(ERL);
+		if (tmp_s != null) {
+			erl = tmp_s;
+		}
+		tmp_s = args.getAsString(DYNAMIC_VOL_MIC);
+		if (tmp_s != null) {
+			dynamic_vol_mic = tmp_s;
+		}
+		tmp_s = args.getAsString(DYNAMIC_VOL_MIC_MIN);
+		if (tmp_s != null) {
+			dynamic_vol_mic_min = tmp_s;
+		}		
+		tmp_s = args.getAsString(UPDATE_SPEED);
+		if (tmp_s != null) {
+			update_speed = tmp_s;
+		} 
+		tmp_s = args.getAsString(WEIGHT_MAX_INDEX);
+		if (tmp_s != null) {
+			weight_max_index = tmp_s;
+		}
+		tmp_s = args.getAsString(WEIGHT_SCALE);
+		if (tmp_s != null) {
+			weight_scale = tmp_s;
+		}
+		tmp_l = args.getAsLong(DATE);
+		if (tmp_i != null) {
+			date = tmp_l;
+		}
+	}
+	
+	/**
+	 * Transform AEC_Tuning_param into ContentValues that can be insert into database
+	 * AECTNTB => ContentValues
+	 */
+	public ContentValues getDbContentValues() {
+		ContentValues args = new ContentValues();
+				
+		if(_id != INVALID_ID){
+			args.put(FIELD_ID, _id);
+		}
+		
+		args.put(MEMO, memo);
+		args.put(DELAY, delay);
+		args.put(TIME_SPAN, time_span);
+		args.put(ERL, erl); 
+		args.put(DYNAMIC_VOL_MIC, dynamic_vol_mic); 
+		args.put(DYNAMIC_VOL_MIC_MIN, dynamic_vol_mic_min); 
+		args.put(UPDATE_SPEED, update_speed);
+		args.put(WEIGHT_MAX_INDEX, weight_max_index);
+		args.put(WEIGHT_SCALE, weight_scale); 
+		args.put(DATE, date);
+		
+		return args;
+	}
+	
+}

+ 963 - 0
WallPadCall/src/main/java/ceres/api/Configuration.java

@@ -0,0 +1,963 @@
+package ceres.api;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import ceres.security.Base64Utils;
+import ceres.utils.printlog;
+
+public class Configuration implements Parcelable {
+	
+	private static final String THIS_FILE = "Configuration";
+
+	//Constants
+	public final static int INVALID_ID = -1;
+	
+	static Base64Utils base64;
+		
+	// Fields for table accounts
+	// -- Call Config
+	public static final String FIELD_ID 			= "_id";
+	public static final String PHONE_NUMBER 		= "phone_number";
+	public static final String ONE_NUMBER			= "one_number";
+	public static final String ADDRESS 				= "address";
+	public static final String PASSWORD				= "password";
+	public static final String AUTH_ID				= "auth_id";
+	public static final String PROXY_ADDR 			= "proxy_addr";
+	public static final String PROXY_PORT 			= "proxy_port";
+	public static final String REG_ADDR				= "reg_addr";
+	public static final String REG_PORT 			= "reg_port";
+	public static final String LOCAL_PORT 			= "local_port";
+	public static final String LOCAL_MEDIA_PORT 	= "local_media_port";
+	public static final String REMOTE_MEDIA_PORT 	= "remote_media_port";
+	// -- Normal Config
+	public static final String PROVIDER 			= "provider";
+	public static final String ACODEC_PRI			= "acodec_pri";
+	public static final String VCODEC_PRI 			= "vcodec_pri";
+	public static final String REREGTIME			= "reregtime";
+	public static final String SESSIONTIME			= "sessiontime";
+	public static final String SESSION_EXPIRE_TIME 	= "session_expire_time";
+	public static final String TRANSACTION_TIME 	= "transaction_time";
+	public static final String DTMF_TYPE			= "dtmf_type";
+	public static final String URL_TYPE 			= "url_type";
+	public static final String SRTPOPTION 			= "srtpoption";
+	public static final String PTIME 				= "ptime";
+	// -- Add Config	
+	public static final String AECONOFF 			= "aeconoff";
+	public static final String JBMINMAX				= "jbminmax";
+	public static final String ONENUMONOFF			= "onenumonoff";
+	public static final String SPAMONOFF 			= "spamonoff";
+	public static final String REDIRECTOPTION		= "redirectoption";
+	public static final String HWSAMPLINGRATE		= "hwsamplingrate";
+	public static final String VAD_ONOFF			= "vad_onoff";
+	public static final String NS_ONOFF				= "ns_onoff";
+	public static final String CNG_ONOFF			= "cng_onoff";
+	public static final String AUDIO_MODE			= "audio_mode";
+	
+	// -- mudule log level
+	public static final String LOG_LV_SIP			= "log_lv_sip";
+	public static final String LOG_LV_RTP			= "log_lv_rtp";
+	public static final String LOG_LV_CM			= "log_lv_cm";
+	public static final String LOG_LV_MCM			= "log_lv_mcm";
+	public static final String LOG_LV_MMM			= "log_lv_mmm";
+	public static final String LOG_LV_UI			= "log_lv_ui";
+	
+	public static final String SDC_ONOFF			= "sdc_onoff";
+	public static final String VIDEO_ONOFF			= "video_onoff";
+	
+	// -- Video Option..
+	public static final String VIDEO_SIZE			= "video_size";
+	public static final String VCODEC_FRAMERATE		= "vcodec_framerate";
+	public static final String VCODEC_BANDWIDTH		= "vcodec_bandwidth";
+	public static final String VCODEC_MAXBR			= "vcodec_maxbr";
+	public static final String VCODEC_H264_PMODE	= "vcodec_h264_pmode";
+	public static final String VCODEC_MPEG4VES_PLI	= "vcodec_mpeg4ves_pli";
+	
+	public final static String[] full_projection = {
+		FIELD_ID,
+		// Application relative fields
+		PHONE_NUMBER, ONE_NUMBER, ADDRESS, PASSWORD, AUTH_ID,
+		PROXY_ADDR, PROXY_PORT, REG_ADDR, REG_PORT, LOCAL_PORT,
+		LOCAL_MEDIA_PORT, REMOTE_MEDIA_PORT, PROVIDER, ACODEC_PRI, 
+		VCODEC_PRI, REREGTIME, SESSIONTIME, SESSION_EXPIRE_TIME,
+		TRANSACTION_TIME, DTMF_TYPE, URL_TYPE, SRTPOPTION, PTIME,
+		AECONOFF, JBMINMAX, ONENUMONOFF, SPAMONOFF, REDIRECTOPTION,
+		HWSAMPLINGRATE, VAD_ONOFF, NS_ONOFF, CNG_ONOFF, 
+		AUDIO_MODE, LOG_LV_SIP, LOG_LV_RTP, LOG_LV_CM,
+		LOG_LV_MCM, LOG_LV_MMM, LOG_LV_UI, SDC_ONOFF,
+		VIDEO_ONOFF, VIDEO_SIZE, VCODEC_FRAMERATE, VCODEC_BANDWIDTH,
+		VCODEC_MAXBR, VCODEC_H264_PMODE, VCODEC_MPEG4VES_PLI
+		};
+	
+	//Properties
+	public int 	  PrimaryKey 			= -1;
+	public int 	  _id 		 			= INVALID_ID;
+	public String phone_number 			= "";
+	public String one_number			= "";
+	public String address 	 			= "";
+	public String password   			= "";
+	public String auth_id    			= "";
+	public String proxy_addr 			= "";
+	public String proxy_port 			= "";
+	public String reg_addr   			= "";
+	public String reg_port   			= "";
+	public String local_port 			= "";
+	public String local_media_port		= "";
+	public String remote_media_port		= "";
+	public String provider 				= "";
+	public String acodec_pri			= "";
+	public String vcodec_pri 	 		= "";
+	public String reregtime   			= "";
+	public String sessiontime    		= "";
+	public String session_expire_time 	= "";
+	public String transaction_time 		= "";
+	public String dtmf_type   			= "";
+	public String url_type   			= "";
+	public String srtpoption			= "";
+	public String ptime					= "";
+	public String aeconoff 				= "";
+	public String jbminmax				= "";
+	public String onenumonoff			= "";
+	public String spamonoff 	 		= "";
+	public String redirectoption   		= "";
+	public String hwsamplingrate		= "";
+	public String vad_onoff				= "";
+	public String ns_onoff				= "";
+	public String cng_onoff				= "";
+	public String audio_mode			= "";
+	public String log_lv_sip			= "";
+	public String log_lv_rtp			= "";
+	public String log_lv_cm				= "";
+	public String log_lv_mcm			= "";
+	public String log_lv_mmm			= "";
+	public String log_lv_ui				= "";
+	public String sdc_onoff				= "";
+	public String video_onoff			= "";
+
+	public String video_size			= "";
+	public String vcodec_framerate		= "";
+	public String vcodec_bandwidth		= "";
+	public String vcodec_maxbr			= "";
+	public String vcodec_h264_pmode		= "";
+	public String vcodec_mpeg4ves_pli	= "";
+		
+	public Configuration(){
+		printlog.i(THIS_FILE, "new Configuration()");
+	}	
+	
+	public Configuration(Parcel in) {
+		PrimaryKey 			= in.readInt();
+		_id 				= in.readInt();
+		phone_number 		= in.readString();
+		one_number 			= in.readString();
+		address 			= in.readString();
+		password 			= in.readString();
+		auth_id 			= in.readString();
+		proxy_addr 			= in.readString();
+		proxy_port 			= in.readString();
+		reg_addr 			= in.readString();
+		reg_port 			= in.readString();
+		local_port 			= in.readString();
+		local_media_port 	= in.readString();
+		remote_media_port 	= in.readString();
+		provider 			= in.readString();
+		acodec_pri 			= in.readString();
+		vcodec_pri 			= in.readString();
+		reregtime 			= in.readString();
+		sessiontime 		= in.readString();
+		session_expire_time = in.readString();
+		transaction_time 	= in.readString();
+		dtmf_type 			= in.readString();
+		url_type 			= in.readString();
+		srtpoption 			= in.readString();
+		ptime 				= in.readString();
+		aeconoff 			= in.readString();
+		onenumonoff 		= in.readString();
+		spamonoff 			= in.readString();
+		redirectoption 		= in.readString();
+		hwsamplingrate		= in.readString();
+		vad_onoff			= in.readString();
+		ns_onoff			= in.readString();
+		cng_onoff			= in.readString();
+		audio_mode			= in.readString();
+		log_lv_sip			= in.readString();
+		log_lv_rtp			= in.readString();
+		log_lv_cm			= in.readString();
+		log_lv_mcm			= in.readString();
+		log_lv_mmm			= in.readString();
+		log_lv_ui			= in.readString();
+		sdc_onoff			= in.readString();
+		video_onoff			= in.readString();		
+		video_size			= in.readString();
+		vcodec_framerate	= in.readString();
+		vcodec_bandwidth	= in.readString();
+		vcodec_maxbr		= in.readString();
+		vcodec_h264_pmode	= in.readString();
+		vcodec_mpeg4ves_pli	= in.readString();
+	}
+			
+	@Override
+	public int describeContents() {
+		return 0;
+	}
+
+	@Override
+	public void writeToParcel(Parcel dest, int flags) {
+		dest.writeInt(PrimaryKey);
+		dest.writeInt(_id);
+		dest.writeString(phone_number);
+		dest.writeString(one_number);
+		dest.writeString(address);
+		dest.writeString(password);
+		dest.writeString(auth_id);
+		dest.writeString(proxy_addr);
+		dest.writeString(proxy_port);
+		dest.writeString(reg_addr);
+		dest.writeString(reg_port);
+		dest.writeString(local_port);
+		dest.writeString(local_media_port);
+		dest.writeString(remote_media_port);
+		dest.writeString(provider);
+		dest.writeString(acodec_pri);
+		dest.writeString(vcodec_pri);
+		dest.writeString(reregtime);
+		dest.writeString(sessiontime);
+		dest.writeString(session_expire_time);
+		dest.writeString(transaction_time);
+		dest.writeString(dtmf_type);
+		dest.writeString(url_type);
+		dest.writeString(srtpoption);
+		dest.writeString(ptime);
+		dest.writeString(aeconoff);
+		dest.writeString(onenumonoff);
+		dest.writeString(spamonoff);
+		dest.writeString(redirectoption);
+		dest.writeString(hwsamplingrate);
+		dest.writeString(vad_onoff);
+		dest.writeString(ns_onoff);
+		dest.writeString(cng_onoff);
+		dest.writeString(audio_mode);
+		dest.writeString(log_lv_sip);
+		dest.writeString(log_lv_rtp);
+		dest.writeString(log_lv_cm);
+		dest.writeString(log_lv_mcm);
+		dest.writeString(log_lv_mmm);
+		dest.writeString(log_lv_ui);
+		dest.writeString(sdc_onoff);
+		dest.writeString(video_onoff);
+		dest.writeString(video_size);
+		dest.writeString(vcodec_framerate);
+		dest.writeString(vcodec_bandwidth);
+		dest.writeString(vcodec_maxbr);
+		dest.writeString(vcodec_h264_pmode);
+		dest.writeString(vcodec_mpeg4ves_pli);	
+	}
+		
+	public static final Creator<Configuration> CREATOR = new Creator<Configuration>() {
+		public Configuration createFromParcel(Parcel in) {
+			return new Configuration(in);
+		}
+
+		public Configuration[] newArray(int size) {
+			return new Configuration[size];
+		}
+	};
+		
+	public void createFromDb(Cursor c) {
+		ContentValues args = new ContentValues();
+		DatabaseUtils.cursorRowToContentValues(c, args);
+		Integer tmp_i;
+		String tmp_s;
+
+		// Application specific settings
+		tmp_i = args.getAsInteger(FIELD_ID);
+		if (tmp_i != null) {
+			_id = tmp_i;
+		}
+		tmp_s = args.getAsString(PHONE_NUMBER);
+		if (tmp_s != null) {
+			phone_number = tmp_s;
+		}
+		tmp_s = args.getAsString(ONE_NUMBER);
+		if (tmp_s != null) {
+			one_number = tmp_s;
+		}
+		tmp_s = args.getAsString(ADDRESS);
+		if (tmp_s != null) {
+			address = tmp_s;
+		}
+		tmp_s = args.getAsString(PASSWORD);
+		if (tmp_s != null) {
+			password = tmp_s;
+		}
+		tmp_s = args.getAsString(AUTH_ID);
+		if (tmp_s != null) {
+			auth_id = tmp_s;
+		}		
+		tmp_s = args.getAsString(PROXY_ADDR);
+		if (tmp_s != null) {
+			proxy_addr = tmp_s;
+		} 
+		tmp_s = args.getAsString(PROXY_PORT);
+		if (tmp_s != null) {
+			proxy_port = tmp_s;
+		}
+		tmp_s = args.getAsString(REG_ADDR);
+		if (tmp_s != null) {
+			reg_addr = tmp_s;
+		}
+		tmp_s = args.getAsString(REG_PORT);
+		if (tmp_s != null) {
+			reg_port = tmp_s;
+		}				
+		tmp_s = args.getAsString(LOCAL_PORT);
+		if (tmp_s != null) {
+			local_port = tmp_s;
+		}
+		tmp_s = args.getAsString(LOCAL_MEDIA_PORT);
+		if (tmp_s != null) {
+			local_media_port = tmp_s;
+		}
+		tmp_s = args.getAsString(REMOTE_MEDIA_PORT);
+		if (tmp_s != null) {
+			remote_media_port = tmp_s;
+		}
+		tmp_s = args.getAsString(PROVIDER);
+		if (tmp_s != null) {
+			provider = tmp_s;
+		}
+		tmp_s = args.getAsString(ACODEC_PRI);
+		if (tmp_s != null) {
+			acodec_pri = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_PRI);
+		if (tmp_s != null) {
+			vcodec_pri = tmp_s;
+		}
+		tmp_s = args.getAsString(REREGTIME);
+		if (tmp_s != null) {
+			reregtime = tmp_s;
+		}
+		tmp_s = args.getAsString(SESSIONTIME);
+		if (tmp_s != null) {
+			sessiontime = tmp_s;
+		}		
+		tmp_s = args.getAsString(SESSION_EXPIRE_TIME);
+		if (tmp_s != null) {
+			session_expire_time = tmp_s;
+		} 
+		tmp_s = args.getAsString(TRANSACTION_TIME);
+		if (tmp_s != null) {
+			transaction_time = tmp_s;
+		}
+		tmp_s = args.getAsString(DTMF_TYPE);
+		if (tmp_s != null) {
+			dtmf_type = tmp_s;
+		}
+		tmp_s = args.getAsString(URL_TYPE);
+		if (tmp_s != null) {
+			url_type = tmp_s;
+		}				
+		tmp_s = args.getAsString(SRTPOPTION);
+		if (tmp_s != null) {
+			srtpoption = tmp_s;
+		}
+		tmp_s = args.getAsString(PTIME);
+		if (tmp_s != null) {
+			ptime = tmp_s;
+		}
+		tmp_s = args.getAsString(AECONOFF);
+		if (tmp_s != null) {
+			aeconoff = tmp_s;
+		}
+		tmp_s = args.getAsString(JBMINMAX);
+		if (tmp_s != null) {
+			jbminmax = tmp_s;
+		}
+		tmp_s = args.getAsString(ONENUMONOFF);
+		if (tmp_s != null) {
+			onenumonoff = tmp_s;
+		}
+		tmp_s = args.getAsString(SPAMONOFF);
+		if (tmp_s != null) {
+			spamonoff = tmp_s;
+		}
+		tmp_s = args.getAsString(REDIRECTOPTION);
+		if (tmp_s != null) {
+			redirectoption = tmp_s;
+		}
+		tmp_s = args.getAsString(HWSAMPLINGRATE);
+		if (tmp_s != null) {
+			hwsamplingrate = tmp_s;
+		}
+		tmp_s = args.getAsString(VAD_ONOFF);
+		if (tmp_s != null) {
+			vad_onoff = tmp_s;
+		}
+		tmp_s = args.getAsString(NS_ONOFF);
+		if (tmp_s != null) {
+			ns_onoff = tmp_s;
+		}
+		tmp_s = args.getAsString(CNG_ONOFF);
+		if (tmp_s != null) {
+			cng_onoff = tmp_s;
+		}
+		tmp_s = args.getAsString(AUDIO_MODE);
+		if (tmp_s != null) {
+			audio_mode = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_SIP);
+		if (tmp_s != null) {
+			log_lv_sip = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_RTP);
+		if (tmp_s != null) {
+			log_lv_rtp = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_CM);
+		if (tmp_s != null) {
+			log_lv_cm = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_MCM);
+		if (tmp_s != null) {
+			log_lv_mcm = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_MMM);
+		if (tmp_s != null) {
+			log_lv_mmm = tmp_s;
+		}
+		tmp_s = args.getAsString(LOG_LV_UI);
+		if (tmp_s != null) {
+			log_lv_ui = tmp_s;
+		}
+		tmp_s = args.getAsString(SDC_ONOFF);
+		if (tmp_s != null) {
+			sdc_onoff = tmp_s;
+		}
+		tmp_s = args.getAsString(VIDEO_ONOFF);
+		if (tmp_s != null) {
+			video_onoff = tmp_s;
+		}
+		
+		tmp_s = args.getAsString(VIDEO_SIZE);
+		if (tmp_s != null) {
+			video_size = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_FRAMERATE);
+		if (tmp_s != null) {
+			vcodec_framerate = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_BANDWIDTH);
+		if (tmp_s != null) {
+			vcodec_bandwidth = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_MAXBR);
+		if (tmp_s != null) {
+			vcodec_maxbr = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_H264_PMODE);
+		if (tmp_s != null) {
+			vcodec_h264_pmode = tmp_s;
+		}
+		tmp_s = args.getAsString(VCODEC_MPEG4VES_PLI);
+		if (tmp_s != null) {
+			vcodec_mpeg4ves_pli = tmp_s;
+		}				
+	}
+		
+	/**
+	 * Transform ceres_config into ContentValues that can be insert into database
+	 * MCONFTB => ContentValues
+	 */
+	public ContentValues getDbContentValues() {
+		ContentValues args = new ContentValues();
+				
+		if(_id != INVALID_ID){
+			args.put(FIELD_ID, _id);
+		}
+		
+		args.put(PHONE_NUMBER, phone_number);
+		args.put(ONE_NUMBER, one_number);
+		args.put(ADDRESS, address); 
+		args.put(PASSWORD, password); 
+		args.put(AUTH_ID, auth_id); 
+		args.put(PROXY_ADDR, proxy_addr);
+		args.put(PROXY_PORT, proxy_port);
+		args.put(REG_ADDR, reg_addr); 
+		args.put(REG_PORT, reg_port); 
+		args.put(LOCAL_PORT, local_port);
+		args.put(LOCAL_MEDIA_PORT, local_media_port); 
+		args.put(REMOTE_MEDIA_PORT, remote_media_port); 
+		
+		args.put(PROVIDER, provider);
+		args.put(ACODEC_PRI, acodec_pri);
+		args.put(VCODEC_PRI, vcodec_pri); 
+		args.put(REREGTIME, reregtime); 
+		args.put(SESSIONTIME, sessiontime); 
+		args.put(SESSION_EXPIRE_TIME, session_expire_time);
+		args.put(TRANSACTION_TIME, transaction_time);
+		args.put(DTMF_TYPE, dtmf_type); 
+		args.put(URL_TYPE, url_type); 
+		args.put(SRTPOPTION, srtpoption);
+		args.put(PTIME, ptime);
+		
+		args.put(AECONOFF, aeconoff);
+		args.put(JBMINMAX, jbminmax);
+		args.put(ONENUMONOFF, onenumonoff);
+		args.put(SPAMONOFF, spamonoff); 
+		args.put(REDIRECTOPTION, redirectoption);
+		args.put(HWSAMPLINGRATE, hwsamplingrate);
+		
+		args.put(VAD_ONOFF, vad_onoff);
+		args.put(NS_ONOFF, ns_onoff); 
+		args.put(CNG_ONOFF, cng_onoff);
+		args.put(AUDIO_MODE, audio_mode);
+		
+		args.put(LOG_LV_SIP, log_lv_sip);
+		args.put(LOG_LV_RTP, log_lv_rtp);
+		args.put(LOG_LV_CM, log_lv_cm);
+		args.put(LOG_LV_MCM, log_lv_mcm);
+		args.put(LOG_LV_MMM, log_lv_mmm);
+		args.put(LOG_LV_UI, log_lv_ui);
+		args.put(SDC_ONOFF, sdc_onoff);
+		args.put(VIDEO_ONOFF, video_onoff);
+		
+		args.put(VIDEO_SIZE, video_size);
+		args.put(VCODEC_FRAMERATE, vcodec_framerate);
+		args.put(VCODEC_BANDWIDTH, vcodec_bandwidth);
+		args.put(VCODEC_MAXBR, vcodec_maxbr);
+		args.put(VCODEC_H264_PMODE, vcodec_h264_pmode);
+		args.put(VCODEC_MPEG4VES_PLI, vcodec_mpeg4ves_pli);			
+		
+		return args;
+	}
+		
+	// Android API
+	@SuppressWarnings("static-access")
+	public String getDisplayName() {
+		if(phone_number != null) {		
+			String mPhoneNumber = base64.decryptToString(phone_number);
+			printlog.i(THIS_FILE,"phone_num is : " + phone_number);
+			printlog.i(THIS_FILE,"decrypt phone_num is : " + mPhoneNumber);
+			
+			return mPhoneNumber;			
+		}
+		return "";
+	}
+	
+	static String RedialNumber = null;
+
+	public String getRedialNumber() {
+		return RedialNumber;
+	}
+
+	public void setRedialNumber(String number) {
+		if (number != null)
+			RedialNumber = number;
+	}
+	
+	public String getSRTPState(){
+		if(srtpoption != null){
+			printlog.i(THIS_FILE,"srtp is state is :" + srtpoption);
+			return srtpoption;
+		}
+		return "";
+	}
+	
+	/**
+	 * Gets the password.
+	 * @return
+	 */
+	public String getPassword() {
+		if(password != null){
+			return password;
+		}		
+		return "";
+	}
+	
+	/**
+	 * Gets the port number of the SIP server.
+	 * @return
+	 */
+	public String getPort() {
+		if(local_port != null){
+			return local_port;
+		}		
+		return "";
+	}
+
+	// 통화주체를 다루는 enum
+	public enum CALLOWNER {
+		NONE,
+		WALLPAD,
+		SUB_WALLPAD,
+		KITCHEN_TV_01,
+		KITCHEN_TV_02,
+		KITCHEN_TV_03,
+		KITCHEN_TV_04,
+		KITCHEN_TV_05,
+		KITCHEN_TV_06,
+		KITCHEN_TV_07,
+		KITCHEN_TV_08,
+		KITCHEN_TV_09,
+		KITCHEN_TV_10,
+		BATH_PHONE_01,
+		BATH_PHONE_02,
+		BATH_PHONE_03,
+		BATH_PHONE_04,
+		BATH_PHONE_05,
+		BATH_PHONE_06,
+		BATH_PHONE_07,
+		BATH_PHONE_08,
+		BATH_PHONE_09,
+		BATH_PHONE_10,
+		BATH_TV_01,
+		BATH_TV_02,
+		BATH_TV_03,
+		BATH_TV_04,
+		BATH_TV_05,
+		BATH_TV_06,
+		BATH_TV_07,
+		BATH_TV_08,
+		BATH_TV_09,
+		BATH_TV_10,
+		UNIVERSAL_DEVICE,
+		MOBILE,
+		ERROR;
+
+		public static CALLOWNER getCALLOWNER(String value) {
+			try {
+				if (value.equals(NONE.toString())) {
+					return NONE;
+				} else if (value.equals(WALLPAD.toString())) {
+					return WALLPAD;
+				} else if (value.equals(SUB_WALLPAD.toString())) {
+					return SUB_WALLPAD;
+				} else if (value.equals(KITCHEN_TV_01.toString())) {
+					return KITCHEN_TV_01;
+				} else if (value.equals(KITCHEN_TV_02.toString())) {
+					return KITCHEN_TV_02;
+				} else if (value.equals(KITCHEN_TV_03.toString())) {
+					return KITCHEN_TV_03;
+				} else if (value.equals(KITCHEN_TV_04.toString())) {
+					return KITCHEN_TV_04;
+				} else if (value.equals(KITCHEN_TV_05.toString())) {
+					return KITCHEN_TV_05;
+				} else if (value.equals(KITCHEN_TV_06.toString())) {
+					return KITCHEN_TV_06;
+				} else if (value.equals(KITCHEN_TV_07.toString())) {
+					return KITCHEN_TV_07;
+				} else if (value.equals(KITCHEN_TV_08.toString())) {
+					return KITCHEN_TV_08;
+				} else if (value.equals(KITCHEN_TV_09.toString())) {
+					return KITCHEN_TV_09;
+				} else if (value.equals(KITCHEN_TV_10.toString())) {
+					return KITCHEN_TV_10;
+				} else if (value.equals(BATH_PHONE_01.toString())) {
+					return BATH_PHONE_01;
+				} else if (value.equals(BATH_PHONE_02.toString())) {
+					return BATH_PHONE_02;
+				} else if (value.equals(BATH_PHONE_03.toString())) {
+					return BATH_PHONE_03;
+				} else if (value.equals(BATH_PHONE_04.toString())) {
+					return BATH_PHONE_04;
+				} else if (value.equals(BATH_PHONE_05.toString())) {
+					return BATH_PHONE_05;
+				} else if (value.equals(BATH_PHONE_06.toString())) {
+					return BATH_PHONE_06;
+				} else if (value.equals(BATH_PHONE_07.toString())) {
+					return BATH_PHONE_07;
+				} else if (value.equals(BATH_PHONE_08.toString())) {
+					return BATH_PHONE_08;
+				} else if (value.equals(BATH_PHONE_09.toString())) {
+					return BATH_PHONE_09;
+				} else if (value.equals(BATH_PHONE_10.toString())) {
+					return BATH_PHONE_10;
+				} else if (value.equals(BATH_TV_01.toString())) {
+					return BATH_TV_01;
+				} else if (value.equals(BATH_TV_02.toString())) {
+					return BATH_TV_02;
+				} else if (value.equals(BATH_TV_03.toString())) {
+					return BATH_TV_03;
+				} else if (value.equals(BATH_TV_04.toString())) {
+					return BATH_TV_04;
+				} else if (value.equals(BATH_TV_05.toString())) {
+					return BATH_TV_05;
+				} else if (value.equals(BATH_TV_06.toString())) {
+					return BATH_TV_06;
+				} else if (value.equals(BATH_TV_07.toString())) {
+					return BATH_TV_07;
+				} else if (value.equals(BATH_TV_08.toString())) {
+					return BATH_TV_08;
+				} else if (value.equals(BATH_TV_09.toString())) {
+					return BATH_TV_09;
+				} else if (value.equals(BATH_TV_10.toString())) {
+					return BATH_TV_10;
+				} else if (value.equals(UNIVERSAL_DEVICE.toString())) {
+					return UNIVERSAL_DEVICE;
+				} else if (value.equals(MOBILE.toString())) {
+					return MOBILE;
+				} else if (value.equals(ERROR.toString())) {
+					return ERROR;
+				} else {
+					return null;
+				}
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] getCALLOWNER()");
+				e.printStackTrace();
+				return null;
+			}
+		}
+	}
+
+	public static class CALLTRIGGER {
+		public static String CALLOWNER = "CALLOWNER";
+		public static String CALLSTATUSTYPE = "CALLSTATUSTYPE";
+		public static String CALLEVENTTYPE = "CALLEVENTTYPE";
+		public static String CALLTYPE = "CALLTYPE";
+		public static String REMOTEINFO = "REMOTEINFO";
+
+		public enum SOURCE {
+			USER,
+			CALL_RECEIVE,
+			SUBPHONE
+		}
+
+		public enum TYPE {
+			MENU,
+			FRONT,
+			LOBBY,
+			GUARD,
+			RESIDENCE,
+			PSTN
+		}
+	}
+
+	public enum CALLEVENTTYPE {
+		RECEIVE_CALL,   // 호출 수신 (호출 수신)
+		TRYING_CALL,   // 호출 시도중 (호출 발신)
+		RECEIVE_CALL_2ND,   // 멀티콜 수신 (호출 수신)
+		RECEIVE_CALL_ACK,   // 호출응답 수신 (호출 발신)
+		REQUEST_FRONT_MONITORING,   // 호출응답 수신 (호출 발신)
+		REQUEST_RESIDENCE_CALL, // 이웃통화 요청 수신 (호출 발신)
+		CONNECT_CALL,   // 통화 시작
+		TERMINATE_CALL,   // 통화 종료
+		CANCEL_CALL,   // 호출 취소
+		CANCEL_CALL_2ND,   // 멀티콜 호출 취소
+		REJECT_CALL,   // 호출수신 거절
+		REJECT_BUSY_CALL,   // 통화중 호출수신 거절
+		FORWARD_CALL,   // 착신전환 설정
+		CALLERID,   // Caller ID
+		TIMEOUT_1STCALL,   // 1st Call Timeout
+		TIMEOUT_2NDCALL,   // 2nd Call Timeout
+		TIMEOUT_3RDCALL,   // 3rd Call Timeout
+		MOIP_VIDEO_SET,   // MoIP 영상통화 설정
+		DOOR_OPEN,   // 문열림 설정
+		PSTN_RING,   // PSTN ARS동작을 위해, UI에서 Ring을 카운트 하기위한 이벤트
+		PSTN_DTMF,   // PSTN DTMF 수신
+		DETECT_STRANGER, // 거동수상자 발생
+		INITIALIZE_ALLCALL, // 초기화 (서브월패드인 경우에만 사용함)
+		NONE;
+
+		public static CALLEVENTTYPE getCALLEVENTTYPE(String value) {
+			try {
+				if (value.equals(RECEIVE_CALL.toString())) {
+					return RECEIVE_CALL;
+				} else if (value.equals(TRYING_CALL.toString())) {
+					return TRYING_CALL;
+				} else if (value.equals(RECEIVE_CALL_2ND.toString())) {
+					return RECEIVE_CALL_2ND;
+				} else if (value.equals(RECEIVE_CALL_ACK.toString())) {
+					return RECEIVE_CALL_ACK;
+				} else if (value.equals(REQUEST_FRONT_MONITORING.toString())) {
+					return REQUEST_FRONT_MONITORING;
+				} else if (value.equals(CONNECT_CALL.toString())) {
+					return CONNECT_CALL;
+				} else if (value.equals(TERMINATE_CALL.toString())) {
+					return TERMINATE_CALL;
+				} else if (value.equals(CANCEL_CALL.toString())) {
+					return CANCEL_CALL;
+				} else if (value.equals(REJECT_CALL.toString())) {
+					return REJECT_CALL;
+				} else if (value.equals(REJECT_BUSY_CALL.toString())) {
+					return REJECT_BUSY_CALL;
+				} else if (value.equals(FORWARD_CALL.toString())) {
+					return FORWARD_CALL;
+				} else if (value.equals(CALLERID.toString())) {
+					return CALLERID;
+				} else if (value.equals(TIMEOUT_1STCALL.toString())) {
+					return TIMEOUT_1STCALL;
+				} else if (value.equals(TIMEOUT_2NDCALL.toString())) {
+					return TIMEOUT_2NDCALL;
+				} else if (value.equals(TIMEOUT_3RDCALL.toString())) {
+					return TIMEOUT_3RDCALL;
+				} else if (value.equals(MOIP_VIDEO_SET.toString())) {
+					return MOIP_VIDEO_SET;
+				} else if (value.equals(DOOR_OPEN.toString())) {
+					return DOOR_OPEN;
+				} else if (value.equals(PSTN_RING.toString())) {
+					return PSTN_RING;
+				} else if (value.equals(PSTN_DTMF.toString())) {
+					return PSTN_DTMF;
+				} else if (value.equals(DETECT_STRANGER.toString())) {
+					return DETECT_STRANGER;
+				} else if (value.equals(INITIALIZE_ALLCALL.toString())) {
+					return INITIALIZE_ALLCALL;
+				} else if (value.equals(NONE.toString())) {
+					return NONE;
+				} else {
+					return null;
+				}
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] getCALLEVENTTYPE()");
+				e.printStackTrace();
+				return null;
+			}
+		}
+	}
+
+	// 통화상태정보를 다루는 enum
+	public enum CALLTYPE {
+		NONE,
+		FRONT,
+		//        FRONT_RECORD, // 현관 거동수상자 영상 녹화
+//        FRONT_TAKEPIC, // 현관 거동수상자 사진 촬영
+		RESIDENCE,
+		RENTRESIDENCE,
+		LOBBY,
+		GUARD,
+		PSTN,
+		IHUB,
+		HISTORY_CALL,
+		HISTORY_VISITORPIC,
+		ERROR;
+
+		public static CALLTYPE getCALLTYPE(String value) {
+			try {
+				if (value.equals(NONE.toString())) {
+					return NONE;
+				}
+				else if (value.equals(FRONT.toString())) {
+					return FRONT;
+				}
+//                else if (value.equals(FRONT_RECORD.toString())) {
+//                    return FRONT_RECORD;
+//                }
+//                else if (value.equals(FRONT_TAKEPIC.toString())) {
+//                    return FRONT_TAKEPIC;
+//                }
+				else if (value.equals(RESIDENCE.toString())) {
+					return RESIDENCE;
+				}
+				else if (value.equals(LOBBY.toString())) {
+					return LOBBY;
+				}
+				else if (value.equals(GUARD.toString())) {
+					return GUARD;
+				}
+				else if (value.equals(PSTN.toString())) {
+					return PSTN;
+				}
+				else if (value.equals(IHUB.toString())) {
+					return IHUB;
+				}
+				else if (value.equals(HISTORY_CALL.toString())) {
+					return HISTORY_CALL;
+				}
+				else if (value.equals(HISTORY_VISITORPIC.toString())) {
+					return HISTORY_VISITORPIC;
+				}
+				else if (value.equals(ERROR.toString())) {
+					return ERROR;
+				}
+				else {
+					return null;
+				}
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] getCALLTYPE()");
+				e.printStackTrace();
+				return null;
+			}
+		}
+	}
+
+	public enum CALLSTATUS {
+		IDLE,   // 대기중
+		TRYING_CALL,   // 통화가능여부 확인중
+		WAITNG_INVITE_ACK,   // 호출에 대한 응답 대기중
+		CALLING,   // 호출중
+		CALLED,   // 호출수신중
+		TALKING,   // 통화중
+		REJECT,   // 거절
+		BUSY,   // 통화중 거절
+		FORWARD,   // 착신전환
+		CANCEL,   // 호출 취소
+		END,   // 종료
+		TIMEOUT_1STCALL,   // 1st Call Timeout
+		TIMEOUT_2NDCALL,   // 2nd Call Timeout
+		TIMEOUT_3RDCALL,   // 3rd Call Timeout
+		CALLERID,   // CALLERID
+		DOOR_OPEN,   // 문열림 요청
+		PSTN_RING,   // ARS 동작을 위해, Ring 카운트를 한다.
+		RECORDING,   // 거동수상자 영상 녹화중
+		TAKINGPIC,   // 거동수상자 사진 촬영중
+		HOMEVIEW;    // 방문객원격통화 홈뷰어
+
+		public static CALLSTATUS getCALLSTATUS(String value) {
+			try {
+				if (value.equals(IDLE.toString())) {
+					return IDLE;
+				} else if (value.equals(TRYING_CALL.toString())) {
+					return TRYING_CALL;
+				} else if (value.equals(WAITNG_INVITE_ACK.toString())) {
+					return WAITNG_INVITE_ACK;
+				} else if (value.equals(CALLING.toString())) {
+					return CALLING;
+				} else if (value.equals(CALLED.toString())) {
+					return CALLED;
+				} else if (value.equals(TALKING.toString())) {
+					return TALKING;
+				} else if (value.equals(REJECT.toString())) {
+					return REJECT;
+				} else if (value.equals(BUSY.toString())) {
+					return BUSY;
+				} else if (value.equals(FORWARD.toString())) {
+					return FORWARD;
+				} else if (value.equals(CANCEL.toString())) {
+					return CANCEL;
+				} else if (value.equals(END.toString())) {
+					return END;
+				} else if (value.equals(TIMEOUT_1STCALL.toString())) {
+					return TIMEOUT_1STCALL;
+				} else if (value.equals(TIMEOUT_2NDCALL.toString())) {
+					return TIMEOUT_2NDCALL;
+				} else if (value.equals(TIMEOUT_3RDCALL.toString())) {
+					return TIMEOUT_3RDCALL;
+				} else if (value.equals(CALLERID.toString())) {
+					return CALLERID;
+				} else if (value.equals(DOOR_OPEN.toString())) {
+					return DOOR_OPEN;
+				} else if (value.equals(PSTN_RING.toString())) {
+					return PSTN_RING;
+				} else if (value.equals(RECORDING.toString())) {
+					return RECORDING;
+				} else if (value.equals(TAKINGPIC.toString())) {
+					return TAKINGPIC;
+				} else if (value.equals(HOMEVIEW.toString())) {
+					return HOMEVIEW;
+				} else {
+					return null;
+				}
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] getCALLSTATUS()");
+				e.printStackTrace();
+				return null;
+			}
+		}
+	}
+
+}

+ 127 - 0
WallPadCall/src/main/java/ceres/api/SipConfigManager.java

@@ -0,0 +1,127 @@
+package ceres.api;
+
+import android.net.ConnectivityManager;
+import android.telephony.TelephonyManager;
+
+import ceres.utils.printlog;
+
+public class SipConfigManager {
+
+	//Media
+	public static final String SND_MEDIA_QUALITY = "snd_media_quality";
+	public static final String ECHO_CANCELLATION_TAIL = "echo_cancellation_tail";
+	public static final String RTP_PORT = "network_rtp_port";
+	public static final String TCP_TRANSPORT_PORT = "network_tcp_transport_port";
+	public static final String UDP_TRANSPORT_PORT = "network_udp_transport_port";
+	public static final String SND_AUTO_CLOSE_TIME = "snd_auto_close_time";
+	public static final String SND_CLOCK_RATE = "snd_clock_rate";
+	public static final String ECHO_CANCELLATION = "echo_cancellation";
+	public static final String ENABLE_VAD = "enable_vad";
+	public static final String SND_MIC_LEVEL = "snd_mic_level";
+	public static final String SND_SPEAKER_LEVEL = "snd_speaker_level";
+	public static final String HAS_IO_QUEUE = "has_io_queue";
+	public static final String BITS_PER_SAMPLE = "bits_per_sample";
+	public static final String SET_AUDIO_GENERATE_TONE = "set_audio_generate_tone";
+	public static final String THREAD_COUNT = "thread_count";
+	public static final String ECHO_MODE = "echo_mode";
+	public static final String SND_PTIME = "snd_ptime";
+	
+	//UI
+	public static final String USE_SOFT_VOLUME = "use_soft_volume";
+	public static final String PREVENT_SCREEN_ROTATION = "prevent_screen_rotation";
+	public static final String LOG_LEVEL = "log_level";
+	public static final String DTMF_MODE = "dtmf_mode";
+	public static final String USE_ROUTING_API = "use_routing_api";
+	public static final String USE_MODE_API = "use_mode_api";
+	public static final String SIP_AUDIO_MODE = "sip_audio_mode";
+	public static final String ICON_IN_STATUS_BAR = "icon_in_status_bar";
+	public static final String KEEP_AWAKE_IN_CALL = "keep_awake_incall";
+	public static final String GSM_INTEGRATION_TYPE = "gsm_integration_type";
+	public static final String DIAL_PRESS_TONE_MODE = "dial_press_tone_mode";
+	public static final String DIAL_PRESS_VIBRATE_MODE = "dial_press_vibrate_mode";
+	public static final String INVERT_PROXIMITY_SENSOR = "invert_proximity_sensor";
+	public static final String USE_PARTIAL_WAKE_LOCK = "use_partial_wake_lock";
+	
+	
+	// NETWORK
+	public static final String TURN_SERVER = "turn_server";
+	public static final String ENABLE_TURN = "enable_turn";
+	public static final String ENABLE_ICE = "enable_ice";
+	public static final String ENABLE_STUN = "enable_stun";
+	public static final String STUN_SERVER = "stun_server";
+	public static final String USE_IPV6 = "use_ipv6";
+	public static final String ENABLE_UDP = "enable_udp";
+	public static final String ENABLE_TCP = "enable_tcp";
+	public static final String LOCK_WIFI = "lock_wifi";
+	public static final String ENABLE_DNS_SRV = "enable_dns_srv";
+	public static final String ENABLE_QOS = "enable_qos";
+	public static final String DSCP_VAL = "dscp_val";
+	public static final String KEEP_ALIVE_INTERVAL_WIFI = "keep_alive_interval_wifi";
+	public static final String KEEP_ALIVE_INTERVAL_MOBILE = "keep_alive_interval_mobile";
+	public static final String OVERRIDE_NAMESERVER = "override_nameserver";
+	
+	// SECURE
+	public static final String ENABLE_TLS = "enable_tls";
+	public static final String TLS_TRANSPORT_PORT = "network_tls_transport_port";
+//	public static final String TLS_SERVER_NAME = "network_tls_server_name";
+//	public static final String CA_LIST_FILE = "ca_list_file";
+//	public static final String CERT_FILE = "cert_file";
+//	public static final String PRIVKEY_FILE = "privkey_file";
+//	public static final String TLS_PASSWORD = "tls_password";
+	public static final String TLS_VERIFY_SERVER = "tls_verify_server";
+//	public static final String TLS_VERIFY_CLIENT = "tls_verify_client";
+	public static final String TLS_METHOD = "tls_method";
+	public static final String USE_SRTP = "use_srtp";
+	
+	// CALLS
+	public static final String AUTO_RECORD_CALLS = "auto_record_calls";
+	public static final String DEFAULT_CALLER_ID = "default_caller_id";
+	
+//	public static final String CODEC_NB = "nb";
+//	public static final String CODEC_WB = "wb";
+	
+	public static final String CODEC_VIDEO = "video";
+	public static final String CODEC_AUDIO = "audio";
+	
+	public static final String THIS_FILE = "SipConfigManager";
+	public static final String FILTER_STR = "codecs_test";
+	
+	public static String getCodecKey(String codecName, String type) {
+		String[] codecParts = codecName.split("/");
+		String preferenceKey = null;
+		if(codecParts.length >=2 ) {
+			printlog.i(THIS_FILE, FILTER_STR, "getCodecKey : " + "codec_" + codecParts[0].toLowerCase() + "_" + codecParts[1] + "_" + type);
+			return "codec_" + codecParts[0].toLowerCase() + "_" + codecParts[1] + "_" + type;
+		}
+		return preferenceKey;
+	}
+	
+	private static String keyForNetwork(int networkType, int subType) {
+		if(networkType == ConnectivityManager.TYPE_WIFI) {
+			return "wifi";
+		}else if(networkType == ConnectivityManager.TYPE_MOBILE) {
+			// 3G (or better)
+			if (subType >= TelephonyManager.NETWORK_TYPE_UMTS) {
+				return "3g";
+			}
+			
+			// GPRS (or unknown)
+			if ( subType == TelephonyManager.NETWORK_TYPE_GPRS || subType == TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+				return "gprs";
+			}
+			
+			// EDGE
+			if ( subType == TelephonyManager.NETWORK_TYPE_EDGE) {
+				return "edge";
+			}
+		}
+		
+		return "other";
+	}
+	
+	public static String getBandTypeKey(int networkType, int subType) {
+		return "band_for_" + keyForNetwork(networkType, subType);
+	}
+	
+	
+}

+ 425 - 0
WallPadCall/src/main/java/ceres/api/SipManager.java

@@ -0,0 +1,425 @@
+package ceres.api;
+
+import android.os.Build;
+
+import ceres.srinterface.SRInterface.VideoSize;
+
+public final class SipManager {
+
+	// ------------------------------------------------------------------------------
+	// Static constants
+	// ------------------------------------------------------------------------------      
+	// ------------------------------------------------------------------------------
+	// ACTIONS
+	// ------------------------------------------------------------------------------
+	public static final String ACTION_SIP_CALL_UI = "com.cnstec.phone.action.CALLUI";
+	public static final String ACTION_SIP_ON_CALL = "com.cnstec.phone.action.ONCALL";
+	public static final String ACTION_SIP_DIALER = "com.cnstec.phone.action.DIALER";
+	public static final String ACTION_SIP_CALLLOG = "com.cnstec.phone.action.CALLLOG";
+	public static final String ACTION_SIP_MESSAGES = "com.cnstec.phone.action.MESSAGES";
+	public static final String ACTION_VIDEO_CALL = "com.cnstec.phone.action.VIDEO";
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// SERVICE BROADCASTS
+	// ------------------------------------------------------------------------------	
+	public static final String ACTION_SIP_CALL_CHANGED = "com.cnstec.service.CALL_CHANGED";
+	public static final String ACTION_SIP_REGISTRATION_CHANGED = "com.cnstec.service.REGISTRATION_CHANGED";
+	public static final String ACTION_SIP_MEDIA_CHANGED = "com.cnstec.service.MEDIA_CHANGED";
+	public static final String ACTION_SIP_ACCOUNT_ACTIVE_CHANGED = "com.cnstec.service.ACCOUNT_ACTIVE_CHANGED";
+	public static final String ACTION_SIP_MESSAGE_RECEIVED = "com.cnstec.service.MESSAGE_RECEIVED";
+	//TODO : message sent?
+	public static final String ACTION_SIP_MESSAGE_STATUS = "com.cnstec.service.MESSAGE_STATUS";
+	// ------------------------------------------------------------------------------
+
+
+	// ------------------------------------------------------------------------------
+	// EXTRAS
+	// ------------------------------------------------------------------------------
+	public static final String EXTRA_CALL_INFO = "call_info";
+	public static final String EXTRA_CALL_STATE = "call_state";
+	public static final String EXTRA_ACCOUNT_ID = "acc_id";
+	public static final String EXTRA_ACTIVATE = "activate";
+	public static final String EXTRA_AECTNTB_ID = "aectntb_id";
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// PROVIDER
+	// ------------------------------------------------------------------------------
+	public static final int PROV_IPDIALING = 0;
+	public static final int PROV_GENERAL = 1;
+	public static final int DEFAULT_PROVIDER = 1;
+	public static final String GENERAL_SETTINGS = "*1234#";
+	public static final String IPDIALING_SETTINGS = "*4321#";
+	public static final String LOOPBACK_STRING = "147.0#";
+	public static final String LOOPBACK_NUMBER = "Loopback";
+	
+	public static final String DEFAULT_SDCONOFF = "0";
+	public static final String DEFAULT_VIDEOONOFF = "1";
+	public static final String VIDEO_OFF = "0";
+	public static final String VIDEO_ON = "1";
+	public static final String SDC_OFF = "0";
+	public static final String SDC_ON = "1";
+	
+	// 0 : QCIF, 1 : CIF, 2 : VGA, 3 : CUSTOM, 4 : QVGA
+	//public static final String DEFAULT_VIDEO_SIZE = "2";
+	public static final String DEFAULT_VIDEO_SIZE = "1"; // homepad
+	public static final String DEFAULT_VCODEC_FRAMERATE = "1";
+	public static final String DEFAULT_VCODEC_BANDWIDTH = "0";
+	public static final String DEFAULT_VCODEC_MAXBR = "0";
+	public static final String DEFAULT_VCODEC_H264_PMODE = "0";
+	public static final String DEFAULT_VCODEC_MPEG4VES_PLI = "1";
+	
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// DEVICE INFO : DEVICE NAME, DEVICE PLATFORM VERSION
+	// ------------------------------------------------------------------------------
+	//public static final String DEVICE_NAME = Build.DEVICE.substring(4, 8);
+	public static final String DEVICE_NAME = Build.DEVICE;
+	public static final String DEVICE_NAME_FULL = Build.DEVICE;
+	public static final String DEVICE_PLATFORM_VERSION = Build.VERSION.RELEASE.substring(0,3);
+
+	// ------------------------------------------------------------------------------
+	// DEVICE INFO 
+	// ------------------------------------------------------------------------------
+	public static final String BUILD_BOARD = "build_board";
+	public static final String BUILD_BRAND = "build_brand";
+	public static final String BUILD_CPU_ABI = "build_cpu_abi";
+	public static final String BUILD_DEVICE = "build_device";
+	public static final String BUILD_VERSION = "build_version";
+	public static final String BUILD_DISPLAY = "build_display";
+	public static final String BUILD_FINGERPRINT = "build_fingerprint";
+	public static final String BUILD_HOST = "build_host";
+	public static final String BUILD_ID = "build_id";
+	public static final String BUILD_MODEL = "build_model";
+	public static final String BUILD_PRODUCT = "build_product";
+	public static final String BUILD_TAGS = "build_tags";
+	public static final String BUILD_TYPE = "build_type";
+	public static final String BUILD_USER = "build_user";
+	public static final String BUILD_SDK = "build_sdk";
+
+	// ------------------------------------------------------------------------------
+	// DEVICE NAME : 
+	// ------------------------------------------------------------------------------
+	public static final int SHW_M110S = 0;	// SKT Galaxy S
+	public static final int SHW_M180S = 1;  // SKT Galaxy Tab
+	public static final int SHW_M250S = 2;  // SKT Galaxy S2     : 2 -
+	public static final int SHV_E120K = 3;  // KT  Galaxy S2 LTE : 3 -
+	public static final int ETC_DEVICE = 4;
+
+	// ------------------------------------------------------------------------------
+	// DEVICE PLATFORM VERSION : 
+	// ------------------------------------------------------------------------------
+	public static final int ECLAIR = 1; 	// API Level
+	public static final int FROYO = 2;
+	public static final int GINGERBREAD = 3;
+	public static final int HONEYCOM = 4;
+	public static final int ICECREAMSANDWITCH = 5;
+	public static final int LOLLIPOP = 6;
+	public static final int MARSHMALLOW = 7;
+	public static final int NOUGAT = 8;
+
+	// ------------------------------------------------------------------------------
+	// CODEC PRIORITY & AEC_ON_OFF
+	// ------------------------------------------------------------------------------
+	//public static final String DEFAULT_ACODEC_LIST = "132456789";  // 1:PCMU(미국, 일본)  2:PCMA(유럽)  3:G723  4:729  5:G722  6
+	public static final String DEFAULT_ACODEC_LIST = "a1a2a3a2a4a6a5a7a8a9"; // 오디오코덱 우선순위
+	public static final String ACODEC_SILK_16K = "a11a1a2a3";
+	public static final String ACODEC_SILK_24K = "a12a1a2a3";
+	public static final String ACODEC_AMR_8K   = "a13a1a2a3";
+	public static final String ACODEC_AMR_16K  = "a14a1a2a3";
+	public static final String ACODEC_G729  = "a4a1a2a3";
+	//public static final String DEFAULT_ACODEC_LIST = "1324";
+	//public static final String DEFAULT_VCODEC_LIST = "2341";
+	// H.264 > MPEG4 > H.263 > H.263+
+	// public static final String DEFAULT_VCODEC_LIST = "a2a3a4a1"; // 128:263 130:264 131:mp4
+	public static final String DEFAULT_VCODEC_LIST = "a128a130a131a129"; // 비디오코덱 우선순위
+	public static final String DEFAULT_AEC_OFF = "0";
+	public static final String DEFAULT_INNER_AEC_ON = "1";	// AEC
+	public static final String DEFAULT_CNS_AEC_ON = "2";	// CNS AEC
+	
+	public static final String DEFAULT_JB_MIN_MAX = "a30a300";
+
+	public static final String AEC_OFF = "0";
+	public static final String INNER_AEC_ON = "1";
+	public static final String CNS_AEC_ON = "2";
+
+	public static final String DEFAULT_SRTP = "0";
+	public static final String DEFAULT_PTIME = "20";
+
+	public static final String DEFAULT_ONENUMBERONOFF = "0"; // 0:off,    1:on
+	public static final String DEFAULT_SPAMONOFF = "0"; 	 // 0:off,    1:on
+	public static final String DEFAULT_REDIRECTOPTION = "0"; // 0:1:2
+	
+	// ------------------------------------------------------------------------------
+	// Audio Sub function On, Off
+	// ------------------------------------------------------------------------------
+	public static final String VAD_ON = "1";
+	public static final String VAD_OFF = "0";
+	public static final String NS_ON = "1";
+	public static final String NS_OFF = "0";
+	public static final String CNG_ON = "1";
+	public static final String CNG_OFF = "0";
+	
+	public static final String DEFAULT_VAD_VALUE  = "0";
+	public static final String DEFAULT_NS_VALUE   = "0";
+	public static final String DEFAULT_CNG_VALUE  = "0";
+	public static final String DEFAULT_AUDIO_MODE = "0";
+	
+	// --------------------------------------------------------------------
+	// midule log level
+	// --------------------------------------------------------------------
+	public static final String LOG_LV_NONE 		= "0";
+	public static final String LOG_LV_ERR 		= "1";
+	public static final String LOG_LV_WARN 		= "2";
+	public static final String LOG_LV_INFO 		= "3";
+	public static final String LOG_LV_DEGUG 	= "4";
+	
+	// --------------------------------------------------------------------
+	// module integer (SIP, RTP, CODEC, CM, MMC, MCM, MMM, UI)
+	// --------------------------------------------------------------------
+	public static final int SIP_MODULE 		= 0;
+	public static final int RTP_MODULE 		= 1;
+	public static final int CODEC_MODULE 	= 2;
+	public static final int CM_MODULE 		= 3;
+	public static final int MMC_MODULE 		= 4;
+	public static final int MCM_MODULE 		= 5;
+	public static final int MMM_MODULE 		= 6;
+	
+
+	// ------------------------------------------------------------------------------
+	// important info SECURITY apply
+	// ------------------------------------------------------------------------------
+	public static final int SECURITY_APPLY = 0;	// 0:off, 1: apply(base64), 2: apply(base64+a)
+	public static final String SECURITY_KEY = "abcdefghijk0";
+	public static final String SRTP_SECURITY_KEY = "d2eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451";
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// ETC CONFIGURATION
+	// ------------------------------------------------------------------------------
+	public static final String TelEventPT = "101";
+	public static final String MAX_CALL = "2";
+	public static final String SERVER_NAME = "Svr0";
+	public static final String SERVER_NAME2 = "Svr1";
+	public static final String SERVER_NAME3 = "Svr2";
+	public static final String SERVER_NAME4 = "Svr3";
+	
+	// ------------------------------------------------------------------------------
+	// TIME SETTING
+	// ------------------------------------------------------------------------------
+	public static final String DEFAULT_REREG_TIME = "3600";
+	public static final String DEFAULT_SESSION_TIME = "60";
+	public static final String DEFAULT_SESSION_EXPIRE_TIME = "0";
+	public static final String DEFAULT_KT_TRANSACTION_TIME = "8";
+	public static final String DEFAULT_GENERAL_TRANSACTION_TIME = "32";
+	public static final String DEFAULT_DTMF_TYPE = "1"; // 2833 : 1, INFO : 2, INBAND : 3
+	public static final String DEFAULT_URL_TYPE = "0";  // normal : 0, standard : 1
+	public static final String DEFAULT_URL_RULE = "1";  // TEL : 0, SIP : 1
+	// ------------------------------------------------------------------------------
+	
+	// ------------------------------------------------------------------------------
+	// TAPS 
+	// ------------------------------------------------------------------------------
+	public static final String TAPS_DISABLE = "0";
+	public static final String TAPS_ENABLE = "1";
+	public static final String DEFAULT_TAPS_FEATURE = TAPS_DISABLE;
+	
+	public static enum eTAPS{		
+		eTAPS_RPT_NONE								,
+		eTAPS_RPT_UPDATE_BEGIN						,
+		eTAPS_RPT_UPDATE_INFO_FTPSRV				,
+		eTAPS_RPT_UPDATE_INFO_ID					,
+		eTAPS_RPT_UPDATE_INFO_PWD					,
+		eTAPS_RPT_UPDATE_INFO_FILENAME				,
+		eTAPS_RPT_UPDATE_INFO_DMNAME				,
+		eTAPS_RPT_UPDATE_DO_ACTION					,
+		eTAPS_RPT_UPDATE_END						,		
+		eTAPS_RPT_SIPCONFIG_BEGIN					,
+		eTAPS_RPT_SIPCONFIG_INFO_PROXYDNS			,
+		eTAPS_RPT_SIPCONFIG_INFO_IMIP				,
+		eTAPS_RPT_SIPCONFIG_INFO_PORTCOUNT			,
+		eTAPS_RPT_SIPCONFIG_INFO_AREACODE			,
+		eTAPS_RPT_SIPCONFIG_INFO_PORTNUMBER			,
+		eTAPS_RPT_SIPCONFIG_INFO_USERNAME			,
+		eTAPS_RPT_SIPCONFIG_INFO_AUTHID				,
+		eTAPS_RPT_SIPCONFIG_INFO_PASSWD				,
+		eTAPS_RPT_SIPCONFIG_INFO_DISPLAYNAME		,
+		eTAPS_RPT_SIPCONFIG_INFO_DOMAINNAME			,
+		eTAPS_RPT_SIPCONFIG_DO_ACTION				,
+		eTAPS_RPT_SIPCONFIG_END						,
+		eTAPS_RPT_REGISTER_BEGIN					,
+		eTAPS_RPT_REGISTER_DO_ACTION				,
+		eTAPS_RPT_REGISTER_END						,
+		eTAPS_RPT_PROVSTAT_BEGIN					,
+		eTAPS_RPT_PROVSTAT_START					,
+		eTAPS_RPT_PROVSTAT_TRYCNT					,
+		eTAPS_RPT_PROVSTAT_SERVER_CONNECT			,
+		eTAPS_RPT_PROVSTAT_STARTUP					,
+		eTAPS_RPT_PROVSTAT_UPGRADE					,
+		eTAPS_RPT_PROVSTAT_SIPCONFIG				,
+		eTAPS_RPT_PROVSTAT_SIPCONFIG_COMPLETE		,
+		eTAPS_RPT_PROVSTAT_REGISTER					,
+		eTAPS_RPT_PROVSTAT_SERVER_DISCONNECT		,
+		eTAPS_RPT_PROVSTAT_EVENT_WAIT				,
+		eTAPS_RPT_PROVSTAT_IPUPDATE					,
+		eTAPS_RPT_PROVSTAT_END						,
+		eTAPS_RPT_PROVRESULT_BEGIN					,
+		eTAPS_RPT_PROVRESULT_SUCCESS				,
+		eTAPS_RPT_PROVRESULT_FAIL					,
+		eTAPS_RPT_PROVRESULT_OPEN_ERROR				,
+		eTAPS_RPT_PROVRESULT_STARTUP_ERROR			,
+		eTAPS_RPT_PROVRESULT_UPGRADE_ERROR			,
+		eTAPS_RPT_PROVRESULT_SIPCONFIG_ERROR		,
+		eTAPS_RPT_PROVRESULT_SIPCONFIGSET_ERROR		,
+		eTAPS_RPT_PROVRESULT_REGISTER_ERROR			,		
+		eTAPS_RPT_PROVRESULT_REQUIRED_MAC			,
+		eTAPS_RPT_PROVRESULT_REQUIRED_ALLOC_IP		,
+		eTAPS_RPT_PROVRESULT_REQUIRED_SW_VERSION	,
+		eTAPS_RPT_PROVRESULT_REQUIRED_SERVER_IP		,
+		eTAPS_RPT_PROVRESULT_REQUIRED_SERVER_PORT	,
+		eTAPS_RPT_PROVRESULT_END					,
+		eTAPS_RPT_UNKNOWN
+	}; 
+		
+	public static final String CERES_LIB = "aCERES";
+	
+	
+	// ------------------------------------------------------------------------------
+	// MEDIA CONTROL : Digital Volume
+	// ------------------------------------------------------------------------------
+	public static final int SPK_PATH = 0;
+	public static final int MIC_PATH = 1;
+	
+	// ------------------------------------------------------------------------------
+	// MEDIA TYPE : AUDIO : 1, VIDEO : 3
+	// ------------------------------------------------------------------------------s
+	public static final int MEDIA_TYPE_AUDIO = 1;
+	public static final int MEDIA_TYPE_VIDEO_ONLY = 2;
+	public static final int MEDIA_TYPE_VIDEO = 3;
+	
+	// ------------------------------------------------------------------------------
+	// VIDEO
+	// ------------------------------------------------------------------------------
+	public static final boolean VIDEO_ENABLED    = false;
+	public static final String VIDEO_SIZE_QCIF   = "0";
+	public static final String VIDEO_SIZE_CIF    = "1";
+	public static final String VIDEO_SIZE_VGA    = "2";
+	public static final String VIDEO_SIZE_CUSTOM = "3";
+	public static final String VIDEO_SIZE_QVGA   = "4";
+	public static final String VIDEO_FRAME_RATE  = "15";
+	public static final String VIDEO_BANDWIDTH   = "256";
+
+	// ---------------------------------------------------------
+	// SipManager.
+	// ---------------------------------------------------------
+
+	public static final int VIDEO_SIZE_VGA_W = 640;
+	public static final int VIDEO_SIZE_VGA_H = 480;	
+	
+	public static final int VIDEO_SIZE_DV_FORMAT_W = 720;
+	public static final int VIDEO_SIZE_DV_FORMAT_H = 480;
+	public static final int VIDEO_SIZE_QVGA_W = 320;
+	public static final int VIDEO_SIZE_QVGA_H = 240;
+	
+	public static final int VIDEO_SIZE_CIF_W = 352;
+	public static final int VIDEO_SIZE_CIF_H = 288;
+	
+	public static final int VIDEO_SIZE_QCIF_W = 176;
+	public static final int VIDEO_SIZE_QCIF_H = 144;
+	
+	
+	public static final VideoSize VIDEO_MAX_SIZE = new VideoSize(VIDEO_SIZE_VGA_W, VIDEO_SIZE_QVGA_H);
+	
+	// ------------------------------------------------------------------------------
+	// SERVER LOCAL
+	//public static final String PROXYADDR = "192.168.217.35";
+	//public static final String PROXYADDR = "123.214.50.18";
+
+	// ------------------------------------------------------------------------------
+	public static final String LOCAL_PORT = "5060";
+	public static final String KT_LOCAL_PORT = "5080";
+	public static final String SKT_LOCAL_PORT = "5060";
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// ACCOUNT GENERAL
+	// provider == 20
+	// ------------------------------------------------------------------------------
+	public static String LOCAL_NUMBER = "2700";
+	public static final String ONE_NUMBER = "9000";
+	public static final String LOCAL_DOMAIN = "123.214.50.15";
+	public static final String LOCAL_PASSWD = "abcd";
+	public static final String LOCAL_AUTH_ID = "abcdef";
+	public static final String LOCAL_PROXY_ADDR = "123.214.50.15";
+	public static final String LOCAL_PROXY_PORT = "5060";
+	public static final String LOCAL_REG_ADDR = "123.214.50.15";
+	public static final String LOCAL_REG_PORT = "5060";
+	public static final String LOCAL_MEDIA_PORT = "40000";
+	//public static final String LOCAL_MEDIA_PORT = "50059"; // yjyoon, for 6410
+	public static final String REMOTE_MEDIA_PORT = "5080";
+	// ------------------------------------------------------------------------------
+	// provider == 21
+	// ------------------------------------------------------------------------------
+	public static final String LOCAL_NUMBER2 = "2800";
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// ACCOUNT KT
+	// provider == 10
+	// ------------------------------------------------------------------------------
+	public static final String KT_TEST_NUMBER_1  = "07077601438"; // phonenumber
+	public static final String KT_TEST_DOMAIN = "ktann.com"; // address
+	public static final String KT_TEST_PASSWD = "12345"; // password
+	public static final String KT_TEST_AUTH_ID_1 = "07077601438@ktann.com"; // auth_id
+	public static final String KT_TEST_PROXY_ADDR = "125.152.136.68"; // auth_id
+	public static final String KT_TEST_PROXY_PORT = "5080"; // auth_id
+	public static final String KT_TEST_REG_ADDR = "125.152.136.68"; // auth_id
+	public static final String KT_TEST_REG_PORT = "5080"; // auth_id
+	// ------------------------------------------------------------------------------
+	// provider == 11
+	// ------------------------------------------------------------------------------
+	public static final String KT_TEST_NUMBER_2  = "07077601439"; // phonenumber
+	public static final String KT_TEST_AUTH_ID_2 = "07077601439@ktann.com"; // auth_id
+	// ------------------------------------------------------------------------------
+	// provider == 30
+	// ------------------------------------------------------------------------------
+	public static final String KT_NUMBER_1  = "07077661124"; // phonenumber
+	public static final String KT_DOMAIN = "ktann.com"; // address
+	public static final String KT_PASSWD_1 = "5019"; // password
+	public static final String KT_AUTH_ID_1 = "07077661124@ktann.com"; // auth_id
+	public static final String KT_PROXY_ADDR = "125.146.2.6"; // auth_id
+	public static final String KT_PROXY_PORT = "5080"; // auth_id
+	public static final String KT_REG_ADDR_SBC = "125.146.2.6"; // auth_id
+	public static final String KT_REG_PORT_SBC = "5080"; // auth_id
+	public static final String KT_REG_ADDR_CSCF = "125.146.0.208"; // auth_id
+	public static final String KT_REG_PORT_CSCF = "5080"; // auth_id
+	// ------------------------------------------------------------------------------
+	// provider == 31
+	// ------------------------------------------------------------------------------
+	public static final String KT_NUMBER_2 = "07041271432"; // phonenumber
+	public static final String KT_PASSWD_2 = "ccumeukr"; // password
+	public static final String KT_AUTH_ID_2 = "10655773181@ktann.com"; // auth_id
+	// ------------------------------------------------------------------------------
+
+	// ------------------------------------------------------------------------------
+	// ACCOUNT SKT
+	// provider == 40
+	// ------------------------------------------------------------------------------
+	public static final String SKT_NUMBER_1  = "07087196260"; // phonenumber
+	public static final String SKT_DOMAIN = "skb.com"; // address
+	public static final String SKT_PASSWD_1 = "FMCTEST"; // password
+	public static final String SKT_AUTH_ID_1 = ""; // auth_id
+	public static final String SKT_PROXY_ADDR = "211.115.7.34"; // proxy_addr
+	public static final String SKT_PROXY_PORT = "5060"; // proxy_port
+	public static final String SKT_REG_ADDR = "211.115.7.34"; // reg_addr
+	public static final String SKT_REG_PORT = "5060"; // reg_port
+	// ------------------------------------------------------------------------------
+	// provider == 41
+	//------------------------------------------------------------------------------
+	public static final String SKT_NUMBER_2  = "07087196261"; // phonenumber
+	public static final String SKT_PASSWD_2 = "FMCTEST"; // password
+	public static final String SKT_AUTH_ID_2 = ""; // auth_id
+	// ------------------------------------------------------------------------------
+}

+ 103 - 0
WallPadCall/src/main/java/ceres/api/SpamList.java

@@ -0,0 +1,103 @@
+package ceres.api;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import ceres.utils.printlog;
+
+public class SpamList implements Parcelable {
+
+private static final String THIS_FILE = "SpamList";
+	
+	//Constants
+	public final static int INVALID_ID = -1;	
+		
+	// Fields for table accounts
+	public static final String FIELD_ID 			= "_id";
+	public static final String SPAMNUMBER 			= "spamnumber";
+	
+	public final static String[] full_projection = {
+		FIELD_ID,
+		// Application relative fields
+		SPAMNUMBER
+	};
+	
+	//Properties
+	public int 	  PrimaryKey 			= -1;
+	public int 	  _id 		 			= INVALID_ID;
+	public String spamnumber 				= "";
+	
+	public SpamList(){
+		printlog.i(THIS_FILE, "new SpamList()");
+	}
+	
+	public SpamList(Parcel in) {
+		PrimaryKey 			= in.readInt();
+		_id 				= in.readInt();
+		spamnumber 			= in.readString();				
+	}
+	
+	@Override
+	public int describeContents() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public void writeToParcel(Parcel dest, int arg1) {
+		// TODO Auto-generated method stub
+		dest.writeInt(PrimaryKey);
+		dest.writeInt(_id);
+		dest.writeString(spamnumber);				
+	}
+	
+	public static final Creator<SpamList> CREATOR = new Creator<SpamList>() {
+		public SpamList createFromParcel(Parcel in) {
+			return new SpamList(in);
+		}
+
+		public SpamList[] newArray(int size) {
+			return new SpamList[size];
+		}
+	};
+	
+	/** 
+	 * Fill account object from cursor
+	 * @param c cursor on the database 
+	 */		
+	public void createFromDb(Cursor c) {
+		ContentValues args = new ContentValues();
+		DatabaseUtils.cursorRowToContentValues(c, args);
+		Integer tmp_i;
+		String tmp_s;
+	
+		// Application specific settings
+		tmp_i = args.getAsInteger(FIELD_ID);
+		if (tmp_i != null) {
+			_id = tmp_i;
+		}
+		tmp_s = args.getAsString(SPAMNUMBER);
+		if (tmp_s != null) {
+			spamnumber = tmp_s;
+		}			
+	}
+		
+	/**
+	 * Transform pjsua_acc_config into ContentValues that can be insert into database
+	 */
+	public ContentValues getDbContentValues() {
+		ContentValues args = new ContentValues();
+		
+		if(_id != INVALID_ID){
+			args.put(FIELD_ID, _id);
+		}
+		
+		args.put(SPAMNUMBER, spamnumber);		
+		
+		return args;
+	}
+
+}

File diff suppressed because it is too large
+ 0 - 0
WallPadCall/src/main/java/ceres/api/UAStateReceiver.java


+ 98 - 0
WallPadCall/src/main/java/ceres/cminterface/CMAccStatus.java

@@ -0,0 +1,98 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.40
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+package ceres.cminterface;
+
+public class CMAccStatus {
+  private long swigCPtr;
+  protected boolean swigCMemOwn;
+
+  protected CMAccStatus(long cPtr, boolean cMemoryOwn) {
+    swigCMemOwn = cMemoryOwn;
+    swigCPtr = cPtr;
+  }
+
+  protected static long getCPtr(CMAccStatus obj) {
+    return (obj == null) ? 0 : obj.swigCPtr;
+  }
+
+  protected void finalize() {
+    delete();
+  }
+
+  public synchronized void delete() {
+    if (swigCPtr != 0) {
+      if (swigCMemOwn) {
+        swigCMemOwn = false;
+        cnssipuaJNI.delete_CMAccStatus(swigCPtr);
+      }
+      swigCPtr = 0;
+    }
+  }
+
+  public void setEnabled(short value) {
+    cnssipuaJNI.CMAccStatus_enabled_set(swigCPtr, this, value);
+  }
+
+  public short getEnabled() {
+    return cnssipuaJNI.CMAccStatus_enabled_get(swigCPtr, this);
+  }
+
+  public void setRegistered(short value) {
+    cnssipuaJNI.CMAccStatus_registered_set(swigCPtr, this, value);
+  }
+
+  public short getRegistered() {
+    return cnssipuaJNI.CMAccStatus_registered_get(swigCPtr, this);
+  }
+
+  public void setRegCode(int value) {
+    cnssipuaJNI.CMAccStatus_regCode_set(swigCPtr, this, value);
+  }
+
+  public int getRegCode() {
+    return cnssipuaJNI.CMAccStatus_regCode_get(swigCPtr, this);
+  }
+
+  public void setUserId(String value) {
+    cnssipuaJNI.CMAccStatus_userId_set(swigCPtr, this, value);
+  }
+
+  public String getUserId() {
+    return cnssipuaJNI.CMAccStatus_userId_get(swigCPtr, this);
+  }
+
+  public void setAuthId(String value) {
+    cnssipuaJNI.CMAccStatus_authId_set(swigCPtr, this, value);
+  }
+
+  public String getAuthId() {
+    return cnssipuaJNI.CMAccStatus_authId_get(swigCPtr, this);
+  }
+
+  public void setUserPw(String value) {
+    cnssipuaJNI.CMAccStatus_userPw_set(swigCPtr, this, value);
+  }
+
+  public String getUserPw() {
+    return cnssipuaJNI.CMAccStatus_userPw_get(swigCPtr, this);
+  }
+
+  public void setDomainName(String value) {
+    cnssipuaJNI.CMAccStatus_domainName_set(swigCPtr, this, value);
+  }
+
+  public String getDomainName() {
+    return cnssipuaJNI.CMAccStatus_domainName_get(swigCPtr, this);
+  }
+
+  public CMAccStatus() {
+    this(cnssipuaJNI.new_CMAccStatus(), true);
+  }
+
+}

+ 80 - 0
WallPadCall/src/main/java/ceres/cminterface/CMCallInfo.java

@@ -0,0 +1,80 @@
+package ceres.cminterface;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+
+public final class CMCallInfo implements Parcelable {
+	public static final String THIS_FILE = "CMCallInfo";
+	
+	public String remoteNumber;
+	public String aCodecName;
+	public String vCodecName;
+	public String vSizeName;
+	public int mediaType;	
+	public int callState;
+	public int prevCallState;
+	public int mediaDir;
+	
+	public static final Creator<CMCallInfo> CREATOR = new Creator<CMCallInfo>() {
+
+		@Override
+		public CMCallInfo createFromParcel(Parcel in) {
+			// TODO Auto-generated method stub
+			return new CMCallInfo(in);
+		}									
+
+		@Override
+		public CMCallInfo[] newArray(int size) {
+			// TODO Auto-generated method stub
+			return new CMCallInfo[size];
+		}		
+	};
+		
+	public CMCallInfo(){
+		Log.d(THIS_FILE, "Call CMCallInfo Constructor!!!");
+	}
+	
+	public CMCallInfo(Parcel in){
+		readFromParcel(in);
+	}
+	
+	@Override
+	public void writeToParcel(Parcel out, int flags) {
+		// TODO Auto-generated method stub
+		out.writeString(remoteNumber);
+		out.writeString(aCodecName);
+		out.writeString(vCodecName);
+		out.writeString(vSizeName);		
+		out.writeInt(mediaType);
+		out.writeInt(callState);		
+	}
+	
+	public void writeToParcel(Parcel out) {
+		// TODO Auto-generated method stub
+		out.writeString(remoteNumber);
+		out.writeString(aCodecName);
+		out.writeString(vCodecName);
+		out.writeString(vSizeName);		
+		out.writeInt(mediaType);
+		out.writeInt(callState);		
+	}
+	
+	public void readFromParcel(Parcel in){
+		remoteNumber = in.readString();
+		aCodecName = in.readString();
+		vCodecName = in.readString();
+		vSizeName = in.readString();
+		mediaType = in.readInt();
+		callState = in.readInt();
+	}
+
+	@Override
+	public int describeContents() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	
+}

+ 2552 - 0
WallPadCall/src/main/java/ceres/cminterface/CMInterface.java

@@ -0,0 +1,2552 @@
+package ceres.cminterface;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager.WakeLock;
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+import java.util.StringTokenizer;
+
+import ceres.api.AECParam;
+import ceres.api.SipManager;
+import ceres.pcminterface.PCMInterface;
+import ceres.security.Base64Utils;
+import ceres.srinterface.SRInterface;
+import ceres.utils.IpAddress;
+import ceres.utils.Threading;
+import ceres.utils.printlog;
+
+public class CMInterface {
+
+	// ---------------------------------------------------------------------------
+	// Class filter string
+	// ---------------------------------------------------------------------------
+	private static final String THIS_FILE = "CMInterface";
+	private static final String FILTER_STR = "codecs_test";
+
+	// ---------------------------------------------------------------------------
+	// Native function
+	// ---------------------------------------------------------------------------
+	native int CMIF_Initialize();
+	native int CMIF_TAPS_Init();
+	native int CMIF_Close();
+	native int CMIF_Register();
+	native int CMIF_UnRegister();
+	native int CMIF_MakeCall(byte[] phoneNumber, int mediaType);
+	native int CMIF_AcceptCall(int callIdx, int mediaType);
+	native int CMIF_ReleaseCall(int callIdx);
+	native int CMIF_CancelCall(int callIdx);
+	native int CMIF_RejectCall(int callIdx);
+	native int CMIF_SendDtmf(int callIdx, byte[] digit);
+	native int CMIF_HoldCall(int callIdx);
+	native int CMIF_UnHoldCall(int callIdx);
+	native int CMIF_SetHeadSetState(int state);
+	native int CMIF_SetBuildDevice(int device);
+	native int CMIF_SetBuildVersion(int version);
+	native int CMIF_SetLocalIPAddress(byte[] localIPAddres);
+	native int CMIF_IsVideoCall(int callIdx);
+	native static int CMIF_SetDigitalVolume(int type, int mute, int volume);
+	native int CMIF_GetDefaultDigitalVolume(int type);
+
+	public final static native int get_account_status(int jarg1, long jarg2,
+			CMAccStatus jarg2_);
+	public final static native long call_dump__SWIG_1(int jarg1, int jarg2,
+			String jarg3);
+	public final static native String char_return_TEST(int jarg1, int jarg2,
+                                                       String jarg3);
+	native String CMIF_GetVersion(int moduleId);
+
+	// native int CMIF_SetLogLevel(int moduleId, int level);
+
+	private static Base64Utils base64;
+
+	// ---------------------------------------------------------------------------
+	// Configuration
+	// String getter
+	// void setter
+	// ---------------------------------------------------------------------------
+	public void CERES_PhoneNumber_set(String phoneNumber){
+		m_PhoneNumber = phoneNumber;
+	}
+	public String CERES_PhoneNumber_get(){
+		return m_PhoneNumber;
+	}
+
+	public void CERES_OneNumber_set(String oneNumber){
+		m_OneNumber = oneNumber;
+	}
+	public String CERES_OneNumber_get(){
+		return m_OneNumber;
+	}
+
+	public void CERES_Address_set(String address){
+		m_Address = address;
+	}
+	public String CERES_Address_get(){
+		return m_Address;
+	}
+
+	public void CERES_Password_set(String password){
+		m_Password = password;
+	}
+	public String CERES_Password_get(){
+		return m_Password;
+	}
+
+	public void CERES_AuthId_set(String authId){
+		m_AuthId = authId;
+	}
+	public String CERES_AuthId_get(){
+		return m_AuthId;
+	}
+
+	public void CERES_ProxyAddr_set(String proxyAddr){
+		m_ProxyAddr = proxyAddr;
+	}
+	public String CERES_ProxyAddr_get(){
+		return m_ProxyAddr;
+	}
+
+	public void CERES_ProxyPort_set(String proxyPort){
+		m_ProxyPort = proxyPort;
+	}
+	public String CERES_ProxyPort_get(){
+		return m_ProxyPort;
+	}
+
+	public void CERES_RegAddr_set(String regAddr){
+		m_RegAddr = regAddr;
+	}
+	public String CERES_RegAddr_get(){
+		return m_RegAddr;
+	}
+
+	public void CERES_RegPort_set(String regPort){
+		m_RegPort = regPort;
+	}
+	public String CERES_RegPort_get(){
+		return m_RegPort;
+	}
+
+	public void CERES_LocalPort_set(String localport){
+		m_LocalPort = localport;
+	}
+	public String CERES_LocalPort_get(){
+		return m_ProxyPort;
+	}
+
+	public void CERES_LocalMediaPort_set(String localMediaPort){
+		m_LocalMediaPort = localMediaPort;
+	}
+	public String CERES_LocalMediaPort_get(){
+		return m_LocalMediaPort;
+	}
+
+	public void CERES_RemoteMediaPort_set(String remoteMediaPort){
+		m_RemoteMediaPort = remoteMediaPort;
+	}
+	public String CERES_RemoteMediaPort_get(){
+		return m_RemoteMediaPort;
+	}
+
+	public void CERES_Provider_set(String provider){
+		m_Provider = provider;
+	}
+	public String CERES_Provider_get(){
+		return m_Provider;
+	}
+
+	public void CERES_AudioCodecPrio_set(String audioCodecPrio){
+		m_ACodecPri = audioCodecPrio;
+	}
+	public String CERES_AudioCodecPrio_get(){
+		return m_ACodecPri;
+	}
+
+	public int CMI_Loopback_AudioCodecInt_get(){
+		String str = "";
+
+		if(m_ACodecPri.length() <= 0){
+			printlog.w(THIS_FILE, "m_ACodecPri.length() : " + m_ACodecPri.length());
+			m_ACodecPri = SipManager.DEFAULT_ACODEC_LIST;
+			printlog.w(THIS_FILE, "m_ACodecPri : " + m_ACodecPri);
+		}
+
+		StringTokenizer st1 = new StringTokenizer(m_ACodecPri, "a");
+		str = st1.nextToken();
+
+		return Integer.parseInt(str);
+	}
+
+	public int CMI_Loopback_VideoCodecInt_get(){
+		String str = "";
+
+		if(m_VCodecPri.length() <= 0){
+			printlog.w(THIS_FILE, "m_VCodecPri.length() : " + m_VCodecPri.length());
+			m_VCodecPri = SipManager.DEFAULT_VCODEC_LIST;
+			printlog.w(THIS_FILE, "m_VCodecPri : " + m_VCodecPri);
+		}
+
+		StringTokenizer st1 = new StringTokenizer(m_VCodecPri, "a");
+		str = st1.nextToken();
+
+		return Integer.parseInt(str);
+	}
+
+	public void CERES_ReRegTime_set(String reRegTime){
+		m_ReRegTime = reRegTime;
+	}
+	public String CERES_ReRegTime_get(){
+		return m_ReRegTime;
+	}
+
+	public void CERES_SessionTime_set(String sessionTime){
+		m_SessionTime = sessionTime;
+	}
+	public String CERES_SessionTime_get(){
+		return m_SessionTime;
+	}
+
+	public void CERES_SessionExpireTime_set(String sessionExpireTime){
+		m_SessionExpireTime = sessionExpireTime;
+	}
+	public String CERES_SessionExpireTime_get(){
+		return m_SessionExpireTime;
+	}
+
+	public void CERES_TransactionTime_set(String transactionTime){
+		m_TransactionTime = transactionTime;
+	}
+	public String CERES_TransactionTime_get(){
+		return m_TransactionTime;
+	}
+
+	public void CERES_DTMFType_set(String dtmfType){
+		m_DTMFType = dtmfType;
+	}
+	public String CERES_DTMFType_get(){
+		return m_DTMFType;
+	}
+
+	public void CERES_URLType_set(String urlType){
+		m_URLType = urlType;
+	}
+	public String CERES_URLType_get(){
+		return m_URLType;
+	}
+
+	public void CERES_PTime_set(String pTime){
+		m_PTime = pTime;
+	}
+	public String CERES_PTime_get(){
+		if(m_PTime.length() <= 0){
+			m_PTime = SipManager.DEFAULT_PTIME;
+		}
+		return m_PTime;
+	}
+
+	public void CERES_AECState_set(String aecState){
+		m_AECOnOff = aecState;
+	}
+	public String CERES_AECState_get(){
+		return m_AECOnOff;
+	}
+
+	public void CERES_JBMinMax_set(String jbMinMax){
+		m_JBMinMax = jbMinMax;
+	}
+	public String CERES_JBMinMax_get(){
+		return m_JBMinMax;
+	}
+
+	public void CERES_VADState_set(String vadState){
+		m_VADOnOff = vadState;
+	}
+	public String CERES_VADState_get(){
+		return m_VADOnOff;
+	}
+
+	public void CERES_NSState_set(String nsState){
+		m_NSOnOff = nsState;
+	}
+	public String CERES_NSState_get(){
+		return m_NSOnOff;
+	}
+
+	public void CERES_CNGState_set(String cngState){
+		m_CNGOnOff = cngState;
+	}
+	public String CERES_CNGState_get(){
+		return m_CNGOnOff;
+	}
+
+	public void CERES_SDCState_set(String vadState){
+		m_SDCOnOff = vadState;
+	}
+	public String CERES_SDCState_get(){
+		return m_SDCOnOff;
+	}
+
+	public void CERES_VideoSize_set(String videoSize){
+		m_VideoSize = videoSize;
+	}
+	public String CERES_VideoSize_get(){
+		return m_VideoSize;
+	}
+	public void CERES_VCodec_FrameRate_set(String frameRate){
+		m_VCodecFrameRate = frameRate;
+	}
+	public String CERES_VCodec_FrameRate_get(){
+		return m_VCodecFrameRate;
+	}
+	public void CERES_VCodec_Bandwidth_set(String bandwidth){
+		m_VCodecBandwidth = bandwidth;
+	}
+	public String CERES_VCodec_Bandwidth_get(){
+		return m_VCodecBandwidth;
+	}
+	public void CERES_VCodec_MAXBR_set(String maxBR){
+		m_VCodec_MAXBR = maxBR;
+	}
+	public String CERES_VCodec_MAXBR_get(){
+		return m_VCodec_MAXBR;
+	}
+	public void CERES_H264_Pmode_set(String h264Pmode){
+		m_H264_Pmode = h264Pmode;
+	}
+	public String CERES_H264_Pmode_get(){
+		return m_H264_Pmode;
+	}
+	public void CERES_MPEG4VES_Pli_set(String mpeg4vesPli){
+		m_MPEG4VES_Pli = mpeg4vesPli;
+	}
+	public String CERES_MPEG4VES_Pli_get(){
+		return m_MPEG4VES_Pli;
+	}
+
+	public void CERES_VideoState_set(String videoState){
+		m_VideoOnOff = videoState;
+	}
+	public String CERES_VideoState_get(){
+		return m_VideoOnOff;
+	}
+
+
+
+
+	public void CERES_OneNumberState_set(String oneNumberState){
+		m_OneNumberOnOff = oneNumberState;
+	}
+	public String CERES_OneNumberState_get(){
+		return m_OneNumberOnOff;
+	}
+
+	public void CERES_SpamState_set(String spamState){
+		m_SpamOnOff = spamState;
+	}
+	public String CERES_SpamState_get(){
+		return m_SpamOnOff;
+	}
+
+	public void CERES_RedirectState_set(String redirectState){
+		m_RedirectOption = redirectState;
+	}
+	public String CERES_RedirectState_get(){
+		return m_RedirectOption;
+	}
+
+	public void CERES_SamplingRate_set(String samplingRate){
+		m_HWSamplingRate = samplingRate;
+	}
+	public String CERES_SamplingRate_get(){
+		return m_HWSamplingRate;
+	}
+
+	public void CERES_AudioMode_set(String audioMode){
+		m_AudioMode = audioMode;
+	}
+	public String CERES_AudioMode_get(){
+		return m_AudioMode;
+	}
+
+	public void CERES_SIPLogLevel_set(String logLevel){
+		m_Log_LV_SIP = logLevel;
+	}
+	public String CERES_SIPLogLevel_get(){
+		return m_Log_LV_SIP;
+	}
+
+	public void CERES_RTPLogLevel_set(String logLevel){
+		m_Log_LV_RTP = logLevel;
+	}
+	public String CERES_RTPLogLevel_get(){
+		return m_Log_LV_RTP;
+	}
+
+	public void CERES_CallManagerLogLevel_set(String logLevel){
+		m_Log_LV_CM = logLevel;
+	}
+	public String CERES_CallManagerLogLevel_get(){
+		return m_Log_LV_CM;
+	}
+
+	public void CERES_MCallManagerLogLevel_set(String logLevel){
+		m_Log_LV_MCM = logLevel;
+	}
+	public String CERES_MCallManagerLogLevel_get(){
+		return m_Log_LV_MCM;
+	}
+
+	public void CERES_MMediaManagerLogLevel_set(String logLevel){
+		m_Log_LV_MMM = logLevel;
+	}
+	public String CERES_MMediaManagerLogLevel_get(){
+		return m_Log_LV_MMM;
+	}
+
+	public void CERES_UILogLevel_set(String logLevel){
+		m_Log_LV_UI = logLevel;
+	}
+	public String CERES_UILogLevel_get(){
+		return m_Log_LV_UI;
+	}
+
+	public void CERES_VideoCodecPrio_set(String videoCodecPrio){
+		m_VCodecPri = videoCodecPrio;
+	}
+	public String CERES_VideoCodecPrio_get(){
+		return m_VCodecPri;
+	}
+
+	public void CERES_SRTPState_set(String srtpState){
+		m_SRTPOption = srtpState;
+	}
+	public String CERES_SRTPState_get(){
+		return m_SRTPOption;
+	}
+
+	// ---------------------------------------------------------------------------
+	// Call Configuration
+	// D(Deprecated) : provider
+	// NU(Not Use) : m_RegAddr2, m_RegPort2 ..........
+	//             , m_SVRName .........
+	//             , m_VCodecPri, mSRTPOption
+	//	           , m_DeviceIP, m_TelEventPT, m_VideoMAXSize, m_VideoSize;
+	//	           , m_VideoFrameRate, m_VideoBandWidth;
+	//			   , m_MAXCall, m_URLRule, m_SRTP_SKey;
+	// ---------------------------------------------------------------------------
+	private static String m_PhoneNumber 	= "";
+	private static String m_OneNumber   	= "";
+	private static String m_Address     	= "";
+	private static String m_Password 		= "";
+	private static String m_AuthId 			= "";
+	private static String m_ProxyAddr 		= "";
+	private static String m_ProxyPort 		= "";
+	private static String m_RegAddr 		= "";
+	private static String m_RegPort 		= "";
+	private static String m_LocalPort 		= "";
+	private static String m_LocalMediaPort 	= "";
+	private static String m_RemoteMediaPort = "";
+	private static String m_RegAddr2 		= "";
+	private static String m_RegPort2 		= "";
+	private static String m_RegAddr3 		= "";
+	private static String m_RegPort3 		= "";
+	private static String m_RegAddr4 		= "";
+	private static String m_RegPort4 		= "";
+	private static String m_SVRName 		= "";
+	private static String m_SVRName2 		= "";
+	private static String m_SVRName3 		= "";
+	private static String m_SVRName4 		= "";
+	// ---------------------------------------------------------------------------
+	// Normal Configuration
+	// ---------------------------------------------------------------------------
+	private static String m_Provider 			= "";
+	private static String m_ACodecPri 			= "";
+	private static String m_ReRegTime 			= "";
+	private static String m_SessionTime 		= "";
+	private static String m_SessionExpireTime 	= "";
+	private static String m_TransactionTime 	= "";
+	private static String m_DTMFType 			= "";
+	private static String m_URLType 			= "";
+	private static String m_PTime				= "";
+	private static String m_VCodecPri 			= "";
+	private static String m_SRTPOption 			= "";
+	// ------------------------------
+	// System Delay Check On/Off
+	// ------------------------------
+	private static String m_SDCOnOff = "";
+
+	private static String m_VideoOnOff = "";
+//
+	private static String m_VideoSize       = "";
+	private static String m_VCodecFrameRate = "";
+	private static String m_VCodecBandwidth = "";
+	private static String m_VCodec_MAXBR    = "";
+	private static String m_H264_Pmode      = "";
+	private static String m_MPEG4VES_Pli    = "";
+
+	// ---------------------------------------------------------------------------
+	// Add Configuration
+	// ---------------------------------------------------------------------------
+	private static String m_AECOnOff 		= "";
+	private static String m_OneNumberOnOff 	= "";
+	private static String m_SpamOnOff 		= "";
+	private static String m_RedirectOption 	= "";
+	private static String m_HWSamplingRate 	= "";
+	private static String m_AudioMode 		= "";
+	private static String m_JBMinMax 		= "";
+	// ---------------------------------------------------------------------------
+	// Device IP Address
+	// ---------------------------------------------------------------------------
+	private static String m_DeviceIP 		= "";
+	private static String m_TelEventPT 		= "";
+	private static String m_VideoMAXSize 	= "";
+	private static String m_MAXCall 		= "";
+	private static String m_URLRule 		= "";
+	private static String m_SRTP_SKey 		= "";
+
+	// ---------------------------------------------------------------------------
+	// Set Module Log level
+	// ---------------------------------------------------------------------------
+	private static String m_Log_LV_SIP = "", m_Log_LV_RTP = "", m_Log_LV_CM = "";
+	private static String m_Log_LV_MCM = "", m_Log_LV_MMM = "", m_Log_LV_UI = "";
+
+
+
+	// ---------------------------------------------------------------------------
+	// Audio Sub function VAD, NS, CNG
+	// ---------------------------------------------------------------------------
+	private static String m_VADOnOff = "", m_NSOnOff = "", m_CNGOnOff = "";
+
+	// ---------------------------------------------------------------------------
+	// AECTNTB
+	// ---------------------------------------------------------------------------
+	private static String m_AECMemo 		= "";
+	private static String m_AECDelay 		= "";
+	private static String m_AECTimeSpan 	= "";
+	private static String m_AECERL 			= "";
+	private static String m_AECDynVol 		= "";
+	private static String m_AECDynVolMin 	= "";
+	private static String m_AECUpdateSpeed 	= "";
+	private static String m_AECWMaxIndex 	= "";
+	private static String m_AECWScale 		= "";
+
+	public static Context mContext;
+	private static AudioManager audioManager;
+	protected static PCMInterface mPCMIF = null;
+	protected static SRInterface mSRIF = null;
+	//protected DBAdapter db = null;
+	protected CMCallInfo dupCallInfo = null;
+	protected AECParam aecparam = null;
+
+	private static void lockCpu() {
+		if (eventLock != null) {
+			eventLock.acquire();
+		}
+	}
+
+	private static void unlockCpu() {
+		if (eventLock != null && eventLock.isHeld()) {
+			eventLock.release();
+		}
+	}
+
+	// -----------------------------------------------------------------------------------
+	// Constructor
+	// -----------------------------------------------------------------------------------
+	public CMInterface() {
+		printlog.d(THIS_FILE, "CMInterface....");
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES Start State Manage ...
+	// -----------------------------------------------------------------------------------
+	// ceres_need_taps_try : 2
+	// After taps_try change ceres_init_state to 0.
+	// -----------------------------------------------------------------------------------
+	// ceres_need_cm_init : 0
+	// -----------------------------------------------------------------------------------
+	// ceres_is_running : 1
+	// skip cm_init.
+	// -----------------------------------------------------------------------------------
+	// If TAPS feature is enabled ceres_init_state is 2, or not it is 0.
+	// -----------------------------------------------------------------------------------
+	@SuppressWarnings("unused")
+	private static final int CERES_DEINIT_STATE = (SipManager.DEFAULT_TAPS_FEATURE == "0") ? 0 : 2;
+	@SuppressWarnings("unused")
+	private static int ceres_init_state = (SipManager.DEFAULT_TAPS_FEATURE == "0") ? 0 : 2;
+	private static int register_state = 0;
+
+	// -----------------------------------------------------------------------------------
+	// CERES_InitState_get
+	// -----------------------------------------------------------------------------------
+	public static int CERES_InitState_get() {
+		Log.v("yjyoon", "CERES_InitState_get()");
+		printlog.i(THIS_FILE, "CERES_InitState_get : " + ceres_init_state);
+		return ceres_init_state;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_InitState_set
+	// -----------------------------------------------------------------------------------
+	private static void CERES_InitState_set(int state) {
+		Log.v("yjyoon", "CERES_InitState_set()");
+		printlog.i(THIS_FILE, "CERES_InitState_set : " + state);
+		ceres_init_state = state;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_RegiState_get
+	// -----------------------------------------------------------------------------------
+	public int CERES_RegiState_get() {
+		return register_state;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_RegiState_set
+	// -----------------------------------------------------------------------------------
+	private static int CERES_RegiState_set(int state) {
+		register_state = state;
+		return register_state;
+	}
+
+	// ------------------------------------------------------------------------------------------
+	// initService
+	// ------------------------------------------------------------------------------------------
+	private void initService(Context context) {
+		if (handlerThread == null) {
+			printlog.i(THIS_FILE, "initService handlerThread Start");
+			handlerThread = new HandlerThread("UAStateAsyncWorker");
+			handlerThread.start();
+		}
+		if (msgHandler == null) {
+			printlog.i(THIS_FILE, "initService new WorkerHandler");
+			msgHandler = new WorkerHandler(handlerThread.getLooper());
+		}
+		//new UAStateReceiver(mContext);
+	}
+
+	// ------------------------------------------------------------------------------------------
+	// deInitService
+	// ------------------------------------------------------------------------------------------
+	private void deInitService() {
+		printlog.d(THIS_FILE, "deInitService");
+		if(handlerThread != null){
+			Threading.stopHandlerThread(handlerThread);
+		}
+		handlerThread = null;
+		msgHandler = null;
+
+		// Ensure lock is released since this lock is a ref counted one.
+		if (eventLock != null) {
+			while (eventLock.isHeld()) {
+				eventLock.release();
+			}
+		}
+	}
+
+	// -----------------------------------------------------------------------------------
+	// Network 변화 감지.. 등록시도..
+	// -----------------------------------------------------------------------------------
+	private WifiManager wifiManager = null;
+	private ConnectivityManager connManager = null;
+	private static int regi_callback_cnt = 0;
+	private static int network_change_cnt = 0;
+
+	BroadcastReceiver mBRWifi = new BroadcastReceiver() {
+		public void onReceive(Context context, Intent intent) {
+			String action = intent.getAction();
+
+			printlog.d(THIS_FILE, "wifichangeReceiver test...");
+
+			network_change_cnt++;
+			if (network_change_cnt >= 2) {
+
+				if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+					printlog.i(THIS_FILE, "NETWORK_STATE_CHANGED_ACTION");
+					onWifiChanged(intent);
+				}
+				if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+					printlog.i(THIS_FILE, "CONNECTIVITY_ACTION");
+					onConnChanged(intent);
+				}
+			}
+		}
+
+		public void onWifiChanged(Intent intent) {
+
+			NetworkInfo networkInfo_wifi = connManager
+					.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+
+			if ((networkInfo_wifi != null)
+					&& (networkInfo_wifi.isAvailable() == true)) {
+				if (networkInfo_wifi.getState() == NetworkInfo.State.CONNECTED) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_CONNECTED");
+					String localIpAddress2 = IpAddress.deviceIP_get();
+					printlog.w(THIS_FILE,"wifi_STATE_ENABLED : localIpAddress2 : " + localIpAddress2);
+					// send to ui : unregister
+					dispatchCallStateCBEvent(0);
+					// CERES_Initialize(mContext);
+					CERES_ModifyConfiguration();
+					// CERES_Register();
+				} else if (networkInfo_wifi.getState() == NetworkInfo.State.CONNECTING) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_CONNECTING");
+				} else if (networkInfo_wifi.getState() == NetworkInfo.State.DISCONNECTED) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_DISCONNECTED");
+				} else if (networkInfo_wifi.getState() == NetworkInfo.State.DISCONNECTING) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_DISCONNECTING");
+				} else if (networkInfo_wifi.getState() == NetworkInfo.State.SUSPENDED) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_SUSPENDED");
+				} else if (networkInfo_wifi.getState() == NetworkInfo.State.UNKNOWN) {
+					printlog.w(THIS_FILE, "wifi_NETWORK_STATE_UNKNOWN");
+				}
+			}
+		}
+
+		public void onConnChanged(Intent intent) {
+
+			NetworkInfo networkInfo_3g = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+			NetworkInfo networkInfo_wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+
+			if (networkInfo_3g != null && networkInfo_3g.isConnected()
+					&& networkInfo_wifi.isConnected() == false) {
+				printlog.w(THIS_FILE, "wifi_3gNETWORK_STATE_CONNECTED : " + networkInfo_3g.getExtraInfo());
+				String localIpAddress = IpAddress.deviceIP_get();
+				printlog.w(THIS_FILE, "wifi_STATE_ENABLED : localIpAddress : "
+								+ localIpAddress + " subtype :"
+								+ networkInfo_3g.getType());
+				// send to ui : unregister
+				dispatchCallStateCBEvent(0);
+				CERES_ModifyConfiguration();
+				// CERES_Initialize(mContext);
+				// CERES_Register();
+			} else if (networkInfo_3g != null
+					&& networkInfo_3g.isConnected() == false
+					&& networkInfo_wifi.isConnected() == false) {
+				// send to ui : unregister
+				dispatchCallStateCBEvent(0);
+			}
+		}
+	};
+
+	// -----------------------------------------------------------------------------------
+	// CERES_ModifyConfiguration
+	// -----------------------------------------------------------------------------------
+	public void CERES_ModifyConfiguration() {
+		CMIF_Close();
+		CMIF_Initialize();
+		CERES_Register();
+	}
+
+
+	private static Handler handler = new Handler() {
+		public void handleMessage(Message msg) {
+
+			switch (msg.what) {
+			case ON_TAPS_REPORT_STATE:
+
+				int state = msg.getData().getInt("state");
+				String str = msg.getData().getString("str");
+				dispatchTapsStatusCBEvent(state, str);
+
+				break;
+
+
+			default:
+				super.handleMessage(msg);
+			}
+		}
+	};
+
+	public int CERES_TAPS_Init(Context context){
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		// ---------------------------------------
+		// CMIF_TAPS_Init
+		// ---------------------------------------
+		System.loadLibrary(SipManager.CERES_LIB);
+		Log.v("yjyoon", "CERES_TAP_INIT loadLibrary.");
+
+		CMIF_TAPS_Init();
+
+//		printlog.v(THIS_FILE, "mContext : " + mContext);
+//
+//		if (mContext == null) {
+//			mContext = context;
+//		}
+//
+//		initService(mContext);
+
+		return iRet;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_Initialize
+	// -----------------------------------------------------------------------------------
+	public void CERES_Initialize(Context context) {
+
+		System.loadLibrary(SipManager.CERES_LIB);
+		Log.v("yjyoon", "CERES_Initialize loadLibrary.");
+
+		network_change_cnt = 0;
+
+		printlog.v(THIS_FILE, "mContext : " + mContext);
+
+		m_DeviceIP = IpAddress.deviceIP_get();
+		// CERES_DeviceIP_set(l_deviceIP);
+
+		if (dupCallInfo == null) {
+			dupCallInfo = new CMCallInfo();
+		}
+
+		if (mContext == null) {
+			mContext = context;
+		}
+
+		if (mPCMIF == null) {
+			mPCMIF = new PCMInterface(mContext);
+		}
+
+		if (mSRIF == null) {
+			mSRIF = new SRInterface(mContext);
+		}
+
+//
+
+		audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+
+//		printlog.d(THIS_FILE, "setMode, audioManager.getMode() : " + audioManager.getMode());
+//
+//		audioManager.setMode(AudioManager.MODE_IN_CALL);
+//		audioManager.setMode(AudioManager.MODE_NORMAL);
+
+		// -------------------------------------------
+		// Device 정보 설정..
+		// -------------------------------------------
+		//DeviceDefaultValue_get(mDeviceInfo);
+
+		// ---------------------------------------
+		// CM_Initailize
+		// ---------------------------------------
+		CMIF_Initialize();
+
+		initService(mContext);
+
+		// -------------------------------------------
+		// CERES가 init 되었음을 설정..
+		// -------------------------------------------
+		CERES_InitState_set(1);
+
+
+		// --------------------------------------------------------
+		// GalaxyS의 경우 setMode(3)을 처리한다.
+		// --------------------------------------------------------
+		if(SipManager.DEVICE_NAME.equalsIgnoreCase("M110")){
+			printlog.d(THIS_FILE, "CERES_INIT : S");
+			//setMode(IN_COMMUNICATION)
+		 	AudioInCall_set(3);
+		}
+		// -----------------------------------------------------------
+		// UI 상에서 변경 가능하도록..단말종류에따라 Default값 설정 되야함.
+		// -----------------------------------------------------------
+//		else if (m_AudioMode.length() > 0) {
+//			printlog.d(THIS_FILE, "m_AudioMode.length() : " + m_AudioMode.length());
+//			// setCallMode(Integer.parseInt(m_SpamOnOff));
+//			AudioInCall_set(Integer.parseInt(m_AudioMode));
+//		}
+
+		// -------------------------------------------
+		// Network 변화 감지 리시버 설정 및 등록..
+		// -------------------------------------------
+		wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+		connManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+		IntentFilter i = new IntentFilter();
+		i.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+		i.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+
+		mContext.registerReceiver(mBRWifi, i);
+	}
+
+	public SRInterface SRInterface_get(){
+		return mSRIF;
+	}
+//
+//	public void DeviceDefaultValue_get(DeviceInfo deviceInfo){
+//
+//		//DeviceInfo deviceInfo = new DeviceInfo();
+//
+//		printlog.d(THIS_FILE, "Build.DEVICE : " + Build.DEVICE);
+//
+//		Compatibility comp = deviceInfo.new Compatibility(deviceInfo.getAsInteger(SipManager.BUILD_DEVICE));
+//
+//		printlog.d(THIS_FILE, "comp.mTrackCorrectBase  : " + comp.mTrackCorrectBase);
+//		printlog.d(THIS_FILE, "comp.mTrackCorrect      : " + comp.mTrackCorrect);
+//		printlog.d(THIS_FILE, "comp.mRecordCorrectBase : " + comp.mRecordCorrectBase);
+//		printlog.d(THIS_FILE, "comp.mRecordCorrect     : " + comp.mRecordCorrect);
+////		printlog.d(THIS_FILE, "comp.mAECParams : " + comp.mAECParams.time_span);
+////		printlog.d(THIS_FILE, "comp.mAECParams : " + comp.mAECParams.delay);
+//
+////		if (db == null) {
+////			db = new DBAdapter(mContext);
+////			db.open();
+////
+////			aecparam = db.selectRecentApplyAECParam();
+////			printlog.d(THIS_FILE, "aecparam._id : " + aecparam._id);
+////		}
+//
+//		// ---------------------------------------
+//		// 가장 최근에 적용한 AECParam 값을 얻는다.
+//		// ---------------------------------------
+//		if (db == null) {
+//			db = new DBAdapter(mContext);
+//			db.open();
+//			aecparam = db.selectRecentApplyAECParam();
+//			printlog.d(THIS_FILE, "aecparam._id : " + aecparam._id);
+//
+//			// 일단 SHW-M250S 만 적용..
+//			if(aecparam._id == -1){
+//
+//				aecparam = comp.DeviceAECParams_get(deviceInfo.getAsInteger(SipManager.BUILD_DEVICE));
+//
+//				db.insertAECParam(aecparam);
+//
+//				db.close();
+//
+//				printlog.d(THIS_FILE, "AECPARAM is Empty.. default value insert...");
+//			}
+//			// ---------------------------------------
+//			// 얻어온 AECParam 값을 m_변수들에 설정한다.
+//			// ---------------------------------------
+//			AECParams_set(aecparam);
+//		}
+//
+//		SharedPreferences pref = mContext.getSharedPreferences("pcmprefs", 0);
+//		SharedPreferences.Editor edit = pref.edit();
+//
+//		int isCustomSet = pref.getInt("isCustomSet", 0);
+//
+//		printlog.d(THIS_FILE, "isCustomSet : " + isCustomSet);
+//
+//		// ------------------------------------------
+//		// isCustomSetting 이 안된경우에만 반영..
+//		// ------------------------------------------
+//		if(isCustomSet == 0){
+//
+//			// PCMInterface로 PCMDataSize 보정 값 전달.
+//			mPCMIF.jsetCorrectInformation(comp.mTrackCorrectBase
+//					, comp.mTrackCorrect
+//					, comp.mRecordCorrectBase
+//					, comp.mRecordCorrect);
+//
+//			edit.putInt("szTrackBase", comp.mTrackCorrectBase);
+//			edit.putInt("szTrack", comp.mTrackCorrect);
+//			edit.putInt("szRecordBase", comp.mRecordCorrectBase);
+//			edit.putInt("szRecord", comp.mRecordCorrect);
+//
+//			edit.commit();
+//		}
+//
+//		//CERES_BuildDevice_set(deviceInfo.getAsInteger(SipManager.BUILD_DEVICE));
+//		//CERES_BuildVersion_set(deviceInfo.getAsInteger(SipManager.BUILD_VERSION));
+//
+//	}
+
+	// ------------------------------------------------------------------------------------
+	// CERES_Close
+	// ------------------------------------------------------------------------------------
+	public int CERES_Close() {
+		deInitService();
+
+		if (SipManager.DEVICE_NAME.equalsIgnoreCase("M110")) {
+			printlog.d(THIS_FILE, "build_device : " + SipManager.DEVICE_NAME);
+			// setMode(NORMAL)
+			AudioInCall_set(AudioManager.MODE_NORMAL);
+		}
+
+		CERES_InitState_set(CERES_DEINIT_STATE);
+
+		if (dupCallInfo != null) {
+			dupCallInfo = null;
+		}
+
+		if (mBRWifi != null) {
+			try {
+				printlog.d(THIS_FILE, " service debug Unregister telephony receiver");
+				if(mContext != null){
+					mContext.unregisterReceiver(mBRWifi);
+				}
+				mBRWifi = null;
+				// Ceres_SetBuildDevice(DEVICE_INIT);
+			} catch (IllegalArgumentException e) {
+				// This is the case if already unregistered itself
+				// Python style usage of try ;) : nothing to do here since it
+				// could
+				// be a standard case
+				// And in this case nothing has to be done
+				printlog.e(THIS_FILE,
+						" service debug Has not to unregister telephony receiver");
+			}
+		}
+
+		mPCMIF = null;
+
+		if (mContext != null) {
+			mContext = null;
+		}
+
+		return CMIF_Close();
+	}
+
+	// ------------------------------------------------------------------------------------------
+	// AECParams_set
+	// ------------------------------------------------------------------------------------------
+	public static void AECParams_set(AECParam aecparam) {
+		printlog.i(THIS_FILE,
+				"   -------------------------------------------------------- ");
+		printlog.i(THIS_FILE, "   id                    : " + aecparam._id);
+		printlog.i(THIS_FILE, "   memo                  : " + aecparam.memo);
+		printlog.i(THIS_FILE, "   delay                 : " + aecparam.delay);
+		printlog.i(THIS_FILE, "   time_span             : "
+				+ aecparam.time_span);
+		printlog.i(THIS_FILE, "   erl                   : " + aecparam.erl);
+		printlog.i(THIS_FILE, "   dynamic_vol_mic       : "
+				+ aecparam.dynamic_vol_mic);
+		printlog.i(THIS_FILE, "   dynamic_vol_mic_min   : "
+				+ aecparam.dynamic_vol_mic_min);
+		printlog.i(THIS_FILE, "   update_speed          : "
+				+ aecparam.update_speed);
+		printlog.i(THIS_FILE, "   weight_max_index      : "
+				+ aecparam.weight_max_index);
+		printlog.i(THIS_FILE, "   weight_scale          : "
+				+ aecparam.weight_scale);
+		printlog.i(THIS_FILE,
+				"   -------------------------------------------------------- ");
+
+		m_AECMemo = aecparam.memo;
+		m_AECDelay = aecparam.delay;
+		m_AECTimeSpan = aecparam.time_span;
+		m_AECERL = aecparam.erl;
+		m_AECDynVol = aecparam.dynamic_vol_mic;
+		m_AECDynVolMin = aecparam.dynamic_vol_mic_min;
+		m_AECUpdateSpeed = aecparam.update_speed;
+		m_AECWMaxIndex = aecparam.weight_max_index;
+		m_AECWScale = aecparam.weight_scale;
+
+		return;
+	}
+
+	private void printDeviceInfo() {
+		printlog.i(THIS_FILE, "BOARD : " + Build.BOARD);
+		printlog.i(THIS_FILE, "BRAND : " + Build.BRAND);
+		printlog.i(THIS_FILE, "CPU_ABI : " + Build.CPU_ABI);
+		printlog.i(THIS_FILE, "DEVICE : " + Build.DEVICE);
+		printlog.i(THIS_FILE, "DEVICE : " + Build.DEVICE.substring(4, 9));
+		printlog.i(THIS_FILE, "DISPLAY : " + Build.DISPLAY);
+		printlog.i(THIS_FILE, "FINGERPRINT : " + Build.FINGERPRINT);
+		printlog.i(THIS_FILE, "HOST : " + Build.HOST);
+		printlog.i(THIS_FILE, "ID : " + Build.ID);
+		printlog.i(THIS_FILE, "MANUFACTURER : " + Build.MANUFACTURER);
+		printlog.i(THIS_FILE, "MODEL : " + Build.MODEL);
+		printlog.i(THIS_FILE, "PRODUCT : " + Build.PRODUCT);
+		printlog.i(THIS_FILE, "TAGS : " + Build.TAGS);
+		printlog.i(THIS_FILE, "TYPE : " + Build.TYPE);
+		printlog.i(THIS_FILE, "USER : " + Build.USER);
+		printlog.i(THIS_FILE, "SDK : " + Build.VERSION.SDK);
+	}
+
+	// -------------------------------------------------------------------------------------------
+	// AudioInCall_set
+	// -------------------------------------------------------------------------------------------
+	public static int AudioInCall_set(int mode) {
+		printlog.i(THIS_FILE, " AudioInCall_set setMode : " + mode);
+		audioManager.setMode(mode);
+		return 0;
+	}
+
+	// -------------------------------------------------------------------------------------------
+	// setParameters
+	// -------------------------------------------------------------------------------------------
+	public static int setParameters(String value) {
+		String param = "\"" + value + "\"";
+		printlog.d(THIS_FILE, "param : " + param);
+		audioManager.setParameters(param);
+		return 0;
+	}
+
+	// ------------------------------------------------------------------------------------
+	// CERES_Register
+	// ------------------------------------------------------------------------------------
+	public int CERES_Register() {
+		return CMIF_Register();
+	}
+
+	// ------------------------------------------------------------------------------------
+	// CERES_UnRegister
+	// ------------------------------------------------------------------------------------
+	public int CERES_UnRegister() {
+		return CMIF_UnRegister();
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_MakeCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_MakeCall(String phoneNumber, int mediaType) {
+		int iRet = 1; // CME_GENERAL_FAIL
+		int len = phoneNumber.length();
+		byte[] l_PhoneNumber = null;
+		Log.v("yjyoon", "33 len=" + len + " phoneNumber=" + phoneNumber +  " mediaType " + mediaType);
+		if (len > 0) {
+			if (l_PhoneNumber == null)
+				l_PhoneNumber = new byte[512];
+			phoneNumber.getBytes(0, len, l_PhoneNumber, 0);
+			l_PhoneNumber[len] = '\0';
+
+			iRet = CMIF_MakeCall(l_PhoneNumber, mediaType);
+		} else {
+			printlog.e(THIS_FILE, "CERES_MakeCall, phoneNumber length error!!!");
+		}
+
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_AcceptCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_AcceptCall(int callIdx, int mediaType) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_AcceptCall(callIdx, mediaType)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_AcceptCall, Error : " + iRet
+					+ ", callIdx : " + callIdx + ", mediaType : " + mediaType);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_CloseCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_CloseCall(int callIdx) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_ReleaseCall(callIdx)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_ReleaseCall, Error : " + iRet
+					+ ", callIdx : " + callIdx);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_HoldCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_HoldCall(int callIdx) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_HoldCall(callIdx)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_HoldCall, Error : " + iRet
+					+ ", callIdx : " + callIdx);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_UnHoldCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_UnHoldCall(int callIdx) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_UnHoldCall(callIdx)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_UnHoldCall, Error : " + iRet
+					+ ", callIdx : " + callIdx);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_CancelCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_CancelCall(int callIdx) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_CancelCall(callIdx)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_CancelCall, Error : " + iRet
+					+ ", callIdx : " + callIdx);
+		}
+
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_RejectCall
+	// -------------------------------------------------------------------------------------
+	public int CERES_RejectCall(int callIdx) {
+		int iRet = 1;
+
+		if ((iRet = CMIF_RejectCall(callIdx)) != 0) {
+			printlog.e(THIS_FILE, "CMIF_RejectCall, Error : " + iRet
+					+ ", callIdx : " + callIdx);
+		}
+
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_SendDTMF
+	// -------------------------------------------------------------------------------------
+	public int CERES_SendDTMF(int callIdx, String digit) {
+		int iRet = 1; // CME_GENERAL_FAIL
+		int len = digit.length();
+
+		byte[] l_Digit = null;
+
+		int moduleId;
+
+		moduleId = Integer.parseInt(digit);
+
+		printlog.d(THIS_FILE, "CERES_Version_get(" + moduleId + ") : "
+				+ CERES_Version_get(moduleId));
+
+		if (len > 0) {
+			if (l_Digit == null)
+				l_Digit = new byte[10];
+			digit.getBytes(0, digit.length(), l_Digit, 0);
+			l_Digit[len] = 0;
+
+			if ((iRet = CMIF_SendDtmf(callIdx, l_Digit)) != 0) {
+				printlog.e(THIS_FILE, "CMIF_RejectCall, Error : " + iRet
+						+ ", callIdx : " + callIdx + ", l_Digit : " + l_Digit);
+			}
+		} else
+			printlog.e(THIS_FILE, " CERES_SendDTMF, digit length error!!!");
+
+		return iRet;
+	}
+
+	public synchronized static int getAccountStatus(int acc_id, CMAccStatus info) {
+		printlog.d(THIS_FILE, " getcallinfo call_id : " + acc_id);
+		return get_account_status(acc_id, CMAccStatus.getCPtr(info), info);
+	}
+
+	public static String charReturnTest(int testId) {
+		return char_return_TEST(testId, 1, " ");
+	}
+
+	/**
+	 * SIP, RTP, CODEC, CM, MMC, CMHANDLER, MMHANDLER, UI
+	 *
+	 * @param moduleId
+	 * @return
+	 */
+	public String CERES_Version_get(int moduleId) {
+		return CMIF_GetVersion(moduleId);
+	}
+
+	// /**
+	// *
+	// * @param moduleId : SipManager ( SIP, RTP, CODEC, CM, MMC, MCM, MMM, UI )
+	// * @param level : SipManager ( NONE, ERR, WARN, INFO, DEBUG )
+	// * @return
+	// */
+	// public int CERES_LogLevel_set(int moduleId, int level) {
+	// return CMIF_SetLogLevel(moduleId, level);
+	// }
+
+	// -------------------------------------------------------------------------------------
+	// CERES_HeadSetState_set
+	// -------------------------------------------------------------------------------------
+	private int CERES_HeadSetState_set(int state) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_SetHeadSetState(state)) != 0) {
+			printlog.e(THIS_FILE, " CMIF_SetHeadSetState ERR : " + iRet
+					+ ", state : " + state);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_BuildDevice_set
+	// -------------------------------------------------------------------------------------
+	private int CERES_BuildDevice_set(int device) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_SetBuildDevice(device)) != 0) {
+			printlog.e(THIS_FILE, " CMIF_SetBuildDevice ERR : " + iRet
+					+ ", device : " + device);
+		}
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_BuildVersion_set
+	// -------------------------------------------------------------------------------------
+	private int CERES_BuildVersion_set(int version) {
+		int iRet = 1; // CME_GENERAL_FAIL
+
+		if ((iRet = CMIF_SetBuildVersion(version)) != 0) {
+			printlog.e(THIS_FILE, " CMIF_SetBuildVersion ERR : " + iRet
+					+ ", version : " + version);
+		}
+		return iRet;
+	}
+
+	private static int mic_volume_level = 0;
+	private static int spk_volume_level = 0;
+
+	// -------------------------------------------------------------------------------------
+	// CERES_DigitalVolume_set
+	// -------------------------------------------------------------------------------------
+	public static int CERES_DigitalVolume_set(int type, int mute, int volume) {
+		int iRet = 1;
+
+		if (type == SipManager.SPK_PATH) {
+			spk_volume_level = volume;
+		} else if (type == SipManager.MIC_PATH) {
+			mic_volume_level = volume;
+		}
+
+		printlog.i(THIS_FILE, "DigitalVolume CERES_DigitalVolume_set, type:"
+				+ type + ", mute:" + mute + ", volume:" + volume);
+
+		iRet = CMIF_SetDigitalVolume(type, mute, volume);
+
+		if ((iRet = CMIF_SetDigitalVolume(type, mute, volume)) != 0) {
+			printlog.e(THIS_FILE, " CMIF_SetDigitalVolume ERR : " + iRet
+					+ ", type : " + type + ", mute : " + mute + ", volume : "
+					+ volume);
+		}
+
+		return iRet;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_DigitalVolume_get
+	// -------------------------------------------------------------------------------------
+	public int CERES_DigitalVolume_get(int type) {
+		int l_volume = -1;
+		if (type == SipManager.SPK_PATH) {
+			l_volume = spk_volume_level;
+		} else if (type == SipManager.MIC_PATH) {
+			l_volume = mic_volume_level;
+		}
+		return l_volume;
+	}
+
+	// -------------------------------------------------------------------------------------
+	// CERES_DefaultDigitalVolume_get
+	// -------------------------------------------------------------------------------------
+	public int CERES_DefaultDigitalVolume_get(int type) {
+		int defaultVolume = 0;
+		defaultVolume = CMIF_GetDefaultDigitalVolume(type);
+
+		printlog.i(THIS_FILE, "CERES_DefaultDigitalVolume_get , type : "
+				+ ((type == SipManager.MIC_PATH) ? "MIC" : "SPK")
+				+ ", defaultVolume : " + defaultVolume);
+		return defaultVolume;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_DeviceIP_set
+	// -----------------------------------------------------------------------------------
+	private int CERES_DeviceIP_set(String deviceIP) {
+
+		int iRet = 1; // CME_GENERAL_FAIL
+		byte[] l_deviceIP = null;
+		l_deviceIP = new byte[32];
+
+		deviceIP.getBytes(0, deviceIP.length(), l_deviceIP, 0);
+
+		if (deviceIP.length() <= 0
+				|| (iRet = CMIF_SetLocalIPAddress(l_deviceIP)) != 0) {
+			printlog.e(THIS_FILE, " CMIF_SetLocalIPAddress ERR : " + iRet
+					+ ", deviceIP : " + deviceIP);
+		}
+
+		return iRet;
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_Vidoe_Ready
+	// -----------------------------------------------------------------------------------
+	public int CERES_Vidoe_Ready(int callIdx) {
+		return CMIF_IsVideoCall(callIdx);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_SYSDelay_chk
+	// -----------------------------------------------------------------------------------
+	public int CERES_SYSDelay_chk(int start) {
+		return mPCMIF.AECDelayCheck(start);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_SYSDelay_set
+	// -----------------------------------------------------------------------------------
+	public int CERES_SYSDelay_set() {
+		return mPCMIF.SystemDelay_set();
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_JBVariation_chk
+	// -----------------------------------------------------------------------------------
+	public int CERES_JBVariation_chk(int start) {
+		return mPCMIF.JBVCheck(start);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// CERES_NP_Metrics
+	// -----------------------------------------------------------------------------------
+	public int CERES_NP_Metrics(int start) {
+		return mPCMIF.NPMetrics(start);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// Get the String value configuration string value -->
+	// callManager(cmHandler)
+	// -----------------------------------------------------------------------------------
+	// -----------------------------------------------------------------------------------
+	// DeviceIP : get ip address
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetDeviceIP(byte[] deviceIP) {
+		// m_DeviceIP = IpAddress.deviceIP_get();
+
+		m_DeviceIP.getBytes(0, m_DeviceIP.length(), deviceIP, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// TelEventPT :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetTelEventPT(byte[] telEventPT) {
+		m_TelEventPT = SipManager.TelEventPT;
+		m_TelEventPT.getBytes(0, m_TelEventPT.length(), telEventPT, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// VideoMAXSize :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVideoMAXSize(byte[] videoMAXSize) {
+		m_VideoMAXSize = SipManager.VIDEO_SIZE_VGA;
+		m_VideoMAXSize.getBytes(0, m_VideoMAXSize.length(), videoMAXSize, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// VideoSize :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVideoSize(byte[] videoSize) {
+		//m_VideoSize = SipManager.VIDEO_SIZE_CIF;
+		m_VideoSize.getBytes(0, m_VideoSize.length(), videoSize, 0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// VCodecFrameRate :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVCodecFrameRate(byte[] vCodecFrameRate) {
+		//m_VCodecFrameRate = SipManager.VIDEO_FRAME_RATE;
+		m_VCodecFrameRate.getBytes(0, m_VCodecFrameRate.length(), vCodecFrameRate,
+				0);
+	}
+	// -----------------------------------------------------------------------------------
+	// VCodecBandwidth :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVCodecBandWidth(byte[] vCodecBandWidth) {
+		//m_VCodecBandwidth = SipManager.VIDEO_BANDWIDTH;
+		m_VCodecBandwidth.getBytes(0, m_VCodecBandwidth.length(), vCodecBandWidth,
+				0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// VCodec_MAXBR :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVCodecMAXBR(byte[] vCodecMAXBR) {
+		//m_VCodecFrameRate = SipManager.VIDEO_FRAME_RATE;
+		m_VCodec_MAXBR.getBytes(0, m_VCodec_MAXBR.length(), vCodecMAXBR,
+				0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// H264_Pmode :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetH264_Pmode(byte[] h264_Pmode) {
+		//m_VCodecBandwidth = SipManager.VIDEO_BANDWIDTH;
+		m_H264_Pmode.getBytes(0, m_H264_Pmode.length(), h264_Pmode,
+				0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// MPEG4VES_Pli :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetMPEG4VES_Pli(byte[] MPEG4VES_Pli) {
+		//m_VCodecBandwidth = SipManager.VIDEO_BANDWIDTH;
+		m_MPEG4VES_Pli.getBytes(0, m_MPEG4VES_Pli.length(), MPEG4VES_Pli,
+				0);
+	}
+	// -----------------------------------------------------------------------------------
+	// MAXCALL :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetMAXCall(byte[] maxCall) {
+		m_MAXCall = SipManager.MAX_CALL;
+		m_MAXCall.getBytes(0, m_MAXCall.length(), maxCall, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// URLRULE :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetURLRule(byte[] urlRule) {
+		m_URLRule = SipManager.DEFAULT_URL_RULE;
+		m_URLRule.getBytes(0, m_URLRule.length(), urlRule, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// SRTP Security KEY :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetSRTPSKey(byte[] sSecurityKey) {
+		m_SRTP_SKey = SipManager.SRTP_SECURITY_KEY;
+		m_SRTP_SKey.getBytes(0, m_SRTP_SKey.length(), sSecurityKey, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// User Address : domain
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetUserAddr(byte[] userAddr) {
+		printlog.w(THIS_FILE, "m_Address : " + m_Address);
+		m_Address.getBytes(0, m_Address.length(), userAddr, 0);
+		printlog.w(THIS_FILE, "userAddr : " + userAddr);
+	}
+	//
+	@SuppressWarnings("static-access")
+	public static void jGetDecryptByteData(byte[] from_enc_data,
+										   byte[] to_dec_data) {
+		String tempStr = "";
+		String tempStr2 = "";
+		// Base64Utils base64 = new Base64Utils();
+		String encryptKey = "abcdefghijk0";
+		printlog.d(THIS_FILE, "from_enc_data : " + from_enc_data);
+		try {
+			tempStr = new String(from_enc_data, "UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		printlog.d(THIS_FILE, "new String(from_enc_data) : " + tempStr);
+		tempStr2 = base64.decrypt(tempStr, encryptKey);
+		printlog.d(THIS_FILE, "tempStr2 " + tempStr2);
+		tempStr2.getBytes(0, tempStr2.length(), to_dec_data, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Server Name
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetServerName(byte[] registrarAddr) {
+		m_SVRName = SipManager.SERVER_NAME;
+		m_SVRName.getBytes(0, m_SVRName.length(), registrarAddr, 0);
+	}
+	public static void jCmGetServerName2(byte[] regPort) {
+		m_SVRName2 = SipManager.SERVER_NAME2;
+		m_SVRName2.getBytes(0, m_SVRName2.length(), regPort, 0);
+	}
+	public static void jCmGetServerName3(byte[] regPort) {
+		m_SVRName3 = SipManager.SERVER_NAME3;
+		m_SVRName3.getBytes(0, m_SVRName3.length(), regPort, 0);
+	}
+	public static void jCmGetServerName4(byte[] regPort) {
+		m_SVRName4 = SipManager.SERVER_NAME4;
+		m_SVRName4.getBytes(0, m_SVRName4.length(), regPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Register Server1 Address : RegAddr / RegPort
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetPRegistrarAddr(byte[] registrarAddr) {
+		m_RegAddr.getBytes(0, m_RegAddr.length(), registrarAddr, 0);
+	}
+	public static void jCmGetPRegistrarPort(byte[] regPort) {
+		m_RegPort.getBytes(0, m_RegPort.length(), regPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Register Server2 Address : RegAddr / RegPort
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetPRegistrarAddr2(byte[] registrarAddr) {
+		m_RegAddr2 = m_RegAddr;
+		m_RegAddr2.getBytes(0, m_RegAddr2.length(), registrarAddr, 0);
+	}
+	public static void jCmGetPRegistrarPort2(byte[] regPort) {
+		m_RegPort2 = m_RegPort;
+		m_RegPort2.getBytes(0, m_RegPort2.length(), regPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Register Server3 Address : RegAddr / RegPort
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetPRegistrarAddr3(byte[] registrarAddr) {
+		m_RegAddr3 = m_RegAddr;
+		m_RegAddr3.getBytes(0, m_RegAddr3.length(), registrarAddr, 0);
+	}
+	public static void jCmGetPRegistrarPort3(byte[] regPort) {
+		m_RegPort3 = m_RegPort;
+		m_RegPort3.getBytes(0, m_RegPort3.length(), regPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Register Server4 Address : RegAddr / RegPort
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetPRegistrarAddr4(byte[] registrarAddr) {
+		m_RegAddr4 = m_RegAddr;
+		m_RegAddr4.getBytes(0, m_RegAddr4.length(), registrarAddr, 0);
+	}
+	public static void jCmGetPRegistrarPort4(byte[] regPort) {
+		m_RegPort4 = m_RegPort;
+		m_RegPort4.getBytes(0, m_RegPort4.length(), regPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// USER ID : Phone Number
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetUserID(byte[] userID) {
+		m_PhoneNumber.getBytes(0, m_PhoneNumber.length(), userID, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Auth ID : Auth-ID
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetAuthID(byte[] authID) {
+		m_AuthId.getBytes(0, m_AuthId.length(), authID, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Password : Password
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetUserPWD(byte[] userPWD) {
+		m_Password.getBytes(0, m_Password.length(), userPWD, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// ReRegisterTime : Re-Register time
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetReRegTime(byte[] reregtime) {
+		m_ReRegTime.getBytes(0, m_ReRegTime.length(), reregtime, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// SessionTime : SessionTime
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetSessionTime(byte[] sessiontime) {
+		m_SessionTime.getBytes(0, m_SessionTime.length(), sessiontime, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// SessionExpireTime : Session_Expire_Time
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetSessionExpireTime(byte[] sessionexpiretime) {
+		m_SessionExpireTime.getBytes(0, m_SessionExpireTime.length(),
+				sessionexpiretime, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// TransactionTime : Transaction Time
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetTransactionTime(byte[] transactiontime) {
+		m_TransactionTime.getBytes(0, m_TransactionTime.length(),
+				transactiontime, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// DTMF Type : DTMF Type
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetDTMFType(byte[] dtmftype) {
+		m_DTMFType.getBytes(0, m_DTMFType.length(), dtmftype, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// URL Type : URL Type
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetURLType(byte[] urltype) {
+		m_URLType.getBytes(0, m_URLType.length(), urltype, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Local Port : Local Port
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetLocalPort(byte[] localPort) {
+		m_LocalPort.getBytes(0, m_LocalPort.length(), localPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Local Media Port : Local Media Port
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetLocalMediaPort(byte[] localMediaPort) {
+		m_LocalMediaPort.getBytes(0, m_LocalMediaPort.length(), localMediaPort,
+				0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Remote Media Port : Remote Media Port
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetRemoteMediaPort(byte[] remoteMediaPort) {
+		m_RemoteMediaPort.getBytes(0, m_RemoteMediaPort.length(),
+				remoteMediaPort, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Audio Codec Priority : Audio Codec Priority
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetCodecPri(byte[] codecPri) {
+		m_ACodecPri.getBytes(0, m_ACodecPri.length(), codecPri, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Video Codec Priority : Video Codec Priority
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetVideoCodecPri(byte[] vcodecPri) {
+		m_VCodecPri.getBytes(0, m_VCodecPri.length(), vcodecPri, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Provider : Provider
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetProvider(byte[] provider) {
+		m_Provider.getBytes(0, m_Provider.length(), provider, 0);
+		Log.v("yjyoon", "jCmGetProvider provider=" + m_Provider);
+	}
+	// -----------------------------------------------------------------------------------
+	// AEC On Off : AEC On Off
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetAEConoff(byte[] aeconoff) {
+		m_AECOnOff.getBytes(0, m_AECOnOff.length(), aeconoff, 0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// System Delay Check On Off :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetSDC(byte[] aeconoff) {
+		m_SDCOnOff.getBytes(0, m_SDCOnOff.length(), aeconoff, 0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// JB Min Max :
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetJBMinMax(byte[] minmax) {
+		m_JBMinMax.getBytes(0, m_JBMinMax.length(), minmax, 0);
+	}
+
+	// -----------------------------------------------------------------------------------
+	// H/W SamplingRate : 48000, 44100, 16000, 8000
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetHWSamplingRate(byte[] hw_sr) {
+		printlog.d(THIS_FILE, "jCmGetHWSamplingRate is called...");
+		m_HWSamplingRate.getBytes(0, m_HWSamplingRate.length(), hw_sr, 0);
+	}
+	/**
+	 * jGetLogLvSIP (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param level
+	 */
+	public static void jGetLogLvSIP(byte[] level) {
+		if (m_Log_LV_SIP.length() == 0) {
+			m_Log_LV_SIP = SipManager.LOG_LV_DEGUG;
+		}
+		m_Log_LV_SIP.getBytes(0, m_Log_LV_SIP.length(), level, 0);
+	}
+	/**
+	 * jGetLogLvRTP (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param level
+	 */
+	public static void jGetLogLvRTP(byte[] level) {
+		if (m_Log_LV_RTP.length() == 0) {
+			m_Log_LV_RTP = SipManager.LOG_LV_DEGUG;
+		}
+		printlog.d(THIS_FILE, "m_Log_LV_RTP : " + m_Log_LV_RTP);
+		m_Log_LV_RTP.getBytes(0, m_Log_LV_RTP.length(), level, 0);
+	}
+	/**
+	 * jGetLogLvCM (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param level
+	 */
+	public static void jGetLogLvCM(byte[] level) {
+		if (m_Log_LV_CM.length() == 0) {
+			m_Log_LV_CM = SipManager.LOG_LV_DEGUG;
+		}
+		m_Log_LV_CM.getBytes(0, m_Log_LV_CM.length(), level, 0);
+	}
+	/**
+	 * jGetLogLvMCM (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param level
+	 */
+	public static void jGetLogLvMCM(byte[] level) {
+		if (m_Log_LV_MCM.length() == 0) {
+			m_Log_LV_MCM = SipManager.LOG_LV_DEGUG;
+		}
+		m_Log_LV_MCM.getBytes(0, m_Log_LV_MCM.length(), level, 0);
+	}
+	/**
+	 * jGetLogLvMMM (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param level
+	 */
+	public static void jGetLogLvMMM(byte[] level) {
+		if (m_Log_LV_MMM.length() == 0) {
+			m_Log_LV_MMM = SipManager.LOG_LV_DEGUG;
+		}
+		m_Log_LV_MMM.getBytes(0, m_Log_LV_MMM.length(), level, 0);
+	}
+	/**
+	 * jGetVAD (mmAudioHandler, mmAudio_SetVAD)
+	 *
+	 * @param onoff
+	 */
+	public static void jGetVAD(byte[] onoff) {
+		if (m_VADOnOff.length() == 0) {
+			m_VADOnOff = SipManager.VAD_OFF;
+		}
+
+		printlog.d(THIS_FILE, "m_VADOnOff : " + m_VADOnOff);
+
+		m_VADOnOff.getBytes(0, m_VADOnOff.length(), onoff, 0);
+	}
+	/**
+	 * jGetNS (mmAudioHandler, mmAudio_SetNS)
+	 *
+	 * @param onoff
+	 */
+	public static void jGetNS(byte[] onoff) {
+		if (m_NSOnOff.length() == 0) {
+			m_NSOnOff = SipManager.NS_OFF;
+		}
+		m_NSOnOff.getBytes(0, m_NSOnOff.length(), onoff, 0);
+	}
+	/**
+	 * jGetCNG (mmAudioHandler, mmAudio_SetCNG)
+	 *
+	 * @param onoff
+	 */
+	public static void jGetCNG(byte[] onoff) {
+		if (m_CNGOnOff.length() == 0) {
+			m_CNGOnOff = SipManager.CNG_OFF;
+		}
+		m_CNGOnOff.getBytes(0, m_CNGOnOff.length(), onoff, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECMemo
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECMemo(byte[] aecmemo, int value) {
+		m_AECMemo.getBytes(0, m_AECMemo.length(), aecmemo, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECDelay
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECDelay(byte[] delay) {
+		m_AECDelay.getBytes(0, m_AECDelay.length(), delay, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECTimeSpan
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECTimeSpan(byte[] timespan) {
+		m_AECTimeSpan.getBytes(0, m_AECTimeSpan.length(), timespan, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECERL
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECERL(byte[] erl) {
+		m_AECERL.getBytes(0, m_AECERL.length(), erl, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECDynVol
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECDynVol(byte[] dynvol) {
+		m_AECDynVol.getBytes(0, m_AECDynVol.length(), dynvol, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECDynVolMin
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECDynVolMin(byte[] dynvolmin) {
+		m_AECDynVolMin.getBytes(0, m_AECDynVolMin.length(), dynvolmin, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECUpdateSpeed
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECUpdateSpeed(byte[] updatespeed) {
+		m_AECUpdateSpeed.getBytes(0, m_AECUpdateSpeed.length(), updatespeed, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECWMaxIndex
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECWMaxIndex(byte[] wmaxindex) {
+		m_AECWMaxIndex.getBytes(0, m_AECWMaxIndex.length(), wmaxindex, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// AECWScale
+	// -----------------------------------------------------------------------------------
+	public static void jGetAECWScale(byte[] wscale) {
+		m_AECWScale.getBytes(0, m_AECWScale.length(), wscale, 0);
+	}
+	// -----------------------------------------------------------------------------------
+	// Secure RTP Option : Secure-RTP Option
+	// -----------------------------------------------------------------------------------
+	public static void jCmGetSRTPState(byte[] srtpstate) {
+		m_SRTPOption.getBytes(0, m_SRTPOption.length(), srtpstate, 0);
+	}
+
+
+	public static void jCmGetSRegistrarAddr(byte[] registrarAddr) {
+		;
+	}
+	public static void jCmGetSBCPRegistrarAddr(byte[] registrarAddr) {
+		;
+	}
+	public static void jCmGetSBCSRegistrarAddr(byte[] registrarAddr) {
+		;
+	}
+	public static void jCmGetSRegistrarPort(byte[] regPort) {
+		;
+	}
+	public static void jCmGetSBCPRegistrarPort(byte[] regPort) {
+		;
+	}
+	public static void jCmGetSBCSRegistrarPort(byte[] regPort) {
+		;
+	}
+
+	// ------------------------------------------------------------------------------------------
+	// UAStateReceiver Callback Register
+	// ------------------------------------------------------------------------------------------
+	public static OnCallbackListener onCallStateCBListener;
+	//public static OnCallbackListener onCheckCBListener;
+	public static OnCallbackListener onMediaUpdateCBListener;
+	public static OnMonitorListener onCheckCBListener;
+	public static OnLoopbackListener onLoopbackCBListener;
+	public static OnTapsStatusListener onTapsStatusEvent;
+
+	/**
+	 * Interface definition for a callback to be invoked when a tab is triggered
+	 * by moving it beyond a target zone.
+	 */
+	public interface OnCallbackListener {
+		void OnCallStateChanged(CMCallInfo callinfo);
+		void OnAccRegChanged(int state);
+		void OnMediaUpdated(int mediaDir);
+	}
+
+	public interface OnMonitorListener {
+		void onSYSDelayCheckEvent(int delay, int max);
+		void onJBVCheckEvent(int currMS, int var);
+		void onNPMetricsEvent(NPMetrics npMetrics);
+	}
+
+	public interface OnTapsStatusListener {
+		void onTapsStatusEvent(int state, String str);
+	}
+
+	public interface OnLoopbackListener {
+		void OnLoopbackStateChanged(int state, int callType);
+	}
+
+	public void setOnCallStateCBListener(OnCallbackListener listener) {
+		onCallStateCBListener = listener;
+	}
+
+	public void setOnCheckCBListener(OnMonitorListener listener) {
+		onCheckCBListener = listener;
+	}
+
+	public void setOnMediaUpdateListener(OnCallbackListener listener) {
+		onMediaUpdateCBListener = listener;
+	}
+
+	public void setOnLoopbackCBListener(OnLoopbackListener listener) {
+		onLoopbackCBListener = listener;
+	}
+
+	public void setOnTapsStatusCBListener(OnTapsStatusListener listener) {
+		onTapsStatusEvent = listener;
+	}
+
+
+	private void dispatchMediaUpdateCBEvent(int mediaDir) {
+		if (onMediaUpdateCBListener != null) {
+			onMediaUpdateCBListener.OnMediaUpdated(mediaDir);
+		}
+	}
+
+	private void dispatchCallStateCBEvent(CMCallInfo callinfo) {
+		if (onCallStateCBListener != null) {
+			onCallStateCBListener.OnCallStateChanged(callinfo);
+		}
+	}
+
+	private void dispatchCallStateCBEvent(int state) {
+		if (onCallStateCBListener != null) {
+			onCallStateCBListener.OnAccRegChanged(state);
+		}
+	}
+
+//	public static void dispatchCheckCBEvent(int delay) {
+//		if (onCheckCBListener != null) {
+//			onCheckCBListener.onSYSDelayCheckEvent(delay, 200);
+//		}
+//	}
+
+	public static void dispatchNPMetricsCBEvent(NPMetrics npMetrics) {
+		if (onCheckCBListener != null) {
+			onCheckCBListener.onNPMetricsEvent(npMetrics);
+		}
+	}
+
+	public static void dispatchCheckCBEvent(int currMS, int var) {
+		if (onCheckCBListener != null) {
+			onCheckCBListener.onJBVCheckEvent(currMS, var);
+		}
+	}
+
+	public static void dispatchSysDelayEvent(int delay, int echo_dB){
+		if (onCheckCBListener != null) {
+			onCheckCBListener.onSYSDelayCheckEvent(delay, echo_dB);
+		}
+	}
+
+	private void dispatchLoopbackCBEvent(int state, int callType) {
+		if (onLoopbackCBListener != null) {
+			onLoopbackCBListener.OnLoopbackStateChanged(state, callType);
+		}
+	}
+
+	private static void dispatchTapsStatusCBEvent(int state, String str) {
+		if (onTapsStatusEvent != null) {
+			onTapsStatusEvent.onTapsStatusEvent(state, str);
+		}
+	}
+
+	private static void currentCallInfo(boolean printfg, DupCallInfo callInfo) {
+
+		if (printfg == true) {
+			printlog.w(THIS_FILE,
+					"callInfo.---------------------------------------------------------");
+			printlog.i(THIS_FILE,
+					"callInfo.getAccId() : " + callInfo.getAccId());
+			printlog.i(THIS_FILE,
+					"callInfo.getAudioCodec() : " + callInfo.getAudioCodec());
+			printlog.i(THIS_FILE, "callInfo.getAudioCodecParamPtime() : "
+					+ callInfo.getAudioCodecParamPtime());
+			printlog.d(THIS_FILE,
+					"callInfo.getAudioDir() : " + callInfo.getAudioDir());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getAudioLocalAddr() : "
+							+ callInfo.getAudioLocalAddr());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getAudioLocalPort() : "
+							+ callInfo.getAudioLocalPort());
+			printlog.d(THIS_FILE, "callInfo.getAudioPayloadType() : "
+					+ callInfo.getAudioPayloadType());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getAudioRemoteAddr() : "
+							+ callInfo.getAudioRemoteAddr());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getAudioRemotePort() : "
+							+ callInfo.getAudioRemotePort());
+			printlog.d(THIS_FILE,
+					"callInfo.getAudioTeltPt() : " + callInfo.getAudioTeltPt());
+			printlog.d(THIS_FILE,
+					"callInfo.getAudioType() : " + callInfo.getAudioType());
+			printlog.d(THIS_FILE,
+					"callInfo.getLocalMedia() : " + callInfo.getLocalMedia());
+			printlog.d(THIS_FILE,
+					"callInfo.getNumRemote() : " + callInfo.getNumRemote());
+			printlog.w(THIS_FILE,
+					"callInfo.getPrevState() : " + callInfo.getPrevState());
+			printlog.d(THIS_FILE,
+					"callInfo.getRemoteMedia() : " + callInfo.getRemoteMedia());
+			printlog.d(THIS_FILE,
+					"callInfo.getRemoteName() : " + callInfo.getRemoteName());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getRemoteStatus() : "
+							+ callInfo.getRemoteStatus());
+			printlog.i(THIS_FILE,
+					"callInfo.getRemoteUri() : " + callInfo.getRemoteUri());
+			printlog.d(
+					THIS_FILE,
+					"callInfo.getRingWithMedia() : "
+							+ callInfo.getRingWithMedia());
+			printlog.i(THIS_FILE,
+					"callInfo.getState() : " + callInfo.getState());
+			printlog.d(THIS_FILE,
+					"callInfo.getStatusCode() : " + callInfo.getStatusCode());
+			printlog.d(THIS_FILE, "callInfo.getType() : " + callInfo.getType());
+		}
+		return;
+	}
+
+	public static int m_callIdx = -1;
+
+	public static void setCallIndex(int callId) {
+		m_callIdx = callId;
+		return;
+	}
+
+	public int CERES_CallIndex_get() {
+		return m_callIdx;
+	}
+
+	public int getCallIndex() {
+		return m_callIdx;
+	}
+
+	public static void jLoopbackConnect(int state, int mediaType){
+		printlog.d(THIS_FILE, "jLoopbackConnect, state : " + state + ", mediaType : " + mediaType);
+		Log.v("yjyoon", "3333");
+		Message msg = msgHandler.obtainMessage(state);
+		Bundle b = new Bundle();
+		b.putInt("mediaType", mediaType);
+
+		msg.setData(b);
+		msgHandler.sendMessage(msg);
+	}
+
+	public static void jLoopbackDisconnect(int state, int mediaType){
+		printlog.d(THIS_FILE, "jLoopbackDisconnect, state : " + state + ", mediaType : " + mediaType);
+		Log.v("yjyoon", "4444");
+		Message msg = msgHandler.obtainMessage(state);
+		Bundle b = new Bundle();
+		b.putInt("mediaType", mediaType);
+
+		msg.setData(b);
+		msgHandler.sendMessage(msg);
+	}
+
+
+	// --------------------------------------------------
+	// InCallMediaControl
+	// --------------------------------------------------
+
+	private static boolean isFirstRun = true;
+
+	private static int mDigital_SpkVolume = 0;
+	private static int mDigital_MicVolume = 0;
+	private static int mInitDigital_SpkVolume = 0;
+	private static int mInitDigital_MicVolume = 0;
+
+
+	public void InCallMedia_isFirstRun_set(boolean value){
+		isFirstRun = value;
+	}
+
+	public boolean InCallMeida_isFirstRun_get(){
+		return isFirstRun;
+	}
+
+	public void InCallMedia_SPK_Volume_set(int setVolume){
+		mDigital_SpkVolume = setVolume;
+	}
+
+	public int InCallMedia_SPK_Volume_get(){
+		return mDigital_SpkVolume;
+	}
+
+	public static void InCallMedia_MIC_Volume_set(int setVolume){
+		mDigital_MicVolume = setVolume;
+	}
+
+	public int InCallMedia_MIC_Volume_get(){
+		return mDigital_MicVolume;
+	}
+
+	// --------------------------------------------------------
+	// Initial Volume
+	// --------------------------------------------------------
+	public void InCallMedia_SPK_InitVolume_set(int setVolume){
+		mInitDigital_SpkVolume = setVolume;
+	}
+
+	public int InCallMedia_SPK_InitVolume_get(){
+		return mInitDigital_SpkVolume;
+	}
+
+	public void InCallMedia_MIC_InitVolume_set(int setVolume){
+		mInitDigital_MicVolume = setVolume;
+	}
+
+	public int InCallMedia_MIC_InitVolume_get(){
+		return mInitDigital_MicVolume;
+	}
+
+
+	// ------------------------------------------------------------------------------------
+	// Receive event from cmHandler.
+	// ------------------------------------------------------------------------------------
+	@SuppressWarnings("static-access")
+	public static void jCmChangeState(int state, int callId) {
+		lockCpu();
+
+		// printlog.d(THIS_FILE, "jCmChangeState. param : " + param);
+		printlog.d(THIS_FILE, "jCmChangeState. callId : " + callId);
+
+		setCallIndex(callId);
+
+		DupCallInfo callInfo = new DupCallInfo(callId);
+		// -------------------------------------------------------------------------
+		// callInfo call info print..
+		// -------------------------------------------------------------------------
+		currentCallInfo(true, callInfo);
+
+		int callState = callInfo.getState();
+
+		// -------------------------------------------------------------------------------------
+		// jCmChangeState state value..
+		// -------------------------------------------------------------------------------------
+		printlog.w(THIS_FILE, "jCmChangeState. -------------------------------------------------");
+		printlog.d(THIS_FILE, "jCmChangeState. state        : " + state);
+		printlog.d(THIS_FILE, "jCmChangeState. callState        : " + callState);
+
+		// -------------------------------------------------------------------------
+		// state 0 : OnCallStateChanged
+		// 1 : OnMediaStart : mediaType audio
+		// 2 : OnMediaStart : mediaType video
+		// 3 : onMediaUpdate : mediaType audio
+		// -------------------------------------------------------------------------
+		if (state == 0) {
+
+			if (callState == DupCallInfo.CMCallState.INCOMING){
+				printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.INCOMING : ");
+				// ------------------------------
+				// SHW-E120K : KT 갤럭시S2 LTE
+				// ------------------------------
+				if (SipManager.DEVICE_NAME.equalsIgnoreCase("E120")) {
+					printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.INCOMING : S2LTE, set MIC 44");
+					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 44);
+//					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 60);
+					InCallMedia_MIC_Volume_set(44);
+				}
+				// ------------------------------
+				// SHW-M250S : SKT 갤럭시S2
+				// ------------------------------
+				else if (SipManager.DEVICE_NAME.equalsIgnoreCase("M250")) {
+					printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.INCOMING : S2, set MIC 53");
+//					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 53);
+					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 60);
+				}
+			}
+			else if (callState == DupCallInfo.CMCallState.CALLING){
+				printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.CALLING : ");
+				// ------------------------------
+				// SHW-E120K : KT 갤럭시S2 LTE
+				// ------------------------------
+				if (SipManager.DEVICE_NAME.equalsIgnoreCase("E120")) {
+					printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.CALLING : S2LTE, set MIC 60");
+					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 60);
+					InCallMedia_MIC_Volume_set(60);
+				}
+				else if (SipManager.DEVICE_NAME.equalsIgnoreCase("M250")) {
+					printlog.d(THIS_FILE, "-----------> DupCallInfo.CMCallState.CALLING : S2, set MIC 53");
+//					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 53);
+					CERES_DigitalVolume_set(SipManager.MIC_PATH, 0, 60);
+				}
+			} else if (callState == DupCallInfo.CMCallState.RELEASED) {
+				// ------------------------------
+				// ALL_AEC_OFF : 0
+				// ------------------------------
+				if (m_AECOnOff.equals(SipManager.AEC_OFF) ||
+						m_AECOnOff.equals(SipManager.CNS_AEC_ON)) {
+					printlog.d(THIS_FILE, "ALL_AEC_OFF end");
+					// ------------------------------
+					// SHW-E120K : KT 갤럭시S2 LTE
+					// ------------------------------
+					if (SipManager.DEVICE_NAME.equalsIgnoreCase("E120")) {
+						printlog.d(THIS_FILE, "ALL_AEC_OFF end : S2 LTE");
+						audioManager.setParameters("realcall=off");
+					}
+					// ------------------------------
+					// SHW-M250S : SKT 갤럭시S2
+					// ------------------------------
+					else if (SipManager.DEVICE_NAME.equalsIgnoreCase("M250")) {
+						printlog.d(THIS_FILE, "ALL_AEC_OFF end : S2");
+						audioManager.setMode(AudioManager.MODE_NORMAL);
+					}
+				}
+				// ------------------------------
+				// INNER_AEC : 1
+				// ------------------------------
+				else if (m_AECOnOff.equals(SipManager.INNER_AEC_ON)) {
+					printlog.d(THIS_FILE, "INNER_AEC end");
+					//setParameters("voip=off");
+				}
+
+				// --------------------------------------------------------------------------------
+				// onBroadcastCallState
+				// --------------------------------------------------------------------------------
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				//onBroadcastCallState(STATE_INPUT_PHONENUM);
+			}
+		} else if (state == 1) {
+			printlog.d(THIS_FILE, " state 1 is onPreMediaStart!!!");
+			if (incomingCallLock != null) {
+				incomingCallLock.release();
+			}
+			// ------------------------------
+			// ALL_AEC_OFF : 0
+			// ------------------------------
+			if (m_AECOnOff.equals(SipManager.AEC_OFF) ||
+					m_AECOnOff.equals(SipManager.CNS_AEC_ON) ) {
+				printlog.d(THIS_FILE, "ALL_AEC_OFF start");
+				// ------------------------------
+				// SHW-E120K : KT 갤럭시S2 LTE
+				// ------------------------------
+				if (SipManager.DEVICE_NAME.equalsIgnoreCase("E120")) {
+					printlog.d(THIS_FILE, "ALL_AEC_OFF start : S2 LTE");
+					audioManager.setMode(AudioManager.MODE_NORMAL);
+					audioManager.setParameters("realcall=on");
+					printlog.e(THIS_FILE, "audioManager.getStreamMaxVolume : " + audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL));
+					printlog.e(THIS_FILE, "audioManager.getStreamVolume : " + audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL));
+				}
+				// ------------------------------
+				// SHW-M250S : SKT 갤럭시S2
+				// ------------------------------
+				else if (SipManager.DEVICE_NAME.equalsIgnoreCase("M250")) {
+					printlog.d(THIS_FILE, "ALL_AEC_OFF start : S2");
+					audioManager.setMode(AudioManager.MODE_IN_CALL);
+				}
+			}
+			// ------------------------------
+			// INNER_AEC : 1
+			// ------------------------------
+			else if (m_AECOnOff.equals(SipManager.INNER_AEC_ON)) {
+				printlog.d(THIS_FILE, "INNER_AEC start");
+				// ------------------------------
+				// SHW-M250S : SKT 갤럭시S2
+				// ------------------------------
+				if (SipManager.DEVICE_NAME.equalsIgnoreCase("M250")) {
+					printlog.d(THIS_FILE, "INNER_AEC start : S2 LTE");
+					//audioManager.setMode(AudioManager.MODE_IN_CALL);
+					audioManager.setMode(AudioManager.MODE_NORMAL);
+				}
+				//setParameters("voip=on");
+			}
+		}
+		// ------------------------------
+		// VideoCall
+		// ------------------------------
+		else if (state == 2) {
+			mPCMIF.MMIF_IsVideoReady(callId);
+		}
+
+		// ------------------------------
+		// mediaUpdate
+		// ------------------------------
+		else if (state == 3) {
+			msgHandler.sendMessage(msgHandler.obtainMessage(ON_MEDIA_UPDATE, callInfo));
+			return;
+		}
+
+		msgHandler.sendMessage(msgHandler.obtainMessage(ON_CALL_STATE, callInfo));
+		//callInfo.delete();
+
+		unlockCpu();
+	}
+
+	public static void jCmRegisterState(int state, int accId) {
+		lockCpu();
+
+		CMAccStatus accInfo = new CMAccStatus();
+		getAccountStatus(0, accInfo);
+
+		printlog.w(THIS_FILE, "jCmRegisterState, state:" + state);
+		printlog.w(THIS_FILE, "jCmRegisterState, accId:" + accId);
+
+		msgHandler.sendMessage(msgHandler.obtainMessage(ON_REGISTRATION_STATE, accInfo));
+
+		unlockCpu();
+	}
+
+	public static void jTAPSReportState(int state, byte[] str) {
+		lockCpu();
+
+		String tempStr = "";
+
+		printlog.w(THIS_FILE, "taps jTAPSReportState, state:" + state);
+		printlog.e(THIS_FILE, "taps jTAPSReportState, str:" + str);
+		try {
+			tempStr = new String(str, "UTF-8");
+		} catch (UnsupportedEncodingException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		//printlog.w(THIS_FILE, "taps jTAPSReportState, dummy:" + dummy);
+//		msgHandler.sendEmptyMessage(ON_TAPS_REPORT_STATE);
+
+		printlog.e(THIS_FILE, "taps jTAPSReportState, tempStr:" + tempStr);
+
+		Message msg = handler.obtainMessage(ON_TAPS_REPORT_STATE);
+		Bundle b = new Bundle();
+		b.putInt("state", state);
+		b.putString("str", tempStr);
+
+		msg.setData(b);
+		handler.sendMessage(msg);
+
+		unlockCpu();
+	}
+
+	private static WorkerHandler msgHandler;
+	private static WakeLock incomingCallLock;
+	private static WakeLock eventLock;
+	private HandlerThread handlerThread;
+
+	// -----------------------------------------------------------------------
+	// CALL_STATE : 0, REGISTARTION_STATE : 1
+	// -----------------------------------------------------------------------
+	public static final int ON_CALL_STATE = 0;
+	public static final int ON_REGISTRATION_STATE = 1;
+	public static final int ON_MEDIA_VIDEO = 2;
+	public static final int ON_MEDIA_UPDATE = 3;
+	public static final int ON_MEDIA_LOOPBACK_CONNECT = 4;
+	public static final int ON_MEDIA_LOOPBACK_DISCONNECT = 5;
+	public static final int ON_TAPS_REPORT_STATE = 6;
+
+
+	// -----------------------------------------------------------------------
+	// ON_CALL_STATE
+	// -----------------------------------------------------------------------
+	public static final int STATE_INPUT_PHONENUM = 0;
+	public static final int STATE_OUT_GOING = 1; // CALLING
+	public static final int STATE_IN_COMMING = 2; // INCOMING
+	public static final int STATE_ON_CALL = 3; // CONFIRMED
+	public static final int STATE_ON_IDLE = 4; // DISCONNECTED
+	public static final int STATE_ERROR = 5;
+
+	private class WorkerHandler extends Handler {
+
+		public WorkerHandler(Looper looper) {
+			super(looper);
+			printlog.i(THIS_FILE, " service debugCreate async worker !!!");
+		}
+
+		public void handleMessage(Message msg) {
+
+			switch (msg.what) {
+
+				case ON_CALL_STATE: {
+
+					DupCallInfo callInfo = (DupCallInfo) msg.obj;
+
+					// -------------------------------------------------------------------------------------
+					// handleMessage callinfo value..
+
+					// -------------------------------------------------------------------------------------
+
+					printlog.w(THIS_FILE, "handleMessage. -------------------------------------------------");
+					printlog.d(THIS_FILE, "handleMessage.state        : " + callInfo.getState());
+					printlog.d(THIS_FILE, "handleMessage.mediaType    : " + callInfo.getRemoteMedia());
+					printlog.d(THIS_FILE, "handleMessage.aCodecName    : " + callInfo.get_ACodecName(callInfo.getAudioCodec()));
+					printlog.d(THIS_FILE, "handleMessage.aCodecInt     : " + callInfo.getAudioCodec());
+					printlog.d(THIS_FILE, "handleMessage.vCodecName    : " + callInfo.get_VCodecName(callInfo.getVideoCodec()));
+					printlog.d(THIS_FILE, "handleMessage.vCodecInt     : " + callInfo.getVideoCodec());
+					printlog.d(THIS_FILE, "handleMessage.vSizeName    : " + callInfo.get_VSizeName(Integer.parseInt(m_VideoSize)));
+					printlog.d(THIS_FILE, "handleMessage.vSizeInt     : " + m_VideoSize);
+					printlog.d(THIS_FILE, "handleMessage.remoteNumber : " + callInfo.getRemoteUri());
+					printlog.d(THIS_FILE, "handleMessage.mediaDir	 : " + callInfo.getAudioDir());
+					printlog.d(THIS_FILE, "handleMessage.prevState	: " + callInfo.getPrevState());
+
+
+					dupCallInfo.callState = callInfo.getState();
+					dupCallInfo.mediaType = callInfo.getRemoteMedia();
+					dupCallInfo.aCodecName = callInfo.get_ACodecName(callInfo.getAudioCodec());
+					dupCallInfo.vCodecName = callInfo.get_VCodecName(callInfo.getVideoCodec());
+					dupCallInfo.vSizeName = callInfo.get_VSizeName(Integer.parseInt(m_VideoSize));
+					dupCallInfo.remoteNumber = callInfo.getRemoteUri();
+					dupCallInfo.mediaDir = callInfo.getAudioDir();
+					dupCallInfo.prevCallState = callInfo.getPrevState();
+
+					// -------------------------------------------------------------------------------------
+					// dispatchCallStateCBEvent
+					// @param : CMCallInfo
+					// -------------------------------------------------------------------------------------
+
+					dispatchCallStateCBEvent(dupCallInfo);
+
+					break;
+				}
+				case ON_REGISTRATION_STATE: {
+
+					CMAccStatus accInfo = (CMAccStatus) msg.obj;
+
+					int registered = accInfo.getRegistered();
+					dupCallInfo.callState = registered;
+
+					// -------------------------------------------------------------------------------------
+					// dispatchCallStateCBEvent
+					// @param : int
+					// -------------------------------------------------------------------------------------
+					dispatchCallStateCBEvent(registered);
+
+					CERES_RegiState_set(registered);
+
+					printlog.i(THIS_FILE, "register_state : " + register_state);
+
+					break;
+				}
+				case ON_MEDIA_UPDATE: {
+
+					DupCallInfo callInfo = (DupCallInfo) msg.obj;
+
+					// -------------------------------------------------------------------------------------
+					// handleMessage callinfo value..
+					// -------------------------------------------------------------------------------------
+
+					printlog.w(THIS_FILE, "handleMessage. -------------------------------------------------");
+					printlog.d(THIS_FILE, "handleMessage.state        : " + callInfo.getState());
+					printlog.d(THIS_FILE, "handleMessage.mediaType    : " + callInfo.getRemoteMedia());
+					printlog.d(THIS_FILE, "handleMessage.aCodecName    : " + callInfo.get_ACodecName(callInfo.getAudioCodec()));
+					printlog.d(THIS_FILE, "handleMessage.vCodecName    : " + callInfo.get_VCodecName(callInfo.getVideoCodec()));
+					printlog.d(THIS_FILE, "handleMessage.remoteNumber : " + callInfo.getRemoteUri());
+					printlog.d(THIS_FILE, "handleMessage.mediaDir	 : " + callInfo.getAudioDir());
+					printlog.d(THIS_FILE, "handleMessage.prevState	: " + callInfo.getPrevState());
+
+					dupCallInfo.mediaDir = callInfo.getAudioDir();
+
+					dispatchMediaUpdateCBEvent(dupCallInfo.mediaDir);
+					break;
+				}
+
+				case ON_MEDIA_LOOPBACK_CONNECT: {
+
+					int mediaType = msg.getData().getInt("mediaType");
+
+					dispatchLoopbackCBEvent(1, mediaType);
+
+					break;
+				}
+
+				case ON_MEDIA_LOOPBACK_DISCONNECT: {
+
+					int mediaType = msg.getData().getInt("mediaType");
+
+					dispatchLoopbackCBEvent(0, mediaType);
+				}
+
+				case ON_TAPS_REPORT_STATE: {
+
+					printlog.d(THIS_FILE, "taps ON_TAPS_REPORT_STATE : ");
+
+					CERES_Initialize(mContext);
+
+					break;
+				}
+			}
+		}
+	}
+
+	// -------------------------------------------------------------------------------------
+	// ACTION_SIP_CALL_RELEASED broadcast
+	// -------------------------------------------------------------------------------------
+//	private static void onBroadcastCallState(int state) {
+//		// Internal event
+//		Intent callStateChangedIntent = new Intent(SipManager.ACTION_SIP_CALL_RELEASED);
+//		//callStateChangedIntent.putExtra(SipManager.EXTRA_CALL_STATE, state);
+//
+//		printlog.i(THIS_FILE, "onBroadcastCallState SipManager.ACTION_SIP_CALL_RELEASED : " + state);
+//		try {
+//			Thread.sleep(100);
+//		} catch (InterruptedException e) {
+//			// TODO Auto-generated catch block
+//			e.printStackTrace();
+//		}
+//		mContext.sendBroadcast(callStateChangedIntent);
+//	}
+}

+ 435 - 0
WallPadCall/src/main/java/ceres/cminterface/DupCallInfo.java

@@ -0,0 +1,435 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.40
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+package ceres.cminterface;
+
+import ceres.utils.printlog;
+
+public class DupCallInfo {
+  private static final String THIS_FILE = "DupCallInfo";	
+  private long swigCPtr;
+  protected boolean swigCMemOwn;
+  private boolean isIncoming;
+  
+  // -------------------------------------------------------
+  public long callStart = 0;
+  // -------------------------------------------------------
+  public String aCodecName = "";
+  public String vCodecName = "";
+  public String remoteNumber = "";
+  public String vSizeName = "";
+  public int mediaType = -1;  
+  public int state = -1;
+  public int mediaDir = 0;
+  //--------------------------------------------------------
+
+  protected DupCallInfo(long cPtr, boolean cMemoryOwn) {
+    swigCMemOwn = cMemoryOwn;
+    swigCPtr = cPtr;
+  }
+
+  protected static long getCPtr(DupCallInfo obj) {
+    return (obj == null) ? 0 : obj.swigCPtr;
+  }
+
+  protected void finalize() {
+    delete();
+  }
+
+  public synchronized void delete() {
+    if (swigCPtr != 0) {
+      if (swigCMemOwn) {
+        swigCMemOwn = false;
+        cnssipuaJNI.delete_DupCallInfo(swigCPtr);
+      }
+      swigCPtr = 0;
+    }
+  }
+
+  public void setId(int value) {
+    cnssipuaJNI.DupCallInfo_id_set(swigCPtr, this, value);
+  }
+
+  public int getId() {
+    return cnssipuaJNI.DupCallInfo_id_get(swigCPtr, this);
+  }
+
+  public void setType(int value) {
+    cnssipuaJNI.DupCallInfo_type_set(swigCPtr, this, value);
+  }
+
+  public int getType() {
+    return cnssipuaJNI.DupCallInfo_type_get(swigCPtr, this);
+  }
+
+  public void setState(int value) {
+    cnssipuaJNI.DupCallInfo_state_set(swigCPtr, this, value);
+  }
+
+  public int getState() {
+    return cnssipuaJNI.DupCallInfo_state_get(swigCPtr, this);
+  }
+
+  public void setPrevState(int value) {
+    cnssipuaJNI.DupCallInfo_prevState_set(swigCPtr, this, value);
+  }
+
+  public int getPrevState() {
+    return cnssipuaJNI.DupCallInfo_prevState_get(swigCPtr, this);
+  }
+
+  public void setAccId(int value) {
+    cnssipuaJNI.DupCallInfo_accId_set(swigCPtr, this, value);
+  }
+
+  public int getAccId() {
+    return cnssipuaJNI.DupCallInfo_accId_get(swigCPtr, this);
+  }
+
+  public void setNumRemote(int value) {
+    cnssipuaJNI.DupCallInfo_numRemote_set(swigCPtr, this, value);
+  }
+
+  public int getNumRemote() {
+    return cnssipuaJNI.DupCallInfo_numRemote_get(swigCPtr, this);
+  }
+
+  public void setStatusCode(int value) {
+    cnssipuaJNI.DupCallInfo_statusCode_set(swigCPtr, this, value);
+  }
+
+  public int getStatusCode() {
+    return cnssipuaJNI.DupCallInfo_statusCode_get(swigCPtr, this);
+  }
+
+  public void setRemoteUri(String value) {
+    cnssipuaJNI.DupCallInfo_remoteUri_set(swigCPtr, this, value);
+  }
+
+  public String getRemoteUri() {
+    return cnssipuaJNI.DupCallInfo_remoteUri_get(swigCPtr, this);
+  }
+
+  public void setRemoteName(String value) {
+    cnssipuaJNI.DupCallInfo_remoteName_set(swigCPtr, this, value);
+  }
+
+  public String getRemoteName() {
+    return cnssipuaJNI.DupCallInfo_remoteName_get(swigCPtr, this);
+  }
+
+  public void setRemoteStatus(String value) {
+    cnssipuaJNI.DupCallInfo_remoteStatus_set(swigCPtr, this, value);
+  }
+
+  public String getRemoteStatus() {
+    return cnssipuaJNI.DupCallInfo_remoteStatus_get(swigCPtr, this);
+  }
+
+  public void setAudioType(int value) {
+    cnssipuaJNI.DupCallInfo_audioType_set(swigCPtr, this, value);
+  }
+
+  public int getAudioType() {
+    return cnssipuaJNI.DupCallInfo_audioType_get(swigCPtr, this);
+  }
+
+  public void setAudioDir(int value) {
+    cnssipuaJNI.DupCallInfo_audioDir_set(swigCPtr, this, value);
+  }
+
+  public int getAudioDir() {
+    return cnssipuaJNI.DupCallInfo_audioDir_get(swigCPtr, this);
+  }
+
+  public void setAudioLocalAddr(int value) {
+    cnssipuaJNI.DupCallInfo_audioLocalAddr_set(swigCPtr, this, value);
+  }
+
+  public int getAudioLocalAddr() {
+    return cnssipuaJNI.DupCallInfo_audioLocalAddr_get(swigCPtr, this);
+  }
+
+  public void setAudioLocalPort(int value) {
+    cnssipuaJNI.DupCallInfo_audioLocalPort_set(swigCPtr, this, value);
+  }
+
+  public int getAudioLocalPort() {
+    return cnssipuaJNI.DupCallInfo_audioLocalPort_get(swigCPtr, this);
+  }
+
+  public void setAudioRemoteAddr(int value) {
+    cnssipuaJNI.DupCallInfo_audioRemoteAddr_set(swigCPtr, this, value);
+  }
+
+  public int getAudioRemoteAddr() {
+    return cnssipuaJNI.DupCallInfo_audioRemoteAddr_get(swigCPtr, this);
+  }
+
+  public void setAudioRemotePort(int value) {
+    cnssipuaJNI.DupCallInfo_audioRemotePort_set(swigCPtr, this, value);
+  }
+
+  public int getAudioRemotePort() {
+    return cnssipuaJNI.DupCallInfo_audioRemotePort_get(swigCPtr, this);
+  }
+
+  public void setAudioPayloadType(int value) {
+    cnssipuaJNI.DupCallInfo_audioPayloadType_set(swigCPtr, this, value);
+  }
+
+  public int getAudioPayloadType() {
+    return cnssipuaJNI.DupCallInfo_audioPayloadType_get(swigCPtr, this);
+  }
+
+  public void setAudioTeltPt(int value) {
+    cnssipuaJNI.DupCallInfo_audioTeltPt_set(swigCPtr, this, value);
+  }
+
+  public int getAudioTeltPt() {
+    return cnssipuaJNI.DupCallInfo_audioTeltPt_get(swigCPtr, this);
+  }
+
+  public void setAudioCodec(int value) {
+    cnssipuaJNI.DupCallInfo_audioCodec_set(swigCPtr, this, value);
+  }
+
+  public int getAudioCodec() {
+    return cnssipuaJNI.DupCallInfo_audioCodec_get(swigCPtr, this);
+  }
+
+  public void setAudioCodecParamPtime(int value) {
+    cnssipuaJNI.DupCallInfo_audioCodecParamPtime_set(swigCPtr, this, value);
+  }
+
+  public int getAudioCodecParamPtime() {
+    return cnssipuaJNI.DupCallInfo_audioCodecParamPtime_get(swigCPtr, this);
+  }
+  
+  public void setVideoType(int value) {
+    cnssipuaJNI.DupCallInfo_videoType_set(swigCPtr, this, value);
+  }
+
+  public int getVideoType() {
+    return cnssipuaJNI.DupCallInfo_videoType_get(swigCPtr, this);
+  }
+  
+  public void setVideoCodec(int value) {
+    cnssipuaJNI.DupCallInfo_videoCodec_set(swigCPtr, this, value);
+  }
+
+  public int getVideoCodec() {
+    return cnssipuaJNI.DupCallInfo_videoCodec_get(swigCPtr, this);
+  }
+
+  public void setVideoCodecParamPtime(int value) {
+    cnssipuaJNI.DupCallInfo_videoCodecParamPtime_set(swigCPtr, this, value);
+  }
+
+  public int getVideoCodecParamPtime() {
+    return cnssipuaJNI.DupCallInfo_videoCodecParamPtime_get(swigCPtr, this);
+  }
+
+  public void setLocalMedia(int value) {
+    cnssipuaJNI.DupCallInfo_localMedia_set(swigCPtr, this, value);
+  }
+
+  public int getLocalMedia() {
+    return cnssipuaJNI.DupCallInfo_localMedia_get(swigCPtr, this);
+  }
+
+  public void setRemoteMedia(int value) {
+    cnssipuaJNI.DupCallInfo_remoteMedia_set(swigCPtr, this, value);
+  }
+
+  public int getRemoteMedia() {
+    return cnssipuaJNI.DupCallInfo_remoteMedia_get(swigCPtr, this);
+  }
+
+  public void setRingWithMedia(int value) {
+    cnssipuaJNI.DupCallInfo_ringWithMedia_set(swigCPtr, this, value);
+  }
+
+  public int getRingWithMedia() {
+    return cnssipuaJNI.DupCallInfo_ringWithMedia_get(swigCPtr, this);
+  }
+
+  public DupCallInfo(int callId) {
+    this(cnssipuaJNI.new_DupCallInfo(callId), true);
+  }
+  
+  public DupCallInfo(){
+	  
+  }
+  
+  /**
+   * @param isIncoming the isIncoming to set
+   */
+  public void setIncoming(boolean isIncoming) {
+	printlog.d(THIS_FILE, " setIncoming : " +isIncoming);  
+    this.isIncoming = isIncoming;
+  }
+	
+  /**
+   * @return the isIncoming
+   */
+  public boolean isIncoming() {
+	printlog.d(THIS_FILE, " isIncoming : " +isIncoming);  
+    return isIncoming;
+  }
+  
+  public String get_ACodecName(int value){
+	  String codec = "";
+	  switch(value){	  
+	  case 1:
+		  codec = "PCMU"; // mu-law scaling. USA
+		  break;
+	  case 2:
+		  codec = "PCMA"; // A-law scaling. Europe
+		  break;
+	  case 3:
+		  codec = "G.723";
+		  break;		  
+	  case 4:
+		  codec = "G.729";
+		  break;
+	  case 5:
+		  codec = "G.722";
+		  break;
+	  case 6:
+		  codec = "PCMU_WB";
+		  break;
+	  case 7:
+		  codec = "PCMA_WB";
+		  break;
+	  case 8:
+		  codec = "PCM";
+		  break;	  
+	  case 9:
+	 	  codec = "SILK-8K";
+		  break;
+	  case 10:
+	  	  codec = "SILK-12K";
+		  break;
+	  case 11:
+	  	  codec = "SILK-16K";	
+		  break;
+	  case 12:
+	  	  codec = "SILK-24K";	
+		  break;
+	  case 13:
+		  codec = "AMR";
+		  break;
+	  case 14:
+		  codec = "AMR-WB";
+		  break;
+	  }	  		
+	  return codec;
+  }
+  
+  public String get_VSizeName(int value) {
+	  String vsize = "";
+	  
+	  switch(value){	  
+	  case 0:
+		  vsize = "QCIF";
+		  break;
+	  case 1:
+		  vsize = "CIF";
+		  break;
+	  case 2:
+		  vsize = "VGA";
+		  break;		  
+	  case 3:
+		  vsize = "CUSTOM";
+		  break;
+	  case 4:
+		  vsize = "QVGA";
+		  break;	  
+	  }
+	  return vsize;
+  }
+  
+// -------------------------------------------------  
+// ref. cmsdk/include/cm/Media.h  
+//CMCODEC_VIDEO_MIN = 128,
+//CMCODEC_H263 = CMCODEC_VIDEO_MIN,
+//CMCODEC_H263PLUS,
+//CMCODEC_H264,
+//CMCODEC_MP4VES,
+//CMCODEC_VIDEO_MAX,
+//-------------------------------------------------
+  
+  public String get_VCodecName(int value){
+	  String codec = "";
+	  switch(value){	  
+	  case 128:
+		  codec = "H263";
+		  break;
+	  case 129:
+		  codec = "H263+";
+		  break;
+	  case 130:
+		  codec = "H264";
+		  break;		  
+	  case 131:
+		  codec = "MP4VES";
+		  break;
+//	  case 5:
+//		  codec = "G.722";
+//		  break;
+//	  case 6:
+//		  codec = "PCMU_WB";
+//		  break;
+//	  case 7:
+//		  codec = "PCMA_WB";
+//		  break;
+//	  case 8:
+//		  codec = "PCM";
+//		  break;	  
+//	  case 9:
+//	 	  codec = "SILK-8K";
+//		  break;
+//	  case 10:
+//	  	  codec = "SILK-12K";
+//		  break;
+//	  case 11:
+//	  	  codec = "SILK-16K";	
+//		  break;
+//	  case 12:
+//	  	  codec = "SILK-24K";	
+//		  break;
+//	  case 13:
+//		  codec = "AMR";
+//		  break;
+//	  case 14:
+//		  codec = "AMR-WB";
+//		  break;
+	  }	  		
+	  return codec;
+  }
+  
+  public static class CMCallState {
+		public static final int MIN = 0;
+		public static final int UNKNOWN = 0;
+		public static final int IDLE = 1;
+		public static final int CALLING = 2;
+		public static final int INCOMING = 3;
+		public static final int RINGING = 4;
+		public static final int CONNECTED = 5;
+		public static final int RELEASING = 6;
+		public static final int RELEASED = 7;
+		public static final int MAX = 8;
+  }
+  
+  public static class CMRegiState{
+	  public static final int UNREGISTERED = 0;
+	  public static final int REGISTERED = 1;
+  }
+
+}

+ 130 - 0
WallPadCall/src/main/java/ceres/cminterface/NPMetrics.java

@@ -0,0 +1,130 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.40
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+package ceres.cminterface;
+
+public class NPMetrics {
+  private long swigCPtr;
+  protected boolean swigCMemOwn;
+
+  protected NPMetrics(long cPtr, boolean cMemoryOwn) {
+    swigCMemOwn = cMemoryOwn;
+    swigCPtr = cPtr;
+  }
+
+  protected static long getCPtr(NPMetrics obj) {
+    return (obj == null) ? 0 : obj.swigCPtr;
+  }
+
+  protected void finalize() {
+    delete();
+  }
+
+  public synchronized void delete() {
+    if (swigCPtr != 0) {
+      if (swigCMemOwn) {
+        swigCMemOwn = false;
+        cnssipuaJNI.delete_NPMetrics(swigCPtr);
+      }
+      swigCPtr = 0;
+    }
+  }
+
+  public void setTPC(int value) {
+    cnssipuaJNI.NPMetrics_TPC_set(swigCPtr, this, value);
+  }
+
+  public int getTPC() {
+    return cnssipuaJNI.NPMetrics_TPC_get(swigCPtr, this);
+  }
+
+  public void setPLC(int value) {
+    cnssipuaJNI.NPMetrics_PLC_set(swigCPtr, this, value);
+  }
+
+  public int getPLC() {
+    return cnssipuaJNI.NPMetrics_PLC_get(swigCPtr, this);
+  }
+
+  public void setJCL(int value) {
+    cnssipuaJNI.NPMetrics_JCL_set(swigCPtr, this, value);
+  }
+
+  public int getJCL() {
+    return cnssipuaJNI.NPMetrics_JCL_get(swigCPtr, this);
+  }
+
+  public void setPIU5MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU5MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU5MC() {
+    return cnssipuaJNI.NPMetrics_PIU5MC_get(swigCPtr, this);
+  }
+
+  public void setPIU12MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU12MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU12MC() {
+    return cnssipuaJNI.NPMetrics_PIU12MC_get(swigCPtr, this);
+  }
+
+  public void setPIU22MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU22MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU22MC() {
+    return cnssipuaJNI.NPMetrics_PIU22MC_get(swigCPtr, this);
+  }
+
+  public void setPIU32MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU32MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU32MC() {
+    return cnssipuaJNI.NPMetrics_PIU32MC_get(swigCPtr, this);
+  }
+
+  public void setPIU50MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU50MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU50MC() {
+    return cnssipuaJNI.NPMetrics_PIU50MC_get(swigCPtr, this);
+  }
+
+  public void setPIU70MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU70MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU70MC() {
+    return cnssipuaJNI.NPMetrics_PIU70MC_get(swigCPtr, this);
+  }
+
+  public void setPIU100MC(int value) {
+    cnssipuaJNI.NPMetrics_PIU100MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIU100MC() {
+    return cnssipuaJNI.NPMetrics_PIU100MC_get(swigCPtr, this);
+  }
+
+  public void setPIO100MC(int value) {
+    cnssipuaJNI.NPMetrics_PIO100MC_set(swigCPtr, this, value);
+  }
+
+  public int getPIO100MC() {
+    return cnssipuaJNI.NPMetrics_PIO100MC_get(swigCPtr, this);
+  }
+
+  public NPMetrics() {
+    this(cnssipuaJNI.new_NPMetrics(), true);
+  }
+
+}

+ 113 - 0
WallPadCall/src/main/java/ceres/cminterface/cnssipuaJNI.java

@@ -0,0 +1,113 @@
+/* ----------------------------------------------------------------------------
+ * This file was automatically generated by SWIG (http://www.swig.org).
+ * Version 1.3.40
+ *
+ * Do not make changes to this file unless you know what you are doing--modify
+ * the SWIG interface file instead.
+ * ----------------------------------------------------------------------------- */
+
+package ceres.cminterface;
+
+class cnssipuaJNI {  
+	
+  public final static native void CMAccStatus_enabled_set(long jarg1, CMAccStatus jarg1_, short jarg2);
+  public final static native short CMAccStatus_enabled_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_registered_set(long jarg1, CMAccStatus jarg1_, short jarg2);
+  public final static native short CMAccStatus_registered_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_sipOp_set(long jarg1, CMAccStatus jarg1_, int jarg2);
+  public final static native int CMAccStatus_sipOp_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_regCode_set(long jarg1, CMAccStatus jarg1_, int jarg2);
+  public final static native int CMAccStatus_regCode_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_userId_set(long jarg1, CMAccStatus jarg1_, String jarg2);
+  public final static native String CMAccStatus_userId_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_authId_set(long jarg1, CMAccStatus jarg1_, String jarg2);
+  public final static native String CMAccStatus_authId_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_userPw_set(long jarg1, CMAccStatus jarg1_, String jarg2);
+  public final static native String CMAccStatus_userPw_get(long jarg1, CMAccStatus jarg1_);
+  public final static native void CMAccStatus_domainName_set(long jarg1, CMAccStatus jarg1_, String jarg2);
+  public final static native String CMAccStatus_domainName_get(long jarg1, CMAccStatus jarg1_);
+  public final static native long new_CMAccStatus();
+  public final static native void delete_CMAccStatus(long jarg1);
+  public final static native int CMSIP_NULL_get();    
+  
+  public final static native void DupCallInfo_id_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_id_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_type_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_type_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_state_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_state_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_prevState_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_prevState_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_accId_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_accId_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_numRemote_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_numRemote_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_statusCode_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_statusCode_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_remoteUri_set(long jarg1, DupCallInfo jarg1_, String jarg2);
+  public final static native String DupCallInfo_remoteUri_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_remoteName_set(long jarg1, DupCallInfo jarg1_, String jarg2);
+  public final static native String DupCallInfo_remoteName_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_remoteStatus_set(long jarg1, DupCallInfo jarg1_, String jarg2);
+  public final static native String DupCallInfo_remoteStatus_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioType_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioType_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioDir_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioDir_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioLocalAddr_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioLocalAddr_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioLocalPort_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioLocalPort_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioRemoteAddr_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioRemoteAddr_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioRemotePort_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioRemotePort_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioPayloadType_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioPayloadType_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioTeltPt_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioTeltPt_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioCodec_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioCodec_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_audioCodecParamPtime_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_audioCodecParamPtime_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_videoType_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_videoType_get(long jarg1, DupCallInfo jarg1_);  
+  public final static native void DupCallInfo_videoCodec_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_videoCodec_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_videoCodecParamPtime_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_videoCodecParamPtime_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_localMedia_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_localMedia_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_remoteMedia_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_remoteMedia_get(long jarg1, DupCallInfo jarg1_);
+  public final static native void DupCallInfo_ringWithMedia_set(long jarg1, DupCallInfo jarg1_, int jarg2);
+  public final static native int DupCallInfo_ringWithMedia_get(long jarg1, DupCallInfo jarg1_);
+  public final static native long new_DupCallInfo(int jarg1);
+  public final static native void delete_DupCallInfo(long jarg1);
+  
+  public final static native void NPMetrics_TPC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_TPC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PLC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PLC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_JCL_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_JCL_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU5MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU5MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU12MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU12MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU22MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU22MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU32MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU32MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU50MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU50MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU70MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU70MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIU100MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIU100MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native void NPMetrics_PIO100MC_set(long jarg1, NPMetrics jarg1_, int jarg2);
+  public final static native int NPMetrics_PIO100MC_get(long jarg1, NPMetrics jarg1_);
+  public final static native long new_NPMetrics();
+  public final static native void delete_NPMetrics(long jarg1);
+  
+}

+ 516 - 0
WallPadCall/src/main/java/ceres/db/DBAdapter.java

@@ -0,0 +1,516 @@
+package ceres.db;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.provider.CallLog;
+
+import ceres.api.AECParam;
+import ceres.api.Configuration;
+import ceres.api.SpamList;
+import ceres.cminterface.CMInterface;
+import ceres.utils.printlog;
+
+public class DBAdapter {
+	static String THIS_FILE = "DBAdapter";
+	
+	static CMInterface mCMIF;
+
+	private static final String DATABASE_NAME = "com.cnstec.db";
+	private static final int DATABASE_VERSION = 17;	
+	private static final String CALLLOGS_TABLE_NAME = "calllogs";
+	
+	// Creation sql command					
+	private final static String TABLE_CALLLOGS_CREATE = "CREATE TABLE IF NOT EXISTS "
+		+ CALLLOGS_TABLE_NAME
+		+ " ("
+			+ CallLog.Calls._ID					+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
+			+ CallLog.Calls.CACHED_NAME			+ " TEXT,"
+			+ CallLog.Calls.CACHED_NUMBER_LABEL	+ " TEXT,"
+			+ CallLog.Calls.CACHED_NUMBER_TYPE	+ " INTEGER,"
+			+ CallLog.Calls.DATE				+ " INTEGER,"
+			+ CallLog.Calls.DURATION			+ " INTEGER,"
+			+ CallLog.Calls.NEW					+ " INTEGER,"
+			+ CallLog.Calls.NUMBER				+ " TEXT,"
+			+ CallLog.Calls.TYPE				+ " INTEGER"
+		+");";
+
+	// ---------------------------------------------------------------------------
+	// MCONFTB - Main CONFiguratioin TaBle
+	// singleton : Only one account is managed.
+	// ---------------------------------------------------------------------------
+	public static final String MCONFTB = "mconftb";
+	
+	private static final String TABLE_MCONFTB_CREATE = "CREATE TABLE IF NOT EXISTS "
+		+ MCONFTB
+		+" ("
+			+ Configuration.FIELD_ID          	+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
+			+ Configuration.PHONE_NUMBER 	   	+ " TEXT,"
+			+ Configuration.ONE_NUMBER		   	+ " TEXT,"
+			+ Configuration.ADDRESS				+ " TEXT,"
+			+ Configuration.PASSWORD			+ " TEXT,"
+			+ Configuration.AUTH_ID				+ " TEXT,"
+			+ Configuration.PROXY_ADDR 		   	+ " TEXT,"
+			+ Configuration.PROXY_PORT 		   	+ " TEXT,"
+			+ Configuration.REG_ADDR			+ " TEXT,"
+			+ Configuration.REG_PORT 			+ " TEXT,"
+			+ Configuration.LOCAL_PORT 		   	+ " TEXT,"
+			+ Configuration.LOCAL_MEDIA_PORT  	+ " TEXT,"
+			+ Configuration.REMOTE_MEDIA_PORT 	+ " TEXT,"
+			+ Configuration.PROVIDER 			+ " TEXT,"
+			+ Configuration.ACODEC_PRI			+ " TEXT,"
+			+ Configuration.VCODEC_PRI 		    + " TEXT,"
+			+ Configuration.REREGTIME			+ " TEXT,"
+			+ Configuration.SESSIONTIME		    + " TEXT,"
+			+ Configuration.SESSION_EXPIRE_TIME + " TEXT,"
+			+ Configuration.TRANSACTION_TIME 	+ " TEXT,"
+			+ Configuration.DTMF_TYPE	        + " TEXT,"
+			+ Configuration.URL_TYPE 	        + " TEXT,"
+			+ Configuration.SRTPOPTION		    + " TEXT,"
+			+ Configuration.PTIME 			    + " TEXT,"
+			+ Configuration.AECONOFF 		    + " TEXT,"
+			+ Configuration.JBMINMAX 		    + " TEXT,"
+			+ Configuration.ONENUMONOFF	        + " TEXT,"
+			+ Configuration.SPAMONOFF 		    + " TEXT,"
+			+ Configuration.REDIRECTOPTION	    + " TEXT,"
+			+ Configuration.HWSAMPLINGRATE	    + " TEXT,"
+			+ Configuration.VAD_ONOFF	        + " TEXT,"
+			+ Configuration.NS_ONOFF 		    + " TEXT,"
+			+ Configuration.CNG_ONOFF		    + " TEXT,"
+			+ Configuration.AUDIO_MODE		    + " TEXT,"
+			+ Configuration.LOG_LV_SIP		    + " TEXT,"
+			+ Configuration.LOG_LV_RTP		    + " TEXT,"
+			+ Configuration.LOG_LV_CM		    + " TEXT,"
+			+ Configuration.LOG_LV_MCM		    + " TEXT,"
+			+ Configuration.LOG_LV_MMM		    + " TEXT,"
+			+ Configuration.LOG_LV_UI		    + " TEXT,"
+			+ Configuration.SDC_ONOFF		    + " TEXT,"
+			+ Configuration.VIDEO_ONOFF			+ " TEXT,"
+			+ Configuration.VIDEO_SIZE			+ " TEXT,"
+			+ Configuration.VCODEC_FRAMERATE	+ " TEXT,"
+			+ Configuration.VCODEC_BANDWIDTH	+ " TEXT,"
+			+ Configuration.VCODEC_MAXBR		+ " TEXT,"
+			+ Configuration.VCODEC_H264_PMODE	+ " TEXT,"
+			+ Configuration.VCODEC_MPEG4VES_PLI	+ " TEXT"
+			
+		+ ");";
+	
+	// ---------------------------------------------------------------------------
+	// AECTNTB - Acountic Echo Canceller TuNing TaBle
+	// Delay, Time Span, ERL, Dynamic Volume(mic), Dynamic Volume MIN(mic), 
+	// Update Speed, Weight MAX Speed, Weight Scale
+	// ---------------------------------------------------------------------------
+	public static final String AECTNTB = "aectntb";
+	
+	private static final String TABLE_AECTNTB_CREATE = "CREATE TABLE IF NOT EXISTS "
+		+ AECTNTB
+		+" ("
+			+ AECParam.FIELD_ID         	+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
+			+ AECParam.MEMO 	   			+ " TEXT,"
+			+ AECParam.DELAY		   		+ " TEXT,"
+			+ AECParam.TIME_SPAN			+ " TEXT,"
+			+ AECParam.ERL					+ " TEXT,"
+			+ AECParam.DYNAMIC_VOL_MIC		+ " TEXT,"
+			+ AECParam.DYNAMIC_VOL_MIC_MIN 	+ " TEXT,"
+			+ AECParam.UPDATE_SPEED 		+ " TEXT,"
+			+ AECParam.WEIGHT_MAX_INDEX		+ " TEXT,"
+			+ AECParam.WEIGHT_SCALE 		+ " TEXT,"
+			+ AECParam.DATE					+ " INTEGER"
+		+ ");";
+			
+	// -------------------------------------------------------------------
+	// SPAMLTB - SPAM List TaBle
+	// -------------------------------------------------------------------
+	private static final String SPAMLTB = "spamltb";
+	
+	private static final String TABLE_SPAMLTB_CREATE = "CREATE TABLE IF NOT EXISTS "
+		+ SPAMLTB
+		+" ("
+			+ "_id"          		+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
+			+ "spamnumber" 			+ " TEXT"							
+		+ ");";
+	
+	private final Context context;
+	private DatabaseHelper databaseHelper;
+	private SQLiteDatabase db;
+
+	public DBAdapter(Context aContext) {
+		context = aContext;
+		databaseHelper = new DatabaseHelper(context);
+	}
+
+	public static class DatabaseHelper extends SQLiteOpenHelper {
+		DatabaseHelper(Context context) {
+			super(context, DATABASE_NAME, null, DATABASE_VERSION);
+
+		}
+
+		@Override
+		public void onCreate(SQLiteDatabase db) {
+			db.execSQL(TABLE_CALLLOGS_CREATE);
+			db.execSQL(TABLE_SPAMLTB_CREATE);
+			db.execSQL(TABLE_MCONFTB_CREATE);
+			db.execSQL(TABLE_AECTNTB_CREATE);			
+		}
+
+		@Override
+		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+			printlog.w(THIS_FILE, "Upgrading database from version "
+							+ oldVersion + " to " + newVersion);			
+			onCreate(db);
+		}
+	}
+
+	private boolean opened = false;
+	/**
+	 * Open database
+	 * 
+	 * @return database adapter
+	 * @throws SQLException
+	 */
+	public DBAdapter open() throws SQLException {
+		db = databaseHelper.getWritableDatabase();
+		opened = true;
+		return this;
+	}
+
+	/**
+	 * Close database
+	 */
+	public void close() {
+		databaseHelper.close();
+		opened = false;
+	}
+	
+	public boolean isOpen() {
+		return opened;
+	}
+	
+	// -----------------------------------------------------------------------------------
+	// MCONFTB (insert / update / select / delete)
+	// -----------------------------------------------------------------------------------	
+	public long insertConf(Configuration conf){
+		ContentValues temp = new ContentValues();
+		temp = conf.getDbContentValues();
+		
+		long raws = db.insert(MCONFTB, null, temp);		
+		//mCMIF.CERES_InitState_set(0);
+		
+		printlog.i(THIS_FILE,"raws : " + raws);
+		return raws;
+	}
+	
+	public boolean updateConf(Configuration conf) {
+		
+		printlog.i(THIS_FILE,"Conf.getDisplayName() : " + conf.getDisplayName());
+		printlog.i(THIS_FILE,"Conf._id : " + conf._id);		
+		//mCMIF.CERES_InitState_set(0);
+		
+		return db.update(MCONFTB, conf.getDbContentValues(),
+				Configuration.FIELD_ID + "=" + conf._id, null) > 0;
+	}
+	
+	public int getConfId(){
+		int _id = 0;
+		
+		Cursor c = db.query(MCONFTB, null, null, null, null, null, null);
+		
+//		int numRows = c.getCount();
+		
+//		if(numRows == 0){
+//			_id = 1;
+//		}
+		// moveToNext
+		while (c.moveToNext()) {
+		
+			_id = c.getInt(0);
+		}
+				
+		printlog.i(THIS_FILE, "getConfId : " + _id);
+		
+		return _id;
+	}
+	
+	public Configuration getConfValue(long conf_id){
+		
+		try {
+			Cursor c = db.query(MCONFTB, Configuration.full_projection,
+					Configuration.FIELD_ID + "=" + conf_id, null, null, null, null);
+
+			int numRows = c.getCount();
+			
+			if(numRows == 0){
+				return new Configuration();
+			}
+			
+			printlog.i(THIS_FILE,"numRows " + numRows);
+			if(numRows > 0){
+				c.moveToFirst();
+				Configuration conf = new Configuration();
+				conf.createFromDb(c);
+				c.close();
+				return conf;
+				
+			}
+			c.close();
+		} catch (SQLException e) {
+			printlog.e("Exception on query", e.toString());
+		}
+		
+		return null;
+	}
+	
+	public boolean deleteConf(Configuration conf) {
+		return db.delete(MCONFTB, Configuration.FIELD_ID + "=" + conf._id, null) > 0;
+	}	
+	// -----------------------------------------------------------------------------------
+	// SPAMLTB (insert / update / select / delete)
+	// -----------------------------------------------------------------------------------
+	
+	public long insertSpamNumber(SpamList number){
+		ContentValues temp = new ContentValues();
+		temp = number.getDbContentValues();
+		
+		long raws = db.insert(SPAMLTB, null, temp);
+		
+		printlog.i(THIS_FILE,"raws : " + raws);
+		return raws;
+	}
+	
+	public boolean updateSpamNumber(SpamList number) {
+		
+		//printlog.i(THIS_FILE,"Conf.getDisplayName() : " + Conf.getDisplayName());
+		printlog.i(THIS_FILE,"Conf._id : " + number._id);
+		
+		return db.update(SPAMLTB, number.getDbContentValues(),
+				SpamList.FIELD_ID + "=" + number._id, null) > 0;
+	}
+	
+	public SpamList getSpamList(long _id){
+		
+		try {
+			Cursor c = db.query(SPAMLTB, SpamList.full_projection,
+					SpamList.FIELD_ID + "=" + _id, null, null, null, null);
+			
+			
+			int numRows = c.getCount();
+			
+			if(numRows == 0){
+				return new SpamList();
+			}
+			
+			printlog.i(THIS_FILE,"numRows " + numRows);
+			if(numRows > 0){
+				c.moveToFirst();
+				SpamList conf = new SpamList();
+				conf.createFromDb(c);
+				c.close();
+				return conf;
+				
+			}
+			c.close();
+		} catch (SQLException e) {
+			printlog.e("Exception on query", e.toString());
+		}
+		
+		return null;
+	}	
+	
+	public boolean deleteSpamNumber(SpamList number) {
+		return db.delete(SPAMLTB, SpamList.FIELD_ID + "=" + number._id, null) > 0;
+	}
+	
+	// -----------------------------------------------------------------------------------
+	// AECTNTB (insert / update / select / delete)
+	// -----------------------------------------------------------------------------------
+	
+	public static final int AEC_ID_INDEX = 0;
+	public static final int AEC_MEMO_INDEX = 1;
+	public static final int AEC_DELAY_INDEX = 2;
+	
+	
+	public long insertAECParam(AECParam param){
+		ContentValues temp = new ContentValues();
+		temp = param.getDbContentValues();
+		
+		long raws = db.insert(AECTNTB, null, temp);
+		
+		printlog.i(THIS_FILE,"raws : " + raws);
+		return raws;
+	}
+	
+	public boolean updateAECParam(AECParam param) {
+		
+		//printlog.i(THIS_FILE,"Conf.getDisplayName() : " + Conf.getDisplayName());
+		printlog.i(THIS_FILE,"Conf._id : " + param._id);
+		
+		return db.update(AECTNTB, param.getDbContentValues(),
+				AECParam.FIELD_ID + "=" + param._id, null) > 0;
+	}
+	// CallLog.Calls.DEFAULT_SORT_ORDER
+	public Cursor getAllAECParamLogs() {
+		return db.query(AECTNTB, AECParam.full_projection, null, null, null, null, "_id desc");
+	}
+	
+	public AECParam selectRecentApplyAECParam(){
+				
+		try {
+			Cursor c = db.query(AECTNTB, AECParam.full_projection,
+					null, null, null, null, "date desc");			
+			
+			int numRows = c.getCount();
+			
+			if(numRows == 0){
+				return new AECParam();
+			}
+			
+			printlog.i(THIS_FILE,"numRows " + numRows);
+			if(numRows > 0){
+				c.moveToFirst();
+				AECParam param = new AECParam();
+				param.createFromDb(c);
+				c.close();
+				return param;
+				
+			}
+			c.close();
+		} catch (SQLException e) {
+			printlog.e("Exception on query", e.toString());
+		}
+		
+		return null;			
+	}
+	
+	public AECParam selectAECParam(long _id){
+		
+		try {
+			Cursor c = db.query(AECTNTB, AECParam.full_projection,
+					AECParam.FIELD_ID + "=" + _id, null, null, null, null);
+			
+			
+			int numRows = c.getCount();
+			
+			if(numRows == 0){
+				return new AECParam();
+			}
+			
+			printlog.i(THIS_FILE,"numRows " + numRows);
+			if(numRows > 0){
+				c.moveToFirst();
+				AECParam param = new AECParam();
+				param.createFromDb(c);
+				c.close();
+				return param;
+				
+			}
+			c.close();
+		} catch (SQLException e) {
+			printlog.e("Exception on query", e.toString());
+		}
+		
+		return null;
+	}		
+	
+	public boolean deleteOneAECParamLog(int aecParamlogId) {
+		return db.delete(AECTNTB, AECParam.FIELD_ID  + "=" + aecParamlogId, null) > 0;
+	}
+
+	public boolean deleteAllAECParamLogs() {
+		return db.delete(AECTNTB, null, null) > 0;
+	}
+	
+//	public boolean deleteAECParam(AECParam param) {
+//		return db.delete(AECTNTB, AECParam.FIELD_ID + "=" + param._id, null) > 0;
+//	}
+	
+	// -------------
+	// Call logs
+	// -------------
+	
+	private final static String[] logs_projection = {
+		CallLog.Calls._ID,
+		CallLog.Calls.CACHED_NAME,
+		CallLog.Calls.CACHED_NUMBER_LABEL,
+		CallLog.Calls.CACHED_NUMBER_TYPE,
+		CallLog.Calls.DURATION,
+		CallLog.Calls.DATE,
+		CallLog.Calls.NEW,
+		CallLog.Calls.NUMBER,
+		CallLog.Calls.TYPE
+	};
+	
+	public static final int ID_COLUMN_INDEX = 0;
+	// Cached columns, not yet supported
+	public static final int CALLER_NAME_COLUMN_INDEX = 1;
+	public static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 2;
+	public static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 3;
+	// Sure this columns are filled
+	public static final int DURATION_COLUMN_INDEX = 4;
+	public static final int DATE_COLUMN_INDEX = 5;
+	public static final int NEW_COLUMN_INDEX = 6;
+	public static final int NUMBER_COLUMN_INDEX = 7;
+	public static final int CALL_TYPE_COLUMN_INDEX = 8;
+	
+	
+	/**
+	 * Insert a new calllog into the database
+	 * @param values calllogs values
+	 * @return the id of inserted row into database
+	 */
+	public long insertCallLog(ContentValues args) {
+		long result = db.insert(CALLLOGS_TABLE_NAME, null, args);
+		removeCallLogExpiredEntries();
+		return result;
+	}
+	
+	/**
+	 * Count the number of account saved in database
+	 * @return the number of account
+	 */
+	public int getNbrOfCallLogs() {
+		Cursor c = db.rawQuery("SELECT COUNT("+ CallLog.Calls._ID+") FROM "+CALLLOGS_TABLE_NAME+";", null);
+		int numRows = 0;
+		if(c.getCount() > 0){
+			c.moveToFirst();
+			numRows = c.getInt(0);
+			
+		}
+		c.close();
+		return numRows;
+	}
+		
+	public Cursor getAllCallLogs() {
+		return db.query(CALLLOGS_TABLE_NAME, logs_projection, null, null, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
+	}
+
+	public Cursor getCallLog(int logId) {
+		if(logId <0){
+			return null;
+		}
+		try {
+			return db.query(CALLLOGS_TABLE_NAME, logs_projection,
+					CallLog.Calls._ID + "=" + logId, null, null, null, null);
+		} catch (SQLException e) {
+			printlog.e(THIS_FILE, "Exception on query", e);
+		}
+		
+		return null;
+	}
+	
+	public boolean deleteOneCallLog(int calllogId) {
+		return db.delete(CALLLOGS_TABLE_NAME, CallLog.Calls._ID  + "=" + calllogId, null) > 0;
+	}
+
+	public boolean deleteAllCallLogs() {
+		return db.delete(CALLLOGS_TABLE_NAME, null, null) > 0;
+	}
+		
+	private void removeCallLogExpiredEntries() {
+		db.delete(CALLLOGS_TABLE_NAME, CallLog.Calls._ID + " IN " +
+			"(SELECT "+ CallLog.Calls._ID+" FROM "+CALLLOGS_TABLE_NAME+" ORDER BY " +
+				CallLog.Calls.DEFAULT_SORT_ORDER + " LIMIT -1 OFFSET 500)", null);
+	}	
+}

+ 1335 - 0
WallPadCall/src/main/java/ceres/pcminterface/PCMInterface.java

@@ -0,0 +1,1335 @@
+package ceres.pcminterface;
+
+import android.content.Context;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.AudioTrack;
+import android.media.MediaRecorder;
+import android.net.rtp.AudioCodec;
+import android.net.rtp.AudioGroup;
+import android.net.rtp.AudioStream;
+import android.net.rtp.RtpStream;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.StrictMode;
+import android.util.Log;
+
+import com.util.LogUtil;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Date;
+
+import bssoft.stack.sip.RFC2833;
+import bssoft.stack.sip.SIPG711;
+import bssoft.stack.sip.SIPStack;
+import ceres.api.SipManager;
+import ceres.cminterface.CMInterface;
+import ceres.cminterface.NPMetrics;
+import ceres.utils.printlog;
+import kr.co.icontrols.callengine.engine.CallManager;
+import kr.co.icontrols.callengine.remotecall.AVPacket;
+import kr.co.icontrols.callengine.remotecall.RemoteCallManager;
+import kr.co.icontrols.callengine.sip.RTPManager;
+import kr.co.icontrols.callengine.sip.SIPController;
+import kr.co.icontrols.callengine.sip.SIPSound;
+import kr.co.icontrols.wallpadcall.MainActivity;
+import kr.co.icontrols.wallpadcall.declare.Declare;
+import kr.co.icontrols.wallpadcall.declare.Global;
+
+public class PCMInterface {
+	private static CMInterface m_CMIF;
+
+	private static final String THIS_FILE = "PcmInterface";
+
+	native void PCMIF_Initialize();
+	native static int PCMIF_SetAECParams();
+	native int PCMIF_LoopbackConnect(int callType, int AcodecNum, int VcodecNum, int ptime, int videoSize, int frameRate);
+	native int PCMIF_LoopbackDisconnect(int mediaType);
+	native static int PCMIF_AECDelayCheck(int start);
+	native static int PCMIF_SystemDelay_set();
+	native static int PCMIF_JBVCheck(int start);
+	native static int PCMIF_NPMetrics(int start);
+	native static void PCMIF_Close();
+	native static void PCMIF_GetJavaVM();
+	native static void PCMIF_GetData();
+
+
+	public static native boolean PCMIF_OnMediaStart(int callid, int mediatype);
+	public static native boolean PCMIF_OnMediaStop(int callid, int mediatype);
+	public native static void MMIF_IsVideoReady(int callId);
+
+	public static int getFrequency() {
+		return frequency;
+	}
+
+	/**
+	* @return the audioEncoding
+	*/
+	public static int getAudioEncoding() {
+		return audioEncoding;
+	}
+
+	/**
+	* @return the channelConfiguration
+	*/
+	public static int getChannelConfiguration() {
+		return channelConfiguration;
+	}
+
+	public static int SetAECParams(){
+		return PCMIF_SetAECParams();
+	}
+	
+	public int PCMI_LoopbackConnect(int callType, int AcodecNum, int VcodecNum, int ptime, int videoSize, int frameRate){
+		return PCMIF_LoopbackConnect(callType, AcodecNum, VcodecNum, ptime, videoSize, frameRate);
+	}
+	
+	public int PCMI_LoopbackDisconnect(int mediaType){
+		return PCMIF_LoopbackDisconnect(mediaType);
+	}
+
+	public int AECDelayCheck(int start)
+	{
+		return PCMIF_AECDelayCheck(start);
+	}
+	
+	public int SystemDelay_set()
+	{
+		return PCMIF_SystemDelay_set();
+	}
+	
+	public int JBVCheck(int start)
+	{
+		return PCMIF_JBVCheck(start);
+	}
+	
+	public int NPMetrics(int start)
+	{
+		if(start == 1){
+			ThreadStart();
+		}
+		else
+			ThreadStop();
+		return PCMIF_NPMetrics(start);
+	}
+
+	@SuppressWarnings("static-access")
+	public static void jAECDelayCheck(int delay, int max)
+	{
+		printlog.d(THIS_FILE, "delay : " + delay);
+		m_CMIF.dispatchSysDelayEvent(delay, max);
+		return;
+	}
+	
+	@SuppressWarnings("static-access")
+	public static void jJBVCheck(int currMS, int var)
+	{
+		printlog.d(THIS_FILE, "currMS : " + currMS);
+		m_CMIF.dispatchCheckCBEvent(currMS, var);
+		return;
+	}
+	
+	//static NPMetrics npMetrics = null;
+	
+	private Handler mHandler = new Handler();
+	private myThread mThread;
+	
+	private void ThreadStart(){
+		if(mThread == null){
+        	mThread = new myThread(true);
+	        mThread.start();	        
+        }
+	}
+	
+	private void ThreadStop(){    	
+    	if(mThread != null){
+			mThread.stopThread();
+			mThread = null;
+		}    	    
+    }
+
+	class myThread extends Thread {
+
+		private boolean isPlay = false;
+
+		public myThread(boolean isPlay){
+			this.isPlay = isPlay;
+		}
+
+		public void stopThread(){
+			isPlay = !isPlay;
+		}
+		
+		public boolean isPlayThread(){
+			return isPlay;
+		}
+		
+		@Override
+		public void run() {
+			super.run();
+			while (isPlay) {
+
+				mHandler.post(new Runnable() {
+					@Override
+					public void run() {
+//						printPCMQueueInfo();
+						jNPMetrics(0,0);
+					}
+				}); // mHandler.post(new Runnable()
+				try {					
+					// Set interval time(ms) : PCMQueueInfo 
+					Thread.sleep(1000);
+
+				} catch (InterruptedException e) {
+					printlog.e(THIS_FILE, "myThread, Run, Thread.sleep : Error.");
+					e.printStackTrace();
+				}
+			}// while
+		}// run
+	}// myThread
+	
+	
+	@SuppressWarnings("static-access")
+	public static void jNPMetrics(int param1, int param2)
+	{
+		//if(npMetrics == null){
+		NPMetrics npMetrics = new NPMetrics();
+		//}		
+//		//CSC_CAL_GetDupCallInfo 처리가 필요 할 수 있음..
+//		> jNPMetrics Debug : 
+		printlog.w(THIS_FILE, "> jNPMetrics Debug : ------------------------------------");
+		printlog.w(THIS_FILE, "npMetrics. ------------------------------------");
+		printlog.w(THIS_FILE, "npMetrics.getTPC()      : " + npMetrics.getTPC());
+		printlog.w(THIS_FILE, "npMetrics.getPLC()      : " + npMetrics.getPLC());
+		printlog.w(THIS_FILE, "npMetrics.getJCL()      : " + npMetrics.getJCL());
+		printlog.w(THIS_FILE, "npMetrics.getPIU5MC()   : " + npMetrics.getPIU5MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU12MC()  : " + npMetrics.getPIU12MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU22MC()  : " + npMetrics.getPIU22MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU32MC()  : " + npMetrics.getPIU32MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU50MC()  : " + npMetrics.getPIU50MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU70MC()  : " + npMetrics.getPIU70MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIU100MC() : " + npMetrics.getPIU100MC());
+		printlog.w(THIS_FILE, "npMetrics.getPIO100MC() : " + npMetrics.getPIO100MC());
+////			
+		m_CMIF.dispatchNPMetricsCBEvent(npMetrics);
+		
+//		npMetrics.delete();
+		
+		return;
+	}
+
+	public static void MatrixTime(int delayTime){
+
+		long saveTime = System.currentTimeMillis();
+		long currTime = 0;
+
+		while( currTime - saveTime < delayTime){
+			currTime = System.currentTimeMillis();
+		}
+	}
+
+	public static void Close()
+	{
+		PCMIF_Close();
+	}
+
+	public static class PCMQueueInformation
+	{
+		public int m_sizeQMin;
+		public int m_sizeQMax;
+		public int m_sizeQPass;
+
+		public int m_sizeQFill;
+		
+		public PCMQueueInformation()
+		{
+		}
+	}
+
+	// TODO Read/Write Lock
+	public static class PCMQueue
+	{
+		private byte[] m_BUF = null;
+		private int m_sizeBUF;
+		private int m_ir;
+		private int m_iw;
+		
+		private int m_sizeQMin;
+		private int m_sizeQMax;
+		private int m_sizeQPass;
+		
+		private int m_sizeCorrectBase;
+		private int m_sizeCorrect;
+		private int m_sizeProcess;
+
+		public PCMQueue( int sizeBUF, int sizeCorrectBase, int sizeCorrect )
+		{
+			m_BUF = new byte[sizeBUF];
+			m_sizeBUF = sizeBUF;
+			m_ir = 0;
+			m_iw = 0;
+			
+			m_sizeQMin = 0;
+			m_sizeQMax = 0;
+			m_sizeQPass = 0;
+			
+			m_sizeCorrectBase = sizeCorrectBase;
+			m_sizeCorrect = sizeCorrect;
+			m_sizeProcess = 0;
+		}
+		
+		public int read( byte buf[], int size )
+		{
+			int sizeQueue;
+
+			sizeQueue = ( ( m_iw + m_sizeBUF ) - m_ir ) % m_sizeBUF;
+
+			if( sizeQueue < m_sizeQMin )
+			{
+				m_sizeQMin = sizeQueue;
+			}
+			if( m_sizeQMax < sizeQueue )
+			{
+				m_sizeQMax = sizeQueue;
+			}
+
+			if( sizeQueue < size )
+			{
+				return 0;
+			}
+			
+			if( ( m_sizeBUF - m_ir ) < size )
+			{
+				System.arraycopy( m_BUF, m_ir, buf, 0, m_sizeBUF - m_ir );
+				System.arraycopy( m_BUF, 0, buf, m_sizeBUF - m_ir, size - ( m_sizeBUF - m_ir ) );
+			}
+			else
+			{
+				System.arraycopy( m_BUF, m_ir, buf, 0, size );
+				//Log.v("yjyoon", "readpcm printhex " + byteArrayToHex(buf, size));
+			}
+			m_ir = ( m_ir + size + m_sizeBUF ) % m_sizeBUF;
+
+			m_sizeQPass += size;
+
+			return size;
+		}
+
+		public int write2( byte buf[], int offset, int size )
+		{
+			int sizeFree;
+
+			sizeFree = ( ( m_ir + m_sizeBUF ) - m_iw ) % m_sizeBUF;
+			if( sizeFree == 0 )
+				sizeFree = m_sizeBUF;
+			sizeFree--;
+			if( sizeFree < size )
+				return 0;
+
+			if (size < 0)
+				return 0;
+
+			if( ( m_sizeBUF - m_iw ) < size )
+			{
+				System.arraycopy( buf, offset, m_BUF, m_iw, m_sizeBUF - m_iw );
+				System.arraycopy( buf, offset + m_sizeBUF - m_iw, m_BUF, 0, size - ( m_sizeBUF - m_iw ) );
+			}
+			else
+			{
+				System.arraycopy( buf, offset, m_BUF, m_iw, size );
+			}
+			m_iw = ( m_iw + size + m_sizeBUF ) % m_sizeBUF;
+
+			return size;
+		}
+
+		public int write( byte buf[], int offset, int size )
+		{
+			// TODO Exception Handling
+			m_sizeProcess += size;
+			if
+			(
+				( ( 0 < m_sizeCorrectBase ) && ( m_sizeCorrect != 0 ) )
+				&& ( m_sizeCorrectBase <= m_sizeProcess )
+			)
+			{
+				if( 0 < m_sizeCorrect )
+				{
+					write2( buf, 0, m_sizeCorrect );
+					write2( buf, 0, size );
+				}
+				else
+				{
+					write2( buf, 0, size + m_sizeCorrect );
+				}
+
+				m_sizeProcess -= m_sizeCorrectBase;
+			}
+			else
+			{
+				write2( buf, 0, size );
+			}
+
+			return size;
+		}
+
+		public void Flush()
+		{
+			m_ir = 0;
+			m_iw = 0;
+		}
+
+		public int getsizeFill()
+		{
+			return ( ( m_iw + m_sizeBUF ) - m_ir ) % m_sizeBUF;
+		}
+
+		public PCMQueueInformation getInformation()
+		{
+			PCMQueueInformation INF = new PCMQueueInformation();
+			
+			INF.m_sizeQMin = m_sizeQMin;
+			INF.m_sizeQMax = m_sizeQMax;
+			INF.m_sizeQPass = m_sizeQPass;
+			INF.m_sizeQFill = ( ( m_iw + m_sizeBUF ) - m_ir ) % m_sizeBUF;
+
+			return INF;
+		}
+	}
+	
+	public static class PCMSetting
+	{
+		public int sizeTrackCorrectBase = 0;
+		public int sizeTrackCorrect = 0;
+
+		public int sizeRecordCorrectBase = 0;
+		public int sizeRecordCorrect = 0;
+
+		public int sizeRecordBUF = 1024 * 5;
+		public int sizeTrackBUF = 1024 * 5;
+		
+		public void Copyfrom( PCMSetting src )
+		{
+			this.sizeTrackCorrectBase = src.sizeTrackCorrectBase;
+			this.sizeTrackCorrect = src.sizeTrackCorrect;
+
+			this.sizeRecordCorrectBase = src.sizeRecordCorrectBase;
+			this.sizeRecordCorrect = src.sizeRecordCorrect;
+
+			this.sizeRecordBUF = src.sizeRecordBUF;
+			this.sizeTrackBUF = src.sizeTrackBUF;
+		}
+	}
+
+	public static class PCMRecord extends Thread
+	{
+		private AudioRecord m_Record = null;
+		private PCMSetting m_Setting = null;
+		
+		private boolean m_bFirstRead = false;
+		
+		private PCMQueue m_Queue = null;
+		private boolean m_bRunThread = false;
+
+		public PCMRecord( PCMSetting Setting )
+		{
+			m_Setting = new PCMSetting();
+			m_Setting.Copyfrom( Setting );
+		}
+
+		public void Open(int samplerate)
+		{
+			//G.722 == 1280
+			int sizeBUFMIM = AudioRecord.getMinBufferSize(
+					samplerate,
+			        AudioFormat.CHANNEL_IN_MONO,
+			        AudioFormat.ENCODING_PCM_16BIT
+			        );
+
+			int sizeBUF = ( sizeBUFMIM > m_Setting.sizeRecordBUF ) ? sizeBUFMIM : m_Setting.sizeRecordBUF;
+
+			m_Record = new AudioRecord(
+						MediaRecorder.AudioSource.MIC,
+						samplerate,
+						AudioFormat.CHANNEL_IN_MONO,
+	                    AudioFormat.ENCODING_PCM_16BIT,
+					1024 * 2);
+	                    //sizeBUFMIM * 2); // G.722 bufferSizeInBytes == 2560
+			
+			printlog.i(THIS_FILE, "flashmir Record run 1");
+			m_Record.startRecording();
+			printlog.i(THIS_FILE, "flashmir Record run 2");
+			
+			m_Queue = new PCMQueue( m_Setting.sizeRecordBUF, m_Setting.sizeRecordCorrectBase, m_Setting.sizeRecordCorrect );
+
+			m_bRunThread = true;
+			start();
+		}
+
+		public void Close(int i)
+		{
+			m_bRunThread = false;
+
+			m_Record.stop();			
+			m_Record.release();
+			m_Record = null;
+		}
+
+		public int Read(byte buf[], int size)
+		{
+			int sizeReturn;
+
+			if( m_bRunThread == false )
+			{
+				sizeReturn = m_Record.read( buf, 0, size );
+			}
+			else
+			{
+				if( m_bFirstRead == false )
+				{
+					if( m_Queue.getsizeFill() <= 512 )
+						return -1;
+
+					m_bFirstRead = true;
+				}
+
+//				printlog.i(THIS_FILE, "flashmir Queue read = " + m_Queue.getsizeFill() );
+
+				sizeReturn = m_Queue.read( buf, size );
+				if( sizeReturn == 0 )
+					sizeReturn = -1;
+			}
+			
+			return sizeReturn;
+		}
+		
+		public void run() {
+			byte[] BUF = new byte[512];
+			int sizeRead;
+			
+			while(m_bRunThread != false) {
+				sizeRead = m_Record.read( BUF, 0, 512 );
+				if( sizeRead != 0 )
+					m_Queue.write( BUF, 0, sizeRead );
+			}
+		}
+	}
+
+	public static class PCMTrack extends Thread
+	{
+		private AudioTrack m_Track = null;
+		private PCMSetting m_Setting = null;
+		
+		private boolean m_bFirstWrite = false;
+
+		private PCMQueue m_Queue = null;
+		private boolean m_bRunThread = false;
+
+		//int aaa = 0;
+		private byte[] tempBUF = new byte[15000];
+		
+		public PCMTrack( PCMSetting Setting )
+		{
+			m_Setting = new PCMSetting();
+			m_Setting.Copyfrom( Setting );
+		}
+
+		public void Open(int samplerate)
+		{		
+			int sizeBUFMIM = AudioTrack.getMinBufferSize(
+					samplerate,
+			        AudioFormat.CHANNEL_OUT_MONO,
+			        AudioFormat.ENCODING_PCM_16BIT
+			        );
+
+			int sizeBUF = ( sizeBUFMIM > m_Setting.sizeTrackBUF ) ? sizeBUFMIM : m_Setting.sizeTrackBUF;
+			printlog.i(THIS_FILE, "flashmir Track sizeBUF = " + sizeBUF );
+
+			m_Track = new AudioTrack(
+	    			AudioManager.STREAM_VOICE_CALL,
+	    			samplerate,
+	                AudioFormat.CHANNEL_OUT_MONO,
+	                AudioFormat.ENCODING_PCM_16BIT,
+					sizeBUF,
+	                AudioTrack.MODE_STREAM);
+
+			m_Track.flush();
+			
+			// LTE 가 아니면..
+			if (!SipManager.DEVICE_NAME.equalsIgnoreCase("SHV-E120K")) {
+				m_Track.write( tempBUF, 0, sizeBUFMIM );
+				m_Track.setPlaybackHeadPosition( sizeBUFMIM / 2 );	
+			}
+			
+
+			//aaa += sizeBUFMIM;
+//			printlog.i(THIS_FILE, "flashmir Track run 1");
+//			m_Track.play();
+//			printlog.i(THIS_FILE, "flashmir Track run 2");
+
+			m_Queue = new PCMQueue( m_Setting.sizeTrackBUF, m_Setting.sizeTrackCorrectBase, m_Setting.sizeTrackCorrect );
+
+			m_bRunThread = true;
+			start();
+
+//			m_bRunThread = false;
+		}
+
+		public void Close(int i)
+		{
+			m_bRunThread = false;
+
+			m_Track.stop();
+			m_Track.flush();
+			m_Track.release();
+			m_Track = null;
+		}
+
+		public int Write(byte buf[], int size)
+		{
+			int sizeReturn;
+
+			if( m_bRunThread == false )
+			{
+				sizeReturn = m_Track.write( buf, 0, size );
+			}
+			else
+			{
+				sizeReturn = m_Queue.write( buf, 0, size );
+//				printlog.i(THIS_FILE, "flashmir Queue write2 = " + m_Queue.getsizeFill() );
+			}
+
+			if( m_bFirstWrite == false )
+			{
+				m_bFirstWrite = true;
+			}
+			
+			return sizeReturn;
+		}
+
+		public void run() {
+			byte[] BUF = new byte[1024 * 5];
+			int sizeRead;
+			int sizeQueue;
+
+//			int iWrite, nWrite = 1;
+//			while( m_Queue.getsizeFill() < 160 * nWrite );
+//			for( iWrite = 0; iWrite < nWrite; iWrite++ )
+//			{
+//				sizeRead = m_Queue.read( BUF, 160 );
+//				m_Track.write( BUF, 0, 160 );
+//			}
+
+			printlog.i(THIS_FILE, "flashmir Track run 1");
+			m_Track.play();
+			printlog.i(THIS_FILE, "flashmir Track run 2");
+
+			while(m_bRunThread != false) {
+				
+				sizeQueue = m_Queue.getsizeFill();
+				if( sizeQueue != 0 )
+				{
+					sizeRead = m_Queue.read( BUF, sizeQueue );
+					m_Track.write( BUF, 0, sizeQueue );
+				}
+
+//				sizeRead = m_Queue.read( BUF, 160 );
+//				if( sizeRead == 160 )
+//				{
+//					m_Track.write( BUF, 0, 160 );
+//					aaa += 160;
+//					printlog.i(THIS_FILE, "flashmir Queue write = " + ( aaa - ( m_Track.getPlaybackHeadPosition() * 2 ) ) );
+//				}
+			}
+		}
+	}
+	
+	private static PCMRecord m_PCMRecord = null;
+	private static PCMTrack m_PCMTrack = null;
+	private static PCMSetting m_Setting = null;
+	static int BUFFER_SIZE = 8000;
+	static byte[] captureBuffer = null;
+
+	private static int frequency;
+	private static int audioEncoding;
+	private static int channelConfiguration;
+	
+	public PCMInterface(){
+		printlog.i(THIS_FILE, "PCMInterface empty constructor...");
+	}
+
+	public PCMInterface(Context context)
+	{
+		//TODO: Load Each Case of Device Setting Value to m_Setting
+		frequency = 8000;
+		audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
+		channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+		
+		PCMIF_Initialize();
+		
+		m_Setting = new PCMSetting();
+
+		captureBuffer = new byte[BUFFER_SIZE];
+	}
+
+//	static byte[] rtpPacketBuffer;
+//	Thread sendThread = null;
+//	public void startSendAudioThread() {
+//		try {
+//			Log.d(THIS_FILE, "[startSendAudioThread]");
+//			Runnable runner = new Runnable() {
+//
+//				public void run() {
+//
+//					while (true) {
+//						if (sendThread == null) break;
+//						if (sendThread.isInterrupted()) break;
+//						try {
+//
+//							boolean bValid = false;
+//							int encpacketsize = 0;
+//
+//							try {
+////                                Log.d(TAG, "[startSendAudioThread] =================== 1 ===================");
+//								encpacketsize = SIPSound.BULK_SIZE;
+//								bValid = SIPController.sipSound.getBulkdata(rtpPacketBuffer, encpacketsize, 12);
+//							} catch (RuntimeException re) {
+//								LogUtil.errorLogInfo("", THIS_FILE, re);
+//								SIPStack.exceptionCountAtCurrentCall++;
+//								bValid = false;
+//							} catch (Exception e) {
+//								//e.printStackTrace();
+//								LogUtil.errorLogInfo("", THIS_FILE, e);
+//								SIPStack.exceptionCountAtCurrentCall++;
+//								bValid = false;
+//							}
+//
+//							try {
+////                                Log.d(TAG, "[startSendAudioThread] bValid [" + bValid + "]");
+//								if (bValid == true) {
+////                                    Log.d(TAG, "[startSendAudioThread] =================== 2 ===================");
+//									//if (rtpCore.remoteMediaIp != null && rtpCore.remoteMediaIp.length() > 0 && rtpCore.remoteMediaPort > 0) {
+//										//Log.i("AS",encpacketsize+" bytes");
+////                                        Log.d(TAG, "[startSendAudioThread] =================== 3 ===================");
+//										rtpWriteEnc(encpacketsize, rtpCore.remotePayloadType, rtpCore.remoteMediaIp, rtpCore.remoteMediaPort);
+//									//}
+//								}
+//							} catch (RuntimeException re) {
+//								SIPStack.exceptionCountAtCurrentCall++;
+//								LogUtil.errorLogInfo("", THIS_FILE, re);
+//							} catch (Exception e) {
+//								SIPStack.exceptionCountAtCurrentCall++;
+//								//e.printStackTrace();
+//								LogUtil.errorLogInfo("", THIS_FILE, e);
+//							}
+////                            Log.d(TAG, "[startSendAudioThread] =================== 4 ===================");
+//							Thread.sleep(SIPSound.PTIME);
+//						} catch (RuntimeException re) {
+//							SIPStack.exceptionCountAtCurrentCall++;
+//							LogUtil.errorLogInfo("", THIS_FILE, re);
+//						} catch (Exception e) {
+//							SIPStack.exceptionCountAtCurrentCall++;
+//							//e.printStackTrace();
+//							LogUtil.errorLogInfo("", THIS_FILE, e);
+//						}
+//					}   //while
+////                    Log.d(TAG, "[startSendAudioThread] =================== 5 ===================");
+//					Log.i(THIS_FILE, "[startSendAudioThread] RTP SEND Thread terminated.");
+//					sendThread = null;
+//				}
+//			};
+//
+////            Log.d(TAG, "[startSendAudioThread] =================== 6 ===================");
+//			sendThread = new Thread(runner);
+//			//sendThread.setPriority(10);
+//			sendThread.start();
+//		} catch (RuntimeException re) {
+//			sendThread = null;
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			LogUtil.errorLogInfo("", THIS_FILE, re);
+//		} catch (Exception e) {
+//			sendThread = null;
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			//e.printStackTrace();
+//			LogUtil.errorLogInfo("", THIS_FILE, e);
+//		}
+//	}
+//
+//	public void rtpWriteEnc(int datasize, int codec, String ip, int port) {
+//		int packetsize = 0;
+//		boolean bSend = false;
+////        Log.e(TAG, "[rtpWriteEnc] ip [" + ip + "], port [" + port + "]");
+//		//DTMF PROCESSING
+//		if (rfc2833.bActive) {
+////            Log.e(TAG, "[rtpWriteEnc] =================== 1 ===================");
+//			byte[] rfcdata = rfc2833.constructDtmfPacket(160);
+//
+//			if (rfcdata != null && rfcdata.length == 4) {
+////                Log.e(TAG, "[rtpWriteEnc] =================== 2 ===================");
+//				rtpCore.rtpPacketBuffer[12] = rfcdata[0];
+//				rtpCore.rtpPacketBuffer[13] = rfcdata[1];
+//				rtpCore.rtpPacketBuffer[14] = rfcdata[2];
+//				rtpCore.rtpPacketBuffer[15] = rfcdata[3];
+//
+//				if (rfc2833.bEnd) rtpCore.RTPmark = 1;
+//				else rtpCore.RTPmark = 0;
+//
+//				bSend = rtpCore.encodeRtpHeader(RFC2833.payloadType);
+//
+//				if (rfc2833.bStart == true) {
+////                    Log.e(TAG, "[rtpWriteEnc] =================== 3 ===================");
+//					if (bSend == true) {
+////                        Log.e(TAG, "[rtpWriteEnc] =================== 4 ===================");
+//						rtpCore.RTPsequence++;
+//						SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
+//						SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
+//					}
+//				} else if (rfc2833.bEnd == true) {
+////                    Log.e(TAG, "[rtpWriteEnc] =================== 5 ===================");
+//					if (bSend == true) {
+////                        Log.e(TAG, "[rtpWriteEnc] =================== 6 ===================");
+//						rtpCore.RTPsequence++;
+//						SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
+//						SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
+//					}
+//					rtpCore.RTPtimestamp += rfc2833.exceedDuration;
+//					rfc2833.resetDtmf();
+//				} else {
+////                    Log.e(TAG, "[rtpWriteEnc] =================== 7 ===================");
+//					if (bSend == true) {
+////                        Log.e(TAG, "[rtpWriteEnc] =================== 8 ===================");
+//						rtpCore.RTPsequence++;
+//						SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
+//					}
+//				}
+//			}
+//			return;
+//		}
+//
+//		try {
+////            Log.e(TAG, "[rtpWriteEnc] =================== 9 ===================");
+//			packetsize = datasize + 12;
+//			if (rtpCore.rtpPacketBuffer != null && packetsize > 0) {
+////                Log.e(TAG, "[rtpWriteEnc] =================== 10 ===================");
+//				bSend = rtpCore.encodeRtpHeader(codec);
+//			}
+//		} catch (RuntimeException re) {
+//			LogUtil.errorLogInfo("", THIS_FILE, re);
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			return;
+//		} catch (Exception e) {
+//			//System.err.println("I/O problems: " + e);
+//			LogUtil.errorLogInfo("", THIS_FILE, e);
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			return;
+//		}
+//
+//		try {
+//			if (bSend == true && ip != null && ip.length() > 0 && port > 0) {
+////                Log.e(TAG, "[rtpWriteEnc] =================== 11 ===================");
+//				rtpCore.RTPsequence++;
+//				rtpCore.RTPtimestamp += 160;
+//				SendRTPPacket(ip, port, rtpPacketBuffer, packetsize);
+//			}
+//		} catch (RuntimeException re) {
+//			LogUtil.errorLogInfo("", THIS_FILE, re);
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			return;
+//		} catch (Exception e) {
+//			//System.err.println("I/O problems: " + e);
+//			LogUtil.errorLogInfo("", THIS_FILE, e);
+//			SIPStack.exceptionCountAtCurrentCall++;
+//			return;
+//		}
+//		return;
+//	}
+
+	public static void jOpenRec(int samplerate)
+	{		
+//		printlog.e(THIS_FILE, "bbbb jOpenRec");
+		
+		m_PCMRecord = new PCMRecord( m_Setting );
+		m_PCMRecord.Open( samplerate );
+
+		//mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, 1024 * 2);   // dadam
+		//mAudioRecord.startRecording();
+
+		//rtpPacketBuffer = new byte[512];
+
+	}
+
+	public static void jStopRec(int i)
+	{		
+//		printlog.e(THIS_FILE, "bbbb jStopRec");
+		m_PCMRecord.Close( i );
+	}
+
+	public static byte[] ShortToByte_ByteBuffer_Method(short [] input)
+	{
+		int index;
+		int iterations = input.length;
+
+		ByteBuffer bb = ByteBuffer.allocate(input.length * 2);
+
+		for(index = 0; index != iterations; ++index)
+		{
+			bb.putShort(input[index]);
+		}
+
+		return bb.array();
+	}
+
+	static boolean bTest = false;
+	static int DMA_SIZE = 768;
+	static short[] dmaShortBuffer = null;
+	public static int jReadPcmData(byte buf[], int size)
+	{		
+		//printlog.e(THIS_FILE, "bbbb jReadPcmData " + size);
+		//printlog.i(THIS_FILE,  "jReadPcmData printHex " + byteArrayToHex(buf, size));
+//		try {
+//			Thread.sleep(10);
+//		} catch (InterruptedException e) {
+//			e.printStackTrace();
+//		}
+		dmaShortBuffer = new short[DMA_SIZE];
+		int size1 = 0;
+		//byte[] buff = new byte[1024];
+		//mAudioRecord.read(buff, 0, DMA_SIZE);
+		//int packetsize = SIPG711.encode2ULawExt(buff, size, buf, 0);
+		//mAudioRecord.read(buf, 0, DMA_SIZE);
+		if(!bTest)
+		{
+
+			bTest = true;
+
+		}
+		else
+		{
+			bTest = false;
+		}
+//		try {
+//			Thread.sleep(5);
+//		} catch (InterruptedException e) {
+//			e.printStackTrace();
+//		}
+
+		//byte[] pcmLinearBuffer = new byte[size * 2];
+		//SIPG711.decodeULawExt(buf, 0, size, pcmLinearBuffer);
+
+		if(Global.ConfigValues.bRemoteCall) {
+			if(RemoteCallManager.bMobileTalk == true)
+			{
+				//sendDoorAudioToMobile(buf,size);
+				//size1 = m_PCMRecord.Read( buf, size );
+				//buf =  captureBuffer;
+				//size = captureBuffer.length;
+				//size1 = m_PCMRecord.Read( buf, size );
+
+				//byte[] buf1 = new byte[size];
+				getEncodeddata(buf, size, 0);
+
+				//SIPG711.decodeULawExt(buf1,0,size,buf);
+				size1 = size;
+				//sendDoorAudioToMobile(buf,size);
+			}
+			else
+			{
+				size1 = m_PCMRecord.Read( buf, size );
+			}
+		}
+		else
+		{
+			size1 = m_PCMRecord.Read( buf, size );
+		}
+
+
+		//SIPG711.encode2ULawExt(pcmLinearBuffer, size, buf, 0);
+//
+//		if(MainActivity.m_iReliefCallNum != 0){
+//			short[] shorts = new short[size/2];
+//	// to turn bytes to shorts as either big endian or little endian.
+//			ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
+//
+//	// to turn shorts back to bytes.
+//	//		byte[] bytes2 = new byte[shortsA.length * 2];
+//		//	ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shorts);
+//
+//			shorts = MainActivity.mReliefCallIF.VRSoftProcessWithDegree(MainActivity.m_iReliefCallNum, shorts);
+//
+//			buf = ShortToByte_ByteBuffer_Method(shorts);
+//		}
+////		short[] shorts = new short[size/2];
+////// to turn bytes to shorts as either big endian or little endian.
+////		ByteBuffer.wrap(buf).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
+////
+////// to turn shorts back to bytes.
+//////		byte[] bytes2 = new byte[shortsA.length * 2];
+//////		ByteBuffer.wrap(bytes2).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shortsA);
+////
+////		shorts = MainActivity.mReliefCallIF.VRSoftProcessWithDegree(1, shorts);
+////
+////		buf = ShortToByte_ByteBuffer_Method(shorts);
+//		//printlog.i(THIS_FILE,  "jReadPcmData printHex " + byteArrayToHex(buf, size));
+//		for(int i=0; i<size; i++) {
+//			//buf[i] = (byte)(buf[i]+50);
+//			//if (buf[i] > 192)
+//			//if(((buf[i] & 0xFF) > 0xF0))// && ((buf[i] & 0xFF) < 0x10)) {
+////			if(((buf[i] & 0xFF) < 0x10) && ((buf[i+1] & 0xFF) < 0x10))
+////			{
+////				//buf[i] = (byte) 0xFF;
+////				//if((buf[i] & 0xFF) < 0x10)
+////					buf[i] = (byte) 0x0;
+////					buf[i+1] = (byte) 0x0;
+////
+////			}
+////			i++;
+//
+//			//buf[i] = (byte) 0xff;
+//			if(((buf[i] & 0xFF) < 0xF0) || ((buf[i] & 0xFF) < 0x10)) {
+//				//buf[i] = (byte) 0x00;
+//
+//				//printlog.i(THIS_FILE,  "jReadPcmData printHex " + buf[i]);
+//			}
+//		}
+
+
+		//printlog.i(THIS_FILE,  "jReadPcmData printHex " + byteArrayToHex(buf, size));
+		return size1;//mAudioRecord.read(buf, 0, size);//m_PCMRecord.Read( buf, size );
+	}
+
+	public static int byte2Int(byte[] src) {
+		int s1 = src[0] & 0xFF;
+		int s2 = src[1] & 0xFF;
+		int s3 = src[2] & 0xFF;
+		int s4 = src[3] & 0xFF;
+
+		return ((s1 << 24) + (s2 << 16) + (s3 << 8) + (s4 << 0));
+	}
+
+	public void receiveMobileAudio_door(AVPacket avPacket) {
+		try {
+			//Log.d(THIS_FILE, "[receiveMobileAudio_KSJ] avPacket.length [" + avPacket.length + "]");
+			//Log.d(THIS_FILE, "[receiveMobileAudio_KSJ] avPacket.avType [" + avPacket.avType + "], avPacket.frameType [" + avPacket.frameType + "]");
+			if (avPacket.data == null || avPacket.length <= 0) {
+				return;
+			}
+
+			int packetSize = avPacket.length - 12;
+			byte[] pcmLinearBuffer = new byte[packetSize * 2];
+			if (SIPG711.decodeULawExt(avPacket.data, 12, packetSize, pcmLinearBuffer)) {
+				//Log.d(THIS_FILE, "[receiveMobileAudio_KSJ] avPacket.length11 [" + packetSize + "]");
+				bufferringMobileAudio(pcmLinearBuffer, pcmLinearBuffer.length);
+//				if (mAudioTrack != null) {
+//					mAudioTrack.play();
+//					mAudioTrack.write(captureBuffer, 0, packetSize * 2);
+//				}
+			}
+		} catch (RuntimeException re) {
+			LogUtil.errorLogInfo("", THIS_FILE, re);
+		} catch (Exception e) {
+			Log.e(THIS_FILE, "[Exception] receiveMobileAudio_door(AVPacket avPacket)");
+			//e.printStackTrace();
+			LogUtil.errorLogInfo("", THIS_FILE, e);
+		}
+	}
+
+	public void receiveMobileAudio_moip(CallManager.CALLTYPE eCallType, AVPacket avPacket) {
+		try {
+			//Log.d(THIS_FILE, "[receiveMobileAudio_moip] eCallType [" + eCallType + "]");
+
+			//bufferringMobileAudio(avPacket.data, avPacket.length);
+
+
+		} catch (RuntimeException re) {
+			LogUtil.errorLogInfo("", THIS_FILE, re);
+		} catch (Exception e) {
+			Log.e(THIS_FILE, "[Exception] receiveMobileAudio_moip(CALLTYPE eCallType, AVPacket avPacket)");
+			//e.printStackTrace();
+			LogUtil.errorLogInfo("", THIS_FILE, e);
+		}
+	}
+
+	static boolean bCaptureBufferLock = false;
+	static int BUFFER_PLAY_INDEX = 0;
+	static int BUFFER_BUFFERREDSIZE = 0;
+
+	public static void bufferringMobileAudio(byte[] data, int dataSize) {
+
+
+		try {
+            //Log.d(THIS_FILE, "[bufferringMobileAudio] data.length [" + data.length + "], dataSize [" + dataSize + "]");
+			bCaptureBufferLock = true;
+			if (data == null || dataSize <= 0) {
+				bCaptureBufferLock = false;
+				return;
+			}
+
+			int packetsize = dataSize;
+			if (BUFFER_BUFFERREDSIZE + packetsize > BUFFER_SIZE) {
+				BUFFER_PLAY_INDEX = 0;
+				BUFFER_BUFFERREDSIZE = 0;
+			}
+
+			int savePos = (BUFFER_PLAY_INDEX + BUFFER_BUFFERREDSIZE) % BUFFER_SIZE;
+			int bufferTrail = BUFFER_SIZE - savePos;
+            //Log.d(THIS_FILE, "[getEncodeddata] packetsize [" + packetsize + "], savePos [" + savePos +"], bufferTrail [" + bufferTrail + "]");
+			if (bufferTrail < packetsize) {
+				System.arraycopy(data, 0, captureBuffer, savePos, bufferTrail);
+				System.arraycopy(data, bufferTrail, captureBuffer, 0, packetsize - bufferTrail);
+			} else {
+				System.arraycopy(data, 0, captureBuffer, savePos, packetsize);
+			}
+			BUFFER_BUFFERREDSIZE += packetsize;
+			bCaptureBufferLock = false;
+
+		} catch (RuntimeException re) {
+			LogUtil.errorLogInfo("", THIS_FILE, re);
+		} catch (Exception e) {
+			Log.e(THIS_FILE, "[Exception] bufferringMobileAudio()");
+			//e.printStackTrace();
+			LogUtil.errorLogInfo("", THIS_FILE, e);
+		}
+
+
+	}
+
+	public static boolean getEncodeddata(byte[] data, int datasize, int pos) {
+		if (bCaptureBufferLock) {
+			try {
+				Date lockTime = null;
+				Date currentTime = null;
+				boolean bOverTime = false;
+				int durationMilli = 0;
+				lockTime = new Date();
+
+				while (bCaptureBufferLock) {
+					Thread.sleep(1, 1);
+					currentTime = new Date();
+					durationMilli = (int) (currentTime.getTime() - lockTime.getTime());
+					if (durationMilli > 2) {
+						bOverTime = true;
+						break;
+					}
+				}
+
+				if (bOverTime == true) {
+					return false;
+				}
+			} catch (RuntimeException re) {
+				LogUtil.errorLogInfo("", THIS_FILE, re);
+				return false;
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] getEncodeddata(byte[] data,int datasize,int pos)");
+				return false;
+			}
+		}
+
+		if (data == null || datasize <= 0) return false;
+
+		if (datasize > BUFFER_BUFFERREDSIZE) {
+			return false;
+		}
+
+		int bufferTrail = BUFFER_SIZE - BUFFER_PLAY_INDEX;
+
+		//Log.d(THIS_FILE, "[getEncodeddata] datasize [" + datasize + "],  bufferTrail [" + bufferTrail + "]");
+		if (bufferTrail < datasize) {
+			System.arraycopy(captureBuffer, BUFFER_PLAY_INDEX, data, pos, bufferTrail);
+			System.arraycopy(captureBuffer, 0, data, pos + bufferTrail, datasize - bufferTrail);
+		} else {
+			System.arraycopy(captureBuffer, BUFFER_PLAY_INDEX, data, pos, datasize);
+		}
+		BUFFER_PLAY_INDEX = (BUFFER_PLAY_INDEX + datasize) % BUFFER_SIZE;
+		BUFFER_BUFFERREDSIZE -= datasize;
+		//Log.d(THIS_FILE,"[getEncodeddata] datasize " + datasize);
+		return true;
+	}
+
+
+
+	static AudioTrack mAudioTrack = null;
+	static AudioRecord mAudioRecord = null;
+	public static void jOpenPlay(int samplerate)
+	{	
+		printlog.i(THIS_FILE, "bbbb jOpenPlay samplerate " + samplerate);
+		//m_PCMTrack = new PCMTrack( m_Setting );
+		//m_PCMTrack.Open( samplerate );
+		// bulk case
+		int minSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
+		int playbufferSize = minSize * 2;
+
+		mAudioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, playbufferSize, AudioTrack.MODE_STREAM);   // original
+		//receiveAudio(false);
+	}
+
+	public synchronized static void jStopPlay(int i)
+	{		
+		printlog.e(THIS_FILE, "bbbb jStopPlay");
+		//m_PCMTrack.Close( i );
+		if (mAudioTrack != null) {
+			mAudioTrack.pause();
+			mAudioTrack.stop();
+			mAudioTrack.flush();
+			mAudioTrack.release();
+		}
+	}
+
+	//static byte[] pcmLinearBuffer = new byte[1024];
+	public static int jWritePcmData(byte buf[], int size)
+	{		
+		//printlog.i(THIS_FILE, "jWritePcmData " + size);
+		printlog.i(THIS_FILE, "jWritePcmData printHex " + byteArrayToHex(buf, size));
+
+		//playAudio(buf, size* 2);
+		//size = size - 12;
+		//if(size != 0) {
+//		for(int i = 0; i < size; i++)
+//		{
+//			if(buf[i] !=0xff)
+//				buf[i] = (byte)(buf[i]-80);
+//		}
+
+//		try {
+//			Thread.sleep(2);
+//		} catch (InterruptedException e) {
+//			e.printStackTrace();
+//		}
+			//byte[] pcmLinearBuffer = new byte[size * 2];
+			//SIPG711.decodeULawExt(buf, 0, size, pcmLinearBuffer);
+			//playAudio(pcmLinearBuffer, size*2);
+			//bTest = false;
+			//m_PCMTrack.Write(buf, size * 2);
+		//}
+
+		if(Global.ConfigValues.bRemoteCall) {
+			if(RemoteCallManager.bMobileTalk == true)
+			{
+				sendDoorAudioToMobile(buf,size);
+			}
+			else
+			{
+				playAudio(buf, size);
+			}
+		}
+		else
+		{
+			playAudio(buf, size);
+		}
+
+		return size;//m_PCMTrack.Write(buf, size);
+	}
+
+	private static void sendDoorAudioToMobile(byte[] data, int size) {
+		try {
+			//Log.d(THIS_FILE, "[sendDoorAudioToMobile] data.length [" + data.length + "], size [" + size + "]");
+			if (MainActivity.mDataSender != null) {
+				AVPacket avp = new AVPacket();
+				avp.avType = 1; // 0:video, 1:audio
+				avp.data = data;
+				avp.length = size;
+				avp.frameType = 1; // 0: G711, 1: PCM 데이터 전송
+
+				try {
+//                    Log.d(TAG, "[sendDoorAudioToMobile] mDataSender.que.put()");
+					MainActivity.mDataSender.blockingQueue.put(avp);
+				} catch (InterruptedException e) {
+					Log.e(THIS_FILE, "[InterruptedException] sendDoorAudioToMobile()");
+					//e.printStackTrace();
+					LogUtil.errorLogInfo("", THIS_FILE, e);
+				}
+			} else {
+//                Log.w(TAG, "[sendDoorAudioToMobile] mDataSender is null!!");
+			}
+		} catch (RuntimeException re) {
+			LogUtil.errorLogInfo("", THIS_FILE, re);
+		} catch (Exception e) {
+			Log.e(THIS_FILE, "[Exception] sendDoorAudioToMobile(byte[] data, int size)");
+			//e.printStackTrace();
+			LogUtil.errorLogInfo("", THIS_FILE, e);
+		}
+	}
+
+
+	public static void playAudio(byte[] data, int dataSize) {
+		//if (bSpeakerLock == true) return;
+		//Log.d(THIS_FILE, "[] playAudio()");
+		if (mAudioTrack != null ){//&& bAudioTrackPlaying == true) {
+
+			//Log.d(THIS_FILE, "[1] playAudio()");
+
+			try {
+				mAudioTrack.write(data, 0, dataSize);
+				//Log.d(THIS_FILE, "[2] playAudio()");
+				if (mAudioTrack != null) {
+					//Log.d(THIS_FILE, "[3] playAudio()");
+					mAudioTrack.play();
+				} else {
+					//Log.d(THIS_FILE, "[4] playAudio()");
+					// bulk case
+					int minSize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
+					int playbufferSize = minSize * 2;
+
+					mAudioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL, 8000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, playbufferSize, AudioTrack.MODE_STREAM);       // original
+
+				}
+			} catch (RuntimeException re) {
+				LogUtil.errorLogInfo("", THIS_FILE, re);
+			} catch (Exception e) {
+				Log.e(THIS_FILE, "[Exception] playAudio(byte[] data, int dataSize) --> BSS DEBUG: TRACK PLAY ERROR");
+				//e.printStackTrace();
+				LogUtil.errorLogInfo("", THIS_FILE, e);
+			}
+		}
+		return;
+	}
+
+	public void jsetCorrectInformation
+	(
+		int sizeTrackCorrectBase,
+		int sizeTrackCorrect,
+		int sizeRecordCorrectBase,
+		int sizeRecordCorrect
+	)
+	{
+		m_Setting.sizeTrackCorrectBase = sizeTrackCorrectBase;
+		m_Setting.sizeTrackCorrect = sizeTrackCorrect;
+		m_Setting.sizeRecordCorrectBase = sizeRecordCorrectBase;
+		m_Setting.sizeRecordCorrect = sizeRecordCorrect;
+		printlog.d(THIS_FILE, "m_Setting.sizeTrackCorrectBase : " + m_Setting.sizeTrackCorrectBase);
+		printlog.d(THIS_FILE, "m_Setting.sizeTrackCorrect : " + m_Setting.sizeTrackCorrect);
+		printlog.d(THIS_FILE, "m_Setting.sizeRecordCorrectBase : " +  m_Setting.sizeRecordCorrectBase);
+		printlog.d(THIS_FILE, "m_Setting.sizeRecordCorrect : " + m_Setting.sizeRecordCorrect);
+	}
+
+	public PCMQueueInformation[] jgetDataInformation()
+	{
+		PCMQueueInformation aINF[] = new PCMQueueInformation[2];
+		
+		if( ( m_PCMTrack == null ) || ( m_PCMRecord == null ) )
+		{
+			return null;
+		}
+		
+		aINF[0] = m_PCMTrack.m_Queue.getInformation();
+		aINF[0].m_sizeQFill = m_PCMTrack.m_Track.getPlaybackHeadPosition() * 2;
+		aINF[0].m_sizeQFill -= aINF[0].m_sizeQPass;
+		aINF[1] = m_PCMRecord.m_Queue.getInformation();
+
+		return aINF;
+	}
+	public static String byteArrayToHex(byte[] a, int len) {
+		StringBuilder sb = new StringBuilder();
+		for(int i=0; i<len; i++) {
+			sb.append(String.format("%02x ", a[i] & 0xff));
+		}
+		return sb.toString();
+	}
+}

+ 149 - 0
WallPadCall/src/main/java/ceres/security/Base64Utils.java

@@ -0,0 +1,149 @@
+package ceres.security;
+
+import android.util.Base64;
+
+import java.io.UnsupportedEncodingException;
+
+import ceres.api.SipManager;
+import ceres.utils.printlog;
+
+public class Base64Utils { 
+
+	/**
+     * Encode txt
+     * @param txt
+     * @return
+     * @throws UnsupportedEncodingException
+     */
+	private final static String THIS_FILE = "Base64Utils";
+	
+    public static String encode(String str) throws UnsupportedEncodingException {
+        byte[] data = str.getBytes("UTF-8");        
+        return Base64.encodeToString(data, Base64.DEFAULT);
+    }
+    
+    /**
+     * Decode txt
+     * @param txt
+     * @return
+     * @throws UnsupportedEncodingException
+     */
+    public static String decode(String str) throws UnsupportedEncodingException {
+            return new String(Base64.decode(str, Base64.DEFAULT), "UTF-8");
+    }    
+    
+    //Base64 + Seed 암호화 
+    public static String encrypt(String str, String key)
+    {
+    	if (key.length() != 12) {
+    		printlog.d(THIS_FILE, "key.length() : " + key.length());
+    		return "";
+    	}
+    	try {
+    		String strResult;
+    		String strTemp = "";
+    		strResult = "";
+    		//BASE64Encoder encoder = new BASE64Encoder();
+    		SeedAlg seedAlg = new SeedAlg(key.getBytes());
+    		//strTemp = new String(encoder.encode(seedAlg.encrypt(str.getBytes())));
+    		strTemp = Base64.encodeToString(seedAlg.encrypt(str.getBytes()), Base64.DEFAULT);
+    		for(int i = 0; i < strTemp.length(); i++) {
+    			if(strTemp.charAt(i) != '\n' && strTemp.charAt(i) != '\r') {
+    				strResult = strResult + strTemp.charAt(i);
+    			}
+    		}
+    		return strResult;
+    	} catch (Exception ex) {
+    		return null;
+    	}
+    }
+       
+    //Base64 + Seed 복호화
+    public static String decrypt(String str, String key) {
+    	if (key.length() != 12) {
+    		return "";
+    	}
+
+    	try {
+    		String strResult;
+    		String strTemp = "";
+    		strResult = "";
+    		//BASE64Decoder decoder = new BASE64Decoder();
+    		SeedAlg seedAlg = new SeedAlg(key.getBytes());
+    		//strTemp = new String(seedAlg.decrypt(decoder.decodeBuffer(str)));
+    		strTemp = new String(seedAlg.decrypt(Base64.decode(str, Base64.DEFAULT)));
+    		for (int i = 0; i < strTemp.length() && strTemp.charAt(i) != 0;) {
+    			if (strTemp.charAt(i) != '\n' && strTemp.charAt(i) != '\r') {
+    				strResult = strResult + strTemp.charAt(i);
+    				i++;
+    			}
+    		}
+    		return strResult;
+    	} catch (Exception ex) {
+    		return null;
+    	}
+    }
+    // -----------------------------------------------------------------------------
+    // string decryption function
+    // security_level : 복호화 레벨 (0 : 복호화 하지 않음, 1 : base64, 2 : base64+seed
+    // -----------------------------------------------------------------------------
+    public static String decryptToString(String str){
+    	String retVal = "";
+    	int security_level = SipManager.SECURITY_APPLY;
+    	
+    	if(security_level == 0){
+    		printlog.d(THIS_FILE, "bypass return str 111 : " + str);
+    		retVal = str;
+    		printlog.d(THIS_FILE, "bypass return str 222 : " + retVal);
+    	}
+    	else if(security_level == 1){    		    
+    		printlog.d(THIS_FILE, "base64 decryption str 111 : " + str);
+    		try {
+				retVal = decode(str);
+			} catch (UnsupportedEncodingException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+    		printlog.d(THIS_FILE, "base64 decryption str 222 : " + retVal);
+    	}
+    	else if(security_level == 2){    		    
+    		printlog.d(THIS_FILE, "base64+a decryption str 111 : " + str);
+    		retVal = decrypt(str, SipManager.SECURITY_KEY);
+    		printlog.d(THIS_FILE, "base64+a decryption str 222 : " + retVal);
+    	}    	    	   
+    	return retVal;
+    }
+    
+    // -----------------------------------------------------------------------------
+    // string encryptToString function
+    // security_level : 암호화 레벨 (0 : 암호화 하지 않음, 1 : base64, 2 : base64+seed
+    // -----------------------------------------------------------------------------
+    public static String encryptToString(String str){
+    	String retVal = "";
+    	int security_level = SipManager.SECURITY_APPLY;
+    	
+    	if(security_level == 0){
+    		printlog.d(THIS_FILE, "bypass return str 111 : " + str);
+    		retVal = str;
+    		printlog.d(THIS_FILE, "bypass return str 222 : " + retVal);
+    	}
+    	else if(security_level == 1){    		    
+    		printlog.d(THIS_FILE, "base64 encryption str 111 : " + str);
+    		try {
+				retVal = encode(str);
+			} catch (UnsupportedEncodingException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+    		printlog.d(THIS_FILE, "base64 encryption str 222 : " + retVal);
+    	}
+    	else if(security_level == 2){    		    
+    		printlog.d(THIS_FILE, "base64+a encryption str 111 : " + str);
+    		retVal = encrypt(str, SipManager.SECURITY_KEY);
+    		printlog.d(THIS_FILE, "base64+a encryption str 222 : " + retVal);
+    	}    	    	   
+    	return retVal;
+    }
+}
+
+

+ 410 - 0
WallPadCall/src/main/java/ceres/security/SeedAlg.java

@@ -0,0 +1,410 @@
+package ceres.security;
+
+public class SeedAlg {
+
+    public SeedAlg(byte key[]) {
+        RoundKey = new long[32];
+        seedEncRoundKey(key);
+    }
+
+    public byte[] encrypt(byte plainData[])
+    {
+        int nLoopCnt = plainData.length / 16 + (plainData.length % 16 == 0 ? 0 : 1);
+        byte retArray[] = new byte[nLoopCnt * 16];
+        for(int i = 0; i < nLoopCnt; i++)
+        {
+            long nTemp[] = new long[4];
+            for(int j = 0; j < 4; j++)
+                nTemp[j] = makeLong(plainData, i * 16 + j * 4);
+
+            nTemp = encrypt16(nTemp);
+            for(int j = 0; j < 16; j++)
+                retArray[i * 16 + j] = getAByteLong(nTemp[j / 4], 3 - j % 4);
+
+        }
+
+        return retArray;
+    }
+    private long[] encrypt16(long plainData[])
+    {
+        boolean bSwapFlag = false;
+        for(int i = 0; i < 16; i++)
+        {
+            plainData = SeedRound(plainData, i, bSwapFlag);
+            bSwapFlag = !bSwapFlag;
+        }
+
+        return (new long[] {
+            plainData[2], plainData[3], plainData[0], plainData[1]
+        });
+    }
+
+
+    public byte[] decrypt(byte cipherData[]) {
+        int nLoopCnt = cipherData.length / 16
+                + (cipherData.length % 16 == 0 ? 0 : 1);
+        byte retArray[] = new byte[nLoopCnt * 16];
+        for (int i = 0; i < nLoopCnt; i++) {
+            long nTemp[] = new long[4];
+            for (int j = 0; j < 4; j++) {
+                nTemp[j] = makeLong(cipherData, i * 16 + j * 4);
+            }
+
+            nTemp = decrypt16(nTemp);
+            for (int j = 0; j < 16; j++) {
+                retArray[i * 16 + j] = getAByteLong(nTemp[j / 4], 3 - j % 4);
+            }
+        }
+
+        return retArray;
+    }
+
+    private void seedEncRoundKey(byte pbUserKey[]) {
+        long keyData[] = { makeLong(pbUserKey, 0), makeLong(pbUserKey, 4),
+                makeLong(pbUserKey, 8), makeLong(pbUserKey, 12) };
+        long T0 = (keyData[0] + keyData[2]) - KC[0];
+        long T1 = (keyData[1] - keyData[3]) + KC[0];
+        RoundKey[0] = SS0[(int) getAByteToLong(T0, 0)]
+                ^ SS1[(int) getAByteToLong(T0, 1)]
+                ^ SS2[(int) getAByteToLong(T0, 2)]
+                ^ SS3[(int) getAByteToLong(T0, 3)];
+        RoundKey[1] = SS0[(int) getAByteToLong(T1, 0)]
+                ^ SS1[(int) getAByteToLong(T1, 1)]
+                ^ SS2[(int) getAByteToLong(T1, 2)]
+                ^ SS3[(int) getAByteToLong(T1, 3)];
+        for (int i = 0; i < 7; i++) {
+            keyData = encRoundKeyUpdate0(keyData, i * 2 + 1);
+            keyData = encRoundKeyUpdate1(keyData, i * 2 + 2);
+        }
+
+        encRoundKeyUpdate0(keyData, 15);
+    }
+
+    private long[] decrypt16(long cipherData[]) {
+        boolean bSwapFlag = false;
+        for (int i = 15; i >= 0; i--) {
+            cipherData = SeedRound(cipherData, i, bSwapFlag);
+            bSwapFlag = !bSwapFlag;
+        }
+
+        return (new long[] { cipherData[2], cipherData[3], cipherData[0],
+                cipherData[1] });
+    }
+
+    private long[] encRoundKeyUpdate0(long keyData[], int roundCnt) {
+        long T0 = keyData[0];
+        keyData[0] = keyData[0] >> 8 & 4294967295L ^ keyData[1] << 24
+                & 4294967295L;
+        keyData[1] = keyData[1] >> 8 & 4294967295L ^ T0 << 24 & 4294967295L;
+        T0 = (keyData[0] + keyData[2]) - KC[roundCnt] & 4294967295L;
+        long T1 = (keyData[1] + KC[roundCnt]) - keyData[3] & 4294967295L;
+        RoundKey[roundCnt * 2] = SS0[(int) getAByteToLong(T0, 0)]
+                ^ SS1[(int) getAByteToLong(T0, 1)]
+                ^ SS2[(int) getAByteToLong(T0, 2)]
+                ^ SS3[(int) getAByteToLong(T0, 3)];
+        RoundKey[roundCnt * 2 + 1] = SS0[(int) getAByteToLong(T1, 0)]
+                ^ SS1[(int) getAByteToLong(T1, 1)]
+                ^ SS2[(int) getAByteToLong(T1, 2)]
+                ^ SS3[(int) getAByteToLong(T1, 3)];
+        return keyData;
+    }
+
+    private long[] encRoundKeyUpdate1(long keyData[], int roundCnt) {
+        long T0 = keyData[2];
+        keyData[2] = (keyData[2] << 8 ^ keyData[3] >> 24) & 4294967295L;
+        keyData[3] = (keyData[3] << 8 ^ T0 >> 24) & 4294967295L;
+        T0 = (keyData[0] + keyData[2]) - KC[roundCnt] & 4294967295L;
+        long T1 = (keyData[1] + KC[roundCnt]) - keyData[3] & 4294967295L;
+        RoundKey[roundCnt * 2] = SS0[(int) getAByteToLong(T0, 0)]
+                ^ SS1[(int) getAByteToLong(T0, 1)]
+                ^ SS2[(int) getAByteToLong(T0, 2)]
+                ^ SS3[(int) getAByteToLong(T0, 3)];
+        RoundKey[roundCnt * 2 + 1] = SS0[(int) getAByteToLong(T1, 0)]
+                ^ SS1[(int) getAByteToLong(T1, 1)]
+                ^ SS2[(int) getAByteToLong(T1, 2)]
+                ^ SS3[(int) getAByteToLong(T1, 3)];
+        return keyData;
+    }
+
+    private byte getAByteLong(long src, int index) {
+        return (byte) (int) (src >>> index * 8 & 255L);
+    }
+
+    private long getAByteToLong(long src, int index) {
+        return src >> index * 8 & 255L;
+    }
+
+    private long makeLong(byte byteArray[], int nStartIndex) {
+        long b1 = byteArray.length <= nStartIndex ? 0L
+                : (255L & (long) byteArray[nStartIndex + 0]) << 24;
+        long b2 = byteArray.length <= nStartIndex + 1 ? 0L
+                : (255L & (long) byteArray[nStartIndex + 1]) << 16;
+        long b3 = byteArray.length <= nStartIndex + 2 ? 0L
+                : (255L & (long) byteArray[nStartIndex + 2]) << 8;
+        long b4 = byteArray.length <= nStartIndex + 3 ? 0L
+                : 255L & (long) byteArray[nStartIndex + 3];
+        return b1 + b2 + b3 + b4;
+    }
+
+    private long[] SeedRound(long data[], int roundIndex, boolean swapFlag) {
+        long L0;
+        long L1;
+        long R0;
+        long R1;
+        if (!swapFlag) {
+            L0 = data[0];
+            L1 = data[1];
+            R0 = data[2];
+            R1 = data[3];
+        } else {
+            R0 = data[0];
+            R1 = data[1];
+            L0 = data[2];
+            L1 = data[3];
+        }
+        long T0 = R0 ^ RoundKey[roundIndex * 2];
+        long T1 = R1 ^ RoundKey[roundIndex * 2 + 1];
+        T1 ^= T0;
+        T1 = SS0[(int) getAByteToLong(T1, 0)]
+                ^ SS1[(int) getAByteToLong(T1, 1)]
+                ^ SS2[(int) getAByteToLong(T1, 2)]
+                ^ SS3[(int) getAByteToLong(T1, 3)];
+        T0 += T1;
+        T0 = SS0[(int) getAByteToLong(T0, 0)]
+                ^ SS1[(int) getAByteToLong(T0, 1)]
+                ^ SS2[(int) getAByteToLong(T0, 2)]
+                ^ SS3[(int) getAByteToLong(T0, 3)];
+        T1 += T0;
+        T1 = SS0[(int) getAByteToLong(T1, 0)]
+                ^ SS1[(int) getAByteToLong(T1, 1)]
+                ^ SS2[(int) getAByteToLong(T1, 2)]
+                ^ SS3[(int) getAByteToLong(T1, 3)];
+        T0 += T1;
+        L0 ^= T0;
+        L1 ^= T1;
+        return swapFlag ? (new long[] { R0, R1, L0, L1 }) : (new long[] { L0,
+                L1, R0, R1 });
+    }
+
+    static long SS0[] = { 696885672L, 92635524L, 382128852L, 331600848L,
+            340021332L, 487395612L, 747413676L, 621093156L, 491606364L,
+            54739776L, 403181592L, 504238620L, 289493328L, 1020063996L,
+            181060296L, 591618912L, 671621160L, 71581764L, 536879136L,
+            495817116L, 549511392L, 583197408L, 147374280L, 386339604L,
+            629514660L, 261063564L, 50529024L, 994800504L, 999011256L,
+            318968592L, 314757840L, 785310444L, 809529456L, 210534540L,
+            1057960764L, 680042664L, 839004720L, 500027868L, 919007988L,
+            876900468L, 751624428L, 361075092L, 185271048L, 390550356L,
+            474763356L, 457921368L, 1032696252L, 16843008L, 604250148L,
+            470552604L, 860058480L, 411603096L, 268439568L, 214745292L,
+            851636976L, 432656856L, 738992172L, 667411428L, 843215472L,
+            58950528L, 462132120L, 297914832L, 109478532L, 164217288L,
+            541089888L, 272650320L, 595829664L, 734782440L, 218956044L,
+            914797236L, 512660124L, 256852812L, 931640244L, 441078360L,
+            113689284L, 944271480L, 646357668L, 302125584L, 797942700L,
+            365285844L, 557932896L, 63161280L, 881111220L, 21053760L,
+            306336336L, 1028485500L, 227377548L, 134742024L, 521081628L,
+            428446104L, 0, 420024600L, 67371012L, 323179344L, 935850996L,
+            566354400L, 1036907004L, 910586484L, 789521196L, 654779172L,
+            813740208L, 193692552L, 235799052L, 730571688L, 578986656L,
+            776888940L, 327390096L, 223166796L, 692674920L, 1011642492L,
+            151585032L, 168428040L, 1066382268L, 802153452L, 868479984L,
+            96846276L, 126321540L, 335810580L, 1053750012L, 608460900L,
+            516870876L, 772678188L, 189481800L, 436867608L, 101057028L,
+            553722144L, 726360936L, 642146916L, 33686016L, 902164980L,
+            310547088L, 176849544L, 202113036L, 864269232L, 1045328508L,
+            281071824L, 977957496L, 122110788L, 377918100L, 633725412L,
+            637936164L, 8421504L, 764256684L, 533713884L, 562143648L,
+            805318704L, 923218740L, 781099692L, 906375732L, 352653588L,
+            570565152L, 940060728L, 885321972L, 663200676L, 88424772L,
+            206323788L, 25264512L, 701096424L, 75792516L, 394761108L,
+            889532724L, 197903304L, 248431308L, 1007431740L, 826372464L,
+            285282576L, 130532292L, 160006536L, 893743476L, 1003222008L,
+            449499864L, 952692984L, 344232084L, 424235352L, 42107520L,
+            80003268L, 1070593020L, 155795784L, 956903736L, 658989924L,
+            12632256L, 265274316L, 398971860L, 948482232L, 252642060L,
+            244220556L, 37896768L, 587408160L, 293704080L, 743202924L,
+            466342872L, 612671652L, 872689716L, 834793968L, 138952776L,
+            46318272L, 793731948L, 1024274748L, 755835180L, 4210752L,
+            1049539260L, 1041117756L, 1015853244L, 29475264L, 713728680L,
+            982168248L, 240009804L, 356864340L, 990589752L, 483184860L,
+            675831912L, 1062171516L, 478974108L, 415813848L, 172638792L,
+            373707348L, 927429492L, 545300640L, 768467436L, 105267780L,
+            897954228L, 722150184L, 625303908L, 986379000L, 600040416L,
+            965325240L, 830583216L, 529503132L, 508449372L, 969535992L,
+            650568420L, 847426224L, 822161712L, 717939432L, 760045932L,
+            525292380L, 616882404L, 817950960L, 231588300L, 143163528L,
+            369496596L, 973746744L, 407392344L, 348442836L, 574775904L,
+            688464168L, 117900036L, 855847728L, 684253416L, 453710616L,
+            84214020L, 961114488L, 276861072L, 709517928L, 705307176L,
+            445289112L };
+
+    static long SS1[] = { 943196208L, -399980320L, 741149985L, -1540979038L,
+            -871379005L, -601960750L, -1338801229L, -1204254544L, -1406169181L,
+            1612726368L, 1410680145L, -1006123069L, 1141130304L, 1815039843L,
+            1747667811L, 1478183763L, -1073495101L, 1612857954L, 808649523L,
+            -1271560783L, 673777953L, -1608482656L, -534592798L, -1540913245L,
+            -804011053L, -1877900911L, 269549841L, 67503618L, 471600144L,
+            -1136882512L, 875955762L, 1208699715L, -332410909L, -2012706688L,
+            1814842464L, -1473738592L, 337053459L, -1006320448L, 336987666L,
+            -197868304L, -1073560894L, 1141196097L, -534658591L, -736704814L,
+            1010765619L, 1010634033L, -1945203070L, -1743222640L, 673712160L,
+            1276005954L, -197736718L, 1010699826L, -1541044831L, -130430479L,
+            202181889L, -601894957L, -669464368L, 673909539L, 1680229986L,
+            2017086066L, 606537507L, 741281571L, -265174543L, 1882342002L,
+            1073889858L, -736836400L, 1073824065L, -1073692480L, 1882407795L,
+            1680295779L, -1406366560L, -2012509309L, -197670925L, -1406300767L,
+            -2147450752L, 471797523L, -938816830L, 741084192L, -1473607006L,
+            875824176L, -804076846L, 134941443L, -332476702L, -399914527L,
+            1545424209L, -1810594672L, 404228112L, -130496272L, 1410811731L,
+            -1406234974L, 134744064L, -1006254655L, 269681427L, -871510591L,
+            -2079947134L, -1204188751L, -62926861L, 2084392305L, -1073626687L,
+            808517937L, -197802511L, -2012575102L, 1747602018L, -1338932815L,
+            -804142639L, 538968096L, -736639021L, 131586L, 539099682L,
+            67372032L, 1747470432L, 1882276209L, 67569411L, -669266989L,
+            -1675784815L, -1743156847L, 1612792161L, -1136750926L, -467220766L,
+            1478052177L, -602026543L, 1343308113L, -1877966704L, -602092336L,
+            -1743091054L, -1608285277L, -1473541213L, -804208432L,
+            -2147384959L, 202313475L, 1141327683L, 404359698L, -534527005L,
+            -332608288L, -1945268863L, -1136685133L, -1810463086L, 2017151859L,
+            1545358416L, -1608351070L, -1608416863L, 1612923747L, 539165475L,
+            1275940161L, -938948416L, -1675719022L, -1675850608L, 943327794L,
+            202116096L, 741215778L, -1204122958L, 1814974050L, -1675653229L,
+            1478117970L, -265108750L, -1877835118L, -265042957L, 1208568129L,
+            2016954480L, -871576384L, 336921873L, -130298893L, 1882210416L,
+            1949648241L, 2084523891L, 875889969L, 269484048L, 197379L,
+            1680098400L, 1814908257L, -1006188862L, 1949582448L, -736770607L,
+            -1271626576L, -399848734L, 134809857L, 1949714034L, 404293905L,
+            -62992654L, 1073758272L, 269615634L, -534724384L, -1136816719L,
+            67437825L, -130364686L, 65793L, -265240336L, 673843746L,
+            1545490002L, -1473672799L, 1410745938L, 1073955651L, -2080012927L,
+            336856080L, -2012640895L, -1743025261L, -1338998608L, -467286559L,
+            1208502336L, 2017020273L, -1810397293L, -63124240L, 471731730L,
+            -2147319166L, 539033889L, -1945334656L, 404425491L, 1545555795L,
+            1949779827L, 1410614352L, -1338867022L, 471665937L, 606405921L,
+            1276071747L, 0, 1141261890L, -332542495L, 1477986384L, 1343373906L,
+            -399782941L, 2084458098L, -669332782L, -938882623L, -63058447L,
+            808452144L, -1810528879L, 1680164193L, 1010568240L, -1271494990L,
+            -467352352L, -1204057165L, 2084326512L, 202247682L, 1343242320L,
+            943262001L, 606471714L, 808583730L, -2080078720L, 1747536225L,
+            -1877769325L, 876021555L, -467154973L, 606340128L, -1541110624L,
+            -938751037L, 1343439699L, 134875650L, -2079881341L, -669398575L,
+            1275874368L, -2147253373L, -1945137277L, -871444798L, 943393587L,
+            1208633922L, -1271429197L };
+
+    static long SS2[] = { -1582814839L, -2122054267L, -757852474L, -741338173L,
+            1347687492L, 287055117L, -1599329140L, 556016901L, 1364991309L,
+            1128268611L, 270014472L, 303832590L, 1364201793L, -251904820L,
+            -1027077430L, 1667244867L, 539502600L, 1078199364L, 538976256L,
+            -1852039795L, -522182464L, -488627518L, -1060632376L, 320083719L,
+            -1583078011L, -2087972977L, 50332419L, 1937259339L, -1279771765L,
+            319820547L, -758115646L, -487838002L, 1886400576L, -2138305396L,
+            859586319L, -1599592312L, 842019330L, -774103603L, -218876218L,
+            1886663748L, -521392948L, -1852566139L, 50858763L, 1398019911L,
+            1348213836L, 1398283083L, -1313063539L, 16777473L, 539239428L,
+            270277644L, 1936732995L, -1869080440L, 269488128L, -1060369204L,
+            -219139390L, -774366775L, 539765772L, -471586873L, 1919955522L,
+            -2088762493L, -1818748021L, -774893119L, -2105276794L,
+            -1043854903L, 1616912448L, 1347424320L, -1549786237L, -471323701L,
+            17566989L, -1296812410L, -1835262322L, 1129058127L, -1280034937L,
+            1381505610L, -1027340602L, 1886926920L, -1566300538L, 303043074L,
+            -1548996721L, -774629947L, 1633689921L, -1010826301L, -1330367356L,
+            1094713665L, 1380979266L, 1903967565L, -2121527923L, 526344L,
+            320610063L, -1852302967L, 0, 286791945L, 263172L, 1397756739L,
+            -202098745L, -505404991L, -235127347L, 1920218694L, 590098191L,
+            589571847L, -1330630528L, -2088236149L, 34344462L, -1549259893L,
+            -1566563710L, 1651256910L, -1819274365L, 1095503181L, 1634216265L,
+            1887190092L, 17303817L, 34081290L, -1279508593L, -471060529L,
+            -202361917L, -1044118075L, -2088499321L, 269751300L, -218349874L,
+            1617175620L, -757326130L, 573320718L, 1128794955L, 303569418L,
+            33818118L, 555753729L, 1667771211L, 1650730566L, 33554946L,
+            -235653691L, -1836051838L, -2105013622L, 789516L, -1280298109L,
+            1920745038L, -791670592L, 1920481866L, 1128531783L, -1835788666L,
+            -505141819L, 572794374L, -2139094912L, -1582551667L, -740548657L,
+            -1583341183L, 808464384L, 859059975L, -1565774194L, 842282502L,
+            286528773L, 572531202L, 808990728L, -252431164L, -1549523065L,
+            1094976837L, 1078725708L, -2122317439L, -504878647L, -2138831740L,
+            -1819011193L, 825505029L, -1010299957L, -1026814258L, 809253900L,
+            1903178049L, 286265601L, -1010563129L, -2121791095L, 1903441221L,
+            -201835573L, -757589302L, -252167992L, -1869343612L, 1364728137L,
+            -2105539966L, -1060895548L, -201572401L, 1095240009L, 825768201L,
+            1667508039L, -1061158720L, -1010036785L, -741075001L, -1330104184L,
+            51121935L, -2104750450L, 1111491138L, 589308675L, -1852829311L,
+            1617701964L, -740811829L, -1599855484L, 808727556L, -235916863L,
+            1078462536L, -1027603774L, 1668034383L, 826031373L, 556543245L,
+            1077936192L, -1296286066L, 842808846L, -1329841012L, -1044381247L,
+            -1566037366L, -1296549238L, 1112280654L, 1364464965L, 859323147L,
+            -790881076L, 1617438792L, 1937522511L, -1868817268L, -791144248L,
+            1112017482L, 1381242438L, 1936996167L, -1600118656L, -504615475L,
+            1111754310L, -1313589883L, 589835019L, 1633953093L, -218613046L,
+            -471850045L, -1313326711L, -1313853055L, -1818484849L, 1381768782L,
+            -235390519L, -488364346L, -1297075582L, 825241857L, -488101174L,
+            1634479437L, 1398546255L, -521919292L, -252694336L, -1043591731L,
+            -2138568568L, 303306246L, 842545674L, 1347950664L, -791407420L,
+            1650467394L, 556280073L, 50595591L, 858796803L, -521656120L,
+            320346891L, 17040645L, 1903704393L, -1869606784L, 1650993738L,
+            573057546L, -1835525494L };
+
+    static long SS3[] = { 137377848L, -924784600L, 220277805L, -2036161498L,
+            -809251825L, -825041890L, -2085375949L, -2001684424L, -1885098961L,
+            1080057888L, 1162957845L, -943471609L, 1145062404L, 1331915823L,
+            1264805931L, 1263753243L, -1010581501L, 1113743394L, 53686323L,
+            -2051951563L, 153167913L, -2136956896L, -1025318878L, -2019318745L,
+            -1009528813L, -2121166831L, 17895441L, 100795398L, 202382364L,
+            -1934574532L, 103953462L, 1262700555L, -807146449L, -2004842488L,
+            1281387564L, -2002737112L, 118690839L, -993999868L, 101848086L,
+            -990841804L, -1027424254L, 1161905157L, -1042161631L, -959261674L,
+            255015999L, 221330493L, -1904047090L, -2003789800L, 136325160L,
+            1312967694L, -957156298L, 238173246L, -2053004251L, -906889159L,
+            218172429L, -808199137L, -925837288L, 186853419L, 1180853286L,
+            1249015866L, 119743527L, 253963311L, -1041108943L, 1114796082L,
+            1111638018L, -992947180L, 1094795265L, -1061109760L, 1131638835L,
+            1197696039L, -1935627220L, -1954314229L, -940313545L, -1918784467L,
+            -2139062272L, 252910623L, -893204470L, 203435052L, -1969051606L,
+            70267956L, -1026371566L, 184748043L, -823989202L, -907941847L,
+            1297177629L, -2070899692L, 135272472L, -923731912L, 1196643351L,
+            -1901941714L, 134219784L, -977157115L, 51580947L, -842937331L,
+            -2038266874L, -1984841671L, -806093761L, 1299283005L, -1044267007L,
+            20000817L, -973999051L, -1971156982L, 1247963178L, -2119061455L,
+            -1043214319L, 2105376L, -942418921L, 33685506L, 35790882L,
+            67109892L, 1214277672L, 1097953329L, 117638151L, -875309029L,
+            -1919837155L, -1986947047L, 1096900641L, -1900889026L, -958208986L,
+            1230067737L, -841884643L, 1095847953L, -2138009584L, -858727396L,
+            -1970104294L, -2086428637L, -1952208853L, -1060057072L,
+            -2122219519L, 251857935L, 1195590663L, 168957978L, -1008476125L,
+            -857674708L, -1920889843L, -1884046273L, -2037214186L, 1265858619L,
+            1280334876L, -2103271390L, -2120114143L, 1130586147L, 52633635L,
+            1296124941L, -926889976L, -1902994402L, -1936679908L, 171063354L,
+            201329676L, 237120558L, -1967998918L, 1315073070L, -1886151649L,
+            1246910490L, -1024266190L, -2104324078L, -1007423437L, 1229015049L,
+            1215330360L, -859780084L, 85005333L, -873203653L, 1081110576L,
+            1165063221L, 1332968511L, 87110709L, 1052688L, 50528259L,
+            1147167780L, 1298230317L, -960314362L, 1148220468L, -976104427L,
+            -2068794316L, -891099094L, 151062537L, 1181905974L, 152115225L,
+            -822936514L, 1077952512L, 34738194L, -1059004384L, -1917731779L,
+            83952645L, -890046406L, 16842753L, -1057951696L, 170010666L,
+            1314020382L, -1985894359L, 1179800598L, 1128480771L, -2055109627L,
+            68162580L, -1987999735L, -1953261541L, -2135904208L, -975051739L,
+            1212172296L, 1232173113L, -2020371433L, -856622020L, 236067870L,
+            -2105376766L, 18948129L, -1937732596L, 185800731L, 1330863135L,
+            1198748727L, 1146115092L, -2102218702L, 219225117L, 86058021L,
+            1329810447L, 0, 1178747910L, -840831955L, 1213224984L, 1112690706L,
+            -874256341L, 1316125758L, -892151782L, -910047223L, -839779267L,
+            3158064L, -2054056939L, 1164010533L, 204487740L, -2035108810L,
+            -991894492L, -1951156165L, 1282440252L, 235015182L, 1079005200L,
+            154220601L, 102900774L, 36843570L, -2071952380L, 1231120425L,
+            -2087481325L, 120796215L, -941366233L, 69215268L, -2069847004L,
+            -876361717L, 1129533459L, 167905290L, -2021424121L, -908994535L,
+            1279282188L, -2088534013L, -1887204337L, -826094578L, 187906107L,
+            1245857802L, -2018266057L };
+
+    static long KC[] = { -1640531527L, 1013904243L, 2027808486L, -239350324L,
+            -478700647L, -957401293L, -1914802585L, 465362127L, 930724254L,
+            1861448508L, -572070280L, -1144140559L, 2006686179L, -281594938L,
+            -563189875L, -1126379749L };
+
+    long RoundKey[];
+
+}
+
+

+ 178 - 0
WallPadCall/src/main/java/ceres/service/MediaManager.java

@@ -0,0 +1,178 @@
+package ceres.service;
+
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+
+import ceres.utils.Ringer;
+import ceres.utils.printlog;
+
+public class MediaManager {
+	
+	final private static String THIS_FILE = "MediaManager";
+	
+	
+//	private SipService service;
+	
+	public Context mContext;
+	
+	private AudioManager audioManager;
+	private Ringer ringer;
+	
+	//By default we assume user want bluetooth.
+	//If bluetooth is not available connection will never be done and then
+	//UI will not show bluetooth is activated
+	private boolean userWantSpeaker = false;
+	private boolean userWantMicrophoneMute = false;
+
+	private Intent mediaStateChangedIntent;
+	
+	public MediaManager(Context context) {
+		mContext = context;
+		audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+		ringer = new Ringer(mContext);
+	}	
+	
+	
+	public void startService() {
+		;
+	}
+	
+	public void stopService() {
+		printlog.i(THIS_FILE, "Remove media manager....");
+	}	
+	
+	public void startRing(String remoteContact) {
+		
+		if(!ringer.isRinging()) {
+			printlog.d(THIS_FILE, "startRing....");
+			ringer.ring(remoteContact, "content://settings/system/ringtone");
+		}else {
+			printlog.d(THIS_FILE, "startRing Already ringing ....");
+		}
+		
+	}
+	
+	public void stopRing() {
+		if(ringer.isRinging()) {
+			printlog.d(THIS_FILE, "stopRing Already ringing ....");
+			ringer.stopRing();
+		}
+	}
+	
+	public void stopAnnoucing() {
+		stopRing();
+	}
+	
+	public void resetSettings() {
+		userWantMicrophoneMute = false;
+		userWantSpeaker = false;
+	}
+
+
+	public void toggleMute() {
+		setMicrophoneMute(!userWantMicrophoneMute);
+	}
+	
+	public synchronized void setMicrophoneMute(boolean on) {
+		if(on != userWantMicrophoneMute ) {
+			userWantMicrophoneMute = on;
+			broadcastMediaChanged();
+		}
+	}
+	// -----------------------------------------------------------------
+	//
+	// -----------------------------------------------------------------
+	public synchronized void setSpeakerphoneOn(boolean on) {
+		audioManager.setSpeakerphoneOn(on);
+	}
+	
+	public synchronized void setBluetoothOn(boolean on) {
+		printlog.d(THIS_FILE, "Set BT "+on);
+		broadcastMediaChanged();
+	}
+	
+	public class MediaState {
+		public boolean isMicrophoneMute = false;
+		public boolean isSpeakerphoneOn = false;
+		public boolean isBluetoothScoOn = false;
+		public boolean canMicrophoneMute = true;
+		public boolean canSpeakerphoneOn = true;
+		public boolean canBluetoothSco = false;
+		
+		@Override
+		public boolean equals(Object o) {
+			
+			if(o != null && o.getClass() == MediaState.class) {
+				MediaState oState = (MediaState) o;
+				if(oState.isBluetoothScoOn == isBluetoothScoOn &&
+						oState.isMicrophoneMute == isMicrophoneMute &&
+						oState.isSpeakerphoneOn == isSpeakerphoneOn &&
+						oState.canBluetoothSco == canBluetoothSco &&
+						oState.canSpeakerphoneOn == canSpeakerphoneOn &&
+						oState.canMicrophoneMute == canMicrophoneMute) {
+					return true;
+				}else {
+					return false;
+				}
+				
+			}
+			return super.equals(o);
+		}
+	}
+	
+
+	public MediaState getMediaState() {
+		MediaState mediaState = new MediaState();
+		
+		// Micro 
+		mediaState.isMicrophoneMute = userWantMicrophoneMute;
+		mediaState.canMicrophoneMute = true; /*&& !mediaState.isBluetoothScoOn*/ //Compatibility.isCompatible(5);
+		
+		// Speaker
+		mediaState.isSpeakerphoneOn = userWantSpeaker;
+		mediaState.canSpeakerphoneOn = true && !mediaState.isBluetoothScoOn; //Compatibility.isCompatible(5);
+		
+		//Bluetooth			
+		return mediaState;
+	}
+	
+	public void broadcastMediaChanged() {
+		mContext.sendBroadcast(mediaStateChangedIntent);
+	}
+	
+	private static final String ACTION_AUDIO_VOLUME_UPDATE = "org.openintents.audio.action_volume_update";
+	private static final String EXTRA_STREAM_TYPE = "org.openintents.audio.extra_stream_type";
+	private static final String EXTRA_VOLUME_INDEX = "org.openintents.audio.extra_volume_index";
+	private static final String EXTRA_RINGER_MODE = "org.openintents.audio.extra_ringer_mode";
+	private static final int EXTRA_VALUE_UNKNOWN = -9999;
+	
+	private void broadcastVolumeWillBeUpdated(int streamType, int index) {
+		Intent notificationIntent = new Intent(ACTION_AUDIO_VOLUME_UPDATE);
+		notificationIntent.putExtra(EXTRA_STREAM_TYPE, streamType);
+		notificationIntent.putExtra(EXTRA_VOLUME_INDEX, index);
+		notificationIntent.putExtra(EXTRA_RINGER_MODE, EXTRA_VALUE_UNKNOWN);
+
+		mContext.sendBroadcast(notificationIntent, null);
+	}
+	
+	public void setStreamVolume(int streamType, int index, int flags) {
+		broadcastVolumeWillBeUpdated(streamType, index);
+        audioManager.setStreamVolume(streamType, index, flags);
+	}
+	
+	public void adjustStreamVolume(int streamType, int direction, int flags) {
+		broadcastVolumeWillBeUpdated(streamType, EXTRA_VALUE_UNKNOWN);
+        audioManager.adjustStreamVolume(streamType, direction, flags);
+        
+        if(streamType == AudioManager.STREAM_RING) {
+        	// Update ringer 
+        	ringer.updateRingerMode();
+        }
+	}
+	
+	// Public accessor
+	public boolean isUserWantMicrophoneMute() {
+		return userWantMicrophoneMute;
+	}
+}

+ 113 - 0
WallPadCall/src/main/java/ceres/service/MyTCPServer.java

@@ -0,0 +1,113 @@
+package ceres.service;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class MyTCPServer {
+    private static final String TAG = "TCPServer";
+    private static int PORT = 4002;
+    private static MyTCPServer mMyTCPServer;
+
+    private TCPServerThread mServerThread;
+    private Context mContext;
+
+    private BufferedReader mInputBuffer;
+    private BufferedWriter mOutputBuffer;
+
+    private Handler mHandler;
+
+    public MyTCPServer(Context context, Handler handler) {
+        mContext = context;
+        mHandler = handler;
+        Log.d(TAG, "MyTCPServer: ");
+    }
+
+    public static MyTCPServer getInstance(Context context, Handler handler) {
+
+        Log.d(TAG, "getInstance: ");
+        if (mMyTCPServer == null) {
+            Log.d(TAG, "getInstance: 1");
+            mMyTCPServer = new MyTCPServer(context, handler);
+        }
+
+        return mMyTCPServer;
+    }
+
+    public void start() {
+        if (mServerThread == null) {
+            Log.d(TAG, "start(): ");
+            mServerThread = new TCPServerThread();
+            mServerThread.start();
+        }
+    }
+
+    class TCPServerThread extends Thread {
+        private Boolean working;
+        private ServerSocket mServerSocket;
+        private Socket client;
+        private String clientIP;
+        DataOutputStream output;
+        DataInputStream input;
+
+        public TCPServerThread() {
+            working = true;
+        }
+
+        @Override
+        public void run() {
+            Thread.currentThread().setName("MyTCPServer");
+            try {
+                //ServerSocketFactory factory = SSLServerSocketFactory.getDefault();
+                //mServerSocket = factory.createServerSocket(PORT);
+                Log.d(TAG, "TCPServerThread(): ");
+                mServerSocket = new ServerSocket(PORT);
+
+                while(working) {
+                    Log.d(TAG, "TCPServerThread(): 1");
+                    // 리스닝
+                    client = mServerSocket.accept(); // Listens for a connection to be made to this socket and accepts it.
+                    clientIP = client.getInetAddress().getHostAddress();
+
+                    mOutputBuffer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
+                    mInputBuffer = new BufferedReader(new InputStreamReader(client.getInputStream()), 10);
+
+                    String data;
+                    while (! client.isClosed()) {
+                        //Log.d(TAG, "TCPServerThread(): 2");
+                        if ((data = mInputBuffer.readLine()) != null) {
+                            Log.d(TAG, "read: " + data);
+                            if (data.equals("HEY")) {
+                                mOutputBuffer.write("ACK", 0, "ACK".length());
+                                mOutputBuffer.flush();
+                                Message msg = mHandler.obtainMessage(100, clientIP);
+                                mHandler.sendMessage(msg);
+                            }
+
+                        }
+
+                    }
+                }
+            } catch (IOException e) {
+                Log.v(TAG, "Fail TCPServer!!");
+                e.printStackTrace();
+            }
+        }
+
+        public void cancel() {
+            working = false;
+        }
+
+    }
+}

+ 187 - 0
WallPadCall/src/main/java/ceres/service/SipNotifications.java

@@ -0,0 +1,187 @@
+package ceres.service;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.net.Uri;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
+
+import ceres.api.SipManager;
+import ceres.cminterface.CMCallInfo;
+import ceres.utils.printlog;
+//import com.cnstec.widgets.RegistrationNotification;
+
+public class SipNotifications {	
+
+	private NotificationManager notificationManager;
+	private Notification inCallNotification;
+	private Context context;
+	private Notification missedCallNotification;
+	private Notification messageVoicemail;
+	
+	private static final String THIS_FILE = "SipNotifications";
+
+	public static final int REGISTER_NOTIF_ID = 1;
+	public static final int CALL_NOTIF_ID = REGISTER_NOTIF_ID + 1;
+	public static final int CALLLOG_NOTIF_ID = REGISTER_NOTIF_ID + 2;
+	public static final int MESSAGE_NOTIF_ID = REGISTER_NOTIF_ID + 3;
+	public static final int VOICEMAIL_NOTIF_ID = REGISTER_NOTIF_ID + 4;
+	
+//	static CMInterface mCMIF;
+	
+	
+	public SipNotifications(Context aContext) {
+		context = aContext;
+		notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+	}	
+
+	//Register
+	public void notifyRegisteredAccounts(int registered, String phonenum) {
+		CharSequence tickerText = "C&S: Registration";
+		String test = "C&S: Registration";
+
+		printlog.d(THIS_FILE, " notifyRegisteredAccounts....");
+
+		Intent notificationIntent = new Intent(SipManager.ACTION_SIP_DIALER);
+//		notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+		notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+		PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+		Notification.Builder mBuilder = new Notification.Builder(context)
+				.setContentTitle(test)
+				.setContentText(phonenum)
+				.setTicker(tickerText)
+				.setContentIntent(contentIntent);
+
+		notificationManager.notify(REGISTER_NOTIF_ID, mBuilder.build());
+	}
+
+	// Calls	
+	public void showNotificationForCall(CMCallInfo currentCallInfo) {
+		// This is the pending call notification		
+		int icon = android.R.drawable.stat_sys_phone_call;
+
+		String remoteUri = currentCallInfo.remoteNumber;
+
+		if(inCallNotification == null) {
+			Intent notificationIntent = new Intent(SipManager.ACTION_SIP_ON_CALL);
+			notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+			PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+			inCallNotification = new Notification.Builder(context)
+					.setSmallIcon(icon)
+					.setContentText(remoteUri)
+
+					.setContentIntent(contentIntent)
+					.setOngoing(true)
+					.setDefaults(Notification.FLAG_NO_CLEAR)
+					.build();
+		}
+
+		notificationManager.notify(CALL_NOTIF_ID, inCallNotification);
+	}
+	
+	public void showNotificationForMissedCall(ContentValues callLog) {
+		int icon = android.R.drawable.stat_notify_missed_call;
+
+		if(missedCallNotification == null) {
+
+
+			missedCallNotification = new Notification.Builder(context)
+					.setSmallIcon(icon)
+					.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
+					.setOnlyAlertOnce(true)
+					.setAutoCancel(true)
+					.build();
+		}		
+	}
+	
+	public void showNotificationForVoiceMail(CMCallInfo acc, int numberOfMessages, String voiceMailNumber) {
+		if(messageVoicemail == null) {
+			Intent notificationIntent = new Intent(Intent.ACTION_CALL);
+			notificationIntent.setData(Uri.parse(voiceMailNumber));
+			notificationIntent.putExtra("acc_id", acc.remoteNumber);
+			notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+			PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+
+			messageVoicemail = new Notification.Builder(context)
+					.setSmallIcon(android.R.drawable.stat_notify_voicemail)
+					.setContentText(acc.remoteNumber+" : "+ Integer.toString(numberOfMessages))
+					.setContentIntent(contentIntent)
+					.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
+					.setOnlyAlertOnce(true)
+					.setAutoCancel(true)
+					.build();
+		}
+
+		notificationManager.notify(VOICEMAIL_NOTIF_ID, messageVoicemail);
+	}
+	
+	public void setViewingMessageFrom(String remoteFrom) {
+		;
+	}
+	
+    protected static CharSequence buildTickerMessage(
+            Context context, String address, String body) {
+        String displayAddress = address;
+
+        StringBuilder buf = new StringBuilder(
+                displayAddress == null
+                ? ""
+                : displayAddress.replace('\n', ' ').replace('\r', ' '));
+        buf.append(':').append(' ');
+
+        int offset = buf.length();
+
+        if (!TextUtils.isEmpty(body)) {
+            body = body.replace('\n', ' ').replace('\r', ' ');
+            buf.append(body);
+        }
+
+        SpannableString spanText = new SpannableString(buf.toString());
+        spanText.setSpan(new StyleSpan(Typeface.BOLD), 0, offset,
+                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        return spanText;
+    }
+	
+	// Cancels
+	public void cancelRegisters() {
+		notificationManager.cancel(REGISTER_NOTIF_ID);
+	}
+	
+	public void cancelCalls() {
+		notificationManager.cancel(CALL_NOTIF_ID);
+	}
+	
+	public void cancelMissedCalls() {
+		notificationManager.cancel(CALLLOG_NOTIF_ID);
+	}
+	
+	public void cancelMessages() {
+		notificationManager.cancel(MESSAGE_NOTIF_ID);
+	}
+	
+	public void cancelVoicemails() {
+		notificationManager.cancel(VOICEMAIL_NOTIF_ID);
+	}
+	
+	
+	public void cancelAll() {
+		//notificationManager.cancelAll();
+		//Do not cancel calls notification since it's possible that there is still an ongoing call.
+		cancelMessages();
+		cancelMissedCalls();
+		cancelRegisters();
+		cancelVoicemails();
+	}
+
+}

+ 243 - 0
WallPadCall/src/main/java/ceres/srinterface/AvcEncoder.java

@@ -0,0 +1,243 @@
+package ceres.srinterface;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.os.Environment;
+import android.util.Log;
+
+
+import com.util.LogUtil;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+
+import kr.co.icontrols.callengine.remotecall.AVPacket;
+import kr.co.icontrols.wallpadcall.MainActivity;
+
+import static kr.co.icontrols.V40IFCCD.V40IFCCD.recvFramecallback;
+
+public class AvcEncoder {
+    //private EncodedFrameListener frameListener;
+    private MediaCodec mediaCodec;
+    private BufferedOutputStream outputStream;
+    String TAG = "AvcEncoder";
+
+    private byte[] sps;
+    private byte[] pps;
+    //private ParameterSetsListener parameterSetsListener;
+
+    public AvcEncoder() throws IOException {
+        mediaCodec = MediaCodec.createEncoderByType("video/avc");
+        /*MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
+        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
+        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
+        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
+        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
+        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        mediaCodec.start();*/
+    }
+
+    public void Init() throws IOException {
+
+//        File f = new File(Environment.getExternalStorageDirectory(), "Download/video_encoded.264");
+//        //touch (f);
+//        try {
+//            outputStream = new BufferedOutputStream(new FileOutputStream(f));
+//
+//        } catch (Exception e){
+//            e.printStackTrace();
+//        }
+        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 352, 288);
+
+        //mediaFormat.setInteger(MediaFormat.KEY_WIDTH, 320);
+        //mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, 240);
+        //mediaFormat.setInteger(MediaFormat.KEY_ROTATION, 240);
+        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
+        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
+        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
+        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
+        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        mediaCodec.start();
+
+
+    }
+
+    public void close() throws IOException {
+        mediaCodec.stop();
+        mediaCodec.release();
+    }
+
+    byte[] outData1;
+
+    public void offerEncoder1(byte[] input) {
+        try {
+            ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
+            ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
+            int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
+            if (inputBufferIndex >= 0) {
+                ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
+                inputBuffer.clear();
+                inputBuffer.put(input);
+                mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
+            }
+
+            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+            int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);
+            while (outputBufferIndex >= 0) {
+                ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
+                byte[] outData = new byte[bufferInfo.size];
+                outputBuffer.get(outData);
+                //outputStream.write(outData, 0, outData.length);
+                //Log.i("AvcEncoder", outData.length + " bytes written");
+/*
+                if (sps == null && pps == null) {
+                    ByteBuffer spsPpsBuffer = ByteBuffer.wrap(outData);
+                    if (spsPpsBuffer.getInt() == 0x00000001) {
+                        System.out.println("parsing sps/pps");
+                    } else {
+                        System.out.println("something is amiss?");
+                    }
+                    int ppsIndex = 0;
+                    //while(!(spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x00 && spsPpsBuffer.get() == 0x01)) {
+
+                    //}
+                    ppsIndex = spsPpsBuffer.position();
+                    sps = new byte[ppsIndex - 8];
+                    System.arraycopy(outData, 4, sps, 0, sps.length);
+                    pps = new byte[outData.length - ppsIndex];
+                    System.arraycopy(outData, ppsIndex, pps, 0, pps.length);
+                }
+*/
+                /*
+                for(int i = 0; i < 10; i++)
+                {
+                    Log.d("KSJ", i + " " + String.format("%02x", outData[i]&0xff));
+                    //str += i + " "+String.format("%02x", outData[i]&0xff) + " ";
+                }*/
+
+                //Log.d("KSJ", " " + String.format("%02x", outData[4]&0xff));
+                if(String.format("%02x", outData[4]&0xff).equals("41"))
+                {
+
+
+
+
+                    //outData[4] = 0x67;
+                    //Log.d("Dialer_KSJ", "[writeHNSRTPPacket] Start " + outData.length + " true " + String.format("%02x", outData[4]&0xff));
+                    //Log.d("Dialer_KSJ", "offerEncoder1 " + outData.length);
+                    //MainActivity.mCallController.mVideoJNI.mV40IFCCD.recvFramecallback(outData, 0, outData.length, outData.length, 0);
+                    //MainActivity.mCallController.mVideoJNI.sendDataToDecoder(outData,0,outData.length,0);
+                    //if (MainActivity.mDataSender != null)
+                        sendVideoToMobile(outData, outData.length, isH264iFrame(outData, outData.length));
+
+                    //recvFramecallback(outData, 0, 320, outData.length, 0);
+                }
+                else if(String.format("%02x", outData[4]&0xff).equals("67"))
+                {
+                    sps = new byte[outData.length];
+                    outData1 = new byte[outData.length];
+                    for(int i = 0; i < outData.length; i++)
+                    {
+                        //Log.d("KSJ", i + " " + String.format("%02x", outData[i]&0xff));
+                        sps[i] = outData[i];
+                        outData1[i] = outData[i];
+                        //str += i + " "+String.format("%02x", outData[i]&0xff) + " ";
+                    }
+
+                    //Log.d("Dialer_KSJ", "offerEncoder2 " + outData.length);
+                    //DatagramPacket packet = new DatagramPacket(outData, outData.length, targetAddr, 50061);
+                    //packet = new DatagramPacket(buf, buf.length, ina, 50061);
+
+                    //Dialer.setDecode_buf(outData);
+                    //mSocket.send(packet);
+                }
+                else {
+                    //Log.d("Dialer_KSJ", "[writeHNSRTPPacket] Start " + outData.length + " false " + String.format("%02x", outData[4] & 0xff));
+                    byte[] bIframe = new byte[sps.length+outData.length];
+
+                    System.arraycopy(sps, 0, bIframe, 0, sps.length);
+                    System.arraycopy(outData, 0, bIframe, sps.length, outData.length);
+
+                    /*for(int i = 0; i < Dialer.m_byteTest.length; i++)
+                    {
+                        Log.d("Dialer_KSJ", i + " " + String.format("%02x", Dialer.m_byteTest[i]&0xff));
+
+                    }*/
+                    //MainActivity.mCallController.mVideoJNI.mV40IFCCD.recvFramecallback(sps, 1, sps.length, sps.length, 0);
+                    //MainActivity.mCallController.mVideoJNI.mV40IFCCD.recvFramecallback(bIframe, 1, bIframe.length, bIframe.length, 0);
+                    //if (MainActivity.mDataSender != null)
+                        sendVideoToMobile(bIframe, bIframe.length, isH264iFrame(bIframe, bIframe.length));
+                    //MainActivity.mCallController.mVideoJNI.sendDataToDecoder(bIframe,0,bIframe.length,0);
+                    //Dialer.setDecode_buf(bIframe);
+
+                    //recvFramecallback(bIframe, 1, 320, bIframe.length, 0);
+                }
+
+                mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
+                outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
+
+            }
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+
+    }
+
+    public int isH264iFrame(byte[] data, int size) {
+//            Log.d(TAG, "[isH264iFrame] data [" + Global.HexToString(data) + "], size [" + size + "]");
+        int index = 0;
+        for (; index + 3 < size; index++) {
+            // This should always succeed in the first iteration.
+            if (data[index] == 0 && data[index + 1] == 0 && data[index + 2] == 1)
+                break;
+        }
+
+        if (index + 3 >= size) return 0;
+        index += 3;
+
+        int nalType = data[index] & 0x1F;
+        if (nalType == 0x05 || nalType == 0x07 || nalType == 0x08)
+            return 1;
+
+        return 2;
+    }
+
+    public void sendVideoToMobile(byte[] data, int size, int IFrame) {
+        try {
+//            Log.d(TAG, "[sendVideoToMobile] data.length [" + data.length + "], size [" + size + "], IFrame [" + IFrame + "]");
+
+                AVPacket avp = new AVPacket();
+                avp.avType = 0; // 0:video, 1:audio
+                avp.data = data;
+                avp.length = size;
+                avp.frameType = IFrame;
+                try {
+//                    Log.d(TAG, "[sendVideoToMobile] mDataSender.que.put()");
+//                    Log.d(TAG, "[sendVideoToMobile] avp.length [" + avp.length + "]");
+                    if (avp != null) MainActivity.mDataSender.blockingQueue.put(avp);
+                } catch (InterruptedException e) {
+                    Log.e(TAG, "[InterruptedException] sendVideoToMobile(byte[] data, int size)");
+                    //e.printStackTrace();
+                    LogUtil.errorLogInfo("", TAG, e);
+                }
+//            if (MainActivity.mDataSender != null) {
+//            } else {
+//                Log.w(TAG, "[sendVideoToMobile] mDataSender is null!!");
+//            }
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] sendVideoToMobile(byte[] data)");
+            //e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+}

+ 285 - 0
WallPadCall/src/main/java/ceres/srinterface/MediaDecoder.java

@@ -0,0 +1,285 @@
+package ceres.srinterface;
+
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+import android.view.Surface;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import kr.co.icontrols.wallpadcall.MainActivity;
+
+import static android.media.MediaFormat.MIMETYPE_VIDEO_H263;
+
+public class MediaDecoder {
+
+    Worker mWorker;
+
+    volatile boolean mRunning;
+    MediaCodec mCodec;
+    volatile boolean mConfigured;
+    long mTimeoutUs;
+
+    public void decodeSample(byte[] data, int offset, int size, long presentationTimeUs, int flags) {
+
+//        if (mConfigured && mRunning) {
+//            //Log.d("KSJ_media","decodeSample1");
+////                try {
+////                    outputStream.write(data, 0, size);
+////                } catch (Throwable t) {
+////                    t.printStackTrace();
+////                }
+//
+//            int index = mCodec.dequeueInputBuffer(mTimeoutUs);
+//            if (index >= 0) {
+//                ByteBuffer buffer;
+//
+//                // since API 21 we have new API to use
+//                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+//                    buffer = mCodec.getInputBuffers()[index];
+//                    buffer.clear();
+//                } else {
+//                    buffer = mCodec.getInputBuffer(index);
+//                }
+//                if (buffer != null) {
+//                    buffer.put(data, offset, size);
+//                    mCodec.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
+//                }
+//            }
+//
+//            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+//
+//            //ByteBuffer[] outputBuffers = mCodec.getOutputBuffers();
+//            int outputBufferIndex = mCodec.dequeueOutputBuffer(info, mTimeoutUs);
+//            while (outputBufferIndex >= 0) {
+//
+//                ByteBuffer[] outputBuffers = mCodec.getOutputBuffers();
+//                ByteBuffer outputBuffer = outputBuffers[index];
+//                byte[] outData = new byte[info.size];
+//                outputBuffer.get(outData);
+//
+//                SRInterface.MediaCodec_buf(outData, outData.length);
+//
+//                mCodec.releaseOutputBuffer(outputBufferIndex, false);
+//                outputBufferIndex = mCodec.dequeueOutputBuffer(info, mTimeoutUs);
+//            }
+//
+//
+//        }
+
+        if (mWorker != null) {
+            mWorker.decodeSample(data, offset, size, presentationTimeUs, flags);
+        }
+    }
+
+    public void configure(int width, int height) {
+        if (mWorker != null) {
+            mWorker.configure(width, height);
+        }
+//
+//        Log.d("KSJ_media","configure");
+//        if (mConfigured) {
+//            throw new IllegalStateException("Decoder is already configured");
+//        }
+//        Log.d("KSJ_media","configure1");
+//        MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_H263, width, height);
+//        // little tricky here, csd-0 is required in order to configure the codec properly
+//        // it is basically the first sample from encoder with flag: BUFFER_FLAG_CODEC_CONFIG
+//        //format.setByteBuffer("csd-0", csd0);]
+//
+//        format.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
+//        format.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
+//        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYCrYCb);
+//        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
+//        Log.d("KSJ_media","configure2");
+//        try {
+//            mCodec = MediaCodec.createDecoderByType(MIMETYPE_VIDEO_H263);
+//        } catch (IOException e) {
+//            throw new RuntimeException("Failed to create codec", e);
+//        }
+//        Log.d("KSJ_media","configure3");
+//        mCodec.configure(format, null, null, 0);
+//        mCodec.start();
+//        mConfigured = true;
+    }
+
+    public void start() {
+//        mRunning = true;
+//        mTimeoutUs = 10000l;
+        if (mWorker == null) {
+            Log.d("KSJ_media","start");
+            mWorker = new Worker();
+            mWorker.setRunning(true);
+            mWorker.start();
+        }
+    }
+
+    public void stop() {
+//        if (mConfigured) {
+//            mRunning = false;
+//            mConfigured = false;
+//            mCodec.stop();
+//            mCodec.release();
+//        }
+        if (mWorker != null) {
+            Log.d("KSJ_media","stop");
+            mWorker.setRunning(false);
+            mWorker = null;
+        }
+    }
+
+    public void video_capture(boolean bSet)
+    {
+        if (mWorker != null) {
+            Log.d("KSJ_media","video_capture");
+            //mWorker.setPath(strPath);
+            mWorker.setCapture(bSet);
+        }
+    }
+
+    class Worker extends Thread {
+
+        volatile boolean mRunning;
+        MediaCodec mCodec;
+        volatile boolean mConfigured;
+        long mTimeoutUs;
+        volatile String m_strPATH = "";
+        volatile boolean m_bCapture = false;
+        Surface m_Surface;
+        //private BufferedOutputStream outputStream;
+
+        public Worker() {
+            mTimeoutUs = 0;
+        }
+
+        public void setRunning(boolean running) {
+            mRunning = running;
+        }
+
+        public void setPath(String strPath) {
+            m_strPATH = strPath;
+        }
+
+        public void setCapture(boolean bCapture) {
+            m_bCapture = bCapture;
+        }
+
+        public void configure(int width, int height) {
+            Log.d("KSJ_media","configure");
+            if (mConfigured) {
+                throw new IllegalStateException("Decoder is already configured");
+            }
+            Log.d("KSJ_media","configure1");
+            MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_H263, width, height);
+            // little tricky here, csd-0 is required in order to configure the codec properly
+            // it is basically the first sample from encoder with flag: BUFFER_FLAG_CODEC_CONFIG
+            //format.setByteBuffer("csd-0", csd0);]
+
+//            format.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
+//            format.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
+//            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYCrYCb);
+//            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
+            Log.d("KSJ_media","configure2");
+            try {
+                mCodec = MediaCodec.createDecoderByType(MIMETYPE_VIDEO_H263);
+            } catch (IOException e) {
+                throw new RuntimeException("Failed to create codec", e);
+            }
+            Log.d("KSJ_media","configure3");
+            mCodec.configure(format, null, null, 0);
+            //m_Surface = surface;
+            mCodec.start();
+            mConfigured = true;
+
+            Log.d("KSJ_media","configure4");
+            //File f = new File(Environment.getExternalStorageDirectory(), "Download/video_encoded.264");
+            //touch (f);
+//            try {
+//                outputStream = new BufferedOutputStream(new FileOutputStream(f));
+//
+//            } catch (Exception e){
+//                e.printStackTrace();
+//            }
+        }
+
+        @SuppressWarnings("deprecation")
+        public void decodeSample(byte[] data, int offset, int size, long presentationTimeUs, int flags) {
+            //Log.d("KSJ_media","decodeSample");
+            //if (mConfigured && mRunning && !m_bCapture) {
+            if (mConfigured && mRunning) {
+                //Log.d("KSJ_media","decodeSample1");
+//                try {
+//                    outputStream.write(data, 0, size);
+//                } catch (Throwable t) {
+//                    t.printStackTrace();
+//                }
+
+                int index = mCodec.dequeueInputBuffer(mTimeoutUs);
+                if (index >= 0) {
+                    ByteBuffer buffer;
+
+                    // since API 21 we have new API to use
+                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+                        buffer = mCodec.getInputBuffers()[index];
+                        buffer.clear();
+                    } else {
+                        buffer = mCodec.getInputBuffer(index);
+                    }
+                    if (buffer != null) {
+                        buffer.put(data, offset, size);
+                        mCodec.queueInputBuffer(index, 0, size, presentationTimeUs, flags);
+
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void run() {
+            try {
+                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+                while (mRunning) {
+                    if (mConfigured) {
+                        //ByteBuffer[] outputBuffers = mCodec.getOutputBuffers();
+                        int index = mCodec.dequeueOutputBuffer(info, mTimeoutUs);
+                        if (index >= 0) {
+
+                            //Log.d("KSJ_media", "info.size : " +  info.size);
+                            ByteBuffer[] outputBuffers = mCodec.getOutputBuffers();
+                            ByteBuffer outputBuffer = outputBuffers[index];
+                            byte[] outData = new byte[info.size];
+                            outputBuffer.get(outData);
+
+                            //MainActivity.mCallController.mVideoJNI.sendDataToDecoder(outData,0,outData.length,0);
+
+                            SRInterface.MediaCodec_buf(outData, outData.length);
+                            // setting true is telling system to render frame onto Surface
+                            mCodec.releaseOutputBuffer(index, true);
+
+                            if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == MediaCodec.BUFFER_FLAG_END_OF_STREAM) {
+
+                                break;
+                            }
+                        }
+                    } else {
+                        // just waiting to be configured, then decode and render
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                e.fillInStackTrace();
+            }
+            finally
+            {
+                if (mConfigured) {
+                    mCodec.stop();
+                    mCodec.release();
+                }
+            }
+        }
+    }
+
+}

+ 1414 - 0
WallPadCall/src/main/java/ceres/srinterface/SRInterface.java

@@ -0,0 +1,1414 @@
+package ceres.srinterface;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ImageFormat;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.hardware.Camera;
+import android.hardware.Camera.ErrorCallback;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.WindowManager;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import ceres.api.SipManager;
+import ceres.cminterface.CMInterface;
+import ceres.utils.printlog;
+import kr.co.icontrols.wallpadcall.MainActivity;
+import kr.co.icontrols.wallpadcall.declare.Global;
+
+public class SRInterface {
+	
+	private static final String THIS_FILE = "SRInterface";
+	private Camera m_Camera;
+	private static Bitmap m_Bitmap = null;
+	private static int[] m_BMPBUF = null;
+	
+	private static int CameraID = 1; // yjyoon. default = 1, F2에서는 0으로 변경
+	private CMInterface mCMIF = null;
+		
+	private static VideoSize DefaultDisplay =  new VideoSize(0, 0);
+	private static VideoSize scaleSize = new VideoSize(0, 0);
+	private static float scale;
+	private static int scaleDpi;
+	private static String m_strFilePath = "";
+	private static boolean m_bCameraPic = false;
+	private static boolean m_bCameraEnc = false;
+	private static int m_iCameraEnc = 0;
+
+	static MediaDecoder m_MediaDecoder;
+	
+	native void SRIF_Initialize();
+	
+	public SRInterface(){
+		printlog.d(THIS_FILE, "SRInterface Constructor is called... ");		
+	}
+
+	static AvcEncoder mAVcEncoder;
+
+	public SRInterface(Context context){
+		printlog.d(THIS_FILE, "SRInterface Constructor is called... ");
+		SRIF_Initialize();
+		
+		if(mCMIF == null){
+			mCMIF = new CMInterface();
+		}
+		
+		Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+
+		Point size =new Point();
+		display.getSize(size);
+
+		DefaultDisplay.width = size.x;
+		DefaultDisplay.height = size.y;
+		
+		printlog.d(THIS_FILE, "displayInfo.displayWidth : " + DefaultDisplay.width);
+		printlog.d(THIS_FILE, "displayInfo.displayHeight : " + DefaultDisplay.height);
+		
+		/*if(DefaultDisplay.width > DefaultDisplay.height) {
+			DefaultDisplay.width = DefaultDisplay.height;
+		}*/
+		
+		if(DefaultDisplay.width == 720 ) {
+			scaleSize.width = DefaultDisplay.width;
+			scaleSize.height = 960;
+		}
+		else if(DefaultDisplay.width == 480 ) {
+			scaleSize.width = DefaultDisplay.width;
+			scaleSize.height = 640;
+		}
+		else{
+			scaleSize.width = DefaultDisplay.width;
+			scaleSize.height = DefaultDisplay.height;
+		}
+				
+		scale = context.getResources().getDisplayMetrics().density;
+		scaleDpi = context.getResources().getDisplayMetrics().densityDpi;
+		
+		printlog.i(THIS_FILE, "displayInfo.scale : " + scale);
+		printlog.i(THIS_FILE, "displayInfo.scaleDpi : " + scaleDpi);
+
+		SRIF_VSIZE_set("1");
+
+//		m_MediaDecoder = new MediaDecoder();
+//
+//		try {
+//			mAVcEncoder = new AvcEncoder();
+//			mAVcEncoder.Init();
+//		}
+//		catch (Exception ex)
+//		{
+//			Log.e("KSJ", "AvcEncoder init error1");
+//		}
+
+
+
+
+	}
+
+
+	public VideoSize SRIF_DefaultDisplay_get() {
+		return DefaultDisplay;
+	}
+	
+	public int SRIF_DensityDpi_get() {
+		return scaleDpi;
+	}
+	
+	public void SRIF_CameraID_set(int cameraId) {
+		CameraID = cameraId;		
+		stopVideoRecording();		
+	}
+	
+	public int SRIF_CameraID_get() {
+		return CameraID;
+	}
+	
+	// ---------------------------------------------------------
+	// Encoding(Preview) SurfaceView
+	// Recording is show preview and encoding..
+	// ---------------------------------------------------------
+	public final void setEncodingView(final SurfaceView sv) {
+		SRIF_VSIZE_set("1");
+		SurfaceHolder holder = sv.getHolder();
+	    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+	    holder.setKeepScreenOn(true);
+		holder.addCallback(new Callback() {
+			
+			public void surfaceDestroyed(SurfaceHolder holder) {
+				printlog.i(THIS_FILE , "surfaceDestroyed...");				
+				stopVideoRecording();											
+			}
+
+			public void surfaceCreated(SurfaceHolder holder) {
+				printlog.i(THIS_FILE , "surfaceCreated changed... Encoding...");
+				tryToStartVideoRecording(holder);
+			}
+
+			public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+				printlog.i(THIS_FILE , "surfaceChanged changed... Encoding...");
+			}
+		});
+	}
+	
+	
+	// ---------------------------------------------------------
+	// Decoding(Render) SurfaceView
+	// ---------------------------------------------------------
+	public static SurfaceView m_DecodingView = null;
+
+	// -----------------------------------------
+	// Width > Height
+	// 
+	// ---------------------------
+	// |                         |
+	// |                         |
+	// |                         |
+	// |                         |
+	// |                         |
+	// |                         |
+	// |                         |
+	// ---------------------------
+	//
+	// -----------------------------------------	
+	public static VideoSize vsize = new VideoSize(0, 0);
+
+	
+	
+	public void SRIF_VideoSize_set(int width, int height) {
+		vsize.width = width;		
+		vsize.height = height;		
+	}
+	
+	public VideoSize SRIF_VideoSize_get() {
+		return vsize;
+	}
+	
+	public static final class VideoSize {		
+
+		public int width;
+		public int height;
+
+		public VideoSize() {}
+		public VideoSize(int width, int height) {
+			this.width = width;
+			this.height = height;
+		}
+	}
+	
+	public static void SRIF_VSIZE_set(String videoSize) {
+		
+		printlog.d(THIS_FILE, "videoSize : " + videoSize);
+		
+		if(vsize.width == 0){
+			if(videoSize.equals(SipManager.VIDEO_SIZE_QCIF)) {			
+				vsize.width = SipManager.VIDEO_SIZE_QCIF_W;
+				vsize.height = SipManager.VIDEO_SIZE_QCIF_H;
+			}
+			else if(videoSize.equals(SipManager.VIDEO_SIZE_CIF)) {			
+				vsize.width = SipManager.VIDEO_SIZE_CIF_W;
+				vsize.height = SipManager.VIDEO_SIZE_CIF_H;
+			}
+			else if(videoSize.equals(SipManager.VIDEO_SIZE_QVGA)) {			
+				vsize.width = SipManager.VIDEO_SIZE_QCIF_W;
+				vsize.height = SipManager.VIDEO_SIZE_QCIF_H;
+			}
+			else if(videoSize.equals(SipManager.VIDEO_SIZE_VGA)) {			
+				vsize.width = SipManager.VIDEO_SIZE_VGA_W;
+				vsize.height = SipManager.VIDEO_SIZE_VGA_H;
+			}
+			else
+				printlog.e(THIS_FILE, " Not supported vsize...");
+		}
+		else
+			printlog.e(THIS_FILE, " Already set vsize...");
+		
+		return;
+	}
+		
+	public final void setDecodingView(final SurfaceView sv) {
+		
+		printlog.e(THIS_FILE, "setRenderSurfaceView is called... : ");
+
+		SRIF_VSIZE_set("1");
+
+		if(m_Bitmap == null){
+			
+			printlog.e(THIS_FILE, "dddd m_Bitmap is null setDecodingView width " + vsize.width +" height " + vsize.height);
+			
+			m_Bitmap = Bitmap.createBitmap(vsize.height,vsize.width, Bitmap.Config.ARGB_8888);
+			m_BMPBUF = new int[SipManager.VIDEO_MAX_SIZE.width * SipManager.VIDEO_MAX_SIZE.width];
+		}
+
+		if(m_DecodingView == null){
+			m_DecodingView = sv;
+			//m_MediaDecoder.start();
+			//m_MediaDecoder.configure(m_DecodingView.getHolder().getSurface(), 352, 288);
+
+
+		}
+	}
+	
+	public static void jOpenCapture(int videoSize)
+	{
+		printlog.d(THIS_FILE, "bbbb jOpenCapture is called... : " + videoSize);
+		
+		SRIF_VSIZE_set(Integer.toString(videoSize));
+
+		if(m_Bitmap == null){
+
+			printlog.e(THIS_FILE, "dddd m_Bitmap is null jOpenCapture");
+
+			m_Bitmap = Bitmap.createBitmap(vsize.height,vsize.width, Bitmap.Config.ARGB_8888);
+			m_BMPBUF = new int[SipManager.VIDEO_MAX_SIZE.width * SipManager.VIDEO_MAX_SIZE.width];
+			//Log.v("yjyoon3", "jOpenCapture m_BMPBUF.length = " + m_BMPBUF.length);
+		}
+
+		m_cRecordBUF = 4;
+		m_RecordBUF = new byte[m_cRecordBUF][((vsize.width * vsize.height) * 3 / 2)];
+	}
+
+	public static void jCloseCapture(int i)
+	{
+		printlog.d(THIS_FILE, "bbbb jCloseCapture is called...");
+		vsize.width = 0;
+		m_DecodingView = null;
+		m_Bitmap = null;
+	}
+
+	// YUV420SP raw data transfer..
+	public static int jCaptureVideoData(byte buf[], int size)
+	{	
+		int sizeRead = -1;
+
+		if( 0 < ( ( ( m_iwRecordBUF + m_cRecordBUF ) - m_irRecordBUF ) % m_cRecordBUF ) )
+		{
+			sizeRead = ((vsize.width * vsize.height) * 3 / 2);		
+	
+			decodeYUV420P2(buf, m_RecordBUF[m_irRecordBUF], vsize.width, vsize.height );
+			m_irRecordBUF = ( m_irRecordBUF + 1 ) % m_cRecordBUF;
+		}
+
+		return sizeRead;
+	}
+
+	public static void jOpenDisplay(int videoSize)
+	{			
+		SRIF_VSIZE_set(Integer.toString(videoSize));
+		
+		android.os.Process.setThreadPriority(
+                android.os.Process.THREAD_PRIORITY_DISPLAY);
+		
+		if (m_Bitmap == null) {
+            try {                
+                printlog.e(THIS_FILE, String.format("dddd m_Bitmap is null jOpenDisplay vsize.height=%d, vsize.width=%d", vsize.height, vsize.width));
+
+                m_Bitmap = Bitmap.createBitmap(vsize.height,vsize.width, Bitmap.Config.ARGB_8888);
+                m_BMPBUF = new int[SipManager.VIDEO_MAX_SIZE.width * SipManager.VIDEO_MAX_SIZE.width];
+
+				//MainActivity.mCallController.mVideoJNI.setComposite(true);
+				//MainActivity.mCallController.mVideoJNI.decoderStartOperation();
+            }
+            catch (Exception e) {
+            }
+        }
+
+//		m_MediaDecoder.start();
+//		m_MediaDecoder.configure(352, 288);
+//
+
+
+
+		try {
+
+			MainActivity.mCallController.mVideoJNI.setComposite(true);
+			MainActivity.mCallController.mVideoJNI.decoderStartOperation();
+		}
+		catch (Exception e) {
+		}
+
+		try {
+			mAVcEncoder = new AvcEncoder();
+			mAVcEncoder.Init();
+		}
+		catch (Exception ex)
+		{
+			Log.e("KSJ", "AvcEncoder init error1");
+		}
+
+
+	}
+
+	public static void jCloseDisplay(int i)
+	{
+		//printlog.d(THIS_FILE, "bbbb jCloseDisplay is called...");
+		MainActivity.mCallController.mVideoJNI.decoderStopOperation();
+
+		vsize.width = 0;
+		m_DecodingView = null;
+		m_Bitmap = null;
+
+//		m_MediaDecoder.stop();
+		try {
+
+			mAVcEncoder.close();
+		}
+		catch (Exception ex)
+		{
+			Log.e("KSJ", "AvcEncoder init error1");
+		}
+	}
+	// size ????? 
+	
+	private static long st2 = 0, et2 = 0, fc = 0;
+	
+	// Ui handler
+	public static Handler handler = new Handler() {
+		public void handleMessage(Message msg) {
+			switch (msg.what) {
+			case 0:
+				printlog.i(THIS_FILE, "dt 1sec frame count : " + fc);
+				fc = 0;
+				break;
+			default:
+				super.handleMessage(msg);
+			}
+		}
+	};
+	
+	private Handler mHandler = new Handler();
+	private myThread mThread;
+	private static boolean fps_fg = false;
+	
+	public void SRIF_FPS_Check(int start)
+	{
+		if(start == 1){
+			ThreadStart();			
+			fps_fg = true;
+		}
+		else {
+			ThreadStop();
+			fps_fg = false;
+		}
+		fc = 0;
+	}
+	
+	public boolean SRIF_FPS_Stats_get(){
+		return fps_fg;
+	}
+	
+	private void ThreadStart(){
+		if(mThread == null){
+        	mThread = new myThread(true);
+	        mThread.start();	        
+        }
+	}
+	
+	private void ThreadStop(){    	
+    	if(mThread != null){
+			mThread.stopThread();
+			mThread = null;
+		}    	    
+    }
+	
+	public static OnCallbackListener onVideoStatsCBListener;
+	
+	public interface OnCallbackListener {		
+		void OnFPSChanged(long fps);					
+	}
+	
+	public void setOnVideoStatsCBListener(OnCallbackListener listener) {
+		onVideoStatsCBListener = listener;
+	}
+	
+	private void dispatchVideoStatsCBEvent(long fps) {
+		if (onVideoStatsCBListener != null) {
+			onVideoStatsCBListener.OnFPSChanged(fps);
+		}
+	}
+
+	class myThread extends Thread {
+
+		private boolean isPlay = false;
+
+		public myThread(boolean isPlay){
+			this.isPlay = isPlay;
+		}
+
+		public void stopThread(){
+			isPlay = !isPlay;
+		}
+		
+		public boolean isPlayThread(){
+			return isPlay;
+		}
+		
+		@Override
+		public void run() {
+			super.run();
+			while (isPlay) {
+				
+				try {					
+					Thread.sleep(1000);
+				} catch (InterruptedException e) {
+					printlog.e(THIS_FILE, "myThread, Run, Thread.sleep : Error.");
+					e.printStackTrace();
+				}
+				
+				mHandler.post(new Runnable() {
+					@Override
+					public void run() {
+						dispatchVideoStatsCBEvent(fc);
+						printlog.i(THIS_FILE, "dt fc : " + fc);
+						fc = 0;
+					}
+				}); // mHandler.post(new Runnable()
+				
+			}// while
+		}// run
+	}// myThread
+
+	public static byte[] integersToBytes(int[] values) throws IOException {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		DataOutputStream dos = new DataOutputStream(baos);
+		for(int i=0; i < values.length; ++i)
+		{
+			dos.writeInt(values[i]);
+		}
+
+		return baos.toByteArray();
+	}
+
+	public static void SaveBitmapToJPG(Bitmap bitmap, String strFilePath, String filename) {
+
+		File file = new File(strFilePath);
+
+		if (!file.exists()) {
+			file.mkdirs();
+		}
+
+		File fileItem = new File(strFilePath + filename);
+		OutputStream outStream = null;
+
+		try {
+			fileItem.createNewFile();
+			outStream = new FileOutputStream(fileItem);
+
+			bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				outStream.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+
+
+	public static void MediaCodec_buf(byte[] buf, int len)
+	{
+		//printlog.e("KSJ_media", "MediaCodec_buf START vsize.width " + scaleSize.width + " vsize.height " + scaleSize.height);
+
+		//byte[] test =  new byte[152064];
+
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		YuvImage yuv = new YuvImage(buf, ImageFormat.NV21, 352, 288, null);
+//
+		yuv.compressToJpeg(new Rect(0, 0, 320, 240), 80, out);
+
+
+		Bitmap image = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.toByteArray().length);
+		Bitmap resizedImage = Bitmap.createScaledBitmap(image, 320, 240, false);
+
+		byte[] arr1 = getNV21(320,240,resizedImage);
+
+		Log.d(THIS_FILE, ""+arr1.length);
+
+		//mAVcEncoder.offerEncoder1(arr1);
+
+		//SaveBitmapToJPG(resizedImage, "/sdcard/", "test2211.jpg");
+
+		//MainActivity.mCallController.mVideoJNI.sendDataToDecoder(arr1,0,arr1.length,0);
+//		MainActivity.mCallController.mVideoJNI.sendDataToDecoder(buf,0,len,0);
+//		try {
+//
+//			//m_MediaDecoder.video_capture(true);
+//			ByteArrayOutputStream out = new ByteArrayOutputStream();
+//
+//
+//			//byte[] buff = YV12toNV21(buf, vsize.width, vsize.height);
+//
+//			//byte[] buff1 = YV12toNV21(buff, vsize.width, vsize.height);
+//
+//			//decodeYUV420P2(buf, buf1, vsize.width, vsize.height );
+//			decodeYUV420P( m_BMPBUF, buf, vsize.width, vsize.height );
+//
+//			//byte[] test1 = integersToBytes(m_BMPBUF);
+//			//MainActivity.mCallController.mVideoJNI.sendDataToDecoder(test1,0,test1.length,0);
+//			//YuvImage yuv = new YuvImage(buf, ImageFormat.NV21, vsize.width, vsize.height, null);
+//			//yuv.compressToJpeg(new Rect(0, 0, vsize.width, vsize.height), 80, out);
+//
+//			//Bitmap image = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.toByteArray().length);
+//			//Bitmap image = Bitmap.createBitmap(vsize.height,vsize.width,Bitmap.Config.ARGB_8888);
+//
+//			//image.setPixels(m_BMPBUF, 0, vsize.height, 0, 0, vsize.height, vsize.width);
+//
+//			Bitmap image = Bitmap.createBitmap(vsize.width,vsize.height, Bitmap.Config.ARGB_8888);
+//			//Bitmap image1 = Bitmap.createBitmap(320,240, Bitmap.Config.ARGB_8888);
+//
+//			image.setPixels(m_BMPBUF, 0, vsize.width, 0, 0, vsize.width, vsize.height);
+//			//image1.setPixels(m_BMPBUF, 0, 320, 0, 0, 320, 240);
+//			//Bitmap image = Bitmap.createBitmap(vsize.width,vsize.height,Bitmap.Config.ARGB_8888);
+//
+//			//image.setPixels(m_BMPBUF, 0, vsize.width, 0, 0, vsize.width, vsize.height);
+//
+//			//Matrix rotateMatrix = new Matrix();
+//			//rotateMatrix.postRotate(270);
+//
+//			//Bitmap sideInversionImg = Bitmap.createBitmap(image, 0, 0,
+//			//		image.getWidth(), image.getHeight(), rotateMatrix, false);
+//
+//			if(m_bCameraPic) {
+//				File fileCacheItem = new File(m_strFilePath);
+//				OutputStream out1 = null;
+//				out1 = new FileOutputStream(fileCacheItem);
+//				image.compress(Bitmap.CompressFormat.JPEG, 100, out1);
+//				out1.close();
+//
+//				m_bCameraPic = false;
+//			}
+//			SurfaceHolder holder = m_DecodingView.getHolder();
+//
+//			Surface sf = holder.getSurface();
+//
+//			Rect rcBMP, rcWND;
+//			Paint testPaint;
+//
+//			//rcBMP = new Rect(0, 0, vsize.height, vsize.width);
+//			rcBMP = new Rect(0, 0, vsize.width, vsize.height);
+//			rcWND = new Rect(0, 0, m_DecodingView.getWidth(), m_DecodingView.getHeight());
+//			//rcWND = new Rect(0, 0, 720, 540);
+//			// 720 x 960
+//			// 480 x 640
+//			testPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+//
+//			Canvas canvas = sf.lockCanvas(null);
+//			canvas.drawBitmap(image, rcBMP, rcWND, testPaint);
+//
+//			sf.unlockCanvasAndPost(canvas);
+////
+////			//et = SystemClock.currentThreadTimeMillis();
+////
+////			fc++;
+//
+//			//printlog.d(THIS_FILE, "dt : " + String.format("%,d msec", et - st) );
+//		} catch (IllegalArgumentException e) {
+//			// TODO Auto-generated catch block
+//			printlog.e(THIS_FILE, "jDisplayVideoData Error1");
+//			e.printStackTrace();
+//		} catch (OutOfResourcesException e) {
+//			// TODO Auto-generated catch block
+//			printlog.e(THIS_FILE, "jDisplayVideoData Error2");
+//			e.printStackTrace();
+//		}
+//		catch (NullPointerException e) {
+//			// TODO Auto-generated catch block
+//			printlog.e(THIS_FILE, "jDisplayVideoData Error3");
+//			e.printStackTrace();
+//		}
+//		catch (Exception e) { e.printStackTrace(); }
+
+		//m_MediaDecoder.video_capture(false);
+		//printlog.e("KSJ_media", "MediaCodec_buf END");
+	}
+
+	public static int jDisplayVideoData(byte buf[], int size)
+	{
+
+		//printlog.e(THIS_FILE, "jDisplayVideoData len " + size);
+		//if(size < 3000)
+		MainActivity.mCallController.mVideoJNI.sendDataToDecoder(buf,0,size,0);
+
+
+//		bSetEncoder = true;
+		//MainActivity.mCallController.mVideoJNI.getDecodedata();
+
+//		ByteArrayOutputStream out = new ByteArrayOutputStream();
+//		YuvImage yuv = new YuvImage(MainActivity.mCallController.mVideoJNI.getDecodedata(), ImageFormat.NV21, 352, 288, null);
+////
+//		yuv.compressToJpeg(new Rect(0, 0, 320, 240), 80, out);
+//
+//
+//		Bitmap image = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.toByteArray().length);
+//		Bitmap resizedImage = Bitmap.createScaledBitmap(image, 320, 240, false);
+//
+//		byte[] arr1 = getNV21(320,240,resizedImage);
+		//Bitmap image = BitmapFactory.decodeByteArray(MainActivity.mCallController.mVideoJNI.getDecodedata(), 0, MainActivity.mCallController.mVideoJNI.getDecodedata().length);
+		//byte[] arr1 = getNV21(352,288,image);
+
+		if(Global.ConfigValues.bRemoteCall) {
+			byte[] yuv = new byte[352 * 288 * 3 / 2];
+			yuv = YV12toNV21(MainActivity.mCallController.mVideoJNI.getDecodedata(), 352, 288);
+
+			//mAVcEncoder.offerEncoder1(MainActivity.mCallController.mVideoJNI.getDecodedata());
+			mAVcEncoder.offerEncoder1(yuv);
+
+			try {
+				Thread.sleep(20);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+		}
+
+
+		//if(size < 1000)
+//		if(m_bCameraPic)
+//		{
+//			m_MediaDecoder.video_snapshot(m_strFilePath);
+//			m_bCameraPic = false;
+//		}
+			//m_MediaDecoder.decodeSample(buf, 0, size, 0, 0);
+
+
+
+		//m_MediaDecoder.decodeSample(buf, 0, size, 0, 0);
+//		if(m_DecodingView == null) {
+//			printlog.w(THIS_FILE, "m_DecodingView is not ready...");
+//			return 0;
+//		}
+//		//printlog.e(THIS_FILE, String.format("dddd m_Bitmap is null jOpenDisplay vsize.height=%d, vsize.width=%d", vsize.height, vsize.width));
+//		decodeYUV420P( m_BMPBUF, buf, vsize.width, vsize.height );
+//		m_Bitmap.setPixels(m_BMPBUF, 0, vsize.height, 0, 0, vsize.height, vsize.width);
+//
+//		//ByteArrayOutputStream out = new ByteArrayOutputStream();
+//		//YuvImage yuv = new YuvImage(buf, ImageFormat.FLEX_RGBA_8888, vsize.width, vsize.height, null);
+//		//yuv.compressToJpeg(new Rect(0, 0,  vsize.width, vsize.height), 100, out);
+//		//byte[] imageBytes = out.toByteArray();
+//		//m_Bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
+////		File fileCacheItem = new File("/sdcard/Pictures/test1.jpg");
+////		OutputStream out = null;
+////		//byte [] output = new byte[vsize.width*vsize.height*3/2];
+////		try {
+////			//output = YV12toNV21(data, vsize.width, vsize.height);
+////			fileCacheItem.createNewFile();
+////			out = new FileOutputStream(fileCacheItem);
+////			ByteArrayOutputStream out1 = new ByteArrayOutputStream();
+////			YuvImage yuv = new YuvImage(buf, ImageFormat.NV21, vsize.width, vsize.height, null);
+////			yuv.compressToJpeg(new Rect(0, 0, vsize.width, vsize.height), 100, out);
+////			Bitmap image = BitmapFactory.decodeByteArray(out1.toByteArray(), 0, out1.toByteArray().length);
+////
+////			image.compress(Bitmap.CompressFormat.JPEG, 100, out);
+////
+////		} catch (Exception e) {
+////			e.printStackTrace();
+////		} finally {
+////			try { out.close();
+////			} catch (IOException e) {
+////				e.printStackTrace();
+////			}
+////		}
+//		//m_Bitmap.setPixels(m_BMPBUF, 0, vsize.width, 0, 0, vsize.width, vsize.height);
+//		try {
+//			SurfaceHolder holder = m_DecodingView.getHolder();
+//
+//			Surface sf = holder.getSurface();
+//
+//			long st, et;
+//
+//			st = SystemClock.currentThreadTimeMillis();
+//
+//			/*
+//			int newWidth = 480, newHeight = 800;
+//
+//			float ratioX = newWidth / (float) m_Bitmap.getWidth();
+//			float ratioY = newHeight / (float) m_Bitmap.getHeight();
+//			float middleX = newWidth / 2.0f;
+//			float middleY = newHeight / 2.0f;
+//
+//			Matrix scaleMatrix = new Matrix();
+//			scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
+//
+//			Canvas canvas = sf.lockCanvas(null);
+//			canvas.setMatrix(scaleMatrix);
+//
+//
+//			canvas.drawBitmap(m_Bitmap
+//					, middleX - m_Bitmap.getWidth() / 2
+//					, middleY - m_Bitmap.getHeight() / 2
+//					, null);
+//
+//			sf.unlockCanvasAndPost(canvas);
+//			*/
+//			Matrix rotateMatrix = new Matrix();
+//			rotateMatrix.postRotate(270);
+//
+//			Bitmap sideInversionImg = Bitmap.createBitmap(m_Bitmap, 0, 0,
+//					m_Bitmap.getWidth(), m_Bitmap.getHeight(), rotateMatrix, false);
+//
+//
+//
+//			Rect rcBMP, rcWND;
+//			Paint testPaint;
+//
+//			//rcBMP = new Rect(0, 0, vsize.height, vsize.width);
+//			rcBMP = new Rect(0, 0, vsize.width, vsize.height);
+//			rcWND = new Rect(0, 0, scaleSize.width, scaleSize.height);
+//			//rcWND = new Rect(0, 0, 720, 540);
+//			// 720 x 960
+//			// 480 x 640
+//			testPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+//
+//			Canvas canvas = sf.lockCanvas(null);
+//			canvas.drawBitmap(sideInversionImg, rcBMP, rcWND, testPaint);
+//
+//			if(m_bCameraPic)
+//			{
+//				File fileCacheItem = new File(m_strFilePath);
+//				OutputStream out1 = null;
+//
+//				out1 = new FileOutputStream(fileCacheItem);
+//
+//				sideInversionImg.compress(Bitmap.CompressFormat.JPEG, 100, out1);
+//				out1.close();
+//				m_bCameraPic = false;
+//			}
+//
+//
+//			sf.unlockCanvasAndPost(canvas);
+//
+//			et = SystemClock.currentThreadTimeMillis();
+//
+//			fc++;
+//
+//			printlog.d(THIS_FILE, "dt : " + String.format("%,d msec", et - st) );
+//
+//		} catch (IllegalArgumentException e) {
+//			// TODO Auto-generated catch block
+//			printlog.e(THIS_FILE, "jDisplayVideoData Error1");
+//			e.printStackTrace();
+//		} catch (OutOfResourcesException e) {
+//			// TODO Auto-generated catch block
+//			printlog.e(THIS_FILE, "jDisplayVideoData Error2");
+//			e.printStackTrace();
+//		}
+//		catch (Exception e) { e.printStackTrace(); }
+
+
+		// CME_SUCCESS : 0 
+		return 0;
+	}
+
+	public void setPicture(String strPATH)
+	{
+		m_strFilePath = strPATH;
+		m_bCameraPic = true;
+	}
+
+	public void setEncoding(boolean bSet)
+	{
+		m_bCameraEnc = bSet;
+	}
+
+	private void saveView( View view )
+
+	{
+		Bitmap b = Bitmap.createBitmap(
+				view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
+		if(b!=null){
+
+			try {
+
+				File fileCacheItem = new File(m_strFilePath);
+				Canvas c = new Canvas( b );
+				view.draw( c );
+				FileOutputStream fos = new FileOutputStream(fileCacheItem);
+				if ( fos != null )
+				{
+					b.compress(Bitmap.CompressFormat.PNG, 100, fos );
+					fos.close();
+				}
+				//setWallpaper( b );
+			} catch( Exception e ){
+				Log.e("testSaveView", "Exception: " + e.toString() );
+			}
+		}
+	}
+
+	public static Bitmap viewToBitmap(View view) {
+		Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
+		Canvas canvas = new Canvas(bitmap);
+		if (view instanceof SurfaceView) {
+			SurfaceView surfaceView = (SurfaceView) view;
+			surfaceView.setZOrderOnTop(true);
+			surfaceView.draw(canvas);
+			surfaceView.setZOrderOnTop(false);
+			return bitmap;
+		} else {
+			//For ViewGroup & View
+			view.draw(canvas);
+			return bitmap;
+		}
+	}
+
+	
+	private static byte[][] m_RecordBUF = null;
+	private static int m_cRecordBUF = 0;
+	private static int m_irRecordBUF = 0;
+	private static int m_iwRecordBUF = 0;
+
+	byte[] wBUF = null;
+	byte[] m_Queue = null; 
+	
+//	private YuvImage yuvimage;
+	
+	public void tryToStartVideoRecording(SurfaceHolder holder) {
+
+		Log.v("yjyoon", "CameraID=" + CameraID);
+		m_Camera = Camera.open(CameraID);
+		m_Camera.setErrorCallback(new ErrorCallback() {
+			public void onError(int error, Camera camera) {
+				printlog.e(THIS_FILE, "Camera error : " + error);
+			}
+			
+		});
+		
+		Camera.Parameters m_CameraParams = m_Camera.getParameters();
+		
+//		yuvimage = new YuvImage(yuv, format, width, height, strides)
+		
+		printlog.i(THIS_FILE, "m_CameraParams.flatten() : " + m_CameraParams.flatten());		
+		
+		
+//		List<String> focusModes = m_CameraParams.getSupportedFocusModes();
+		
+		
+		List<Size> arSize = m_CameraParams.getSupportedPreviewSizes();
+		List<Integer> arfps = m_CameraParams.getSupportedPreviewFrameRates();
+		List<Integer> arPF = m_CameraParams.getSupportedPreviewFormats();
+//		m_CameraParams.getSu
+		
+		
+						
+		for(Size size : arSize){
+			printlog.d(THIS_FILE, "cccc size.width : " + size.width);
+			printlog.d(THIS_FILE, "cccc size.height : " + size.height);
+		}
+		
+		for(Integer fps : arfps){
+			printlog.d(THIS_FILE, "cccc fps : " + fps);
+		}
+		
+		for(Integer PF : arPF){
+			printlog.d(THIS_FILE, "cccc PF : " + PF);
+		}
+		
+//		if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {  
+//			printlog.d(THIS_FILE, "supported FOCUS_MODE_AUTO...");
+//			m_CameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
+//		}
+
+
+		Log.d(THIS_FILE, "vsize.width : " + vsize.width + " vsize.height : " + vsize.height);
+		
+		
+		m_CameraParams.setPreviewSize(vsize.width, vsize.height);
+		//m_CameraParams.setPreviewSize(640,480);
+		//m_CameraParams.setPreviewFormat(842094169);
+		//m_CameraParams.set("iso-values", "auto");
+		//m_CameraParams.set("preview-fps-range-values", "(30000, 30000)");
+		//m_CameraParams.set("focus-mode", "auto");
+		
+		int fps = Integer.parseInt(mCMIF.CERES_VCodec_FrameRate_get());
+		m_CameraParams.setPreviewFrameRate(fps);
+		Log.d(THIS_FILE, "mCMIF.CERES_VCodec_FrameRate_get()) : " + fps);
+
+		// front camera only apply....
+		// don't care rear camera..
+		if(fps <= 15) {
+			m_CameraParams.set( "cam_mode", 0 );
+		}
+		else {
+			m_CameraParams.set( "cam_mode", 1 );
+		}
+		
+		//m_CameraParams.setPreviewFrameRate(Integer.parseInt(mCMIF.CERES_VCodec_FrameRate_get()));
+		//m_CameraParams.setPreviewFrameRate(30);
+		//m_CameraParams.set("preview-frame-rate", "25");
+		//m_CameraParams.set("camera-id","1");
+		
+		m_Camera.setDisplayOrientation(0);
+		
+		m_Camera.setParameters(m_CameraParams);
+		
+		printlog.i(THIS_FILE, "cccc m_CameraParams.getPreviewFormat() : " + m_CameraParams.getPreviewFormat());
+		printlog.i(THIS_FILE, "cccc m_CameraParams.get(redeye-reduction-values) : " + m_CameraParams.get("redeye-reduction-values"));
+		printlog.i(THIS_FILE, "cccc m_CameraParams.get(iso-values) : " + m_CameraParams.get("iso-values"));
+		printlog.i(THIS_FILE, "cccc m_CameraParams.get(preview-frame-rate) : " + m_CameraParams.get("preview-frame-rate"));
+		printlog.i(THIS_FILE, "cccc m_CameraParams.get(preview-fps-range-values) : " + m_CameraParams.get("preview-fps-range-values"));
+		printlog.i(THIS_FILE, "cccc m_CameraParams.get(cam_mode) : " + m_CameraParams.get("cam_mode"));
+		//printlog.i(THIS_FILE, "cccc m_CameraParams.get(focus-mode) : " + m_CameraParams.get("focus-mode"));
+		
+		
+		
+		try {
+			m_Camera.setPreviewDisplay(holder);
+		}
+		catch (Throwable t) {
+			printlog.e(THIS_FILE, "Exception in Video capture setPreviewDisplay()", t);
+		}				
+
+		try {
+			m_Camera.startPreview();
+		} catch (Throwable e) {
+			printlog.e(THIS_FILE, "Can't start camera preview");
+		}
+		
+		m_irRecordBUF = 0;
+		m_iwRecordBUF = 0;
+		
+		m_Camera.addCallbackBuffer(m_RecordBUF[m_iwRecordBUF]);
+
+		//m_Camera.setPreviewCallback(new CameraGreenFilter());
+		//m_Camera.setPreviewCallback(new Camera.PreviewCallback());
+		m_Camera.setPreviewCallbackWithBuffer
+		(
+			new PreviewCallback()
+			{
+				@Override
+				public void onPreviewFrame(byte[] data	, Camera camera) {
+					// putdata....
+					//Log.d(THIS_FILE, " m_bCameraEnc "+ m_iCameraEnc);
+
+					if(m_bCameraEnc) {
+
+						m_iwRecordBUF = (m_iwRecordBUF + 1) % m_cRecordBUF;
+						if (m_irRecordBUF == m_iwRecordBUF) {
+							m_irRecordBUF = (m_irRecordBUF + 1) % m_cRecordBUF;
+						}
+
+//						if(m_iCameraEnc == 0)
+//						{
+//							m_iwRecordBUF = (m_iwRecordBUF + 1) % m_cRecordBUF;
+//							if (m_irRecordBUF == m_iwRecordBUF) {
+//								m_irRecordBUF = (m_irRecordBUF + 1) % m_cRecordBUF;
+//							}
+//							m_iCameraEnc++;
+//						}
+//						else
+//						{
+//							m_iCameraEnc++;
+//							if(m_iCameraEnc > 5)
+//								m_iCameraEnc = 0;
+//
+//
+//						}
+
+					}
+					m_Camera.addCallbackBuffer(m_RecordBUF[m_iwRecordBUF]);
+
+
+				}
+			}
+		);
+	}
+
+	 static byte[] YV12toNV21(byte[] input,
+									 int width, int height) {
+
+		int size = width * height;
+		int quarter = size / 4;
+		int vPosition = size; // This is where V starts
+		int uPosition = size + quarter; // This is where U starts
+
+		 byte [] yuv = new byte[width*height*3/2];
+
+		System.arraycopy(input, 0, yuv, 0, size); // Y is same
+
+		for (int i = 0; i < quarter; i++) {
+			yuv[size + i*2 ] = input[vPosition + i]; // For NV21, V first
+			yuv[size + i*2 + 1] = input[uPosition + i]; // For Nv21, U second
+		}
+		return yuv;
+	}
+
+	static byte [] getNV21(int inputWidth, int inputHeight, Bitmap scaled) {
+		try {
+
+			int [] argb = new int[inputWidth * inputHeight];
+
+			scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);
+
+			byte [] yuv = new byte[inputWidth*inputHeight*3/2];
+			yuv = encodeYUV420SP(argb, inputWidth, inputHeight);
+
+			scaled.recycle();
+
+			return yuv;
+		} catch (Exception e) {
+			Log.e("KSJ", "[Exception] getNV21(int inputWidth, int inputHeight, Bitmap scaled)");
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	static public byte [] encodeYUV420SP(int[] argb, int width, int height) {
+		try {
+
+			final int frameSize = width * height;
+			byte [] yuv = new byte[width*height*3/2];
+			int yIndex = 0;
+			int uvIndex = frameSize;
+
+			int a, R, G, B, Y, U, V;
+			int index = 0;
+			for (int j = 0; j < height; j++) {
+				for (int i = 0; i < width; i++) {
+
+					a = (argb[index] & 0xff000000) >> 24; // a is not used obviously
+					R = (argb[index] & 0xff0000) >> 16;
+					G = (argb[index] & 0xff00) >> 8;
+					B = (argb[index] & 0xff) >> 0;
+
+					// well known RGB to YUV algorithm
+					Y = ( (  66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
+					//U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
+					//V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
+
+					V = ( ( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
+					U = ( ( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
+
+					// NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2
+					// meaning for every 4 Y pixels there are 1 V and 1 U. Note the sampling is every other
+					// pixel AND every other scanline.
+					yuv[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
+					if (j % 2 == 0 && index % 2 == 0) {
+						yuv[uvIndex++] = (byte)((V<0) ? 0 : ((V > 255) ? 255 : V));
+						yuv[uvIndex++] = (byte)((U<0) ? 0 : ((U > 255) ? 255 : U));
+					}
+					index ++;
+				}
+			}
+			return yuv;
+		} catch (Exception e) {
+			Log.e("KSJ", "[Exception] encodeYUV420SP(int[] argb, int width, int height)");
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {
+    	final int frameSize = width * height;
+
+    	int rotateYp = 0;
+    	
+    	for (int j = 0, yp = 0; j < height; j++) {
+    		int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+    		for (int i = 0; i < width; i++, yp++) {
+    			int y = (0xff & ((int) yuv420sp[yp])) - 16;
+    			if (y < 0) y = 0;
+    			if ((i & 1) == 0) {
+    				v = (0xff & yuv420sp[uvp++]) - 128;
+    				u = (0xff & yuv420sp[uvp++]) - 128;
+    			}
+    			
+    			int y1192 = 1192 * y;
+    			int r = (y1192 + 1634 * v);
+    			int g = (y1192 - 833 * v - 400 * u);
+    			int b = (y1192 + 2066 * u);
+    			
+    			if (r < 0) r = 0; else if (r > 262143) r = 262143;
+    			if (g < 0) g = 0; else if (g > 262143) g = 262143;
+    			if (b < 0) b = 0; else if (b > 262143) b = 262143;
+//    			if( CameraID == 1 )
+//    				rotateYp = ( ( width - i - 1 ) * height ) + j;
+//    			else
+//    				rotateYp = ( i * height ) + ( height - j - 1 );
+    			
+    			rotateYp = ( ( width - i - 1 ) * height ) + j;
+    			
+    			rgb[rotateYp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
+    		}
+    	}
+    }
+
+	static public void decodeYUV420SP1(int[] rgba, byte[] yuv420sp, int width,
+									  int height) {
+		final int frameSize = width * height;
+
+		for (int j = 0, yp = 0; j < height; j++) {
+			int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+			for (int i = 0; i < width; i++, yp++) {
+				int y = (int) yuv420sp[yp]+127;
+				if ((i & 1) == 0) {
+					v = (int)yuv420sp[uvp++]+127;
+					u = (int)yuv420sp[uvp++]+127;
+				}
+				rgba[yp] = 0xFF000000+(y<<16) | (u<<8) | v;
+			}
+		}
+	}
+
+	static public void decodeYUV420P(int[] rgb, byte[] yuv420sp, int width, int height) {
+
+    	final int frameSize = width * height;
+
+    	int rotateYp = 0;
+    	int up, vp;
+
+    	for (int j = 0, yp = 0; j < height; j++) {
+
+    		int u = 0, v = 0;
+        	up = frameSize + ( (j >> 2) * width );
+        	vp = ( frameSize / 4 * 5 ) + ( (j >> 2) * width );
+
+    		for (int i = 0; i < width; i++, yp++) {
+    			int y = (0xff & ((int) yuv420sp[yp])) - 16;
+    			if (y < 0) y = 0;
+    			if ((i & 1) == 0) {
+    				v = (0xff & yuv420sp[vp++]) - 128;
+    				u = (0xff & yuv420sp[up++]) - 128;
+    			}
+
+
+    			int y1192 = 1192 * y;
+    			int r = (y1192 + 1634 * v);
+    			int g = (y1192 - 833 * v - 400 * u);
+    			int b = (y1192 + 2066 * u);
+
+    			if (r < 0) r = 0; else if (r > 262143) r = 262143;
+    			if (g < 0) g = 0; else if (g > 262143) g = 262143;
+    			if (b < 0) b = 0; else if (b > 262143) b = 262143;
+
+//    			if( CameraID == 1 )
+//    				rotateYp = ( ( width - i - 1 ) * height ) + j;
+//    			else
+//    				rotateYp = ( i * height ) + ( height - j - 1 );
+				//rotateYp = ( ( width - i - 1 ) * height ) + j;
+    			//rotateYp = ( i * height ) + ( height - j - 1 );
+    			//rotateYp = ( ( height - i - 1 ) * width ) + j;
+    			rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
+				//rgb[yp] = 0xFF000000+(y<<16) | (u<<8) | v;
+
+    		}
+    	}
+    }
+
+	static public void decodeYUV420SP3(int[] rgba, byte[] yuv420sp, int width,
+									  int height) {
+		final int frameSize = width * height;
+
+		for (int j = 0, yp = 0; j < height; j++) {
+			int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
+			for (int i = 0; i < width; i++, yp++) {
+				int y = (0xff & ((int) yuv420sp[yp])) - 16;
+				if (y < 0)
+					y = 0;
+				if ((i & 1) == 0) {
+					v = (0xff & yuv420sp[uvp++]) - 128;
+					u = (0xff & yuv420sp[uvp++]) - 128;
+				}
+
+				int y1192 = 1192 * y;
+				int r = (y1192 + 1634 * v);
+				int g = (y1192 - 833 * v - 400 * u);
+				int b = (y1192 + 2066 * u);
+
+				if (r < 0)
+					r = 0;
+				else if (r > 262143)
+					r = 262143;
+				if (g < 0)
+					g = 0;
+				else if (g > 262143)
+					g = 262143;
+				if (b < 0)
+					b = 0;
+				else if (b > 262143)
+					b = 262143;
+
+				// rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &
+				// 0xff00) | ((b >> 10) & 0xff);
+				// rgba, divide 2^10 ( >> 10)
+				//rgba[yp] = 0xFF000000+(r<<16) | (g<<8) | b;
+				//rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
+				rgba[yp] = 0xff000000 | ((r << 14) & 0xff0000) | ((g >> 6) & 0xff00) | ((b >> 10) & 0xff);
+				//rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000)
+				//		| ((b >> 2) | 0xff00);
+			}
+		}
+	}
+
+	static public void decodeYUV420SP4(int[] rgba, byte[] yuv420sp, int width,
+									  int height) {
+		final int frameSize = width * height;
+		int r, g, b, y1192, y, i, uvp, u, v;
+		for (int j = 0, yp = 0; j < height; j++) {
+			uvp = frameSize + (j >> 1) * width;
+			u = 0;
+			v = 0;
+			for (i = 0; i < width; i++, yp++) {
+				y = (0xff & ((int) yuv420sp[yp])) - 16;
+				if (y < 0)
+					y = 0;
+				if ((i & 1) == 0) {
+					// above answer is wrong at the following lines. just swap ***u*** and ***v***
+					u = (0xff & yuv420sp[uvp++]) - 128;
+					v = (0xff & yuv420sp[uvp++]) - 128;
+				}
+
+				y1192 = 1192 * y;
+				r = (y1192 + 1634 * v);
+				g = (y1192 - 833 * v - 400 * u);
+				b = (y1192 + 2066 * u);
+
+				r = Math.max(0, Math.min(r, 262143));
+				g = Math.max(0, Math.min(g, 262143));
+				b = Math.max(0, Math.min(b, 262143));
+
+				// combine ARGB
+				rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00)
+						| ((b >> 10) & 0xff);
+			}
+		}
+	}
+
+	public static void decodeYUV420SP2(int[] out, byte[] fg, int width, int height)
+			throws NullPointerException, IllegalArgumentException {
+		int sz = width * height;
+		if (out == null)
+			throw new NullPointerException("buffer out is null");
+		if (out.length < sz)
+			throw new IllegalArgumentException("buffer out size " + out.length
+					+ " < minimum " + sz);
+		if (fg == null)
+			throw new NullPointerException("buffer 'fg' is null");
+		if (fg.length < sz)
+			throw new IllegalArgumentException("buffer fg size " + fg.length
+					+ " < minimum " + sz * 3 / 2);
+
+		int frameSize = width*height;
+		for (int i = 0; i < height; i++)
+			for (int j = 0; j < width; j++) {
+				int y = (0xff & ((int) fg[i * width + j]));
+				int u = (0xff & ((int) fg[frameSize + (i >> 1) * width + (j & ~1) + 0]));
+				int v = (0xff & ((int) fg[frameSize + (i >> 1) * width + (j & ~1) + 1]));
+				y = y < 16 ? 16 : y;
+
+				int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128));
+				int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
+				int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128));
+
+				r = r < 0 ? 0 : (r > 255 ? 255 : r);
+				g = g < 0 ? 0 : (g > 255 ? 255 : g);
+				b = b < 0 ? 0 : (b > 255 ? 255 : b);
+
+				out[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;
+			}
+	}
+
+	static public void decodeYUV420P2(byte[] yuv420p, byte[] yuv420sp, int width, int height) {
+
+    	final int frameSize = width * height;
+    	final int uvSize = frameSize / 2;
+    	final int vSize = uvSize / 2;
+
+    	int up, vp;
+		up = frameSize;
+    	vp = frameSize / 4 * 5;
+
+		if( CameraID == 1 )
+		{
+			System.arraycopy( yuv420sp, 0, yuv420p, 0, frameSize );
+
+			for( int i = 0; i < vSize; i++ )
+	    	{
+	    		yuv420p[up + i] = yuv420sp[up + (i*2) + 1];
+	    		yuv420p[vp + i] = yuv420sp[up + (i*2)];
+	    	}
+		}
+		else
+		{
+	    	for( int i = 0; i < frameSize; i++ )
+	    	{
+	    		yuv420p[i] = yuv420sp[frameSize - i - 1];
+	    	}
+
+	    	for( int i = 0; i < vSize; i++ )
+	    	{
+	    		yuv420p[up + ( vSize - i - 1 )] = yuv420sp[up + (i*2) + 1];
+	    		yuv420p[vp + ( vSize - i - 1 )] = yuv420sp[up + (i*2)];
+	    	}
+	    	
+	    	/*
+	    	int temp = 0;
+	    	int srcp = ( frameSize / 2 * 3 ) - width - 1;
+	    	for( int i = 0; i < vSize; i++ )
+	    	{
+	    		yuv420p[up + i] = yuv420sp[srcp + (temp*2) + 1];
+	    		yuv420p[vp + i] = yuv420sp[srcp + (temp*2)];
+	    		temp++;
+	    		if( temp == width )
+	    		{
+	    			srcp -= width;
+	    			temp = 0;
+	    		}
+	    	}
+	    	*/
+		}
+    }
+
+
+	public void stopVideoRecording() {		
+		if(m_Camera != null){
+			m_Camera.setPreviewCallbackWithBuffer(null);
+			m_Camera.stopPreview();
+			m_Camera.release();			
+			m_Camera = null;
+		}		
+	}
+	
+	public static class SRQueueInformation
+	{
+		public int m_sizeQMin;
+		public int m_sizeQMax;
+		public int m_sizeQPass;
+
+		public int m_sizeQFill;
+		
+		public SRQueueInformation()
+		{
+		}
+	}
+
+	public static class SRElementList
+	{
+		public SRElementList()
+		{
+		}
+	}
+}

+ 118 - 0
WallPadCall/src/main/java/ceres/utils/CallLogHelper.java

@@ -0,0 +1,118 @@
+package ceres.utils;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.provider.CallLog;
+
+import ceres.cminterface.DupCallInfo;
+
+
+public class CallLogHelper {
+
+	//private static final String THIS_FILE = "CallLogHelper";
+	
+	public static void addCallLog(Context context, ContentValues values) {
+		ContentResolver contentResolver = context.getContentResolver();
+		contentResolver.insert(CallLog.Calls.CONTENT_URI, values);
+	}
+	
+//	private static String LOGS_FOLDER = "logs";
+//	
+//	private static File getStorageFolder() {
+//		File root = Environment.getExternalStorageDirectory();
+//	    if (root.canWrite()){
+//			File dir = new File(root.getAbsolutePath() + File.separator + "ceresphone");
+//			dir.mkdirs();
+//			printlog.d(THIS_FILE, "Create directory " + dir.getAbsolutePath());
+//			return dir;
+//	    }
+//	    return null;
+//	}
+//	
+//	private static File getSubFolder(String subFolder) {
+//		File root = getStorageFolder();
+//		if(root != null) {
+//			File dir = new File(root.getAbsoluteFile() + File.separator + subFolder);
+//			dir.mkdirs();
+//			return dir;
+//		}
+//		return null;
+//	}
+//	
+//	public static File getLogsFolder() {
+//		return getSubFolder(LOGS_FOLDER);
+//	}
+	
+	public static ContentValues logValuesForCall(Context context, DupCallInfo call, long callStart) {
+		ContentValues cv = new ContentValues();
+//		String remoteContact = call.getRemote().getUri();
+		String remoteUri = call.getRemoteUri();
+		
+		cv.put(CallLog.Calls.NUMBER, remoteUri);
+		
+		cv.put(CallLog.Calls.NEW, (callStart > 0)?1:0);
+		cv.put(CallLog.Calls.DATE, (callStart>0 )?callStart: System.currentTimeMillis());
+		int type = CallLog.Calls.OUTGOING_TYPE;
+		int nonAcknowledge = 0; 
+		if(call.isIncoming()) {
+			type = CallLog.Calls.MISSED_TYPE;
+			nonAcknowledge = 1;
+			//printlog.d("CallLogHelper", "Last status code is "+call.getLastStatusCode());
+			if(callStart > 0) {
+				// Has started on the remote side, so not missed call
+				type = CallLog.Calls.INCOMING_TYPE;
+				nonAcknowledge = 0;
+			}
+		}
+		cv.put(CallLog.Calls.TYPE, type);
+		cv.put(CallLog.Calls.NEW, nonAcknowledge);
+		cv.put(CallLog.Calls.DURATION, (callStart>0)?(System.currentTimeMillis()-callStart)/1000:0);
+		
+//		CallerInfo callerInfo = CallerInfo.getCallerInfoFromSipUri(context, remoteContact);
+//		if(callerInfo != null) {
+//			cv.put(CallLog.Calls.CACHED_NAME, callerInfo.name);
+//			cv.put(CallLog.Calls.CACHED_NUMBER_LABEL, callerInfo.numberLabel);
+//			cv.put(CallLog.Calls.CACHED_NUMBER_TYPE, callerInfo.numberType);
+//		}
+		
+		return cv;
+	}
+	
+	
+	
+	
+	public static ContentValues logValuesForCall2(Context context, String remoteContact, int calltype, long callStart) {
+		ContentValues cv = new ContentValues();
+		//String remoteContact = "123456789";//call.getRemoteContact();
+		//callStart = 1270738207361;
+		cv.put(CallLog.Calls.NUMBER, remoteContact);
+		
+		cv.put(CallLog.Calls.NEW, 1);
+		cv.put(CallLog.Calls.DATE, System.currentTimeMillis());
+		
+		int type = CallLog.Calls.OUTGOING_TYPE;
+		int nonAcknowledge = 0;
+
+		if(calltype == 1) { //MISSED_TYPE
+			type = CallLog.Calls.MISSED_TYPE;
+			nonAcknowledge = 1;
+		}
+		else if(calltype == 2) 
+		{
+			type = CallLog.Calls.INCOMING_TYPE;
+			nonAcknowledge = 0;			
+		}
+
+		cv.put(CallLog.Calls.TYPE, type);
+		cv.put(CallLog.Calls.NEW, nonAcknowledge);
+		//cv.put(CallLog.Calls.DURATION, (callStart>0)?(System.currentTimeMillis()-callStart)/1000:0);
+			
+
+		//cv.put(CallLog.Calls.CACHED_NAME, 0);
+		//cv.put(CallLog.Calls.CACHED_NUMBER_LABEL, 0);
+		//cv.put(CallLog.Calls.CACHED_NUMBER_TYPE, 0);
+		
+		return cv;
+	}
+}

+ 177 - 0
WallPadCall/src/main/java/ceres/utils/CollectLogs.java

@@ -0,0 +1,177 @@
+package ceres.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.text.format.DateFormat;
+import android.util.Pair;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Date;
+
+public class CollectLogs {
+
+	private static final Object LINE_SEPARATOR = "\n";
+	private static final String THIS_FILE = "Collect Logs";
+	
+
+	/*Usage: logcat [options] [filterspecs]
+    options include:
+      -s              Set default filter to silent.
+                      Like specifying filterspec '*:s'
+      -f <filename>   Log to file. Default to stdout
+      -r [<kbytes>]   Rotate log every kbytes. (16 if unspecified). Requires -f
+      -n <count>      Sets max number of rotated logs to <count>, default 4
+      -v <format>     Sets the log print format, where <format> is one of:
+
+                      brief process tag thread raw time threadtime long
+
+      -c              clear (flush) the entire log and exit
+      -d              dump the log and then exit (don't block)
+      -g              get the size of the log's ring buffer and exit
+      -b <buffer>     request alternate ring buffer
+                      ('main' (default), 'radio', 'events')
+      -B              output the log in binary
+    filterspecs are a series of
+      <tag>[:priority]
+
+    where <tag> is a log component tag (or * for all) and priority is:
+      V    Verbose
+      D    Debug
+      I    Info
+      W    Warn
+      E    Error
+      F    Fatal
+      S    Silent (supress all output)
+
+    '*' means '*:d' and <tag> by itself means <tag>:v
+
+    If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
+    If no filterspec is found, filter defaults to '*:I'
+
+    If not specified with -v, format is set from ANDROID_PRINTF_LOG
+    or defaults to "brief"*/
+	public final static Pair<StringBuilder, File> getLogs() {
+        final StringBuilder log = new StringBuilder();
+        File outFile = null;
+        try{
+        	ArrayList<String> commandLine = new ArrayList<String>();
+            commandLine.add("logcat");
+        	
+        	
+        	File dir = PreferencesWrapper.getLogsFolder();
+        	if( dir != null) {
+    			Date d = new Date();
+    			outFile = new File(dir.getAbsoluteFile() + File.separator + "logs_"+ DateFormat.format("MM-dd-yy_kkmmss", d)+".txt");
+    			
+    			commandLine.add("-f");
+    			commandLine.add(outFile.getAbsolutePath());
+    			printlog.d(THIS_FILE, commandLine.toString());
+        	}
+
+            commandLine.add("-d");
+            commandLine.add("D");
+            
+            Process process = Runtime.getRuntime().exec(commandLine.toArray(new String[0]));
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            
+            String line ;
+            while ((line = bufferedReader.readLine()) != null){ 
+                log.append(line);
+                log.append(LINE_SEPARATOR); 
+            }
+            
+        } 
+        catch (IOException e){
+            printlog.e(THIS_FILE, "Collect logs failed : ", e);//$NON-NLS-1$
+            log.append("Unable to get logs : " + e.toString());
+        }
+        return new Pair<StringBuilder, File>(log, outFile);
+	}
+	
+	public final static StringBuilder getDeviceInfo() {
+		final StringBuilder log = new StringBuilder();
+		
+		log.append( "Here are important informations about Device : ");
+        log.append(LINE_SEPARATOR); 
+        log.append("android.os.Build.BOARD : " + android.os.Build.BOARD );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.BRAND : " + android.os.Build.BRAND );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.DEVICE : " + android.os.Build.DEVICE );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.ID : " + android.os.Build.ID );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.MODEL : " + android.os.Build.MODEL );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.PRODUCT : " + android.os.Build.PRODUCT );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.TAGS : " + android.os.Build.TAGS );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.VERSION.INCREMENTAL : " + android.os.Build.VERSION.INCREMENTAL );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.VERSION.RELEASE : " + android.os.Build.VERSION.RELEASE );
+        log.append(LINE_SEPARATOR); 
+		log.append("android.os.Build.VERSION.SDK : " + android.os.Build.VERSION.SDK );
+        log.append(LINE_SEPARATOR); 
+		try {
+			log.append("android.os.Build.VERSION.SDK_INT : " + android.os.Build.VERSION.SDK_INT);
+	        log.append(LINE_SEPARATOR); 
+		}catch(Exception e) {
+			//android 1.5
+		}
+		
+		return log;
+	}
+	
+	public final static String getApplicationInfo(Context ctx) {
+		String result = "";
+		result += "Based on the GPL CSipSimple version : ";
+		
+		PackageInfo pinfo;
+		try {
+			pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
+			result += pinfo.versionName + " r" + pinfo.versionCode;
+		} catch (NameNotFoundException e) {
+			printlog.e(THIS_FILE, "Impossible to find version of current package !!");
+		}
+		return result;
+	}
+	
+	public static Intent getLogReportIntent(String userComment, Context ctx) {
+		Pair<StringBuilder, File> logs = getLogs();
+		
+		
+		Intent sendIntent = new Intent(Intent.ACTION_SEND);
+        sendIntent.putExtra(Intent.EXTRA_SUBJECT, "CSipSimple Error-Log report");
+        sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { CustomDistribution.getSupportEmail() });
+        sendIntent.setType("text/plain");
+        
+        if(logs.second != null) {
+        	sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(logs.second));
+        }
+        
+        StringBuilder log = new StringBuilder();
+        log.append(userComment);
+        log.append(LINE_SEPARATOR);
+        log.append(LINE_SEPARATOR);
+        log.append(getApplicationInfo(ctx));
+        log.append(LINE_SEPARATOR);
+        log.append(getDeviceInfo());
+        log.append(LINE_SEPARATOR);
+        log.append(logs.first);
+        log.append(LINE_SEPARATOR);
+        log.append(LINE_SEPARATOR);
+        log.append(userComment);
+        
+        sendIntent.putExtra(Intent.EXTRA_TEXT, log.toString());
+        
+        return sendIntent;
+	}
+}

+ 424 - 0
WallPadCall/src/main/java/ceres/utils/Compatibility.java

@@ -0,0 +1,424 @@
+package ceres.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.net.Uri.Builder;
+import android.os.Build;
+import android.text.TextUtils;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import ceres.api.SipConfigManager;
+
+public class Compatibility {
+	
+	private static final String THIS_FILE = "Compatibility";
+	private static int currentApi = 0;	
+
+	public static int getApiLevel() {
+
+		if (currentApi > 0) {
+			return currentApi;
+		}
+
+		if (Build.VERSION.SDK.equalsIgnoreCase("3")) {
+			currentApi = 3;
+		} else {
+			try {
+				Field f = Build.VERSION.class.getDeclaredField("SDK_INT");
+				currentApi = (Integer) f.get(null);
+			} catch (Exception e) {
+				return 0;
+			}
+		}
+
+		return currentApi;
+	}
+
+	public static boolean isCompatible(int apiLevel) {
+		return getApiLevel() >= apiLevel;
+	}
+
+
+	/**
+	 * Get the stream id for in call track. Can differ on some devices.
+	 * Current device for which it's different :
+	 * Archos 5IT
+	 * @return
+	 */
+	public static int getInCallStream() {
+		if (Build.BRAND.equalsIgnoreCase("archos")) {
+			//Since archos has no voice call capabilities, voice call stream is not implemented
+			//So we have to choose the good stream tag, which is by default falled back to music
+			return AudioManager.STREAM_MUSIC;
+		}
+		//return AudioManager.STREAM_MUSIC;
+		return AudioManager.STREAM_VOICE_CALL;
+	}
+
+	public static boolean shouldUseRoutingApi() {
+		printlog.d(THIS_FILE, "Current device " + Build.BRAND + " - " + Build.DEVICE);
+
+		//HTC evo 4G
+		if(Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+			return true;
+		}
+
+		if (!isCompatible(4)) {
+			//If android 1.5, force routing api use
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	public static boolean shouldUseModeApi() {
+		printlog.d(THIS_FILE, "Current device " + Build.BRAND + " - " + Build.DEVICE);
+		//ZTE blade
+		if(Build.DEVICE.equalsIgnoreCase("blade")) {
+			return true;
+		}
+		//Samsung GT-I5500
+		if(Build.DEVICE.equalsIgnoreCase("GT-I5500")) {
+			return true;
+		}
+		//HTC evo 4G
+		if(Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+			return true;
+		}
+		//LG P500
+		if(Build.DEVICE.equalsIgnoreCase("LG-P500")) {
+			return true;
+		}
+		//Huawei
+		if(Build.DEVICE.equalsIgnoreCase("U8150") ||
+				Build.DEVICE.equalsIgnoreCase("U8110") ) {
+			return true;
+		}
+
+		return false;
+	}
+
+
+	public static String guessInCallMode() {
+		if (Build.BRAND.equalsIgnoreCase("sdg")) {
+			return "3";
+		}
+		if(Build.DEVICE.equalsIgnoreCase("blade")) {
+			return Integer.toString(AudioManager.MODE_IN_CALL);
+		}
+
+		if (!isCompatible(5)) {
+			return Integer.toString(AudioManager.MODE_IN_CALL);
+		}
+
+		return Integer.toString(AudioManager.MODE_NORMAL);
+	}
+
+	public static String getCpuAbi() {
+		if (isCompatible(4)) {
+			Field field;
+			try {
+				field = Build.class.getField("CPU_ABI");
+				return field.get(null).toString();
+			} catch (Exception e) {
+				printlog.w(THIS_FILE, "Announce to be android 1.6 but no CPU ABI field", e);
+			}
+
+		}
+		return "armeabi";
+	}
+
+	private static boolean needPspWorkaround(PreferencesWrapper preferencesWrapper) {
+		//Nexus one is impacted
+		if(Build.DEVICE.equalsIgnoreCase("passion")){
+			return true;
+		}
+		//All htc except....
+		if(Build.PRODUCT.toLowerCase().startsWith("htc")
+				|| Build.BRAND.toLowerCase().startsWith("htc")
+				|| Build.PRODUCT.toLowerCase().equalsIgnoreCase("inc") /* For Incredible */ ) {
+			if(Build.DEVICE.equalsIgnoreCase("hero") /* HTC HERO */
+					|| Build.DEVICE.equalsIgnoreCase("magic") /* Magic Aka Dev G2 */
+					|| Build.DEVICE.equalsIgnoreCase("tatoo") /* Tatoo */
+					|| Build.DEVICE.equalsIgnoreCase("dream") /* Dream Aka Dev G1 */
+					|| Build.DEVICE.equalsIgnoreCase("legend") /* Legend */
+
+					) {
+				return false;
+			}
+			return true;
+		}
+		//Dell streak
+		if(Build.BRAND.toLowerCase().startsWith("dell") &&
+				Build.DEVICE.equalsIgnoreCase("streak")) {
+			return true;
+		}
+		//Motorola milestone 2
+		if(Build.DEVICE.toLowerCase().contains("milestone2")) {
+			return true;
+		}
+
+		return false;
+	}
+
+
+	private static boolean needToneWorkaround(PreferencesWrapper prefWrapper) {
+		if(Build.PRODUCT.toLowerCase().startsWith("gt-i5800") ||
+				Build.PRODUCT.toLowerCase().startsWith("gt-i5801") ) {
+			return true;
+		}
+		return false;
+	}
+
+
+	private static void resetCodecsSettings(PreferencesWrapper preferencesWrapper) {
+		//Disable iLBC if not armv7
+		boolean supportFloating = getCpuAbi().equalsIgnoreCase("armeabi-v7a");
+
+
+		//For Narrowband
+		preferencesWrapper.setCodecPriority("PCMU/8000/1", SipConfigManager.CODEC_VIDEO, "60");
+		preferencesWrapper.setCodecPriority("PCMA/8000/1", SipConfigManager.CODEC_VIDEO, "50");
+		preferencesWrapper.setCodecPriority("speex/8000/1", SipConfigManager.CODEC_VIDEO, "220");
+		preferencesWrapper.setCodecPriority("speex/16000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("speex/32000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("GSM/8000/1", SipConfigManager.CODEC_VIDEO, "230");
+		preferencesWrapper.setCodecPriority("G722/16000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("G729/8000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("iLBC/8000/1", SipConfigManager.CODEC_VIDEO, supportFloating ? "240" : "0");
+		preferencesWrapper.setCodecPriority("SILK/8000/1", SipConfigManager.CODEC_VIDEO, "235");
+		preferencesWrapper.setCodecPriority("SILK/12000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("SILK/16000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("SILK/24000/1", SipConfigManager.CODEC_VIDEO, "0");
+		preferencesWrapper.setCodecPriority("CODEC2/8000/1", SipConfigManager.CODEC_VIDEO, "237");
+
+
+		//For Wideband
+		preferencesWrapper.setCodecPriority("PCMU/8000/1", SipConfigManager.CODEC_AUDIO, "60");
+		preferencesWrapper.setCodecPriority("PCMA/8000/1", SipConfigManager.CODEC_AUDIO, "50");
+		preferencesWrapper.setCodecPriority("speex/8000/1", SipConfigManager.CODEC_AUDIO, "70"); /*This is for addressing asterisk bug */
+		preferencesWrapper.setCodecPriority("speex/16000/1", SipConfigManager.CODEC_AUDIO, "219");
+		preferencesWrapper.setCodecPriority("speex/32000/1", SipConfigManager.CODEC_AUDIO, "220");
+		preferencesWrapper.setCodecPriority("GSM/8000/1", SipConfigManager.CODEC_AUDIO, "10");
+		preferencesWrapper.setCodecPriority("G722/16000/1", SipConfigManager.CODEC_AUDIO, "235");
+		preferencesWrapper.setCodecPriority("G729/8000/1", SipConfigManager.CODEC_AUDIO, "0");
+		preferencesWrapper.setCodecPriority("iLBC/8000/1", SipConfigManager.CODEC_AUDIO, supportFloating ? "100" : "0");
+		preferencesWrapper.setCodecPriority("SILK/8000/1", SipConfigManager.CODEC_AUDIO, "80");
+		preferencesWrapper.setCodecPriority("SILK/12000/1", SipConfigManager.CODEC_AUDIO, "75");
+		preferencesWrapper.setCodecPriority("SILK/16000/1", SipConfigManager.CODEC_AUDIO, "230");
+		preferencesWrapper.setCodecPriority("SILK/24000/1", SipConfigManager.CODEC_AUDIO, "240");
+		preferencesWrapper.setCodecPriority("CODEC2/8000/1", SipConfigManager.CODEC_AUDIO, "0");
+
+
+		// Bands repartition
+		preferencesWrapper.setPreferenceStringValue("band_for_wifi",  SipConfigManager.CODEC_AUDIO);
+		preferencesWrapper.setPreferenceStringValue("band_for_other",  SipConfigManager.CODEC_AUDIO);
+		preferencesWrapper.setPreferenceStringValue("band_for_3g",  SipConfigManager.CODEC_VIDEO);
+		preferencesWrapper.setPreferenceStringValue("band_for_gprs", SipConfigManager.CODEC_VIDEO);
+		preferencesWrapper.setPreferenceStringValue("band_for_edge", SipConfigManager.CODEC_VIDEO);
+
+	}
+
+	public static void setFirstRunParameters(PreferencesWrapper preferencesWrapper) {
+		resetCodecsSettings(preferencesWrapper);
+
+		preferencesWrapper.setPreferenceStringValue(SipConfigManager.SND_MEDIA_QUALITY, getCpuAbi().equalsIgnoreCase("armeabi-v7a") ? "4" : "3");
+		preferencesWrapper.setPreferenceStringValue(SipConfigManager.SND_AUTO_CLOSE_TIME, isCompatible(4) ? "1" : "5");
+		preferencesWrapper.setPreferenceStringValue(SipConfigManager.SND_CLOCK_RATE, isCompatible(4) ? "16000" : "8000");
+		preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.ECHO_CANCELLATION, isCompatible(4) ? true : false);
+		//HTC PSP mode hack
+		preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.KEEP_AWAKE_IN_CALL, needPspWorkaround(preferencesWrapper));
+
+		//Proximity sensor inverted
+		if( Build.PRODUCT.equalsIgnoreCase("SPH-M900") /*Sgs moment*/) {
+			preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.INVERT_PROXIMITY_SENSOR, true);
+		}
+
+		// Galaxy S default settings
+		if (Build.DEVICE.toUpperCase().startsWith("GT-I9000")) {
+			preferencesWrapper.setPreferenceFloatValue(SipConfigManager.SND_MIC_LEVEL, (float) 0.4);
+			preferencesWrapper.setPreferenceFloatValue(SipConfigManager.SND_SPEAKER_LEVEL, (float) 0.2);
+			preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.USE_SOFT_VOLUME, true);
+		}
+		//HTC evo 4G
+		if(Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+			preferencesWrapper.setPreferenceFloatValue(SipConfigManager.SND_MIC_LEVEL, (float) 0.5);
+			preferencesWrapper.setPreferenceFloatValue(SipConfigManager.SND_SPEAKER_LEVEL, (float) 1.5);
+
+		}
+
+		//Use routing API?
+		preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.USE_ROUTING_API, shouldUseRoutingApi());
+		preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.USE_MODE_API, shouldUseModeApi());
+		preferencesWrapper.setPreferenceBooleanValue(SipConfigManager.SET_AUDIO_GENERATE_TONE, needToneWorkaround(preferencesWrapper));
+	}
+
+	public static boolean useFlipAnimation() {
+		if (Build.BRAND.equalsIgnoreCase("archos")) {
+			return false;
+		}
+		return true;
+	}
+
+	public static String ModelNameTest(){
+		/** Called when the activity is first created. */
+		printlog.i("ModelNameTest", "ModelNameTest BOARD: " + Build.BOARD);
+        printlog.i("ModelNameTest", "ModelNameTest BRAND: " + Build.BRAND);
+        printlog.i("ModelNameTest", "ModelNameTest CPU_ABI: " + Build.CPU_ABI);
+        printlog.i("ModelNameTest", "ModelNameTest DEVICE: " + Build.DEVICE);
+        printlog.i("ModelNameTest", "ModelNameTest DISPLAY: " + Build.DISPLAY);
+        printlog.i("ModelNameTest", "ModelNameTest FINGERPRINT: " + Build.FINGERPRINT);
+        printlog.i("ModelNameTest", "ModelNameTest HOST: " + Build.HOST);
+        printlog.i("ModelNameTest", "ModelNameTest ID: " + Build.ID);
+        printlog.i("ModelNameTest", "ModelNameTest MANUFACTURER: " + Build.MANUFACTURER);
+        printlog.i("ModelNameTest", "ModelNameTest MODEL: " + Build.MODEL);
+        printlog.i("ModelNameTest", "ModelNameTest PRODUCT: " + Build.PRODUCT);
+        printlog.i("ModelNameTest", "ModelNameTest TAGS: " + Build.TAGS);
+        printlog.i("ModelNameTest", "ModelNameTest TIME: " + Build.TIME);
+        printlog.i("ModelNameTest", "ModelNameTest TYPE: " + Build.TYPE);
+        printlog.i("ModelNameTest", "ModelNameTest USER: " + Build.USER);
+        return Build.BOARD;
+	}
+
+	public static List<ResolveInfo> getPossibleActivities(Context ctxt, Intent i){
+		PackageManager pm = ctxt.getPackageManager();
+		try {
+			return pm.queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
+		}catch(NullPointerException e) {
+			return new ArrayList<ResolveInfo>();
+		}
+	}
+
+
+	public static Intent getPriviledgedIntent(String number) {
+		Intent i = new Intent("android.intent.action.CALL_PRIVILEGED");
+		Builder b = new Builder();
+		b.scheme("tel").appendPath(number);
+		i.setData( b.build() );
+		return i;
+	}
+
+	private static List<ResolveInfo> callIntents = null;
+	public final static List<ResolveInfo> getIntentsForCall(Context ctxt){
+		if(callIntents == null) {
+			callIntents = getPossibleActivities(ctxt, getPriviledgedIntent("123"));
+		}
+		return callIntents;
+	}
+
+	public static boolean canResolveIntent(Context context, final Intent intent) {
+		 final PackageManager packageManager = context.getPackageManager();
+		 //final Intent intent = new Intent(action);
+		 List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+		 return list.size() > 0;
+	}
+
+	private static Boolean canMakeGSMCall = null;
+	private static Boolean canMakeSkypeCall = null;
+
+	public static boolean canMakeGSMCall(Context context) {
+		PreferencesWrapper prefs = new PreferencesWrapper(context);
+		if(prefs.getGsmIntegrationType() == PreferencesWrapper.GSM_TYPE_AUTO) {
+			if (canMakeGSMCall == null) {
+				Intent intentMakePstnCall = new Intent(Intent.ACTION_CALL);
+				intentMakePstnCall.setData(Uri.fromParts("tel", "12345", null));
+				canMakeGSMCall = canResolveIntent(context, intentMakePstnCall);
+			}
+			return canMakeGSMCall;
+		}
+		if(prefs.getGsmIntegrationType() == PreferencesWrapper.GSM_TYPE_PREVENT) {
+			return false;
+		}
+		return true;
+	}
+
+	public static boolean canMakeSkypeCall(Context context) {
+		if (canMakeSkypeCall == null) {
+			try {
+			    PackageInfo skype = context.getPackageManager().getPackageInfo("com.skype.raider", 0);
+			    if(skype != null) {
+			    	canMakeSkypeCall = true;
+			    }
+			} catch (NameNotFoundException e) {
+				canMakeSkypeCall = false;
+			}
+		}
+		return canMakeSkypeCall;
+	}
+
+
+	public static void updateVersion(PreferencesWrapper prefWrapper, int lastSeenVersion, int runningVersion) {
+		if (lastSeenVersion < 14) {
+
+			// Galaxy S default settings
+			if (Build.DEVICE.toUpperCase().startsWith("GT-I9000")) {
+				prefWrapper.setPreferenceFloatValue(SipConfigManager.SND_MIC_LEVEL, (float) 0.4);
+				prefWrapper.setPreferenceFloatValue(SipConfigManager.SND_SPEAKER_LEVEL, (float) 0.2);
+			}
+
+			if (TextUtils.isEmpty(prefWrapper.getStunServer())) {
+				prefWrapper.setPreferenceStringValue(SipConfigManager.STUN_SERVER, "stun.counterpath.com");
+			}
+		}
+		if (lastSeenVersion < 15) {
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.ENABLE_STUN, false);
+		}
+		//Now we use svn revisions
+		if (lastSeenVersion < 369) {
+			// Galaxy S default settings
+			if (Build.DEVICE.toUpperCase().startsWith("GT-I9000")) {
+				prefWrapper.setPreferenceBooleanValue(SipConfigManager.USE_SOFT_VOLUME, true);
+			}
+
+		}
+
+		if(lastSeenVersion < 385) {
+			if(needPspWorkaround(prefWrapper)) {
+				prefWrapper.setPreferenceBooleanValue(SipConfigManager.KEEP_AWAKE_IN_CALL, true);
+			}
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.USE_ROUTING_API, shouldUseRoutingApi());
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.USE_MODE_API, shouldUseModeApi());
+			prefWrapper.setPreferenceStringValue(SipConfigManager.SIP_AUDIO_MODE, guessInCallMode());
+		}
+
+		if(lastSeenVersion < 394) {
+			//HTC PSP mode hack
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.KEEP_AWAKE_IN_CALL, needPspWorkaround(prefWrapper));
+		}
+		if(lastSeenVersion < 575) {
+			prefWrapper.setPreferenceStringValue(SipConfigManager.THREAD_COUNT, "3");
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.SET_AUDIO_GENERATE_TONE, needToneWorkaround(prefWrapper));
+
+			if(lastSeenVersion > 0) {
+				prefWrapper.setPreferenceBooleanValue(PreferencesWrapper.HAS_ALREADY_SETUP_SERVICE, true);
+			}
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.ENABLE_QOS, false);
+			//HTC evo 4G
+			if(Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+				prefWrapper.setPreferenceFloatValue(SipConfigManager.SND_MIC_LEVEL, (float) 0.5);
+				prefWrapper.setPreferenceFloatValue(SipConfigManager.SND_SPEAKER_LEVEL, (float) 1.5);
+				prefWrapper.setPreferenceBooleanValue(SipConfigManager.USE_ROUTING_API, true);
+			}
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.USE_MODE_API, shouldUseModeApi());
+			prefWrapper.setPreferenceBooleanValue(SipConfigManager.KEEP_AWAKE_IN_CALL, needPspWorkaround(prefWrapper));
+			//Proximity sensor inverted
+			if( Build.PRODUCT.equalsIgnoreCase("SPH-M900") /*Sgs moment*/) {
+				prefWrapper.setPreferenceBooleanValue(SipConfigManager.INVERT_PROXIMITY_SENSOR, true);
+			}
+		}
+		if(lastSeenVersion < 591) {
+			resetCodecsSettings(prefWrapper);
+		}
+		
+	}
+}
+

+ 47 - 0
WallPadCall/src/main/java/ceres/utils/CustomDistribution.java

@@ -0,0 +1,47 @@
+package ceres.utils;
+
+
+
+public class CustomDistribution {
+
+	// CSipSimple trunk distribution
+	
+	public static boolean distributionWantsOtherAccounts() {
+		return true;
+	}
+	
+	public static boolean distributionWantsOtherProviders() {
+		return true;
+	}
+	
+	public static String getSupportEmail() {
+		return "developers@cnstec.com";
+	}
+	
+	public static String getUserAgent() {
+		return "CSipSimple";
+	}
+	
+
+	
+	public static String getRootPackage() {
+		return "com.cnstec";
+	}
+	
+	public static boolean showIssueList() {
+		return true;
+	}
+	
+	public static String getFaqLink() {
+		return "http://code.google.com/p/cnstec/wiki/FAQ#Summary";
+	}
+	
+	public static boolean showFirstSettingScreen() {
+		return true;
+	}
+	
+	public static boolean supportMessaging() {
+		return true;
+	}
+	
+}

+ 164 - 0
WallPadCall/src/main/java/ceres/utils/DialingFeedback.java

@@ -0,0 +1,164 @@
+package ceres.utils;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.ToneGenerator;
+import android.os.Vibrator;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class DialingFeedback {
+
+	private static final String THIS_FILE = "DialingFeedback";
+	
+	/** The length of vibrate (haptic) feedback in milliseconds */
+	private static final int HAPTIC_LENGTH_MS = 50;
+	
+    /** The length of DTMF tones in milliseconds */
+    private static final int TONE_LENGTH_MS = 150;
+
+    /** The DTMF tone volume relative to other sounds in the stream */
+    private static final int TONE_RELATIVE_VOLUME = 80;
+
+    private boolean inCall;
+    private int toneStream;
+    private Activity context;
+    
+	private ToneGenerator toneGenerator = null;
+	private Object toneGeneratorLock = new Object();
+	private Vibrator vibrator = null;
+	private Timer toneTimer = null;
+
+	private PreferencesWrapper prefsWrapper;
+	private boolean dialPressTone = false;
+	private boolean dialPressVibrate = false;
+
+	private int ringerMode;
+
+	public DialingFeedback(Activity context, boolean inCall) {
+		
+		this.context = context;
+		this.inCall = inCall;
+		//toneStream = inCall ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_RING;
+		toneStream = inCall ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_VOICE_CALL;
+		printlog.d(THIS_FILE, "toneStream : " + toneStream);
+		prefsWrapper = new PreferencesWrapper(context);
+	}
+	
+	public void resume() {
+		
+		dialPressTone = prefsWrapper.getDialPressTone();
+		dialPressVibrate = prefsWrapper.getDialPressVibrate();
+		
+		printlog.d(THIS_FILE, "toneStream : dialPressTone : " + dialPressTone);
+		
+		dialPressTone = true; 
+		
+		
+		if(dialPressTone ) {
+			//Create dialtone just for user feedback
+			printlog.d(THIS_FILE, "toneStream : dialPressTone : 2222" + dialPressTone);
+			synchronized (toneGeneratorLock) {
+				printlog.d(THIS_FILE, "toneStream : dialPressTone 3333: " + dialPressTone);
+				if(toneTimer == null) {
+					printlog.d(THIS_FILE, "toneStream : dialPressTone 4444: " + dialPressTone);
+					toneTimer = new Timer();
+				}
+				if (toneGenerator == null) {
+					printlog.d(THIS_FILE, "toneStream : dialPressTone 5555: " + dialPressTone);
+					try {
+						toneGenerator = new ToneGenerator(toneStream, TONE_RELATIVE_VOLUME);
+						//Allow user to control dialtone
+						if (!inCall){
+							printlog.d(THIS_FILE, "toneStream : 6666" + toneStream);
+							context.setVolumeControlStream(0);
+						}
+					} catch (RuntimeException e) {
+						//If impossible, nothing to do
+						toneGenerator = null;
+					}
+				}
+			}
+		} else {
+			toneTimer = null;
+			toneGenerator = null;
+		}
+		
+		//Create the vibrator
+		if (dialPressVibrate) {
+			if (vibrator == null) {
+				vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+			}
+		} else {
+			vibrator = null;
+		}
+
+		//Store the current ringer mode
+		AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+		ringerMode = am.getRingerMode();
+		printlog.d(THIS_FILE, "toneStream : end : " + dialPressTone);
+	}
+	
+	public void pause() {
+
+		//Destroy dialtone
+		synchronized (toneGeneratorLock) {
+			if (toneGenerator != null) {
+				toneGenerator.release();
+				toneGenerator = null;
+			}
+			if(toneTimer != null) {
+				toneTimer.cancel();
+				toneTimer.purge();
+				toneTimer = null;
+			}
+		}
+		
+	}
+
+	public void giveFeedback(int tone) {
+		
+		switch (ringerMode) {
+			case AudioManager.RINGER_MODE_NORMAL:
+				if (dialPressVibrate) vibrator.vibrate(HAPTIC_LENGTH_MS);
+				if (dialPressTone) {
+					synchronized (toneGeneratorLock) {
+						if (toneGenerator == null) {
+							return;
+						}
+						toneGenerator.startTone(tone);
+						
+						//TODO : see if it could not be factorized
+						toneTimer.schedule(new StopTimerTask(), TONE_LENGTH_MS);
+					}					
+				}
+				break;
+			case AudioManager.RINGER_MODE_VIBRATE:
+				if (dialPressVibrate) vibrator.vibrate(HAPTIC_LENGTH_MS);
+				break;
+			case AudioManager.RINGER_MODE_SILENT:
+				break;
+		}
+	}
+	
+	public void hapticFeedback() {
+		if (dialPressVibrate && ringerMode != AudioManager.RINGER_MODE_SILENT) {
+			vibrator.vibrate(HAPTIC_LENGTH_MS);
+		}
+	}
+	
+	class StopTimerTask extends TimerTask {
+		@Override
+		public void run() {
+			synchronized (toneGeneratorLock) {
+				if (toneGenerator == null) {
+					return;
+				}
+				toneGenerator.stopTone();
+			}
+		}
+	}
+
+}

+ 146 - 0
WallPadCall/src/main/java/ceres/utils/IpAddress.java

@@ -0,0 +1,146 @@
+package ceres.utils;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
+
+
+/**
+ * IpAddress is an IP address.
+ */
+public class IpAddress {
+
+	/** The host address/name */
+	static String address = null;
+
+	/** The InetAddress */
+	static InetAddress inet_address;
+	
+	/** Local IP address */
+	public static String localIpAddress = "127.0.0.1";
+	public static String THIS_FILE = "IpAddress";
+	
+	
+	// ********************* Protected *********************
+
+	/** Creates an IpAddress */
+	IpAddress(InetAddress iaddress) {
+		init(null, iaddress);
+	}
+
+	/** Inits the IpAddress */
+	@SuppressWarnings("static-access")
+	private void init(String address, InetAddress iaddress) {
+		this.address = address;
+		this.inet_address = iaddress;
+	}
+	
+	public IpAddress(){
+		printlog.i(THIS_FILE, "IpAddress is called...");
+		
+	}
+
+	/** Gets the InetAddress */
+	InetAddress getInetAddress() {
+		if (inet_address == null)
+			try {
+				inet_address = InetAddress.getByName(address);
+				printlog.d("IpAddress","inet_address ---------------------------------------------- : " + inet_address);				
+			} catch (java.net.UnknownHostException e) {
+				inet_address = null;
+			}
+		return inet_address;
+	}
+
+	// ********************** Public ***********************
+
+	/** Creates an IpAddress */
+	public IpAddress(String address) {
+		init(address, null);
+	}
+
+	/** Creates an IpAddress */
+	@SuppressWarnings("static-access")
+	public IpAddress(IpAddress ipaddr) {
+		init(ipaddr.address, ipaddr.inet_address);
+	}
+
+	/** Gets the host address */
+	
+	public static String getAddress() {
+		if (address==null){
+			address=inet_address.getHostAddress();
+			printlog.i(THIS_FILE, "getAddress : " +address);
+		}
+		return address; 
+	}
+			
+
+	/** Makes a copy */
+	public Object clone() {
+		return new IpAddress(this);
+	}
+
+	/** Wthether it is equal to Object <i>obj</i> */
+	public boolean equals(Object obj) {
+		try {
+			IpAddress ipaddr = (IpAddress) obj;
+			if (!toString().equals(ipaddr.toString()))
+				return false;
+			return true;
+		} catch (Exception e) {
+			return false;
+		}
+	}
+
+	/** Gets a String representation of the Object */
+	public String toString() {
+		if (address == null && inet_address != null)
+			address = inet_address.getHostAddress();
+		return address;
+	}
+
+	// *********************** Static ***********************
+
+	/** Gets the IpAddress for a given fully-qualified host name. */
+	public static IpAddress getByName(String host_addr)
+			throws java.net.UnknownHostException {
+		InetAddress iaddr = InetAddress.getByName(host_addr);
+		return new IpAddress(iaddr);
+	}
+	
+	/** Sets the local IP address into the variable <i>localIpAddress</i> */
+	public static String deviceIP_get() {
+		localIpAddress = "127.0.0.1";
+				
+		printlog.d(THIS_FILE,"localIpAddress start : " + localIpAddress);
+
+		try {
+//			String ipv4;
+			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
+				
+				NetworkInterface intf = en.nextElement();
+
+				for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
+					
+					InetAddress inetAddress = enumIpAddr.nextElement();
+
+					//if (!inetAddress.isLoopbackAddress() && InetAddressUtils.isIPv4Address(inetAddress.getHostAddress()) ) {
+					if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
+						localIpAddress = inetAddress.getHostAddress().toString();
+						printlog.d(THIS_FILE,"localIpAddress : inetAddress.getHostAddress().toString() : " + localIpAddress);
+						return localIpAddress;
+					}					
+				}
+			}
+		} catch (SocketException ex) {
+			// do nothing
+			printlog.e(THIS_FILE,"localIpAddress : SocketException ex : " + localIpAddress);
+			return localIpAddress;
+		}
+		printlog.d(THIS_FILE,"localIpAddress end : " + localIpAddress);
+		return localIpAddress;
+	}
+}

+ 941 - 0
WallPadCall/src/main/java/ceres/utils/PreferencesWrapper.java

@@ -0,0 +1,941 @@
+package ceres.utils;
+
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.media.AudioManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Environment;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import ceres.api.SipConfigManager;
+
+
+public class PreferencesWrapper {
+	
+
+	
+	//Internal use
+	public static final String HAS_BEEN_QUIT = "has_been_quit";
+	public static final String USER_AGENT = "user_agent";
+	public static final String IS_ADVANCED_USER = "is_advanced_user";
+	public static final String HAS_ALREADY_SETUP = "has_already_setup";
+	public static final String HAS_ALREADY_SETUP_SERVICE = "has_already_setup_service";
+	
+	
+	private static final String THIS_FILE = "PreferencesWrapper";
+	private SharedPreferences prefs;
+	private ConnectivityManager connectivityManager;
+	private ContentResolver resolver;
+
+	
+	
+	private final static HashMap<String, String> STRING_PREFS = new HashMap<String, String>(){
+		private static final long serialVersionUID = 1L;
+	{
+		
+		put(USER_AGENT, CustomDistribution.getUserAgent());
+		put(SipConfigManager.LOG_LEVEL, "1");
+		
+		put(SipConfigManager.USE_SRTP, "0");
+		put(SipConfigManager.UDP_TRANSPORT_PORT, "5060");
+		put(SipConfigManager.TCP_TRANSPORT_PORT, "5060");
+		put(SipConfigManager.TLS_TRANSPORT_PORT, "5061");
+		put(SipConfigManager.KEEP_ALIVE_INTERVAL_WIFI, "100");
+		put(SipConfigManager.KEEP_ALIVE_INTERVAL_MOBILE, "40");
+		put(SipConfigManager.RTP_PORT, "4000");
+		put(SipConfigManager.OVERRIDE_NAMESERVER, "");
+		
+		put(SipConfigManager.SND_AUTO_CLOSE_TIME, "1");
+		put(SipConfigManager.ECHO_CANCELLATION_TAIL, "200");
+		put(SipConfigManager.ECHO_MODE, "2");
+		put(SipConfigManager.SND_MEDIA_QUALITY, "4");
+		put(SipConfigManager.SND_CLOCK_RATE, "16000");
+		put(SipConfigManager.SND_PTIME, "20");
+		put(SipConfigManager.BITS_PER_SAMPLE, "16");
+		put(SipConfigManager.SIP_AUDIO_MODE, "0");
+		put(SipConfigManager.THREAD_COUNT, "3");
+		
+		put(SipConfigManager.STUN_SERVER, "stun.counterpath.com");
+		put(SipConfigManager.TURN_SERVER, "");
+		put(SipConfigManager.TLS_METHOD, "0");
+		
+		put(SipConfigManager.DSCP_VAL, "26");
+		put(SipConfigManager.DTMF_MODE, "0");
+		
+
+		put(SipConfigManager.GSM_INTEGRATION_TYPE, "0");
+		put(SipConfigManager.DIAL_PRESS_TONE_MODE, "0");
+		put(SipConfigManager.DIAL_PRESS_VIBRATE_MODE, "0");
+		
+		put(SipConfigManager.DEFAULT_CALLER_ID, "");
+		
+		
+	}};
+	
+	
+	private final static HashMap<String, Boolean> BOOLEAN_PREFS = new HashMap<String, Boolean>(){
+		private static final long serialVersionUID = 1L;
+	{
+		//Network
+		put(SipConfigManager.LOCK_WIFI, true);
+		put(SipConfigManager.ENABLE_TCP, true);
+		put(SipConfigManager.ENABLE_UDP, true);
+		put(SipConfigManager.ENABLE_TLS, false);
+		put(SipConfigManager.USE_IPV6, false);
+		put(SipConfigManager.ENABLE_DNS_SRV, false);
+		put(SipConfigManager.ENABLE_ICE, false);
+		put(SipConfigManager.ENABLE_TURN, false);
+		put(SipConfigManager.ENABLE_STUN, false);
+		put(SipConfigManager.ENABLE_QOS, false);
+		put(SipConfigManager.TLS_VERIFY_SERVER, false);
+		put("use_wifi_in", true);
+		put("use_wifi_out", true);
+		put("use_other_in", true);
+		put("use_other_out", true);
+		put("use_3g_in", false);
+		put("use_3g_out", false);
+		put("use_gprs_in", false);
+		put("use_gprs_out", false);
+		put("use_edge_in", false);
+		put("use_edge_out", false);
+		
+		//Media
+		put(SipConfigManager.ECHO_CANCELLATION, false);
+		put(SipConfigManager.ENABLE_VAD, false);
+		put(SipConfigManager.USE_SOFT_VOLUME, false);
+		put(SipConfigManager.USE_ROUTING_API, false);
+		put(SipConfigManager.USE_MODE_API, false);
+		put(SipConfigManager.HAS_IO_QUEUE, false);
+		put(SipConfigManager.SET_AUDIO_GENERATE_TONE, true);
+		
+		//UI
+		put(SipConfigManager.PREVENT_SCREEN_ROTATION, true);
+		put(SipConfigManager.KEEP_AWAKE_IN_CALL, false);
+		put(SipConfigManager.INVERT_PROXIMITY_SENSOR, false);
+		put(SipConfigManager.ICON_IN_STATUS_BAR, true);
+		put(SipConfigManager.USE_PARTIAL_WAKE_LOCK, false);
+		
+		//Calls
+		put(SipConfigManager.AUTO_RECORD_CALLS, false);
+	}};
+	
+	private final static HashMap<String, Float> FLOAT_PREFS = new HashMap<String, Float>(){
+		private static final long serialVersionUID = 1L;
+	{
+		put(SipConfigManager.SND_MIC_LEVEL, (float)1.0);
+		put(SipConfigManager.SND_SPEAKER_LEVEL, (float)1.0);
+	}};
+	
+	
+	public PreferencesWrapper(Context aContext) {
+		prefs = PreferenceManager.getDefaultSharedPreferences(aContext);
+		connectivityManager = (ConnectivityManager) aContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+		resolver = aContext.getContentResolver();
+		
+	}
+
+	//Public setters
+	/**
+	 * Set a preference string value
+	 * @param key the preference key to set
+	 * @param value the value for this key
+	 */
+	public void setPreferenceStringValue(String key, String value) {
+		//TODO : authorized values
+		Editor editor = prefs.edit();
+		editor.putString(key, value);
+		editor.commit();
+	}
+	
+	/**
+	 * Set a preference boolean value
+	 * @param key the preference key to set
+	 * @param value the value for this key
+	 */
+	public void setPreferenceBooleanValue(String key, boolean value) {
+		Editor editor = prefs.edit();
+		editor.putBoolean(key, value);
+		editor.commit();
+	}
+	
+	/**
+	 * Set a preference float value
+	 * @param key the preference key to set
+	 * @param value the value for this key
+	 */
+	public void setPreferenceFloatValue(String key, float value) {
+		Editor editor = prefs.edit();
+		editor.putFloat(key, value);
+		editor.commit();
+	}
+	
+	//Private static getters
+	// For string
+	private static String gPrefStringValue(SharedPreferences aPrefs, String key) {
+		if(STRING_PREFS.containsKey(key)) {
+			return aPrefs.getString(key, STRING_PREFS.get(key));
+		}
+		return null;
+	}
+	
+	// For boolean
+	private static Boolean gPrefBooleanValue(SharedPreferences aPrefs, String key) {
+		if(BOOLEAN_PREFS.containsKey(key)) {
+			return aPrefs.getBoolean(key, BOOLEAN_PREFS.get(key));
+		}
+		return null;
+	}
+	
+	// For float
+	private static Float gPrefFloatValue(SharedPreferences aPrefs, String key) {
+		if(FLOAT_PREFS.containsKey(key)) {
+			return aPrefs.getFloat(key, FLOAT_PREFS.get(key));
+		}
+		return null;
+	}
+	
+	/**
+	 * Get string preference value
+	 * @param key the key preference to retrieve
+	 * @return the value
+	 */
+	public String getPreferenceStringValue(String key) {
+		return gPrefStringValue(prefs, key);
+	}
+	
+	/**
+	 * Get boolean preference value
+	 * @param key the key preference to retrieve
+	 * @return the value
+	 */
+	public Boolean getPreferenceBooleanValue(String key) {
+		return gPrefBooleanValue(prefs, key);
+	}
+	
+	/**
+	 * Get float preference value
+	 * @param key the key preference to retrieve
+	 * @return the value
+	 */
+	public Float getPreferenceFloatValue(String key) {
+		return gPrefFloatValue(prefs, key);
+	}
+	
+	/**
+	 * Get integer preference value
+	 * @param key the key preference to retrieve
+	 * @return the value
+	 */
+	public int getPreferenceIntegerValue(String key) {
+		try {
+			return Integer.parseInt(getPreferenceStringValue(key));
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Invalid "+key+" format : expect a int");
+		}
+		return Integer.parseInt(STRING_PREFS.get(key));
+	}
+	
+	/**
+	 * Set all values to default
+	 */
+	public void resetAllDefaultValues() {
+		for(String key : STRING_PREFS.keySet() ) {
+			setPreferenceStringValue(key, STRING_PREFS.get(key));
+		}
+		for(String key : BOOLEAN_PREFS.keySet() ) {
+			setPreferenceBooleanValue(key, BOOLEAN_PREFS.get(key));
+		}
+		for(String key : FLOAT_PREFS.keySet() ) {
+			setPreferenceFloatValue(key, FLOAT_PREFS.get(key));
+		}
+		Compatibility.setFirstRunParameters(this);
+	}
+	
+	
+	
+	// Network part
+	
+	// Check for wifi
+	static public boolean isValidWifiConnectionFor(NetworkInfo ni, SharedPreferences aPrefs, String suffix) {
+		
+		boolean valid_for_wifi = gPrefBooleanValue(aPrefs, "use_wifi_" + suffix);
+		if (valid_for_wifi && 
+			ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) {
+			
+			// Wifi connected
+			//TODO : check if not CONNECTING is not good as value here
+			printlog.d(THIS_FILE, "Wifi state is now "+ni.getState().name());
+			if (ni.getState() == NetworkInfo.State.CONNECTED) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	// Check for acceptable mobile data network connection
+	static public boolean isValidMobileConnectionFor(NetworkInfo ni, SharedPreferences aPrefs, String suffix) {
+
+		boolean valid_for_3g = gPrefBooleanValue(aPrefs, "use_3g_" + suffix);
+		boolean valid_for_edge = gPrefBooleanValue(aPrefs, "use_edge_" + suffix);
+		boolean valid_for_gprs = gPrefBooleanValue(aPrefs, "use_gprs_" + suffix);
+		
+		if ((valid_for_3g || valid_for_edge || valid_for_gprs) &&
+			 ni != null && ni.getType() == ConnectivityManager.TYPE_MOBILE) {
+
+			// Any mobile network connected
+			if (ni.getState() == NetworkInfo.State.CONNECTED) {
+				int subType = ni.getSubtype();
+				
+				// 3G (or better)
+				if (valid_for_3g &&
+					subType >= TelephonyManager.NETWORK_TYPE_UMTS) {
+					return true;
+				}
+				
+				// GPRS (or unknown)
+				if (valid_for_gprs &&	
+					(subType == TelephonyManager.NETWORK_TYPE_GPRS || subType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) {
+					return true;
+				}
+				
+				// EDGE
+				if (valid_for_edge &&
+					subType == TelephonyManager.NETWORK_TYPE_EDGE) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
+	// Check for other (wimax for example)
+	static public boolean isValidOtherConnectionFor(NetworkInfo ni, SharedPreferences aPrefs, String suffix) {
+		
+		boolean valid_for_other = gPrefBooleanValue(aPrefs, "use_other_" + suffix);
+		//boolean valid_for_other = true;
+		if (valid_for_other && 
+			ni != null && 
+			ni.getType() != ConnectivityManager.TYPE_MOBILE && ni.getType() != ConnectivityManager.TYPE_WIFI) {
+			
+			if (ni.getState() == NetworkInfo.State.CONNECTED) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	// Generic function for both incoming and outgoing
+	static public boolean isValidConnectionFor(NetworkInfo ni, SharedPreferences aPrefs, String suffix) {
+		if (isValidWifiConnectionFor(ni, aPrefs, suffix)) {
+			printlog.d(THIS_FILE, "We are valid for WIFI");
+			return true;
+		}
+		if(isValidMobileConnectionFor(ni, aPrefs, suffix)) {
+			printlog.d(THIS_FILE, "We are valid for MOBILE");
+			return true;
+		}
+		if(isValidOtherConnectionFor(ni, aPrefs, suffix)) {
+			printlog.d(THIS_FILE, "We are valid for OTHER");
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Say whether current connection is valid for outgoing calls 
+	 * @return true if connection is valid
+	 */
+	public boolean isValidConnectionForOutgoing() {
+		NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
+		return isValidConnectionFor(ni, prefs, "out");
+	}
+
+	/**
+	 * Say whether current connection is valid for incoming calls 
+	 * @return true if connection is valid
+	 */
+	public boolean isValidConnectionForIncoming() {
+		NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
+		return isValidConnectionFor(ni, prefs, "in");
+	}
+
+	public ArrayList<String> getAllIncomingNetworks(){
+		ArrayList<String> incomingNetworks = new ArrayList<String>();
+		String[] availableNetworks = {"3g", "edge", "gprs", "wifi", "other"};
+		for(String network:availableNetworks) {
+			if(getPreferenceBooleanValue("use_"+network+"_in")) {
+				incomingNetworks.add(network);
+			}
+		}
+		
+		return incomingNetworks;
+	}
+	
+
+	public void disableAllForIncoming() {
+		String[] availableNetworks = {"3g", "edge", "gprs", "wifi", "other"};
+		for(String network:availableNetworks) {
+			setPreferenceBooleanValue("use_"+network+"_in", false);
+		}
+	}
+	
+	public boolean getLockWifi() {
+		return getPreferenceBooleanValue(SipConfigManager.LOCK_WIFI);
+	}
+	
+	public int getUseSrtp() {		
+		int use_srtp = Integer.parseInt(getPreferenceStringValue(SipConfigManager.USE_SRTP));
+		return use_srtp;
+	}
+	
+	public void setUseSrtp(int state) {
+		setPreferenceStringValue(SipConfigManager.USE_SRTP, Integer.toString(state));
+	}
+
+	public boolean isTCPEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_TCP);
+	}
+	
+	public boolean isUDPEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_UDP);
+	}
+
+	public boolean isTLSEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_TLS);
+	}
+	
+	public boolean useIPv6() {
+		return getPreferenceBooleanValue(SipConfigManager.USE_IPV6);
+	}
+	
+	private int getPrefPort(String key) {
+		int port = getPreferenceIntegerValue(key);
+		if(isValidPort(port)) {
+			return port;
+		}
+		return Integer.parseInt(STRING_PREFS.get(key));
+	}
+	
+	public int getUDPTransportPort() {
+		return getPrefPort(SipConfigManager.UDP_TRANSPORT_PORT);
+	}
+	
+	public int getTCPTransportPort() {
+		return getPrefPort(SipConfigManager.TCP_TRANSPORT_PORT);
+	}
+	
+	public int getTLSTransportPort() {
+		return getPrefPort(SipConfigManager.TLS_TRANSPORT_PORT);
+	}
+	
+	public int getKeepAliveInterval() {
+		NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
+		if(ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) {
+			return getPreferenceIntegerValue(SipConfigManager.KEEP_ALIVE_INTERVAL_WIFI);
+		}
+		return getPreferenceIntegerValue(SipConfigManager.KEEP_ALIVE_INTERVAL_MOBILE);
+	}
+	
+	public int getRTPPort() {
+		return getPrefPort(SipConfigManager.RTP_PORT);
+	}
+	
+	public boolean enableDNSSRV() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_DNS_SRV);
+	}
+
+	public int getDSCPVal() {
+		return getPreferenceIntegerValue(SipConfigManager.DSCP_VAL);
+	}
+	
+	public int getTLSMethod() {
+		return getPreferenceIntegerValue(SipConfigManager.TLS_METHOD);
+	}
+	
+	private boolean hasStunServer(String string) {
+		String[] servers = getPreferenceStringValue(SipConfigManager.STUN_SERVER).split(",");
+		for(String server : servers) {
+			if(server.equalsIgnoreCase(string)) {
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	public void addStunServer(String server) {
+		if(!hasStunServer(server)) {
+			setPreferenceStringValue(SipConfigManager.STUN_SERVER, getPreferenceStringValue(SipConfigManager.STUN_SERVER)+","+server);
+		}
+		
+	}
+
+	public String getUserAgent() {
+		return getPreferenceStringValue(USER_AGENT);
+	}
+	
+	
+	//Media part
+	
+	/**
+	 * Get auto close time after end of the call
+	 * To avoid crash after hangup -- android 1.5 only but
+	 * even sometimes crash
+	 */
+	public int getAutoCloseTime() {
+		return getPreferenceIntegerValue(SipConfigManager.SND_AUTO_CLOSE_TIME);
+	}
+	
+	
+	/**
+	 * Whether echo cancellation is enabled
+	 * @return true if enabled
+	 */
+	public boolean hasEchoCancellation() {
+		return getPreferenceBooleanValue(SipConfigManager.ECHO_CANCELLATION);
+	}
+
+	public long getEchoCancellationTail() {
+		if(!hasEchoCancellation()) {
+			return 0;
+		}
+		return getPreferenceIntegerValue(SipConfigManager.ECHO_CANCELLATION_TAIL);
+	}
+	
+	public int getEchoMode() {
+		return getPreferenceIntegerValue(SipConfigManager.ECHO_MODE);
+		
+	}
+
+	/**
+	 * Whether voice audio detection is enabled
+	 * @return 1 if Voice audio detection is disabled
+	 */
+	public int getNoVad() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_VAD) ?0:1;
+	}
+
+	/**
+	 * Get the audio codec quality setting
+	 * @return the audio quality
+	 */
+	public long getMediaQuality() {
+		String mediaQuality = getPreferenceStringValue(SipConfigManager.SND_MEDIA_QUALITY);
+		//prefs.getString(SND_MEDIA_QUALITY, String.valueOf(defaultValue));
+		try {
+			int prefsValue = Integer.parseInt(mediaQuality);
+			if(prefsValue <= 10 && prefsValue >= 0) {
+				return prefsValue;
+			}
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Audio quality "+mediaQuality+" not well formated");
+		}
+		
+		return 4;
+	}
+	
+	public int getBitsPerSample() {
+		try {
+			return Integer.parseInt(getPreferenceStringValue(SipConfigManager.BITS_PER_SAMPLE));
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Bits per sample not well formated");
+		}
+		return Integer.parseInt(STRING_PREFS.get(SipConfigManager.BITS_PER_SAMPLE));
+	}
+	
+	/**
+	 * Get the audio codec quality setting
+	 * @return the audio quality
+	 */
+	public int getInCallMode() {
+		String mode = getPreferenceStringValue(SipConfigManager.SIP_AUDIO_MODE);
+		try {
+			return Integer.parseInt(mode);
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "In call mode "+mode+" not well formated");
+		}
+		
+		return AudioManager.MODE_NORMAL;
+	}
+	
+	/**
+	 * Get current clock rate
+	 * @return clock rate in Hz
+	 */
+	public long getClockRate() {
+		String clockRate = getPreferenceStringValue(SipConfigManager.SND_CLOCK_RATE);
+		try {
+			return Integer.parseInt(clockRate);
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Clock rate "+clockRate+" not well formated");
+		}
+		return 16000;
+	}
+
+	public boolean getUseRoutingApi() {
+		return getPreferenceBooleanValue(SipConfigManager.USE_ROUTING_API);
+	}
+	
+	public boolean getUseModeApi() {
+		return getPreferenceBooleanValue(SipConfigManager.USE_MODE_API);
+	}
+	
+	/**
+	 * Get whether ice is enabled
+	 * @return 1 if enabled (pjstyle)
+	 */
+	public int getIceEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_ICE)?1:0;
+	}
+
+	/**
+	 * Get whether turn is enabled
+	 * @return 1 if enabled (pjstyle)
+	 */ 
+	public int getTurnEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_TURN)?1:0;
+	}
+	
+	/**
+	 * Get stun server
+	 * @return host:port or blank if not set
+	 */
+	public String getStunServer() {
+		return getPreferenceStringValue(SipConfigManager.STUN_SERVER);
+	}
+
+	/**
+	 * Get whether turn is enabled
+	 * @return 1 if enabled (pjstyle)
+	 */ 
+	public int getStunEnabled() {
+		return getPreferenceBooleanValue(SipConfigManager.ENABLE_STUN)?1:0;
+	}
+	
+	/**
+	 * Get turn server
+	 * @return host:port or blank if not set
+	 */
+	public String getTurnServer() {
+		return getPreferenceStringValue(SipConfigManager.TURN_SERVER);
+	}
+	
+	/**
+	 * Get the codec priority
+	 * @param codecName codec name formated in the pjsip format (the corresponding pref is codec_{{lower(codecName)}}_{{codecFreq}})
+	 * @param defaultValue the default value if the pref is not found MUST be casteable as Integer/short
+	 * @return the priority of the codec as defined in preferences
+	 */
+	
+	public short getCodecPriority(String codecName, String defaultValue) {
+		NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
+		if(ni != null) {
+			String currentBandType = prefs.getString(SipConfigManager.getBandTypeKey(ni.getType(), ni.getSubtype()),
+					SipConfigManager.CODEC_AUDIO);
+			
+			return getCodecPriority(codecName, currentBandType, defaultValue);
+		}
+		return (short) Integer.parseInt(defaultValue);
+		
+	}
+	
+	public short getCodecPriority(String codecName, String type, String defaultValue) {
+		String key = SipConfigManager.getCodecKey(codecName, type);
+		if(key != null) {
+			return (short) Integer.parseInt(prefs.getString(key, defaultValue));
+		}
+		return (short) Integer.parseInt(defaultValue);
+	}
+	
+	public void setCodecPriority(String codecName, String type, String newValue) {
+		String key = SipConfigManager.getCodecKey(codecName, type);
+		if(key != null) {
+			setPreferenceStringValue(key, newValue);
+		}
+		//TODO : else raise error
+	}
+	
+	
+	public boolean hasCodecPriority(String codecName) {
+		NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
+		String[] codecParts = codecName.split("/");
+		if(codecParts.length >=2 ) {
+			String currentBandType = prefs.getString(SipConfigManager.getBandTypeKey(ni.getType(), ni.getSubtype()),
+					SipConfigManager.CODEC_AUDIO);
+			String key = SipConfigManager.getCodecKey(codecName, currentBandType);
+			return prefs.contains(key);
+		}
+		return false;
+	}
+
+	/**
+	 * Get sip ringtone
+	 * @return string uri
+	 */
+	public String getRingtone() {
+		String ringtone = prefs.getString("ringtone", Settings.System.DEFAULT_RINGTONE_URI.toString());
+		
+		if(ringtone == null || TextUtils.isEmpty(ringtone)) {
+			ringtone = Settings.System.DEFAULT_RINGTONE_URI.toString();
+		}
+		return ringtone;
+	}
+
+	public float getMicLevel() {
+		return getPreferenceFloatValue(SipConfigManager.SND_MIC_LEVEL);
+	}
+	
+	public float getSpeakerLevel() {
+		return getPreferenceFloatValue(SipConfigManager.SND_SPEAKER_LEVEL);
+	}
+	
+	public int getAudioFramePtime() {
+		return getPreferenceIntegerValue(SipConfigManager.SND_PTIME);
+	}
+	
+	public int getHasIOQueue() {
+		return getPreferenceBooleanValue(SipConfigManager.HAS_IO_QUEUE)?1:0;
+	}
+	
+	public boolean generateForSetCall() {
+		return getPreferenceBooleanValue(SipConfigManager.SET_AUDIO_GENERATE_TONE);
+	}
+
+	public static final String DTMF_MODE_AUTO = "0";
+	public static final String DTMF_MODE_RTP = "1";
+	public static final String DTMF_MODE_INBAND = "2";
+	public static final String DTMF_MODE_INFO = "3";
+
+	public boolean useSipInfoDtmf() {
+		return getPreferenceStringValue(SipConfigManager.DTMF_MODE).equalsIgnoreCase(DTMF_MODE_INFO);
+	}
+	
+	public boolean forceDtmfInBand() {
+		return getPreferenceStringValue(SipConfigManager.DTMF_MODE).equalsIgnoreCase(DTMF_MODE_INBAND);
+	}
+
+	public boolean forceDtmfRTP() {
+		return getPreferenceStringValue(SipConfigManager.DTMF_MODE).equalsIgnoreCase(DTMF_MODE_RTP);
+	}
+
+
+	public long getThreadCount() {
+		int value = getPreferenceIntegerValue(SipConfigManager.THREAD_COUNT);
+		if(value < 10) {
+			return value;
+		}
+		return Integer.parseInt(STRING_PREFS.get(SipConfigManager.THREAD_COUNT));
+	}
+
+	// ---- 
+	// UI related
+	// ----
+	public boolean getDialPressTone() {
+		int mode = getPreferenceIntegerValue(SipConfigManager.DIAL_PRESS_TONE_MODE);
+		switch (mode) {
+		case 0:
+			return Settings.System.getInt(resolver,
+	                Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
+		case 1:
+			return true;
+		case 2:
+			return false;
+		default:
+			break;
+		}
+		return false;
+	}
+
+	public boolean getDialPressVibrate() {
+		int mode = getPreferenceIntegerValue(SipConfigManager.DIAL_PRESS_VIBRATE_MODE);
+		switch (mode) {
+		case 0:
+			return Settings.System.getInt(resolver,
+	                Settings.System.HAPTIC_FEEDBACK_ENABLED, 1) == 1;
+		case 1:
+			return true;
+		case 2:
+			return false;
+		default:
+			break;
+		}
+		return false;
+	}
+
+	public boolean startIsDigit() {
+		return !prefs.getBoolean("start_with_text_dialer", false);
+	}
+
+	public boolean getUseAlternateUnlocker() {
+		return prefs.getBoolean("use_alternate_unlocker", false);
+	}
+	
+	public boolean useIntegrateDialer() {
+		return prefs.getBoolean("integrate_with_native_dialer", true);
+	}
+	public boolean useIntegrateCallLogs() {
+		return prefs.getBoolean("integrate_with_native_calllogs", true);
+	}
+
+
+	public boolean keepAwakeInCall() {
+		return getPreferenceBooleanValue(SipConfigManager.KEEP_AWAKE_IN_CALL);
+	}
+	
+	public boolean invertProximitySensor() {
+		return getPreferenceBooleanValue(SipConfigManager.INVERT_PROXIMITY_SENSOR);
+	}
+
+	public float getInitialVolumeLevel() {
+		return (float) ((float) (prefs.getFloat("snd_stream_level", (float) 8.0)) / 10.0);
+	}
+
+	public boolean usePartialWakeLock() {
+		return getPreferenceBooleanValue(SipConfigManager.USE_PARTIAL_WAKE_LOCK);
+	}
+	
+
+	public boolean integrateWithMusicApp() {
+		return prefs.getBoolean("integrate_with_native_music", true);
+	}
+	
+	public int getLogLevel() {
+		int prefsValue = getPreferenceIntegerValue(SipConfigManager.LOG_LEVEL);
+		if(prefsValue <= 6 && prefsValue >= 1) {
+			return prefsValue;
+		}
+		return 1;
+	}
+
+	public final static int GSM_TYPE_AUTO = 0;
+	public final static int GSM_TYPE_FORCE = 1;
+	public final static int GSM_TYPE_PREVENT = 2;
+	
+	public int getGsmIntegrationType() {
+		int prefsValue = 1;
+		String gsmType = getPreferenceStringValue(SipConfigManager.GSM_INTEGRATION_TYPE);
+		try {
+			prefsValue = Integer.parseInt(gsmType);
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Gsm type " + gsmType + " not well formated");
+		}
+		return prefsValue;
+	}
+	
+	public boolean showIconInStatusBar() {
+		return getPreferenceBooleanValue(SipConfigManager.ICON_IN_STATUS_BAR);
+	}
+
+	public final static int HEADSET_ACTION_CLEAR_CALL = 0;
+	public final static int HEADSET_ACTION_MUTE = 1;
+	public final static int HEADSET_ACTION_HOLD = 2;
+	/**
+	 * Action do do when headset is pressed
+	 * @return
+	 */
+	public int getHeadsetAction() {
+		try {
+			return Integer.parseInt(prefs.getString("headset_action", "0"));
+		}catch(NumberFormatException e) {
+			printlog.e(THIS_FILE, "Headset action option not well formated");
+		}
+		return HEADSET_ACTION_CLEAR_CALL;
+	}
+
+	/**
+	 * Check wether setup has already been done
+	 * @return
+	 */
+	public boolean hasAlreadySetup() {
+		return prefs.getBoolean(HAS_ALREADY_SETUP, false);
+	}
+	
+	public boolean hasAlreadySetupService() {
+		return prefs.getBoolean(HAS_ALREADY_SETUP_SERVICE, false);
+	}
+
+	//Utils
+	
+	/**
+	 * Check TCP/UDP validity of a network port
+	 */
+	private boolean isValidPort(int port) {
+		return (port>0 && port < 65535);
+	}
+
+	private static String CONFIG_FOLDER = "configs";
+	private static String RECORDS_FOLDER = "records";
+	private static String LOGS_FOLDER = "logs";
+	
+	private static File getStorageFolder() {
+		File root = Environment.getExternalStorageDirectory();
+	    if (root.canWrite()){
+			File dir = new File(root.getAbsolutePath() + File.separator + "CSipSimple");
+			dir.mkdirs();
+			printlog.d(THIS_FILE, "Create directory " + dir.getAbsolutePath());
+			return dir;
+	    }
+	    return null;
+	}
+
+	private static File getSubFolder(String subFolder) {
+		File root = getStorageFolder();
+		if(root != null) {
+			File dir = new File(root.getAbsoluteFile() + File.separator + subFolder);
+			dir.mkdirs();
+			return dir;
+		}
+		return null;
+	}
+	
+	public static File getConfigFolder() {
+		return getSubFolder(CONFIG_FOLDER);
+	}
+	
+	public static File getRecordsFolder() {
+		return getSubFolder(RECORDS_FOLDER);
+	}
+	
+	public static File getLogsFolder() {
+		return getSubFolder(LOGS_FOLDER);
+	}
+
+	public static void cleanLogsFiles() {
+		File logsFolder = getLogsFolder();
+		if(logsFolder != null) {
+			File[] files = logsFolder.listFiles();
+			for(File file: files) {
+				if(file.isFile()) {
+					file.delete();
+				}
+			}
+		}
+	}
+
+	public boolean isAdvancedUser() {
+		return prefs.getBoolean(IS_ADVANCED_USER, false);
+	}
+
+	public void toogleExpertMode() {
+		setPreferenceBooleanValue(IS_ADVANCED_USER, !isAdvancedUser());
+	}
+	
+	public boolean hasBeenQuit() {
+		return prefs.getBoolean(HAS_BEEN_QUIT, false);
+	}
+
+	public void setQuit(boolean quit) {
+		setPreferenceBooleanValue(HAS_BEEN_QUIT, quit);
+	}
+}

+ 232 - 0
WallPadCall/src/main/java/ceres/utils/Ringer.java

@@ -0,0 +1,232 @@
+package ceres.utils;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Vibrator;
+
+
+/**
+ * Ringer manager for the Phone app.
+ */
+public class Ringer {
+    private static final String THIS_FILE = "Ringer";
+   
+    private static final int VIBRATE_LENGTH = 1000; // ms
+    private static final int PAUSE_LENGTH = 1000; // ms
+
+    // Uri for the ringtone.
+    Uri customRingtoneUri;
+
+    Ringtone ringtone = null;				// [sentinel]
+    Vibrator vibrator;
+    VibratorThread vibratorThread;
+    RingerThread ringerThread;
+    Context context;
+    public int audioMode;
+
+    public Ringer(Context aContext) {
+        context = aContext;
+        vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
+    }
+
+    /**
+     * Starts the ringtone and/or vibrator. 
+     * 
+     */
+    //public void ring(String remoteContact, String defaultRingtone) {
+    public void ring(String remoteContact, String defaultRingtone) {
+        printlog.d(THIS_FILE, "  ==> ring() called...");
+        synchronized (this) {
+
+        	AudioManager audioManager =
+                (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        	
+        	//Save ringtone at the begining in case we raise vol
+            ringtone = getRingtone(remoteContact, defaultRingtone);
+            printlog.w(THIS_FILE, "remoteContact:" + remoteContact + " defaultRingtone:" + defaultRingtone + "ringtone:" +ringtone);
+       
+          //No ring no vibrate
+            int ringerMode = audioManager.getRingerMode();
+//            printlog.e(THIS_FILE, "ringerMode : " + ringerMode);
+            if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
+            	//printlog.d(THIS_FILE, "  skipping ring and vibrate because profile is Silent");
+            	return;
+            }
+
+//            // Vibrate
+//            int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
+//            //printlog.d(THIS_FILE, "  v=" + vibrateSetting + " rm=" + ringerMode);
+//            if (vibratorThread == null &&
+//            		(vibrateSetting == AudioManager.VIBRATE_SETTING_ON || 
+//            				ringerMode == AudioManager.RINGER_MODE_VIBRATE)) {
+//                vibratorThread = new VibratorThread();
+//                //printlog.d(THIS_FILE, "  Starting vibrator...");
+//                vibratorThread.start();
+//             }                      
+
+            // Vibrate only
+            if (ringerMode == AudioManager.RINGER_MODE_VIBRATE ||
+            		audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0 ) {
+            	printlog.d(THIS_FILE, "  skipping ring because profile is Vibrate OR because volume is zero");  
+            	return;
+            }            
+            // Ringer normal, audio set for ring, do it
+            if(ringtone == null) {
+            	printlog.d(THIS_FILE, "  No ringtone available - do not ring");
+            	return;
+            }
+
+            printlog.d(THIS_FILE, "  Starting ring with " + ringtone.getTitle(context));
+            
+            if (ringerThread == null) {
+            	ringerThread = new RingerThread();
+            	printlog.d(THIS_FILE, "  Starting ringer...");
+            	            	            
+            	ringerThread.start();            	   
+            }
+        }
+    }
+
+    /**
+     * @return true if we're playing a ringtone and/or vibrating
+     *     to indicate that there's an incoming call.
+     *     ("Ringing" here is used in the general sense.  If you literally
+     *     need to know if we're playing a ringtone or vibrating, use
+     *     isRingtonePlaying() or isVibrating() instead.)
+     */
+    public boolean isRinging() {
+    	return (ringerThread != null || vibratorThread != null);
+    }
+    
+    /**
+     * Stops the ringtone and/or vibrator if any of these are actually
+     * ringing/vibrating.
+     */
+	public void stopRing() {
+		synchronized (this) {
+			printlog.d(THIS_FILE, "  ==> stopRing() called...");
+
+			stopVibrator();
+			stopRinger();
+		}
+	}
+    
+    
+	private void stopRinger() {
+		if (ringerThread != null) {
+			ringerThread.interrupt();
+			try {
+				ringerThread.join(250);
+			} catch (InterruptedException e) {
+			}
+			ringerThread = null;
+		}
+	}
+    
+	private void stopVibrator() {
+
+		if (vibratorThread != null) {
+			vibratorThread.interrupt();
+			try {
+				vibratorThread.join(250); // Should be plenty long (typ.)
+			} catch (InterruptedException e) {
+			} // Best efforts (typ.)
+			vibratorThread = null;
+		}
+	}
+
+	public void updateRingerMode() {
+
+		AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+		synchronized (this) {
+			int ringerMode = audioManager.getRingerMode();
+			// Silent : stop everything
+			if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
+				stopRing();
+				return;
+			}
+
+			// Vibrate
+			int vibrateSetting = audioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
+			// If not already started restart it
+			if (vibratorThread == null && (vibrateSetting == AudioManager.VIBRATE_SETTING_ON || ringerMode == AudioManager.RINGER_MODE_VIBRATE)) {
+				vibratorThread = new VibratorThread();
+				vibratorThread.start();
+			}
+
+			// Vibrate only
+			if (ringerMode == AudioManager.RINGER_MODE_VIBRATE || audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
+				stopRinger();
+				return;
+			}
+			
+			//Ringer
+			if (ringerThread == null) {
+            	ringerThread = new RingerThread();
+            	printlog.d(THIS_FILE, "  Starting ringer...");
+//            	audioManager.setMode(AudioManager.MODE_RINGTONE);
+            	ringerThread.start();
+            }
+
+		}
+	}
+
+    private class VibratorThread extends Thread {
+        public void run() {
+        	try {
+	            while (true) {
+	                vibrator.vibrate(VIBRATE_LENGTH);
+	                Thread.sleep(VIBRATE_LENGTH + PAUSE_LENGTH);
+	            }
+        	} catch (InterruptedException ex) {
+        		printlog.d(THIS_FILE, "  Vibrator thread interrupt");
+        	} finally {
+        		vibrator.cancel();
+        	}
+    		printlog.d(THIS_FILE, "  Vibrator thread exiting");
+        }
+    }
+    
+    private class RingerThread extends Thread {
+    	public void run() {
+    		AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+            try {
+            	audioMode = audioManager.getMode();            	
+            	printlog.d(THIS_FILE, "  try Ringer run()111" + audioMode);
+            	//audioManager.setMode(0);
+            	//audioManager.setMode(AudioManager.MODE_RINGTONE);
+            	//printlog.d(THIS_FILE, "  try Ringer run()222" + audioMode);
+	    		while (true) {	    				    		
+	    			ringtone.play();	    			
+	    			while (ringtone.isPlaying()) {
+	    				Thread.sleep(100);
+	    			}
+	    		}
+            } catch (InterruptedException ex) {
+        		printlog.d(THIS_FILE, "  Ringer thread interrupt");
+            } finally {
+            	printlog.d(THIS_FILE, "  ringtone.stop()");
+            	ringtone.stop();
+            	//audioManager.setMode(AudioManager.MODE_NORMAL);
+            	//audioManager.setMode(0);
+            	printlog.d(THIS_FILE, "  finally Ringer run()" + audioMode);
+            	//audioManager.setMode(AudioManager.MODE_NORMAL);
+            }
+    		printlog.d(THIS_FILE, "  Ringer thread exiting");
+    	}
+    }
+
+    private Ringtone getRingtone(String remoteContact, String defaultRingtone) {
+    	//String defaultRingtone1 = "content://media/internal/audio/media/8";
+    	Uri ringtoneUri = Uri.parse(defaultRingtone);
+
+		// TODO - Should this be in a separate thread? We would still have to wait for
+		// it to complete, so at present, no.
+
+    	printlog.w(THIS_FILE, "--------------->>> ringtoneUri : " + ringtoneUri);		
+		return RingtoneManager.getRingtone(context, ringtoneUri);
+    }
+}

+ 32 - 0
WallPadCall/src/main/java/ceres/utils/Threading.java

@@ -0,0 +1,32 @@
+package ceres.utils;
+
+import android.os.HandlerThread;
+
+public class Threading {
+
+	
+	private static final String THIS_FILE = "Threading";
+
+	public final static void stopHandlerThread(HandlerThread handlerThread) {
+		if(handlerThread == null) {
+			//Nothing to do if already null
+			return;
+		}
+		boolean fails = true;
+				
+		if (fails && handlerThread.isAlive()) {
+			try {
+				//This is needed for android 4 and lower
+				printlog.d(THIS_FILE, "handlerThread.join...");
+				handlerThread.join(500);
+				/*
+				if (handlerThread.isAlive()) {
+					handlerThread.
+				}
+				*/
+			} catch (Exception e) {
+				printlog.e(THIS_FILE, "Can t finish handler thread....", e);
+			}
+		}
+	}
+}

+ 151 - 0
WallPadCall/src/main/java/ceres/utils/printlog.java

@@ -0,0 +1,151 @@
+package ceres.utils;
+
+public class printlog {
+	private static int LOG_LEVEL = 5;	
+	private static boolean EXCUTE_MODE = false;
+	// If you want to see debug message, you have to set LOG_LEVEL and EXCUTE_MODE.
+	public static void setPrintLogLevel(int level) {
+		LOG_LEVEL = level;
+	}
+	
+	public static int getCurPirntLogLevel() {
+		return LOG_LEVEL;
+	}
+	
+	// true : log not print
+	// false : log print
+	public static void setPrintLogDisabled(boolean setmode) {
+		EXCUTE_MODE = setmode;
+	}
+	
+	public static boolean isCurExcuteMode() {
+		return EXCUTE_MODE;
+	}
+	
+	public static void v(String tag, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 5) {
+			android.util.Log.v(tag, tag + " " +msg);
+		}
+	}	
+	public static void v(String tag, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 5) {
+			android.util.Log.v(tag, tag + " " +msg, tr);
+		}
+	}	
+	public static void d(String tag, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 4) {
+			android.util.Log.d(tag, tag + " " +msg);
+		}
+	}	
+	public static void d(String tag, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 4) {
+			android.util.Log.d(tag, tag + " " +msg, tr);
+		}
+	}	
+	public static void i(String tag, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 3) {
+			android.util.Log.i(tag, tag + " " +msg);
+		}
+	}	
+	static void i(String tag, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 3) {
+			android.util.Log.i(tag, tag + " " +msg, tr);
+		}
+	}	
+	public static void w(String tag, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 2) {
+			android.util.Log.w(tag, tag + " " +msg);
+		}
+	}	
+	public static void w(String tag, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 2) {
+			android.util.Log.w(tag, tag + " " +msg, tr);
+		}
+	}	
+	public static void e(String tag, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 1) {
+			android.util.Log.e(tag, tag + " " +msg);
+		}
+	}	
+	public static void e(String tag, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 1) {
+			android.util.Log.e(tag, tag + " " +msg, tr);
+		}
+	}
+	
+	
+	//---------------------------------------------------------------------
+	// log function parameter added  : filter
+	//---------------------------------------------------------------------	
+	public static void v(String tag, String filter, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 5) {
+			android.util.Log.v(tag, tag + " / " + filter + " " +msg);
+		}
+	}	
+	public static void v(String tag, String filter, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 5) {
+			android.util.Log.v(tag, tag + " / " + filter + " " +msg, tr);
+		}
+	}	
+	public static void d(String tag, String filter, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 4) {
+			android.util.Log.d(tag, tag + " / " + filter + " " +msg);
+		}
+	}	
+	public static void d(String tag, String filter, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 4) {
+			android.util.Log.d(tag, tag + " / " + filter + " " +msg, tr);
+		}
+	}	
+	public static void i(String tag, String filter, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 3) {
+			android.util.Log.i(tag, tag + " / " + filter + " " +msg);
+		}
+	}	
+	static void i(String tag, String filter, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 3) {
+			android.util.Log.i(tag, tag + " / " + filter + " " +msg, tr);
+		}
+	}	
+	public static void w(String tag, String filter, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 2) {
+			android.util.Log.w(tag, tag + " / " + filter + " " +msg);
+		}
+	}	
+	public static void w(String tag, String filter, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 2) {
+			android.util.Log.w(tag, tag + " / " + filter + " " +msg, tr);
+		}
+	}	
+	public static void e(String tag, String filter, String msg) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 1) {
+			android.util.Log.e(tag, tag + " / " + filter + " " +msg);
+		}
+	}	
+	public static void e(String tag, String filter, String msg, Throwable tr) {
+		if(EXCUTE_MODE) return;
+		if(LOG_LEVEL >= 1) {
+			android.util.Log.e(tag, tag + " / " + filter + " " +msg, tr);
+		}
+	}
+	
+}

+ 1 - 1
WallPadCall/src/main/java/kr/co/icontrols/V40IFCCD/V40IFCCD.java

@@ -98,7 +98,7 @@ public class V40IFCCD {
     public static int recvFramecallback(byte[] encodedFrame, int picType, int headerLen, int frameLen, int timeStamp) {
         try {
            //Log.d(TAG, "[recvFrame_callback] !! picType [" + picType + "], headerLen [" + headerLen + "], frameLen [" + frameLen + "], timeStamp [" + timeStamp + "], bShowMyVideo [" + MainActivity.mCallController.mSIPInterface.bShowMyVideo + "]");
-            if (frameLen > 50000) {
+            if (frameLen > 70000) {
                 Log.e(TAG, "[recvFrame_callback] !! Buffer Overflow !! picType [" + picType + "], headerLen [" + headerLen + "], frameLen [" + frameLen + "], timeStamp [" + timeStamp + "]");
                 return 0;
             }

+ 12 - 0
WallPadCall/src/main/java/kr/co/icontrols/callengine/engine/SIPInterface.java

@@ -90,6 +90,8 @@ public class SIPInterface {
     private int mNativeSurfaceTexture = 0;  // accessed by native methods
     Context mContext;
 
+    static boolean bBlock = false;
+
     public interface SIPEventListener {
         public void onSIPEvent(CALLEVENTTYPE eEventType, CALLTYPE eCallType, String strRemoteIP, String strRemoteSIPID, String strMessage);
 
@@ -462,6 +464,11 @@ public class SIPInterface {
                     }
                     break;
 
+                case CMCore.BSSSIPStun_ICONTROLS_UPDATE_BLOCK_STATUS:
+                    bBlock = msg.getData().getBoolean("ISBLOCK");
+                    Log.v(TAG, "update block_status " + bBlock);
+                    break;
+
                 default: {
                     LOG_INFO("[CmPiper] default [" + msg.toString() + "]");
                     super.handleMessage(msg);
@@ -3165,4 +3172,9 @@ public class SIPInterface {
             }
         }
     };
+
+    public boolean getBlockStatus() {
+        return bBlock;
+    }
+
 }

+ 2 - 2
WallPadCall/src/main/java/kr/co/icontrols/callengine/engine/VideoJNI.java

@@ -360,10 +360,10 @@ public class VideoJNI {
             else if (BOARDTYPE == BOARD_TYPE.V40_IGW300_NOUGAT) {
                 if (bFFMPEGEnable) {
                     SWSendDataToDecoder(hData, nFrameLen);
-                    mV40IFCCD.sendDataToDecoder(hData, nHeaderLen, nFrameLen, nTimeStamp);
+                    if (bDecoderStarted) mV40IFCCD.sendDataToDecoder(hData, nHeaderLen, nFrameLen, nTimeStamp);
                 }
                 else {
-                    mV40IFCCD.sendDataToDecoder(hData, nHeaderLen, nFrameLen, nTimeStamp);
+                    if (bDecoderStarted) mV40IFCCD.sendDataToDecoder(hData, nHeaderLen, nFrameLen, nTimeStamp);
                 }
             }
             else if (BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {

+ 26 - 6
WallPadCall/src/main/java/kr/co/icontrols/callengine/sip/SIPStun.java

@@ -130,6 +130,9 @@ public class SIPStun extends Service {
                 case CMCore.BSSSIPStun_ICONTROLS_REGISTER:
                     mClients.add(msg.replyTo);
                     Log.i(TAG, "SIPStun CmPiper DIALER_REGISTER : " + msg.toString());
+
+                    updateBlockStatus();
+
                     if (SIPStack.bDirectCall == true) {
                         if (padNumber == null || padNumber.length() == 0) {
                             boolean bValidroom = getMyroomname();
@@ -253,6 +256,7 @@ public class SIPStun extends Service {
             switch (msg.what) {
                 case HANDLERMSG.RELEASE_BLOCK_INVITE_MSG:
                     bBLOCK_INVITE_MSG = false;
+                    updateBlockStatus();
                     break;
 
                 case HANDLERMSG.NEWCALL_TRY_01:
@@ -2213,8 +2217,6 @@ public class SIPStun extends Service {
                 return;
             }
 
-
-
             if (nMSGType == SIPStack.SIP_MSGTYPE_REQUEST) {
                 if (SIPController.sipCall != null) {
                     Log.d(TAG, "[INVITEParser] [SIPController.sipCall.flag = " + SIPController.sipCall.flag + "]");
@@ -5272,8 +5274,26 @@ public class SIPStun extends Service {
         }
     }
 
-
-
-
-
+    public void updateBlockStatus() {
+        Log.v(TAG, "updateBlockStatus()");
+        for (int i = mClients.size() - 1; i >= 0; i--) {
+            try {
+                Bundle b = new Bundle();
+                b.putBoolean("ISBLOCK", bBLOCK_INVITE_MSG);
+                Message msg = null;
+                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_UPDATE_BLOCK_STATUS);
+                msg.setData(b);
+                mClients.get(i).send(msg);
+            } catch (RemoteException e) {
+                Log.e(TAG, "[RemoteException] updateBlockStatus()");
+                //e.printStackTrace();
+                LogUtil.errorLogInfo("", TAG, e);
+                mClients.remove(i);
+            } catch (Exception e) {
+                Log.e(TAG, "[Exception] updateBlockStatus()");
+                //e.printStackTrace();
+                LogUtil.errorLogInfo("", TAG, e);
+            }
+        }
+    }
 }

+ 2 - 2
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/declare/Global.java

@@ -998,8 +998,8 @@ public final class Global {
 
                 LOG("[add1stCallHistoryInfoFinal] getCallResult() " + Temp_1stCallHistoryInfo.getCallResult());
 
-                //if (Temp_1stCallHistoryInfo.getCallResult().equals(CALLRESULT.IN_MISS.toString())) {
-                if(((MainActivity) mContext).m_bMissCall)
+                if (Temp_1stCallHistoryInfo.getCallResult().equals(CALLRESULT.IN_MISS.toString()))
+                //if(((MainActivity) mContext).m_bMissCall)
                 {
                     MissedCallVisitorPicture.saveTakenPicture2();
                 } else {

+ 191 - 0
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/popup/UpdateInfo.java

@@ -0,0 +1,191 @@
+package kr.co.icontrols.wallpadcall.popup;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import com.artncore.wallpadapi.WallPadAPI;
+import com.util.LogUtil;
+
+import kr.co.icontrols.callengine.engine.CallController.PopupEventListener;
+import kr.co.icontrols.callengine.engine.CallManager.CALLOWNER;
+import kr.co.icontrols.callengine.engine.CallManager.CALLPATH;
+import kr.co.icontrols.callengine.engine.CallManager.CALLSTATUS;
+import kr.co.icontrols.callengine.engine.CallManager.CALLTYPE;
+import kr.co.icontrols.wallpadcall.MainActivity;
+import kr.co.icontrols.wallpadcall.PopupActivity;
+import kr.co.icontrols.wallpadcall.R;
+import kr.co.icontrols.wallpadcall.declare.Common;
+import kr.co.icontrols.wallpadcall.declare.Declare;
+import kr.co.icontrols.wallpadcall.declare.Global.BOARD_TYPE;
+import kr.co.icontrols.wallpadcall.declare.Global.ConfigValues;
+import kr.co.icontrols.wallpadcall.declare.ID;
+import kr.co.icontrols.wallpadsupport.WpadImageView;
+import kr.co.icontrols.wallpadsupport.WpadImageView.TOUCH_KIND;
+import kr.co.icontrols.wallpadsupport.WpadScreen;
+import kr.co.icontrols.wallpadsupport.WpadSound.SND;
+import kr.co.icontrols.wallpadsupport.WpadTextView;
+
+public class UpdateInfo extends WpadScreen implements PopupEventListener {
+
+    private final String TAG = "MultiCall";
+
+    boolean bLOG = true;
+
+    private void LOG(String log) {
+        if (bLOG) Log.v(TAG, log);
+    }
+
+    boolean bLOG_DEBUG = false;
+
+    private void LOG_DEBUG(String log) {
+        if (bLOG_DEBUG) Log.d(TAG, log);
+    }
+
+    boolean bLOG_INFO = true;
+
+    private void LOG_INFO(String log) {
+        if (bLOG_INFO) Log.i(TAG, log);
+    }
+
+    boolean bLOG_WARN = true;
+
+    private void LOG_WARN(String log) {
+        if (bLOG_WARN) Log.w(TAG, log);
+    }
+
+    WpadImageView IMG_BACKGROUND;
+    WpadImageView IMG_ICON;
+    WpadImageView BTN_ACCEPT;
+
+    WpadTextView TXT_INSTRUCTION;
+
+    int nICON_ID = R.drawable.icon_update;
+
+    Context mContext;
+
+    public UpdateInfo(Context context, RelativeLayout layout) {
+        super(context, layout);
+        try {
+            LOG("=================== [UpdateInfo] popup start ===================");
+            mContext = context;
+
+//            TXT_RECORDINFO = new WpadTextView(context, false, 984, 174, Gravity.CENTER, Color.WHITE, Common.fontsize._20, false, ID.POPUP.UPDATEINFO.ELEMENT.TEXT.INFO);
+//            ViewRegistration(layout, TXT_RECORDINFO, Common.PopupAlarmMarginLEFT(148), Common.PopupAlarmMarginTOP(115));
+//            TXT_RECORDINFO.setText("안정적인 통화를 위해 \n 월패드 업데이트가 필요합니다.");
+
+
+
+            Initialize();
+
+            IMG_BACKGROUND = new WpadImageView(context, TOUCH_KIND.NONE, 990, 576, R.drawable.bg_update_popup, 0, ID.POPUP.UPDATEINFO.ELEMENT.IMAGE.BACKGROUND);
+            ViewRegistration(layout, IMG_BACKGROUND, Common.PopupAlarmMarginLEFT(145), Common.PopupAlarmMarginTOP(112));
+
+            IMG_ICON = new WpadImageView(context, TOUCH_KIND.NONE, 180, 180, nICON_ID, 0, ID.POPUP.UPDATEINFO.ELEMENT.IMAGE.ICON);
+            ViewRegistration(layout, IMG_ICON, Common.PopupAlarmMarginLEFT(550), Common.PopupAlarmMarginTOP(329));
+
+            BTN_ACCEPT = new WpadImageView(context, TOUCH_KIND.BUTTON, 360, 80, R.drawable.btn_update_ok_normal, R.drawable.btn_update_ok_pressed, ID.POPUP.UPDATEINFO.ELEMENT.BUTTON.ACCEPT);
+            ViewRegistration(layout, BTN_ACCEPT, Common.PopupAlarmMarginLEFT(460), Common.PopupAlarmMarginTOP(585));
+
+            TXT_INSTRUCTION = new WpadTextView(context, false, 984, 174, Gravity.CENTER, Color.WHITE, Common.fontsize._46, true, ID.POPUP.UPDATEINFO.ELEMENT.TEXT.INSTRUCTION);
+            ViewRegistration(layout, TXT_INSTRUCTION, Common.PopupAlarmMarginLEFT(148), Common.PopupAlarmMarginTOP(115));
+
+            LOG_INFO("[Initialize] mCurrentScreenId_update " + MainActivity.mCallController.mCurrentScreenId_update);
+            if(MainActivity.mCallController.mCurrentScreenId_update == ID.SCREEN.SCREEN_TALKRESIDENCE)
+                TXT_INSTRUCTION.setText("안정적인 통화를 위해\n월패드 업데이트가 필요합니다.");
+            else if(MainActivity.mCallController.mCurrentScreenId_update == ID.SCREEN.SCREEN_TALKLOBBY)
+                TXT_INSTRUCTION.setText("안정적인 통화를 위해\n로비폰 업데이트가 필요합니다.");
+
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+            re.printStackTrace();
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] MultiCall(Context context, RelativeLayout layout, WallPadAPI wpapi, int operationMode)");
+            e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+    protected void Initialize() {
+        try {
+            LOG_INFO("[Initialize]");
+
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] Initialize()");
+            //e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+    @Override
+    protected void onClose() {
+        super.onClose();
+        try {
+
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] onClose()");
+            //e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+    @Override
+    protected void onBrReceive(Intent intent) {
+        super.onBrReceive(intent);
+        try {
+            LOG_INFO("[onBrReceive] intent : " + intent);
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] onBrReceive()");
+            //e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+    @Override
+    protected void onTouchEvent(View v, MotionEvent event) {
+        super.onTouchEvent(v, event);
+        try {
+            int nEvent = event.getAction();
+            int nID = v.getId();
+            if (nEvent == MotionEvent.ACTION_UP) {
+                if (nID == ID.POPUP.UPDATEINFO.ELEMENT.BUTTON.ACCEPT) {
+                    super.finish();
+                }
+
+            }
+        } catch (RuntimeException re) {
+            LogUtil.errorLogInfo("", TAG, re);
+        } catch (Exception e) {
+            Log.e(TAG, "[Exception] onTouchEvent(View v, MotionEvent event)");
+            //e.printStackTrace();
+            LogUtil.errorLogInfo("", TAG, e);
+        }
+    }
+
+    @Override
+    public void onCallerID(String strCallerID) {
+
+    }
+
+    @Override
+    public void onMulticallChange(CALLTYPE eCallType, CALLSTATUS eCallStatus, String strRemoteInfo) {
+
+    }
+
+    @Override
+    public void onShowPopupRemoteVideo(boolean bShow) {
+
+    }
+}

+ 7 - 0
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/InquiryCallHistory.java

@@ -314,6 +314,13 @@ public class InquiryCallHistory extends WpadScreen implements CallEventListener,
                         if (bSelectMode) checkSelectedLists(nID);
                     } else if (ID.SCREEN.INQUIRYCALLHISTORY.ELEMENT.BUTTON.TALK_01 <= nID && nID <= ID.SCREEN.INQUIRYCALLHISTORY.ELEMENT.BUTTON.TALK_06) {
                         MainActivity.mSound.Play(SND.effect.TOUCH_LATCHED);
+
+                        // 20220527 yjyoon. SIPStun 5초 block 중인 경우 통화를 하지 않는다.
+                        if ((MainActivity.mCallController.mSIPInterface.getBlockStatus())) {
+                            Log.e(TAG, "[onTouchEvent] SIPStun is not ready. SIPStun > bBLOCK_INVITE_MSG[true]" );
+                            return;
+                        }
+
                         if (!tryAutoCall(nID)) {
                             MainActivity.mSound.PlayMent(SND.guard.RETRYINPUT);
                             bProcessing = false;

+ 19 - 2
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkFront.java

@@ -1288,6 +1288,14 @@ public class TalkFront extends WpadScreen implements CallEventListener, MainEven
                         ((MainActivity) mContext).sendHandlerMsg(IGW300CMD.AUDIO_OFF, 0, 0); // 현관카메라로 음원이 나가는 것을 방지하기 위하여 path off (seulki)
 //                        sendHandlerMsgDelayed(HANDLERMSG.SET_PATH_NORMAL, 0, 0, 2000);
                         enableEndBTN(false); // 멘트 출력중일 경우 종료 버튼 이벤트 disable (seulki)
+
+                        //>> 220503.yjyoon
+                        // 안심통화 > 문열림버튼 클릭시 멘트가 작게 나오는 문제.
+						// 멘트 재생 전 audio path를 normal 로 변경.
+                        sendHandlerMsg(HANDLERMSG.SET_PATH_NORMAL, 0, 0);
+                        sendHandlerMsg(HANDLERMSG.STOP_AUDIO_RECORD, 0, 0);
+                        //<<
+
                         sendHandlerMsgDelayed(HANDLERMSG.PLAYMENT_OPENDOOR_TALKING, 0, 0, 1000);
                     }
                     else if (ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40 || ConfigValues.DEVICE_BOARDTYPE == BOARD_TYPE.V40_NOUGAT) {
@@ -1299,8 +1307,8 @@ public class TalkFront extends WpadScreen implements CallEventListener, MainEven
                         MainActivity.mSound.PlayMent(SND.mode.OPENDOOR);
                     }
 
-                   // if (ConfigValues.eDoorLockType == DOORLOCKTYPE.WIRELESS || ConfigValues.eDoorLockType == DOORLOCKTYPE.FINGERPRINT) {
-                        sendHandlerMsgDelayed(HANDLERMSG.RELEASE_OCCUPIEDMODE, 0, 0, 2000);
+                    //if (ConfigValues.eDoorLockType == DOORLOCKTYPE.WIRELESS || ConfigValues.eDoorLockType == DOORLOCKTYPE.FINGERPRINT) {
+                    sendHandlerMsgDelayed(HANDLERMSG.RELEASE_OCCUPIEDMODE, 0, 0, 2000);
                     //}
 
                     sendHandlerMsgDelayed(HANDLERMSG.END_CALL, 0, 0, 3000);
@@ -2571,6 +2579,15 @@ public class TalkFront extends WpadScreen implements CallEventListener, MainEven
                     if (MainActivity.mCallController.getTalkPath() != CALLPATH.DOOR_RELIEFCALL) {
                         sendHandlerMsg(HANDLERMSG.SET_PATH_DOOR_RELIEFCALL, 0, 0);
                         startAudioRecording(false);
+
+                        // 220415 yjyoon. 모드 전환시 볼륨 재설정. 그러지 않을 경우 월패드에서 현관 음성이 들리지 않음
+                        new Handler().postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                ((MainActivity) mContext).sendHandlerMsg(MainActivity.HANDLERMSG.SET_RELIEFCALL_VOLUME, 0, 0); // 안심통화시 볼륨 11로 설정
+                                sendHandlerMsg(HANDLERMSG.SET_VOLUME_TABLE, 0, 0);
+                            }
+                        }, 300);
                     }
                 } else {
                     LOG_WARN("[selectReliefCallFilter] nSelectedFilter is not correct!! [nSelectedFilter] " + nSelectedFilter);

+ 44 - 2
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkGuard.java

@@ -343,6 +343,12 @@ public class TalkGuard extends WpadScreen implements CallEventListener, MainEven
                     // 통화중에 버튼 터치음을 발생시키면, 통화 상대방에게 터치음이 전달되므로 통화중에는 터치음을 출력하지 않는다.(JEFF, 2019.12.24)
                     if (MainActivity.mCallController.mCallInfo.getGUARD() != CALLSTATUS.TALKING) MainActivity.mSound.Play(SND.effect.TOUCH_LATCHED);
 
+                    // 20220527 yjyoon. SIPStun 5초 block 중인 경우 통화를 하지 않는다.
+                    if ((MainActivity.mCallController.mSIPInterface.getBlockStatus()) && nID != ID.SCREEN.TALKGUARD.ELEMENT.BUTTON.END) {
+                        Log.e(TAG, "[onTouchEvent] SIPStun is not ready. SIPStun > bBLOCK_INVITE_MSG[true]" );
+                        return;
+                    }
+
                     if (nID == ID.SCREEN.TALKGUARD.ELEMENT.BUTTON.CONTROL) {
                         if (MainActivity.mCallController.mCallInfo.getGUARD() == CALLSTATUS.IDLE) {
                             ((MainActivity) mContext).setMenuBTNEnable(false);
@@ -431,7 +437,16 @@ public class TalkGuard extends WpadScreen implements CallEventListener, MainEven
             LOG_INFO("[onMainTouchEvent] eEvent [" + eEvent + "]");
             if (eEvent == MAINEVENT.BTN_HOME) {
                 if (MainActivity.mCallController.mCallInfo.getGUARD() != CALLSTATUS.TALKING) Sound().Play(SND.effect.TOUCH_LATCHED);
-                finishWallpadCallApp();
+
+                // 20220530 yjyoon.
+                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        finishWallpadCallApp();
+                    }
+                }, MainActivity.mCallController.mCallInfo.getGUARD() == CALLSTATUS.IDLE ? 0 : 500);
+                //finishWallpadCallApp();
+
             } else if (eEvent == MAINEVENT.BTN_HOME_MOBILE) {
                 finishWallpadCallApp();
             }
@@ -514,6 +529,33 @@ public class TalkGuard extends WpadScreen implements CallEventListener, MainEven
                     ((MainActivity) mContext).displayRemoteID(RemoteIDInfo.strName);
                     Global.make1stCallHistoryInfo(strRemoteIP, strRemoteSIPID, CALLDIRECTION.IN, CALLACTION.MISS, CALLRESULT.IN_MISS);
                 } else if (eCallStatus == CALLSTATUS.TALKING) {
+
+                    // 20220530 yjyoon. 통화 연결 후 3초 뒤에 종료버튼 활성화.
+                    // 송/수신 상태값이 서로 달라 setBTNStatus() 대신 onCallEvent 내에서 직접 처리.
+                    // 수신일 때는 MainActivity.mCallController.mCallInfo.getGUARD() == CALLSTATUS.TALKING
+                    // 송신일 때는 MainActivity.mCallController.mCallInfo.getGUARD() == CALLSTATUS.TRYING_CALL
+                    if (ConfigValues.bEasyModeUse) {
+                        BTN_TALK.setButtonEventOffEnable(R.drawable.btn_call_disabled_easymode);
+                        BTN_END.setButtonEventOffEnable(R.drawable.btn_end_disabled_easymode);
+                        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                BTN_END.setButtonEventOffDisable();
+                                BTN_END.setImageResource(R.drawable.btn_end_normal_easymode);
+                            }
+                        }, 3000);
+                    } else {
+                        BTN_TALK.setButtonEventOffEnable(R.drawable.btn_guard_call_disabled);
+                        BTN_END.setButtonEventOffEnable(R.drawable.btn_guard_end_disabled);
+                        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                BTN_END.setButtonEventOffDisable();
+                                BTN_END.setImageResource(R.drawable.btn_guard_end_normal);
+                            }
+                        },  3000);
+                    }
+
                     Global.stopMelodyRepeat();
                     if (eCallOwner == CALLOWNER.MOBILE) {
                         // 모바일에서 경비 호출 수신!! (방문객 원격통화)
@@ -1666,7 +1708,7 @@ public class TalkGuard extends WpadScreen implements CallEventListener, MainEven
                 ((MainActivity) mContext).setMenuBTNEnable(false);
                 changeBTNImage_Selected(strRemoteIP);
                 setOnCallLED();
-                swap5thBTN(true);
+                //swap5thBTN(true); // yjyoon. onCallEvent에서 처리
             } else {
                 mCallBTNAnimHandler.removeMessages(0);
                 mCallBTNAnimHandler.removeMessages(1);

+ 11 - 0
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkLobby.java

@@ -331,6 +331,7 @@ public class TalkLobby extends WpadScreen implements CallEventListener, MainEven
 
             bEnableVisitorPic = false;
             bReliefCallInit = false;
+            ((MainActivity) mContext).m_bMissCall_Lobby = false;
             //MainActivity.mCallController.selectVideoSourceToSubPhone(CALLTYPE.NONE, true);
             initCallVariables();
             if (ConfigValues.bReliefCall) selectReliefCallFilter(nSelectedFilter);
@@ -662,6 +663,12 @@ public class TalkLobby extends WpadScreen implements CallEventListener, MainEven
                     sendReliefFilterSelectBR(nSelectedFilter);
                     MainActivity.mCallController.MultiCallScenarioManager();
                 } else if (eCallStatus == CALLSTATUS.DOOR_OPEN) {
+
+                    if(!((MainActivity) mContext).m_bMissCall_Lobby)
+                        ((MainActivity) mContext).m_bMissCall = true;
+
+                    ((MainActivity) mContext).m_bMissCall_Lobby = false;
+
                     sendHandlerMsg(HANDLERMSG.DOOR_OPEN, 0, 0, null); // 방문객 원격통화 모바일에서 문열림
                 } else {
                     Log.w(TAG, "[onCallEvent] Incorrect eCallStatus!!! eCallStatus = " + eCallStatus);
@@ -1163,6 +1170,10 @@ public class TalkLobby extends WpadScreen implements CallEventListener, MainEven
 
     private void doDoorOpen() {
         try {
+
+            if(!((MainActivity) mContext).m_bMissCall_Lobby)
+                ((MainActivity) mContext).m_bMissCall = true;
+
             if (MainActivity.mCallController.mCallInfo.getLOBBY() == CALLSTATUS.CALLED) {
                 Global.stopMelodyRepeat();
 //                Global.changeVolumeMoIPMode(CALLTYPE.NONE);

+ 6 - 0
WallPadCall/src/main/java/kr/co/icontrols/wallpadcall/screen/TalkResidence.java

@@ -379,6 +379,12 @@ public class TalkResidence extends WpadScreen implements CallEventListener, Main
                         // 통화중에 버튼 터치음을 발생시키면, 통화 상대방에게 터치음이 전달되므로 통화중에는 터치음을 출력하지 않는다.(JEFF, 2019.12.24)
                         if (MainActivity.mCallController.mCallInfo.getRESI() != CALLSTATUS.TALKING) MainActivity.mSound.Play(SND.effect.TOUCH_LATCHED);
 
+                        // 20220527 yjyoon. SIPStun 5초 block 중인 경우 통화를 하지 않는다.
+                        if ((MainActivity.mCallController.mSIPInterface.getBlockStatus())) {
+                            Log.e(TAG, "[onTouchEvent] SIPStun is not ready. SIPStun > bBLOCK_INVITE_MSG[true]" );
+                            return;
+                        }
+
                         if (Global.TargetInputStep == TARGETINFOINPUTSTEP.DONE) {
                             doTalk(CALLOWNER.WALLPAD);
                         }

BIN
WallPadCall/src/main/res/drawable-ldpi/bg_update_popup.png


BIN
WallPadCall/src/main/res/drawable-ldpi/btn_update_ok_normal.png


BIN
WallPadCall/src/main/res/drawable-ldpi/btn_update_ok_pressed.png


BIN
WallPadCall/src/main/res/drawable-ldpi/icon_update.png


Some files were not shown because too many files changed in this diff