Pārlūkot izejas kodu

<init project: 中央服务器病床分机>

weizhengliang 5 gadi atpakaļ
revīzija
8cd9724ad5
100 mainītis faili ar 10155 papildinājumiem un 0 dzēšanām
  1. 71 0
      .gitignore
  2. BIN
      .idea/caches/build_file_checksums.ser
  3. BIN
      .idea/caches/gradle_models.ser
  4. 113 0
      .idea/codeStyles/Project.xml
  5. 12 0
      .idea/runConfigurations.xml
  6. BIN
      AmDemo_R/$projectDir/libs/Native_Libs2.jar
  7. 9 0
      AmDemo_R/.classpath
  8. 33 0
      AmDemo_R/.project
  9. 4 0
      AmDemo_R/.settings/org.eclipse.jdt.core.prefs
  10. 61 0
      AmDemo_R/AndroidManifest.xml
  11. 39 0
      AmDemo_R/build.gradle
  12. BIN
      AmDemo_R/ic_launcher-web.png
  13. BIN
      AmDemo_R/keystore
  14. BIN
      AmDemo_R/keystorefile/keystore.jks
  15. BIN
      AmDemo_R/libs/android-support-v4.jar
  16. BIN
      AmDemo_R/libs/armeabi-v7a/libcheckcpu.so
  17. BIN
      AmDemo_R/libs/armeabi-v7a/libvvsip-v7a-neon.so
  18. BIN
      AmDemo_R/libs/armeabi-v7a/libvvsip-v7a.so
  19. BIN
      AmDemo_R/libs/armeabi/libcheckcpu.so
  20. BIN
      AmDemo_R/libs/armeabi/libvvsip-v5.so
  21. 8 0
      AmDemo_R/lint.xml
  22. 20 0
      AmDemo_R/proguard-project.txt
  23. 15 0
      AmDemo_R/project.properties
  24. BIN
      AmDemo_R/res/drawable-hdpi/ic_call_end_white_48dp.png
  25. BIN
      AmDemo_R/res/drawable-hdpi/ic_launcher.png
  26. BIN
      AmDemo_R/res/drawable-hdpi/ic_videocam_off_white_48dp.png
  27. BIN
      AmDemo_R/res/drawable-mdpi/ic_launcher.png
  28. BIN
      AmDemo_R/res/drawable-xhdpi/ic_launcher.png
  29. BIN
      AmDemo_R/res/drawable-xxhdpi/ic_launcher.png
  30. 169 0
      AmDemo_R/res/layout/activity_main.xml
  31. 85 0
      AmDemo_R/res/layout/splash_layout.xml
  32. 200 0
      AmDemo_R/res/layout/video_camera.xml
  33. 3 0
      AmDemo_R/res/menu/main.xml
  34. BIN
      AmDemo_R/res/raw/holdmusic.wav
  35. BIN
      AmDemo_R/res/raw/ringback.wav
  36. 8 0
      AmDemo_R/res/values-v11/styles.xml
  37. 9 0
      AmDemo_R/res/values-v14/styles.xml
  38. 10 0
      AmDemo_R/res/values-w820dp/dimens.xml
  39. 7 0
      AmDemo_R/res/values/dimens.xml
  40. 87 0
      AmDemo_R/res/values/preference_values.xml
  41. 74 0
      AmDemo_R/res/values/strings.xml
  42. 10 0
      AmDemo_R/res/values/styles.xml
  43. 17 0
      AmDemo_R/res/xml/advanced_pref.xml
  44. 5 0
      AmDemo_R/res/xml/pref_media_advanced_audio.xml
  45. 7 0
      AmDemo_R/res/xml/pref_media_advanced_video.xml
  46. 167 0
      AmDemo_R/res/xml/pref_media_audio.xml
  47. 62 0
      AmDemo_R/res/xml/pref_media_video.xml
  48. 21 0
      AmDemo_R/res/xml/pref_sip_account.xml
  49. 66 0
      AmDemo_R/res/xml/pref_sip_optional.xml
  50. 1264 0
      AmDemo_R/src/com/vvsip/amdemo/FragmentInVideoCall.java
  51. 376 0
      AmDemo_R/src/com/vvsip/amdemo/MainActivity.java
  52. 220 0
      AmDemo_R/src/com/vvsip/amdemo/SplashActivity.java
  53. 273 0
      AmDemo_R/src/com/vvsip/ansip/AudioCompatibility.java
  54. 306 0
      AmDemo_R/src/com/vvsip/ansip/AudioInput.java
  55. 157 0
      AmDemo_R/src/com/vvsip/ansip/AudioOutput.java
  56. 32 0
      AmDemo_R/src/com/vvsip/ansip/CheckCpu.java
  57. 392 0
      AmDemo_R/src/com/vvsip/ansip/H264MediaCodecDecoder.java
  58. 189 0
      AmDemo_R/src/com/vvsip/ansip/H264MediaCodecEncoder.java
  59. 32 0
      AmDemo_R/src/com/vvsip/ansip/IVvsipService.java
  60. 18 0
      AmDemo_R/src/com/vvsip/ansip/IVvsipServiceListener.java
  61. 239 0
      AmDemo_R/src/com/vvsip/ansip/VideoOrientationCompatibility.java
  62. 163 0
      AmDemo_R/src/com/vvsip/ansip/VvsipAccount.java
  63. 165 0
      AmDemo_R/src/com/vvsip/ansip/VvsipCall.java
  64. 58 0
      AmDemo_R/src/com/vvsip/ansip/VvsipDTMF.java
  65. 246 0
      AmDemo_R/src/com/vvsip/ansip/VvsipMediaCodecFinder.java
  66. 29 0
      AmDemo_R/src/com/vvsip/ansip/VvsipMediaCodecInfo.java
  67. 6 0
      AmDemo_R/src/com/vvsip/ansip/VvsipNeighbor.java
  68. 2631 0
      AmDemo_R/src/com/vvsip/ansip/VvsipService.java
  69. 23 0
      AmDemo_R/src/com/vvsip/ansip/VvsipServiceBinder.java
  70. 413 0
      AmDemo_R/src/com/vvsip/ansip/VvsipTask.java
  71. 591 0
      AmDemo_R/src/com/vvsip/ansip/video/VideoCameraPreview.java
  72. 293 0
      AmDemo_R/src/com/vvsip/viewsip/VideoDisplay.java
  73. 1 0
      README.md
  74. 1 0
      app/.gitignore
  75. 94 0
      app/build.gradle
  76. BIN
      app/keystore/callingbed.jks
  77. BIN
      app/keystore/wdkl_bed.jks
  78. 139 0
      app/keystore_wuyuqing_3128/keytool-importkeypair
  79. 1 0
      app/keystore_wuyuqing_3128/password.txt
  80. BIN
      app/keystore_wuyuqing_3128/platform.pk8
  81. 24 0
      app/keystore_wuyuqing_3128/platform.x509.pem
  82. BIN
      app/keystore_wuyuqing_3128/rk3128.jks
  83. 7 0
      app/keystore_wuyuqing_3128/rk3128_generate_key.sh
  84. 139 0
      app/keystore_wuyuqing_3128/rk3128_signapk/keytool-importkeypair
  85. BIN
      app/keystore_wuyuqing_3128/rk3128_signapk/platform.pk8
  86. 24 0
      app/keystore_wuyuqing_3128/rk3128_signapk/platform.x509.pem
  87. BIN
      app/keystore_wuyuqing_3128/rk3128_signapk/rk3128.jks
  88. 7 0
      app/keystore_wuyuqing_3128/rk3128_signapk/rk3128_generate_key.sh
  89. BIN
      app/keystore_wuyuqing_3128/rk3128_signapk/signapk.jar
  90. BIN
      app/keystore_wuyuqing_3128/signapk.jar
  91. BIN
      app/libs/core-3.2.1.jar
  92. 25 0
      app/proguard-rules.pro
  93. BIN
      app/sign_apk/platform.pk8
  94. 27 0
      app/sign_apk/platform.x509.pem
  95. BIN
      app/sign_apk/signapk.jar
  96. 1 0
      app/sign_apk/签名方法.txt
  97. 26 0
      app/src/androidTest/java/com/wdkl/callingbed/ExampleInstrumentedTest.java
  98. 105 0
      app/src/main/AndroidManifest.xml
  99. 26 0
      app/src/main/aidl/android/content/pm/IPackageDataObserver.aidl
  100. 0 0
      app/src/main/aidl/android/content/pm/IPackageDeleteObserver.aidl

+ 71 - 0
.gitignore

@@ -0,0 +1,71 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+### Android template
+# Built application files
+*.apk
+*.ap_
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/dictionaries
+.idea/libraries
+.idea/misc.xml
+.idea/modules.xml
+
+# Keystore files
+# Uncomment the following line if you do not want to check your keystore files in.
+#*.jks
+
+# External native build folder generated in Android Studio 2.2 and later
+
+
+# Google Services (e.g. APIs or Firebase)
+google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+
+

BIN
.idea/caches/build_file_checksums.ser


BIN
.idea/caches/gradle_models.ser


+ 113 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,113 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <codeStyleSettings language="XML">
+      <arrangement>
+        <rules>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:android</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:id</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>style</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>ANDROID_ATTRIBUTE_ORDER</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>.*</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+        </rules>
+      </arrangement>
+    </codeStyleSettings>
+  </code_scheme>
+</component>

+ 12 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

BIN
AmDemo_R/$projectDir/libs/Native_Libs2.jar


+ 9 - 0
AmDemo_R/.classpath

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>

+ 33 - 0
AmDemo_R/.project

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>AmDemo_R</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 4 - 0
AmDemo_R/.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6

+ 61 - 0
AmDemo_R/AndroidManifest.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.vvsip.amdemo"
+    android:versionCode="2"
+    android:versionName="1.0.1" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="21" />
+    
+    <uses-permission android:name="android.permission.INTERNET" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.RECORD_AUDIO" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.READ_CONTACTS" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.WAKE_LOCK" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.CAMERA" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.BLUETOOTH" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.VIBRATE" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
+    </uses-permission>
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS">
+    </uses-permission>   
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
+    </uses-permission>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+         >
+        
+        <service
+            android:name="com.vvsip.ansip.VvsipService"
+            android:icon="@drawable/ic_launcher" >
+        </service>
+        
+
+
+    </application>
+
+</manifest>

+ 39 - 0
AmDemo_R/build.gradle

@@ -0,0 +1,39 @@
+apply plugin: 'com.android.library'
+
+dependencies {
+    provided fileTree(include: ['*.jar'], dir: 'libs')
+}
+
+android {
+    compileSdkVersion 26
+    buildToolsVersion "26.0.1"
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            resources.srcDirs = ['src']
+            aidl.srcDirs = ['src']
+            renderscript.srcDirs = ['src']
+            res.srcDirs = ['res']
+            assets.srcDirs = ['assets']
+        }
+
+        // Move the tests to tests/java, tests/res, etc...
+        instrumentTest.setRoot('tests')
+
+        // Move the build types to build-types/<type>
+        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
+        // This moves them out of them default location under src/<type>/... which would
+        // conflict with src/ being used by the main source set.
+        // Adding new build types or product flavors should be accompanied
+        // by a similar customization.
+        debug.setRoot('build-types/debug')
+        release.setRoot('build-types/release')
+    }
+
+    sourceSets {
+        main {
+            jniLibs.srcDirs = ['libs']
+        }
+    }
+}

BIN
AmDemo_R/ic_launcher-web.png


BIN
AmDemo_R/keystore


BIN
AmDemo_R/keystorefile/keystore.jks


BIN
AmDemo_R/libs/android-support-v4.jar


BIN
AmDemo_R/libs/armeabi-v7a/libcheckcpu.so


BIN
AmDemo_R/libs/armeabi-v7a/libvvsip-v7a-neon.so


BIN
AmDemo_R/libs/armeabi-v7a/libvvsip-v7a.so


BIN
AmDemo_R/libs/armeabi/libcheckcpu.so


BIN
AmDemo_R/libs/armeabi/libvvsip-v5.so


+ 8 - 0
AmDemo_R/lint.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+    <issue id="NewApi">
+        <ignore path="src/com/vvsip/ansip/H264MediaCodecDecoder.java" />
+        <ignore path="src/com/vvsip/ansip/H264MediaCodecEncoder.java" />
+        <ignore path="src/com/vvsip/ansip/VvsipService.java" />
+    </issue>
+</lint>

+ 20 - 0
AmDemo_R/proguard-project.txt

@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 15 - 0
AmDemo_R/project.properties

@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-21
+android.library.reference.1=../appcompat_v7

BIN
AmDemo_R/res/drawable-hdpi/ic_call_end_white_48dp.png


BIN
AmDemo_R/res/drawable-hdpi/ic_launcher.png


BIN
AmDemo_R/res/drawable-hdpi/ic_videocam_off_white_48dp.png


BIN
AmDemo_R/res/drawable-mdpi/ic_launcher.png


BIN
AmDemo_R/res/drawable-xhdpi/ic_launcher.png


BIN
AmDemo_R/res/drawable-xxhdpi/ic_launcher.png


+ 169 - 0
AmDemo_R/res/layout/activity_main.xml

@@ -0,0 +1,169 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.vvsip.amdemo.MainActivity" >
+
+    <FrameLayout
+        android:id="@+id/content_frame"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:orientation="vertical" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <EditText
+                android:id="@+id/server_addr"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:ems="10"
+                android:text="192.168.1.103:5060" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <EditText
+                android:id="@+id/userphone"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:ems="10"
+                android:text="1001" >
+
+                <requestFocus />
+            </EditText>
+
+            <EditText
+                android:id="@+id/passwd"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:ems="10"
+                android:text="1234" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <Button
+                android:id="@+id/register"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="注册" />
+
+        </LinearLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/linearLayout1"
+        android:layout_weight="1"
+        android:orientation="vertical" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <EditText
+                android:id="@+id/callee"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="6"
+                android:text="1002" />
+
+            <Button
+                android:id="@+id/audio_call"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="打电话" />
+
+            <Button
+                android:id="@+id/add_video"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="视频" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <Button
+                android:id="@+id/end_call"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="结束通话" />
+
+            <Button
+                android:id="@+id/off_hook"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:text="接电话" />
+            
+            
+            
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+        <EditText
+            android:id="@+id/dtmf"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="6"
+            android:text="1" />
+
+        <Button
+                android:id="@+id/send_dtmf"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="发送DTMF" 
+                android:layout_weight="1"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+
+            <ScrollView
+                android:id="@+id/scrollView1"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" >
+
+                <TextView
+                    android:id="@+id/call_status"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="..." />
+            </ScrollView>
+        </LinearLayout>
+    </LinearLayout>
+
+</RelativeLayout>

+ 85 - 0
AmDemo_R/res/layout/splash_layout.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:layout_gravity="center"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:id="@+id/LinearLayout03"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_weight="1"
+        android:orientation="horizontal" >
+
+        <ImageView
+            android:id="@+id/ImageView01"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom|center"
+            android:contentDescription="www.vvsip.com"
+            android:src="@drawable/ic_launcher" >
+        </ImageView>
+
+        <LinearLayout
+            android:id="@+id/LinearLayout01"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="bottom|center"
+            android:orientation="vertical" >
+
+            <TextView
+                android:id="@+id/TextView01"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/app_name" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_version"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:text="customized by vvsip" >
+            </TextView>
+        </LinearLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/LinearLayout05"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginTop="40dp"
+        android:layout_weight="1"
+        android:orientation="vertical" >
+
+        <TextView
+            android:id="@+id/my_version"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:text="V2.0:www.vvsip.com\nV1.0:www.vv-net.com" >
+        </TextView>
+
+        <TextView
+            android:id="@+id/TextView_link"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:text="QQ272108638"
+            android:visibility="gone" >
+        </TextView>
+
+        <TextView
+            android:id="@+id/TextView_licencelink"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:text="copyright by vvsip"
+            android:visibility="gone" >
+        </TextView>
+    </LinearLayout>
+
+</LinearLayout>

+ 200 - 0
AmDemo_R/res/layout/video_camera.xml

@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/TopLevelView"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+
+    <com.vvsip.viewsip.VideoDisplay
+        android:id="@+id/video_view2"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"/>
+
+    <com.vvsip.ansip.video.VideoCameraPreview
+        android:id="@+id/camera_preview2"
+        android:layout_width="160dp"
+        android:layout_height="120dp"
+        android:layout_gravity="bottom|end"
+        android:layout_marginBottom="50dp"
+        android:layout_marginLeft="3dp"
+        android:layout_marginRight="3dp" >
+    </com.vvsip.ansip.video.VideoCameraPreview>
+
+    <LinearLayout
+        android:id="@+id/ButtonRow"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:gravity="center" >
+
+        <!-- HANG BUTTON -->
+
+        <ImageButton
+            android:id="@+id/Button_hang"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_marginLeft="3dp"
+            android:layout_marginRight="3dp"
+            android:layout_weight="1"
+            android:background="#f22121"
+            android:clickable="true"
+            android:contentDescription="挂断"
+            android:focusable="false"
+            android:minHeight="56dp"
+            android:src="@drawable/ic_call_end_white_48dp" />
+
+        <!-- STOP VIDEO BUTTON -->
+
+        <ImageButton
+            android:id="@+id/Button_stopvideo"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:layout_marginLeft="3dp"
+            android:layout_marginRight="3dp"
+            android:layout_weight="1"
+            android:background="#f22121"
+            android:clickable="true"
+            android:contentDescription="previous"
+            android:focusable="false"
+            android:minHeight="56dp"
+            android:src="@drawable/ic_videocam_off_white_48dp" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ButtonStatistics"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:gravity="center"
+        android:orientation="vertical" >
+
+        <LinearLayout
+            android:id="@+id/LinearLayoutAudio"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical|center_horizontal" >
+
+            <TextView
+                android:id="@+id/TextView_uploadrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="up_kbps"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_downloadrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="down_kbps"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_lossrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="loss_percent"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_remotelossrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:textColor="#ffff4444"
+                android:text="loss_percent"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+            </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/LinearLayoutVideo"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical|center_horizontal" >
+
+            <TextView
+                android:id="@+id/TextView_videouploadrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="up_kbps"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_videodownloadrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="down_kbps"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_videolossrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_marginRight="10dp"
+                android:layout_marginEnd="10dp"
+                android:textColor="#ffff4444"
+                android:text="loss_percent"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+
+            <TextView
+                android:id="@+id/TextView_videoremotelossrate"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:textColor="#ffff4444"
+                android:text="loss_percent"
+                android:textSize="12sp"
+                android:visibility="gone" >
+            </TextView>
+            </LinearLayout>
+    </LinearLayout>
+
+</FrameLayout>

+ 3 - 0
AmDemo_R/res/menu/main.xml

@@ -0,0 +1,3 @@
+<menu xmlns:tools="http://schemas.android.com/tools"
+    tools:context="com.vvsip.amdemo.MainActivity">
+</menu>

BIN
AmDemo_R/res/raw/holdmusic.wav


BIN
AmDemo_R/res/raw/ringback.wav


+ 8 - 0
AmDemo_R/res/values-v11/styles.xml

@@ -0,0 +1,8 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+
+</resources>

+ 9 - 0
AmDemo_R/res/values-v14/styles.xml

@@ -0,0 +1,9 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+
+</resources>

+ 10 - 0
AmDemo_R/res/values-w820dp/dimens.xml

@@ -0,0 +1,10 @@
+<resources>
+
+    <!--
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>

+ 7 - 0
AmDemo_R/res/values/dimens.xml

@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>

+ 87 - 0
AmDemo_R/res/values/preference_values.xml

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string-array name="listProtocolDisplay" translatable="false">
+        <item>UDP</item>
+        <item>TCP</item>
+        <item>TLS</item>
+    </string-array>
+    <string-array name="listProtocolValue" translatable="false">
+        <item>UDP</item>
+        <item>TCP</item>
+        <item>TLS</item>
+    </string-array>
+    <string-array name="listCameraFps" translatable="false">
+        <item>5</item>
+        <item>10</item>
+        <item>15</item>
+        <item>20</item>
+    </string-array>
+    <string-array name="listCameraFpsValue" translatable="false">
+        <item>5</item>
+        <item>10</item>
+        <item>15</item>
+        <item>20</item>
+    </string-array>
+    <string-array name="listCameraSize" translatable="false">
+        <item>default</item>
+        <item>small</item>
+        <item>normal</item>
+        <item>large</item>
+        <item>HD</item>
+    </string-array>
+    <string-array name="listCameraSizeValue" translatable="false">
+        <item>default</item>
+        <item>small</item>
+        <item>normal</item>
+        <item>large</item>
+        <item>HD</item>
+    </string-array>
+    <string-array name="listVideoUploadRate" translatable="false">
+        <item>64</item>
+        <item>128</item>
+        <item>256</item>
+        <item>512</item>
+        <item>1024</item>
+    </string-array>
+    <string-array name="listVideoUploadRateValue" translatable="false">
+        <item>64</item>
+        <item>128</item>
+        <item>256</item>
+        <item>512</item>
+        <item>1024</item>
+    </string-array>
+    <string-array name="listVideoDownloadRate" translatable="false">
+        <item>64</item>
+        <item>128</item>
+        <item>256</item>
+        <item>512</item>
+        <item>1024</item>
+    </string-array>
+    <string-array name="listVideoDownloadRateValue" translatable="false">
+        <item>64</item>
+        <item>128</item>
+        <item>256</item>
+        <item>512</item>
+        <item>1024</item>
+    </string-array>
+    <string-array name="listEncryptionDisplay" translatable="false">
+        <item>RTP</item>
+        <item>optional SRTP</item>
+        <item>SRTP</item>
+    </string-array>
+    <string-array name="listEncryptionValue" translatable="false">
+        <item>RTP</item>
+        <item>optional SRTP</item>
+        <item>SRTP</item>
+    </string-array>
+    <string-array name="listAudioProcessingAlternative" translatable="false">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
+    <string-array name="listAudioProcessingAlternativeValue" translatable="false">
+        <item>webrtc audio processing</item>
+        <item>speex audio processing</item>
+    </string-array>
+    
+</resources>

+ 74 - 0
AmDemo_R/res/values/strings.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">AmDemo</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="action_settings">Settings</string>
+    <string name="advanced_pref">Advanced Preferences</string>
+    <string name="pref_audio_advanced">Audio Options</string>
+    <string name="pref_audio_fastoutputsetup">Fast Input Setup</string>
+    <string name="pref_audio_fastinputsetup">Fast Output Setup</string>
+    <string name="pref_videocodec_advanced">Video Options</string>
+    <string name="pref_videocodec_h264_hw_decoder">HW H264 Decoder</string>
+    <string name="pref_videocodec_h264_hw_encoder">HW H264 Encoder</string>
+    <string name="pref_video_disablecamera">Disable Camera</string>
+    <string name="pref_echo_limiter">Echo Limitation</string>
+    <string name="pref_threshold">Threshold (0.02)</string>
+    <string name="pref_speed">Speed (0.02)</string>
+    <string name="pref_force">Force (50.0)</string>
+    <string name="pref_sustain">Sustain (300ms)</string>
+    <string name="pref_apm_alternative">Audio Module</string>
+    <string name="pref_agc">AGC</string>
+    <string name="pref_highpassfilter">High Pass Filter</string>
+    <string name="pref_noisesuppression">Noise Suppression</string>
+    
+    <string name="pref_audiocodec_g729" translatable="false">G729</string>
+    <string name="pref_audiocodec_silkwb" translatable="false">SILK (16Khz)</string>
+    <string name="pref_audiocodec_opus" translatable="false">OPUS</string>
+    <string name="pref_audiocodec_isac16" translatable="false">iSAC (16Khz)</string>
+    <string name="pref_audiocodec_speex16" translatable="false">speex (16KHz)</string>
+    <string name="pref_audiocodec_g722" translatable="false">g722 (16Khz)</string>
+    <string name="pref_audiocodec_silknb" translatable="false">SILK (8Khz)</string>
+    <string name="pref_audiocodec_speex8" translatable="false">speex (8KHz)</string>
+    <string name="pref_audiocodec_ilbc" translatable="false">iLBC (30ms)</string>
+    <string name="pref_audiocodec_gsm" translatable="false">GSM</string>
+    <string name="pref_audiocodec_pcmu" translatable="false">PCMU</string>
+    <string name="pref_audiocodec_pcma" translatable="false">PCMA</string>
+    <string name="pref_videocodec_vp8" translatable="false">VP8</string>
+    <string name="pref_videocodec_h264" translatable="false">H264</string>
+    <string name="pref_videocodec_h2631998" translatable="false">H263&#8211;1998</string>
+    <string name="pref_videocodec_h263" translatable="false">H263</string>
+    <string name="pref_videocodec_mp4v" translatable="false">MP4V&#8211;ES</string>
+    
+    <string name="pref_domain">Domain</string>
+    <string name="pref_username">Username</string>
+    <string name="pref_password">Password</string>
+    <string name="pref_optional_settings">Extra SIP Settings</string>
+    <string name="pref_ringer_duration">Ringer Duration</string>
+    <string name="pref_local_sip_port">Local SIP Port</string>
+    <string name="pref_rtp_port_range">RTP Port range</string>
+    <string name="pref_sip_identity">SIP Identity</string>
+    <string name="pref_outboundproxy">SIP Outbound Proxy</string>
+    <string name="pref_stunserver">STUN Server</string>
+    <string name="pref_transportlayer">Protocol</string>
+    <string name="pref_interval">refresh interval</string>
+    <string name="pref_autostart">Start On Boot</string>
+    <string name="pref_audio_parameters">Audio Parameters</string>
+    <string name="pref_echocancellation">Echo Cancellation</string>
+    <string name="pref_haveearpiecemode">Smartphone (vs tablet)?</string>
+    <string name="pref_apminearpiecemode">Audio Module in earpiece mode</string>
+    <string name="pref_audiocodec">Audio Codecs</string>
+    <string name="pref_audiogain">Audio Gains</string>
+    <string name="pref_outputgain_speakeroff">Output</string>
+    <string name="pref_inputgain_speakeroff">Input</string>
+    <string name="pref_outputgain_speakeron">Output (Speaker Mode)</string>
+    <string name="pref_inputgain_speakeron">Input (Speaker Mode)</string>
+    <string name="pref_video_parameters">Video Parameters</string>
+    <string name="pref_video_fps">Frame per second (fps)</string>
+    <string name="pref_video_size">Image Size</string>
+    <string name="pref_videouploadrate">Max Upload Rate</string>
+    <string name="pref_videodownloadrate">Max Download Rate</string>
+    <string name="pref_videocodec">Video Codec</string>
+    <string name="pref_encryption">encryption</string>
+
+</resources>

+ 10 - 0
AmDemo_R/res/values/styles.xml

@@ -0,0 +1,10 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+
+    <!-- Application theme. -->
+
+</resources>

+ 17 - 0
AmDemo_R/res/xml/advanced_pref.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+  xmlns:android="http://schemas.android.com/apk/res/android">
+
+<PreferenceCategory android:title="@string/advanced_pref">
+<PreferenceScreen android:title="@string/pref_audio_advanced" android:key="key_audio_advanced">
+    <CheckBoxPreference android:title="@string/pref_audio_fastoutputsetup" android:key="key_audio_fastoutputsetup" android:defaultValue="true"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_audio_fastinputsetup" android:key="key_audio_fastinputsetup" android:defaultValue="false"></CheckBoxPreference>
+</PreferenceScreen>
+
+<PreferenceScreen android:title="@string/pref_videocodec_advanced" android:key="key_videocodec_advanced">
+    <CheckBoxPreference android:title="@string/pref_videocodec_h264_hw_encoder" android:key="key_videocodec_h264_hw_encoder" android:defaultValue="false"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_videocodec_h264_hw_decoder" android:key="key_videocodec_h264_hw_decoder" android:defaultValue="false"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_video_disablecamera" android:key="key_video_disablecamera" android:defaultValue="false"></CheckBoxPreference>
+</PreferenceScreen>
+</PreferenceCategory> 
+</PreferenceScreen>

+ 5 - 0
AmDemo_R/res/xml/pref_media_advanced_audio.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <CheckBoxPreference android:title="@string/pref_audio_fastoutputsetup" android:key="key_audio_fastoutputsetup" android:defaultValue="true"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_audio_fastinputsetup" android:key="key_audio_fastinputsetup" android:defaultValue="false"></CheckBoxPreference>
+</PreferenceScreen>

+ 7 - 0
AmDemo_R/res/xml/pref_media_advanced_video.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="key_videocodec_advanced">
+    <CheckBoxPreference android:title="@string/pref_videocodec_h264_hw_encoder" android:key="key_videocodec_h264_hw_encoder" android:defaultValue="false"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_videocodec_h264_hw_decoder" android:key="key_videocodec_h264_hw_decoder" android:defaultValue="false"></CheckBoxPreference>
+    <CheckBoxPreference android:title="@string/pref_video_disablecamera" android:key="key_video_disablecamera" android:defaultValue="false"></CheckBoxPreference>
+</PreferenceScreen>

+ 167 - 0
AmDemo_R/res/xml/pref_media_audio.xml

@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <ListPreference
+        android:defaultValue="0"
+        android:entries="@array/listAudioProcessingAlternativeValue"
+        android:entryValues="@array/listAudioProcessingAlternative"
+        android:key="key_apm_alternative"
+        android:title="@string/pref_apm_alternative" >
+    </ListPreference>
+
+    <CheckBoxPreference
+        android:defaultValue="true"
+        android:key="key_agc"
+        android:title="@string/pref_agc" >
+    </CheckBoxPreference>
+    <CheckBoxPreference
+        android:defaultValue="true"
+        android:key="key_noisesuppression"
+        android:title="@string/pref_noisesuppression" >
+    </CheckBoxPreference>
+    <CheckBoxPreference
+        android:defaultValue="true"
+        android:key="key_highpassfilter"
+        android:title="@string/pref_highpassfilter" >
+    </CheckBoxPreference>
+    <CheckBoxPreference
+        android:defaultValue="true"
+        android:key="key_echocancellation"
+        android:title="@string/pref_echocancellation" >
+    </CheckBoxPreference>
+
+    <PreferenceScreen
+        android:key="key_ps_echo_limiter"
+        android:title="@string/pref_echo_limiter" >
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="key_echo_limiter"
+            android:title="@string/pref_echo_limiter" >
+        </CheckBoxPreference>
+
+        <EditTextPreference
+            android:defaultValue="0.02"
+            android:key="key_threshold"
+            android:numeric="decimal"
+            android:title="@string/pref_threshold" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="0.02"
+            android:key="key_speed"
+            android:numeric="decimal"
+            android:title="@string/pref_speed" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="50.0"
+            android:key="key_force"
+            android:numeric="decimal"
+            android:title="@string/pref_force" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="300"
+            android:key="key_sustain"
+            android:numeric="integer"
+            android:title="@string/pref_sustain" >
+        </EditTextPreference>
+    </PreferenceScreen>
+
+    <CheckBoxPreference
+        android:key="key_haveearpiecemode"
+        android:title="@string/pref_haveearpiecemode" >
+    </CheckBoxPreference>
+    <CheckBoxPreference
+        android:defaultValue="false"
+        android:key="key_apm_in_earpiecemode"
+        android:title="@string/pref_apminearpiecemode" >
+    </CheckBoxPreference>
+
+    <PreferenceScreen android:title="@string/pref_audiogain" >
+        <EditTextPreference
+            android:defaultValue="1.0"
+            android:key="key_outputgain_speakeroff"
+            android:numeric="decimal"
+            android:title="@string/pref_outputgain_speakeroff" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="1.0"
+            android:key="key_inputgain_speakeroff"
+            android:numeric="decimal"
+            android:title="@string/pref_inputgain_speakeroff" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="1.0"
+            android:key="key_outputgain_speakeron"
+            android:numeric="decimal"
+            android:title="@string/pref_outputgain_speakeron" >
+        </EditTextPreference>
+        <EditTextPreference
+            android:defaultValue="1.0"
+            android:key="key_inputgain_speakeron"
+            android:numeric="decimal"
+            android:title="@string/pref_inputgain_speakeron" >
+        </EditTextPreference>
+    </PreferenceScreen>
+    <PreferenceScreen android:title="@string/pref_audiocodec" >
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_g729"
+            android:title="@string/pref_audiocodec_g729" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_silknb"
+            android:title="@string/pref_audiocodec_silknb" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_ilbc"
+            android:title="@string/pref_audiocodec_ilbc" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="key_audiocodec_pcmu"
+            android:title="@string/pref_audiocodec_pcmu" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="key_audiocodec_pcma"
+            android:title="@string/pref_audiocodec_pcma" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_silkwb"
+            android:title="@string/pref_audiocodec_silkwb" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_opus"
+            android:title="@string/pref_audiocodec_opus" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_isac16"
+            android:title="@string/pref_audiocodec_isac16" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_speex16"
+            android:title="@string/pref_audiocodec_speex16" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="key_audiocodec_g722"
+            android:title="@string/pref_audiocodec_g722" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_speex8"
+            android:title="@string/pref_audiocodec_speex8" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_audiocodec_gsm"
+            android:title="@string/pref_audiocodec_gsm" >
+        </CheckBoxPreference>
+    </PreferenceScreen>
+
+</PreferenceScreen>

+ 62 - 0
AmDemo_R/res/xml/pref_media_video.xml

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <ListPreference
+        android:defaultValue="5"
+        android:entries="@array/listCameraFpsValue"
+        android:entryValues="@array/listCameraFps"
+        android:key="key_video_fps"
+        android:title="@string/pref_video_fps" >
+    </ListPreference>
+    <ListPreference
+        android:defaultValue="normal"
+        android:entries="@array/listCameraSizeValue"
+        android:entryValues="@array/listCameraSize"
+        android:key="key_video_size"
+        android:title="@string/pref_video_size" >
+    </ListPreference>
+    <ListPreference
+        android:defaultValue="512"
+        android:entries="@array/listVideoUploadRateValue"
+        android:entryValues="@array/listVideoUploadRate"
+        android:key="key_videouploadrate"
+        android:title="@string/pref_videouploadrate" >
+    </ListPreference>
+    <ListPreference
+        android:defaultValue="512"
+        android:entries="@array/listVideoDownloadRateValue"
+        android:entryValues="@array/listVideoDownloadRate"
+        android:key="key_videodownloadrate"
+        android:title="@string/pref_videodownloadrate" >
+    </ListPreference>
+
+    <PreferenceScreen android:title="@string/pref_videocodec" >
+        <CheckBoxPreference
+            android:defaultValue="true"
+            android:key="key_videocodec_h264"
+            android:title="@string/pref_videocodec_h264" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_videocodec_vp8"
+            android:title="@string/pref_videocodec_vp8" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_videocodec_mp4v"
+            android:title="@string/pref_videocodec_mp4v" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_videocodec_h2631998"
+            android:title="@string/pref_videocodec_h2631998" >
+        </CheckBoxPreference>
+        <CheckBoxPreference
+            android:defaultValue="false"
+            android:key="key_videocodec_h263"
+            android:title="@string/pref_videocodec_h263" >
+        </CheckBoxPreference>
+        
+    </PreferenceScreen>
+
+</PreferenceScreen>

+ 21 - 0
AmDemo_R/res/xml/pref_sip_account.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <EditTextPreference
+        android:inputType="textNoSuggestions"
+        android:key="key_domain"
+        android:title="@string/pref_domain" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:inputType="textNoSuggestions"
+        android:key="key_username"
+        android:title="@string/pref_username" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:inputType="textPassword"
+        android:key="key_password"
+        android:password="true"
+        android:title="@string/pref_password" >
+    </EditTextPreference>
+
+</PreferenceScreen>

+ 66 - 0
AmDemo_R/res/xml/pref_sip_optional.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <EditTextPreference
+        android:defaultValue="40"
+        android:key="key_ringer_duration"
+        android:numeric="integer"
+        android:title="@string/pref_ringer_duration" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:defaultValue="0"
+        android:key="key_local_sip_port"
+        android:numeric="integer"
+        android:title="@string/pref_local_sip_port" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:defaultValue="40100"
+        android:key="key_rtp_port_range"
+        android:numeric="integer"
+        android:title="@string/pref_rtp_port_range" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:inputType="textNoSuggestions"
+        android:key="key_outboundproxy"
+        android:title="@string/pref_outboundproxy" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:inputType="textNoSuggestions"
+        android:key="key_stunserver"
+        android:title="@string/pref_stunserver" >
+    </EditTextPreference>
+
+    <ListPreference
+        android:defaultValue="UDP"
+        android:entries="@array/listProtocolDisplay"
+        android:entryValues="@array/listProtocolValue"
+        android:key="key_protocol"
+        android:title="@string/pref_transportlayer" >
+    </ListPreference>
+
+    <EditTextPreference
+        android:defaultValue="600"
+        android:key="key_interval"
+        android:numeric="integer"
+        android:title="@string/pref_interval" >
+    </EditTextPreference>
+    <EditTextPreference
+        android:inputType="textNoSuggestions"
+        android:key="key_identity"
+        android:title="@string/pref_sip_identity" >
+    </EditTextPreference>
+
+    <CheckBoxPreference
+        android:key="key_autostart"
+        android:title="@string/pref_autostart" >
+    </CheckBoxPreference>
+
+    <ListPreference
+        android:defaultValue="RTP"
+        android:entries="@array/listEncryptionDisplay"
+        android:entryValues="@array/listEncryptionValue"
+        android:key="key_encryption"
+        android:title="@string/pref_encryption" >
+    </ListPreference>
+
+</PreferenceScreen>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1264 - 0
AmDemo_R/src/com/vvsip/amdemo/FragmentInVideoCall.java


+ 376 - 0
AmDemo_R/src/com/vvsip/amdemo/MainActivity.java

@@ -0,0 +1,376 @@
+//package com.vvsip.amdemo;
+//
+//import android.annotation.SuppressLint;
+//import android.app.Fragment;
+//import android.app.FragmentManager;
+//import android.app.FragmentTransaction;
+//import android.os.Build;
+//import android.os.Bundle;
+//import android.os.Handler;
+//import android.os.Message;
+//import android.support.v7.app.ActionBarActivity;
+//import android.util.Log;
+//import android.view.Menu;
+//import android.view.MenuItem;
+//import android.view.View;
+//import android.view.WindowManager;
+//import android.widget.Button;
+//import android.widget.EditText;
+//import android.widget.FrameLayout;
+//import android.widget.TextView;
+//
+//import com.vvsip.ansip.IVvsipService;
+//import com.vvsip.ansip.IVvsipServiceListener;
+//import com.vvsip.ansip.VvsipCall;
+//import com.vvsip.ansip.VvsipService;
+//import com.vvsip.ansip.VvsipTask;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//
+///*
+// * ������Activity
+// */
+//public class MainActivity extends ActionBarActivity implements
+//		View.OnClickListener, IVvsipServiceListener {
+//
+//	private EditText serverAddr;
+//	private EditText userphone;
+//	private EditText passwd;
+//	private EditText callee;
+//
+//	private TextView callStatus;
+//
+//	private Button mButton_register;
+//	private Button mButton_audioCall;
+//	private Button mButton_endCall;
+//	private Button mButton_offHook;
+//	private Button mButton_addVideo;
+//	private EditText dtmf;
+//	private Button mButton_sendDTMF;
+//
+//
+//	static String mTag = "MainActivity";
+//	private List<VvsipCall> mVvsipCalls = null;
+//
+//	private String lan_callee;
+//
+//	@Override
+//	protected void onCreate(Bundle savedInstanceState) {
+//		super.onCreate(savedInstanceState);
+//		setContentView(R.layout.activity_main);
+//
+//		serverAddr = (EditText) findViewById(R.id.server_addr);
+//		userphone = (EditText) findViewById(R.id.userphone);
+//		passwd = (EditText) findViewById(R.id.passwd);
+//		callee = (EditText) findViewById(R.id.callee);
+//
+//		callStatus = (TextView) findViewById(R.id.call_status);
+//
+//		mButton_register = (Button) findViewById(R.id.register);
+//		mButton_audioCall = (Button) findViewById(R.id.audio_call);
+//		mButton_endCall = (Button) findViewById(R.id.end_call);
+//		mButton_offHook = (Button) findViewById(R.id.off_hook);
+//		mButton_addVideo = (Button) findViewById(R.id.add_video);
+//		mButton_sendDTMF = (Button) findViewById(R.id.send_dtmf);
+//
+//
+//
+//		mButton_register.setOnClickListener(this);
+//		mButton_audioCall.setOnClickListener(this);
+//		mButton_endCall.setOnClickListener(this);
+//		mButton_offHook.setOnClickListener(this);
+//		mButton_addVideo.setOnClickListener(this);
+//		mButton_sendDTMF.setOnClickListener(this);
+//
+//		IVvsipService _service = VvsipService.getService();
+//		Log.i(mTag, "lifecycle // _service");
+//		if (_service != null) {
+//
+//			_service.addListener(this);
+//			_service.setMessageHandler(messageHandler);
+//			Log.i(mTag, "lifecycle // addListener");
+//		} else {
+//			Log.i(mTag, "lifecycle // _service==null");
+//		}
+//
+//		if (mVvsipCalls == null) {
+//			mVvsipCalls = new ArrayList<VvsipCall>();
+//		}
+//
+//	}
+//
+//	@Override
+//	public void onDestroy() {
+//		IVvsipService _service = VvsipService.getService();
+//		if (_service != null)
+//			_service.removeListener(this);
+//		if (mVvsipCalls != null) {
+//			mVvsipCalls.clear();
+//			mVvsipCalls = null;
+//		}
+//		super.onDestroy();
+//		Log.i(mTag, "lifecycle // onDestroy");
+//	}
+//
+//	@Override
+//	public boolean onCreateOptionsMenu(Menu menu) {
+//		// Inflate the menu; this adds items to the action bar if it is present.
+//		getMenuInflater().inflate(R.menu.main, menu);
+//		return true;
+//	}
+//
+//	@Override
+//	public boolean onOptionsItemSelected(MenuItem item) {
+//		// Handle action bar item clicks here. The action bar will
+//		// automatically handle clicks on the Home/Up button, so long
+//		// as you specify a parent activity in AndroidManifest.xml.
+//		int id = item.getItemId();
+//		if (id == R.id.action_settings) {
+//			return true;
+//		}
+//		return super.onOptionsItemSelected(item);
+//	}
+//
+//	@Override
+//	public void onNewVvsipCallEvent(final VvsipCall call) {
+//
+//		MainActivity.this.runOnUiThread(new Runnable() {
+//			public void run() {
+//				try {
+//					if (call == null) {
+//						return;
+//					}
+//
+//					if (mVvsipCalls == null)
+//						return;
+//					mVvsipCalls.add(call);
+//
+//					if (Build.VERSION.SDK_INT >= 5) {
+//						getWindow()
+//								.addFlags( // WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+//											// |
+//										WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+//												| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+//												| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+//					}
+//
+//				} catch (Exception e) {
+//					Log.e(mTag, "onNewVvsipCallEvent: " + e);
+//				}
+//			}
+//		});
+//	}
+//
+//	@Override
+//	public void onStatusVvsipCallEvent(VvsipCall call) {
+//		Log.d("SIPTES","call :"+call.mState);
+//	}
+//
+//	@Override
+//	public void onRemoveVvsipCallEvent(final VvsipCall call) {
+//
+//		MainActivity.this.runOnUiThread(new Runnable() {
+//			public void run() {
+//				try {
+//					if (call == null) {
+//						return;
+//					}
+//
+//					// 4 crash detected here for 4.0.9 with mVvsipCalls=NULL
+//					if (mVvsipCalls == null)
+//						return;
+//					mVvsipCalls.remove(call);
+//
+//					if (mVvsipCalls.size() == 0) {
+//						if (Build.VERSION.SDK_INT >= 5) {
+//							getWindow()
+//									.clearFlags( // WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+//													// |
+//											WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+//													| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+//													| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+//						}
+//					}
+//				} catch (Exception e) {
+//					Log.e(mTag, "onRemoveVvsipCallEvent: " + e);
+//				}
+//			}
+//		});
+//	}
+//
+//	@Override
+//	public void onRegistrationEvent(final int rid, final String remoteUri,
+//			final int code, String reason) {
+//
+//	}
+//
+//	@SuppressLint("HandlerLeak")
+//	private Handler messageHandler = new Handler() {
+//
+//		@Override
+//		public void handleMessage(Message msg) {
+//			Log.i(mTag, "VvsipEvent received (?" + msg.what + " " + msg.arg1
+//					+ " " + msg.arg2 + ")\n");
+//			Log.i(mTag, "#" + msg.obj);
+//			callStatus.setText("" + msg.obj + callStatus.getText());
+//
+//			if(msg.obj.toString().contains("autocall")){ //��������
+//				VvsipCall pCall = null;
+//				Log.e(mTag, "onClick1");
+//				for (VvsipCall _pCall : mVvsipCalls) {
+//					if(_pCall.cid > 0)
+//						Log.e(mTag, "state#"+_pCall.mState);
+//					if (_pCall.cid > 0 && _pCall.mState <= 2) {
+//						pCall = _pCall;
+//						break;
+//					}
+//				}
+//				Log.e(mTag, "onClick2");
+//				if (pCall == null)
+//					return;
+//				Log.e(mTag, "onClick3#"+pCall.mState);
+//				IVvsipService _service = VvsipService.getService();
+//				if (_service == null)
+//					return;
+//				VvsipTask _vvsipTask = _service.getVvsipTask();
+//				if (_vvsipTask == null)
+//					return;
+//				pCall.stop();
+//				_service.setSpeakerModeOff();
+//			}
+//
+//
+//		}
+//
+//	};
+//
+//	@Override
+//	public void onClick(View v) {
+//
+//		/*
+//		 * ע��
+//		 */
+//		if (v == mButton_register) {
+//			MainActivity.this.runOnUiThread(new Runnable() {
+//				public void run() {
+//					IVvsipService _service = VvsipService.getService();
+//					if (_service != null) {
+//						// _service.StartVvsipLayer();
+//
+//						_service.register(serverAddr.getText().toString(),
+//								userphone.getText().toString(), passwd
+//										.getText().toString());
+//					}
+//				}
+//			});
+//			return;
+//		}
+//		/*
+//		 * �������
+//		 */
+//		if (v == mButton_audioCall) {
+//			if (callee.getText().length() == 0)
+//				return;
+//			MainActivity.this.runOnUiThread(new Runnable() {
+//				public void run() {
+//					IVvsipService _service = VvsipService.getService();
+//					if (_service == null)
+//						return;
+//					_service.initiateOutgoingCall(callee.getText().toString());
+//				}
+//			});
+//			return;
+//		}
+//		/*
+//		 * ����ͨ��
+//		 */
+//		if (v == mButton_endCall) {
+//			VvsipCall pCall = null;
+//			Log.e(mTag, "onClick1");
+//			for (VvsipCall _pCall : mVvsipCalls) {
+//				if(_pCall.cid > 0)
+//					Log.e(mTag, "state#"+_pCall.mState);
+//				if (_pCall.cid > 0 && _pCall.mState <= 2) {
+//					pCall = _pCall;
+//					break;
+//				}
+//			}
+//			Log.e(mTag, "onClick2");
+//			if (pCall == null)
+//				return;
+//			Log.e(mTag, "onClick3#"+pCall.mState);
+//			IVvsipService _service = VvsipService.getService();
+//			if (_service == null)
+//				return;
+//			VvsipTask _vvsipTask = _service.getVvsipTask();
+//			if (_vvsipTask == null)
+//				return;
+//			pCall.stop();
+//			_service.setSpeakerModeOff();
+//			_service.stopPlayer();   //���йҶϣ�����ֹͣ;��������Closed��Released״̬�л������������ġ�
+//									 //����HDL�DZ�û��Ч����������������һ�� ,By 20160822
+//			_service.setAudioNormalMode();
+//			return;
+//		}
+//
+//		/*
+//		 * �����绰
+//		 */
+//		if (v == mButton_offHook) {
+//			for (VvsipCall _pCall : mVvsipCalls) {
+//				if (_pCall.cid > 0 && _pCall.mState < 2 && _pCall.mIncomingCall) {
+//					// ANSWER EXISTING CALL
+//					int i = _pCall.answer(200, 1);
+//					IVvsipService _service = VvsipService.getService();
+//					if (_service != null) {
+//						if (i >= 0) {
+//							_service.stopPlayer();
+//							_service.setSpeakerModeOff();
+//							_service.setAudioInCallMode();
+//						}
+//					}
+//					break;
+//				}
+//			}
+//		}
+//		/*
+//		 * ������Ƶͨ��
+//		 */
+//		if (v == mButton_addVideo) {
+//			MainActivity.this.runOnUiThread(new Runnable() {
+//				public void run() {
+//					Fragment fragment = null;
+//					fragment = new FragmentInVideoCall();
+//					FragmentManager frgManager = getFragmentManager();
+//					FragmentTransaction ft = frgManager.beginTransaction()
+//							.replace(R.id.content_frame, fragment);
+//
+//					ft.addToBackStack(null);
+//					ft.commit();
+//					FrameLayout fly = (FrameLayout) MainActivity.this
+//							.findViewById(R.id.content_frame);
+//					fly.bringToFront();
+//				}
+//			});
+//		}
+//
+//		/*
+//		 * ����DTMF
+//		 */
+//		if (v == mButton_sendDTMF) {
+//			if (dtmf.getText().length() == 0)
+//				return;
+//			MainActivity.this.runOnUiThread(new Runnable() {
+//				public void run() {
+//					IVvsipService _service = VvsipService.getService();
+//					if (_service == null)
+//						return;
+//					_service.sendDTMF(dtmf.getText().toString());
+//				}
+//			});
+//			return;
+//		}
+//
+//	}
+//}

+ 220 - 0
AmDemo_R/src/com/vvsip/amdemo/SplashActivity.java

@@ -0,0 +1,220 @@
+///*
+//  vvphone is a SIP app for android.
+//  vvsip is a SIP library for softphone (SIP -rfc3261-)
+//  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+// */
+//
+//package com.vvsip.amdemo;
+//
+//import java.text.SimpleDateFormat;
+//import java.util.Date;
+//
+//import com.vvsip.ansip.IVvsipService;
+//import com.vvsip.ansip.IVvsipServiceListener;
+//import com.vvsip.ansip.VvsipCall;
+//import com.vvsip.ansip.VvsipService;
+//import com.vvsip.ansip.VvsipServiceBinder;
+//import com.vvsip.ansip.VvsipTask;
+//
+//import android.app.Activity;
+//import android.app.AlertDialog;
+//import android.content.ComponentName;
+//import android.content.Context;
+//import android.content.DialogInterface;
+//import android.content.Intent;
+//import android.content.ServiceConnection;
+//import android.os.Bundle;
+//import android.os.Handler;
+//import android.text.Html;
+//import android.text.method.LinkMovementMethod;
+//import android.text.method.MovementMethod;
+//import android.util.Log;
+//import android.view.MotionEvent;
+//import android.view.View;
+//import android.widget.TextView;
+//import android.os.IBinder;
+//
+//public class SplashActivity extends Activity implements IVvsipServiceListener {
+//
+//	protected int _splashTime = 3000;
+//	protected Handler _exitHandler = null;
+//	protected Runnable _exitRunnable = null;
+//	protected Handler _startServiceHandler = null;
+//	protected Runnable _startServiceRunnable = null;
+//
+//	private ServiceConnection connection;
+//
+//	private TextView mTextView_link;
+//	private TextView mTextView_licenselink;
+//	private TextView myVersion;
+//
+//	/** Called when the activity is first created. */
+//	@Override
+//	public void onCreate(Bundle savedInstanceState) {
+//		Log.i("ActivitySplash", "lifecycle // onCreate");
+//		super.onCreate(savedInstanceState);
+//		setContentView(R.layout.splash_layout);
+//
+//		mTextView_link = (TextView) findViewById(R.id.TextView_link);
+//		if (mTextView_link != null) {
+//			MovementMethod lMM = LinkMovementMethod.getInstance();
+//			if (lMM != null) {
+//				mTextView_link.setMovementMethod(lMM);
+//				mTextView_link.setText(Html.fromHtml("www.vvsip.com"));
+//			}
+//			mTextView_licenselink = (TextView) findViewById(R.id.TextView_licencelink);
+//			if (lMM != null) {
+//				mTextView_licenselink.setMovementMethod(lMM);
+//				mTextView_licenselink.setText(Html.fromHtml("vvsip.com"));
+//			}
+//		}
+//
+//		myVersion = (TextView) findViewById(R.id.my_version);
+//		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+//		String today = formatter.format(new Date());
+//		if(today.compareTo("2016-02-08")>0){
+//			myVersion.setVisibility(View.VISIBLE);
+//			myVersion.setText(myVersion.getText()+"\n"+"This version has expired.Please contact QQ272108638");
+//		}else{
+//			myVersion.setVisibility(View.GONE);
+//		}
+//
+//		// Runnable exiting the splash screen and launching the menu
+//		_exitRunnable = new Runnable() {
+//			public void run() {
+//				exitSplash();
+//			}
+//		};
+//		// Run the exitRunnable in in _splashTime ms
+//		_exitHandler = new Handler();
+//
+//		IVvsipService _service = VvsipService.getService();
+//		if (_service != null) {
+//			_exitHandler.postDelayed(_exitRunnable, 0);
+//			return;
+//		}
+//
+//		_exitHandler.postDelayed(_exitRunnable, _splashTime);
+//
+//		_startServiceHandler = new Handler();
+//
+//		_startServiceRunnable = new Runnable() {
+//			public void run() {
+//
+//				Intent intent = new Intent(SplashActivity.this.getApplicationContext(), VvsipService.class);
+//				startService(intent);
+//
+//				connection = new ServiceConnection() {
+//					public void onServiceConnected(ComponentName name, IBinder service) {
+//						Log.i("ActivitySplash", "Connected!");
+//						IVvsipService _service = ((VvsipServiceBinder) service).getService();
+//						_service.addListener(SplashActivity.this);
+//					}
+//
+//					public void onServiceDisconnected(ComponentName name) {
+//						Log.i("ActivitySplash", "Disconnected!");
+//					}
+//				};
+//
+//				bindService(intent, connection, Context.BIND_AUTO_CREATE);
+//				Log.i("ActivitySplash", "bindService done!");
+//			}
+//		};
+//
+//		_startServiceHandler.postDelayed(_startServiceRunnable, 0);
+//	}
+//
+//	@Override
+//	public void onDestroy() {
+//		Log.i("ActivitySplash", "lifecycle // onDestroy");
+//		super.onDestroy();
+//
+//		IVvsipService _service = VvsipService.getService();
+//		if (_service != null) {
+//			_service.removeListener(this);
+//		}
+//
+//		_exitHandler.removeCallbacks(_startServiceRunnable);
+//		_exitHandler.removeCallbacks(_exitRunnable);
+//		if (connection != null) {
+//			unbindService(connection);
+//			connection = null;
+//		}
+//	}
+//
+//	@Override
+//	public boolean onTouchEvent(MotionEvent event) {
+//		if (event.getAction() == MotionEvent.ACTION_DOWN) {
+//			// Remove the exitRunnable callback from the handler queue
+//			_exitHandler.removeCallbacks(_exitRunnable);
+//			// Run the exit code manually
+//			exitSplash();
+//		}
+//		return true;
+//	}
+//
+//	private void exitSplash() {
+//		Log.i("ActivitySplash", "lifecycle // exitSplash");
+//		VvsipTask vvsipTask = VvsipTask.getVvsipTask();
+//		if (vvsipTask != null && VvsipTask.global_failure != 0) {
+//			final AlertDialog.Builder b = new AlertDialog.Builder(this);
+//			b.setIcon(R.drawable.ic_launcher);
+//			b.setTitle(getString(R.string.app_name));
+//			b.setMessage("global_installation_failure");
+//
+//			b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+//				public void onClick(DialogInterface dialog, int whichButton) {
+//					finish();
+//				}
+//			});
+//			b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+//				public void onClick(DialogInterface dialog, int whichButton) {
+//					finish();
+//				}
+//			});
+//			b.show();
+//
+//			Intent intent = new Intent(Intent.ACTION_MAIN);
+//			intent.setClass(this.getApplicationContext(), VvsipService.class);
+//			stopService(intent);
+//		} else {
+//			finish();
+//
+//			Intent intent = new Intent();
+//			intent.setClass(SplashActivity.this, MainActivity.class);
+//			startActivity(intent);
+//		}
+//	}
+//
+//	@Override
+//	public void onNewVvsipCallEvent(VvsipCall call) {
+//		// TODO Auto-generated method stub
+//
+//	}
+//
+//	@Override
+//	public void onRemoveVvsipCallEvent(VvsipCall call) {
+//		// TODO Auto-generated method stub
+//
+//	}
+//
+//	@Override
+//	public void onStatusVvsipCallEvent(VvsipCall call) {
+//		// TODO Auto-generated method stub
+//
+//	}
+//
+//	@Override
+//	public void onRegistrationEvent(int rid, String remote_uri, final int code, String reason) {
+//		SplashActivity.this.runOnUiThread(new Runnable() {
+//			public void run() {
+//				if (code >= 200 && code < 300) {
+//					// Remove the exitRunnable callback from the handler queue
+//					_exitHandler.removeCallbacks(_exitRunnable);
+//					// Run the exit code manually
+//					exitSplash();
+//				}
+//			}
+//		});
+//	}
+//}

+ 273 - 0
AmDemo_R/src/com/vvsip/ansip/AudioCompatibility.java

@@ -0,0 +1,273 @@
+package com.vvsip.ansip;
+
+import java.util.Locale;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.MediaRecorder;
+import android.os.Build;
+import android.util.Log;
+
+/*
+ * 语音兼容性解决方案,此类不必改动,可直接使用
+ */
+public class AudioCompatibility {
+
+    public static int mAudiomanager_mode_internal = AudioManager.MODE_IN_COMMUNICATION;
+    public static int mAudiomanager_mode_speakermode = AudioManager.MODE_IN_COMMUNICATION;
+    public static int mAudiomanager_wa_galaxyS = -1; 
+    public static int mAudiomanager_stream_type = AudioManager.STREAM_VOICE_CALL;
+    public static int mAudiomanager_audio_source_internal = MediaRecorder.AudioSource.MIC;
+    public static int mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.MIC;
+    
+    static public void configureAudioManagerMode(Context context)
+    {
+		Log.i("AudioCompatibility", "API level is " + Build.VERSION.SDK_INT);
+    	
+        if (Build.VERSION.SDK_INT<=4)
+			mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+        else if (Build.VERSION.SDK_INT<10)
+			mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+        else if (Build.VERSION.SDK_INT<11)
+			mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+        else 
+			mAudiomanager_mode_internal = AudioManager.MODE_IN_COMMUNICATION;
+
+        //TESTED
+    	mAudiomanager_wa_galaxyS = -1;
+        if (Build.VERSION.SDK_INT<10)
+        {
+    		if (android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-I9000")
+    				||android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("SHW-M110S")) {
+            	//low gain for MIC in all use-case: (wrong for speacker mode)
+            	mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+            	//setSpeakerphoneOn -> will use WRONG microphone with above code in speaker mode
+            	//setSpeakerphoneOff -> will use CORRECT microphone with above code in earpiece mode
+
+            	//YOU CAN USE THIS HACK INSTEAD TO HAVE HIGHER GAIN IN SPEAKER MODE:
+            	//high gain for MIC in ALL use-case: (wrong for earpiece mode)
+            	// mAudiomanager_wa_galaxyS = AudioManager.MODE_IN_CALL;
+            	// mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+        	}
+        }
+
+        //UNTESTED
+        if (Build.VERSION.SDK_INT<10 && android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-P1000")) {
+        	//low gain for MIC in all use-case: (wrong for speacker mode)
+        	mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+        	//setSpeakerphoneOn -> will use WRONG microphone with above code in speaker mode
+        	//setSpeakerphoneOff -> will use CORRECT microphone with above code in earpiece mode
+
+        	//high gain for MIC in ALL use-case: (wrong for earpiece mode)
+        	// mAudiomanager_wa_galaxyS = AudioManager.MODE_IN_CALL;
+        	// mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+        }
+        //UNTESTED
+        if (Build.VERSION.SDK_INT<10 && android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-S5660")) {
+        	//low gain for MIC in all use-case: (wrong for speacker mode)
+        	mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+        	//setSpeakerphoneOn -> will use WRONG microphone with above code in speaker mode
+        	//setSpeakerphoneOff -> will use CORRECT microphone with above code in earpiece mode
+
+        	//high gain for MIC in ALL use-case: (wrong for earpiece mode)
+        	// mAudiomanager_wa_galaxyS = AudioManager.MODE_IN_CALL;
+        	// mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+        }
+        
+        //TESTED FOR "GT-P1010" (default)
+		//if (Build.VERSION.SDK_INT<10 && android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-P1010"))
+        //	mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL; // this allow to have CORRECT microphone gain
+
+        if ( android.os.Build.BRAND.equalsIgnoreCase("Samsung") && (8 == Build.VERSION.SDK_INT)) {
+            // Set Samsung specific VoIP mode for 2.2 devices
+        	AudioManager mAManager;
+            mAManager = ((AudioManager)context.getSystemService(Context.AUDIO_SERVICE));
+        	int mode = 4;
+        	mAManager.setMode(mode);
+            if (mAManager.getMode() == mode) {
+        		Log.i("AudioCompatibility", "Samsung 2.2 detected // AudioManager.4 support detected");
+        		mAudiomanager_mode_internal = mode;
+        	}
+        	mAManager.setMode(AudioManager.MODE_NORMAL);
+        }
+
+        if ( (9 == Build.VERSION.SDK_INT || 10 == Build.VERSION.SDK_INT) ) {
+        	AudioManager mAManager;
+            mAManager = ((AudioManager)context.getSystemService(Context.AUDIO_SERVICE));
+        	int mode = AudioManager.MODE_IN_COMMUNICATION;
+        	mAManager.setMode(mode);
+            if (mAManager.getMode() == mode) {
+        		Log.i("AudioCompatibility", "Android 2.3.x  // AudioManager.MODE_IN_COMMUNICATION support detected");
+        		mAudiomanager_mode_internal = mode;
+        	}
+        	mAManager.setMode(AudioManager.MODE_NORMAL);
+        }
+        
+        //UNTESTED
+        if (android.os.Build.BRAND.equalsIgnoreCase("sdg"))
+			mAudiomanager_mode_internal = AudioManager.MODE_IN_COMMUNICATION;
+
+        if (android.os.Build.MODEL.equalsIgnoreCase("Milestone"))
+			mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+
+        if (android.os.Build.MODEL.equalsIgnoreCase("Titanium"))
+        	mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+
+        if (android.os.Build.BRAND.equalsIgnoreCase("motorola") && mAudiomanager_mode_internal == AudioManager.MODE_IN_CALL) {
+        	mAudiomanager_mode_internal = AudioManager.MODE_NORMAL;
+        }
+        
+        
+        if (android.os.Build.MODEL.equalsIgnoreCase("Galaxy nexus"))
+			mAudiomanager_mode_internal = AudioManager.MODE_IN_CALL;
+        
+		if (mAudiomanager_mode_internal == AudioManager.MODE_NORMAL)
+			Log.i("AudioCompatibility", "MODE for earpiece mode: configure to use AudioManager.MODE_NORMAL");
+		else if (mAudiomanager_mode_internal == AudioManager.MODE_IN_CALL)
+			Log.i("AudioCompatibility", "MODE for earpiece mode: configure to use AudioManager.MODE_IN_CALL");
+		else if (mAudiomanager_mode_internal == AudioManager.MODE_IN_COMMUNICATION)
+			Log.i("AudioCompatibility", "MODE for earpiece mode: configure to use AudioManager.MODE_IN_COMMUNICATION");
+		else if (mAudiomanager_mode_internal == 4)
+			Log.i("AudioCompatibility", "MODE for earpiece mode: configure to use AudioManager.4");
+
+    	if (mAudiomanager_wa_galaxyS == AudioManager.MODE_IN_CALL)
+    		Log.i("AudioCompatibility", "MODE for earpiece mode: AudioManager.MODE_IN_CALL hack enabled!");
+    	else if (mAudiomanager_wa_galaxyS == AudioManager.MODE_NORMAL)
+    		Log.i("AudioCompatibility", "MODE for earpiece mode: AudioManager.MODE_NORMAL hack enabled!");
+    
+    	configureAudioManagerMode_speakermode(context);
+    }
+
+    static private void configureAudioManagerMode_speakermode(Context context)
+    {
+		mAudiomanager_mode_speakermode = mAudiomanager_mode_internal;
+
+        if (android.os.Build.MODEL.equalsIgnoreCase("Galaxy nexus"))
+			mAudiomanager_mode_speakermode = AudioManager.MODE_IN_COMMUNICATION;
+        
+		if (mAudiomanager_mode_speakermode == AudioManager.MODE_NORMAL)
+			Log.i("AudioCompatibility", "MODE for speakermode: configure to use AudioManager.MODE_NORMAL");
+		else if (mAudiomanager_mode_speakermode == AudioManager.MODE_IN_CALL)
+			Log.i("AudioCompatibility", "MODE for speakermode: configure to use AudioManager.MODE_IN_CALL");
+		else if (mAudiomanager_mode_speakermode == AudioManager.MODE_IN_COMMUNICATION)
+			Log.i("AudioCompatibility", "MODE for speakermode: configure to use AudioManager.MODE_IN_COMMUNICATION");
+		else if (mAudiomanager_mode_speakermode == 4)
+			Log.i("AudioCompatibility", "MODE for speakermode: configure to use AudioManager.4");
+
+    	if (mAudiomanager_wa_galaxyS == AudioManager.MODE_IN_CALL)
+    		Log.i("AudioCompatibility", "MODE for speakermode: AudioManager.MODE_IN_CALL hack enabled!");
+    	else if (mAudiomanager_wa_galaxyS == AudioManager.MODE_NORMAL)
+    		Log.i("AudioCompatibility", "MODE for speakermode: AudioManager.MODE_NORMAL hack enabled!");
+    }
+    
+    static public void configureAudioManagerStreamType()
+    {
+    	if (android.os.Build.BRAND.toUpperCase(Locale.US).startsWith("ARCHOS")) {
+    		mAudiomanager_stream_type = AudioManager.STREAM_MUSIC;
+    	}
+    	if (android.os.Build.MODEL.toUpperCase(Locale.US).startsWith("ST8002")) {
+    		mAudiomanager_stream_type = AudioManager.STREAM_MUSIC;
+    	}
+    	if (android.os.Build.MODEL.toUpperCase(Locale.US).startsWith("SAMBM8001ND")) {
+    		mAudiomanager_stream_type = AudioManager.STREAM_MUSIC;
+    	}
+
+		if (mAudiomanager_stream_type == AudioManager.STREAM_MUSIC)
+			Log.i("AudioCompatibility", "configure to use AudioManager.STREAM_MUSIC");
+		else if (mAudiomanager_stream_type == AudioManager.STREAM_VOICE_CALL)
+			Log.i("AudioCompatibility", "configure to use AudioManager.STREAM_VOICE_CALL");
+    }
+
+    static public void configureAudioRecordAudioSource()
+    {
+    	//API 11
+    	if (Build.VERSION.SDK_INT>=11)
+    		mAudiomanager_audio_source_internal = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
+    	else
+    		mAudiomanager_audio_source_internal = MediaRecorder.AudioSource.MIC;
+    	
+    	if (android.os.Build.MODEL.equalsIgnoreCase("NEXUS S")) {
+    		mAudiomanager_audio_source_internal = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
+    	}
+    	
+    	if (android.os.Build.MODEL.equalsIgnoreCase("MZ604")) {
+    		mAudiomanager_audio_source_internal = MediaRecorder.AudioSource.MIC;
+    	}
+    	
+    	//fix for Galaxy Nexus: using VOICE_COMMUNICATION -> "no sound mainly when coming back from speakermode" 
+    	if (android.os.Build.MODEL.equalsIgnoreCase("Galaxy Nexus")) {
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.MIC;
+    	}
+    	
+		if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.DEFAULT)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.DEFAULT");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.MIC)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.MIC");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.VOICE_UPLINK)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.VOICE_UPLINK");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.VOICE_DOWNLINK)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.VOICE_DOWNLINK");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.VOICE_CALL) //uplink + downlink
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.VOICE_CALL");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.CAMCORDER)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.CAMCORDER");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.VOICE_RECOGNITION)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.VOICE_RECOGNITION");
+		else if (mAudiomanager_audio_source_internal == MediaRecorder.AudioSource.VOICE_COMMUNICATION)
+			Log.i("AudioCompatibility", "configure to use MediaRecorder.AudioSource.VOICE_COMMUNICATION");
+		
+		configureAudioRecordAudioSource_speakermode();
+    }
+
+    static private void configureAudioRecordAudioSource_speakermode()
+    {
+    	if (Build.VERSION.SDK_INT>=11)
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
+    	else
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.MIC;
+
+    	if (android.os.Build.MODEL.equalsIgnoreCase("NEXUS S")) {
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
+    	}
+    	
+    	if (android.os.Build.MODEL.equalsIgnoreCase("MZ604")) {
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.MIC;
+    	}
+    	
+    	//fix for Galaxy Nexus: using VOICE_COMMUNICATION -> "no sound mainly when coming back from speakermode" 
+    	if (android.os.Build.MODEL.equalsIgnoreCase("Galaxy Nexus")) {
+    		mAudiomanager_audio_source_speakermode = MediaRecorder.AudioSource.MIC;
+    	}
+    	
+		if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.DEFAULT)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.DEFAULT");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.MIC)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.MIC");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.VOICE_UPLINK)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.VOICE_UPLINK");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.VOICE_DOWNLINK)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.VOICE_DOWNLINK");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.VOICE_CALL) //uplink + downlink
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.VOICE_CALL");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.CAMCORDER)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.CAMCORDER");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.VOICE_RECOGNITION)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.VOICE_RECOGNITION");
+		else if (mAudiomanager_audio_source_speakermode == MediaRecorder.AudioSource.VOICE_COMMUNICATION)
+			Log.i("AudioCompatibility", "MIC for speakermode: configure to use MediaRecorder.AudioSource.VOICE_COMMUNICATION");
+    }
+    
+    static public int getRate(int mRate)
+    {
+		if (android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-P1010"))
+    		return 44100;
+		return mRate;
+    }
+    
+    static public int getAudioRecord_getMinBufferSize(int bufsize)
+    {
+		if (android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-P1010"))
+    		return bufsize*3;
+		return bufsize;
+    }    
+}

+ 306 - 0
AmDemo_R/src/com/vvsip/ansip/AudioInput.java

@@ -0,0 +1,306 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+ */
+
+package com.vvsip.ansip;
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+//import android.media.audiofx.AcousticEchoCanceler;
+//import android.media.audiofx.AutomaticGainControl;
+import android.os.Build;
+import android.util.Log;
+
+/*
+ * 语音输入类,功能:采集语音
+ */
+public class AudioInput {
+
+	public static boolean beready=false;
+	public static boolean restart = false;
+	public static int mAudiomanager_audio_source = MediaRecorder.AudioSource.MIC;
+	public static boolean muted = false;
+
+	AudioRecord record;
+	// AutomaticGainControl agc;
+	// AcousticEchoCanceler aec;
+	boolean running = false;
+	int offset = 0;
+	int mRate = 8000;//20160617.8000->16000
+
+	AudioInput(int rate) {
+
+	//	rate = 8000;//20160617.add line.
+		
+		mRate = rate;
+		
+		if (beready==false)
+			return;
+			
+		int bufsize = AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
+		if (bufsize < 2048)
+			bufsize = 2048;
+		bufsize = AudioCompatibility.getAudioRecord_getMinBufferSize(bufsize);
+		Log.i("AudioInput", "AudioRecord will use buffer = " + bufsize);
+		Log.i("AudioInput", "AudioRecord will use rate = " + rate);
+
+		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
+
+		record = new AudioRecord(mAudiomanager_audio_source, rate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufsize);
+		if (record != null) {
+			// if (Build.VERSION.SDK_INT>=16)
+			// {
+			// try {
+			//
+			// if (AutomaticGainControl.isAvailable()) {
+			// int session_id = record.getAudioSessionId();
+			// agc = AutomaticGainControl.create(session_id);
+			// Log.w("AudioInput",
+			// "AudioRecord with AGC created / session id = " + session_id);
+			// if (agc.getEnabled()==false) {
+			// Log.w("AudioInput", "AudioRecord with AGC not yet enabled");
+			// agc.setEnabled(true);
+			// }
+			// if (agc.getEnabled()==true) {
+			// Log.w("AudioInput", "AudioRecord with AGC enabled");
+			// }
+			// }
+			// } catch (Exception e) {
+			// }
+			// try {
+			// if (AcousticEchoCanceler.isAvailable()) {
+			// int session_id = record.getAudioSessionId();
+			// aec = AcousticEchoCanceler.create(session_id);
+			// Log.w("AudioInput",
+			// "AudioRecord with AEC created / session id = " + session_id);
+			// if (aec!=null) {
+			// if (aec.getEnabled()==false) {
+			// Log.w("AudioInput", "AudioRecord with AEC not yet enabled");
+			// aec.setEnabled(true);
+			// }
+			// if (aec.getEnabled()==true) {
+			// Log.w("AudioInput",
+			// "AudioRecord with AEC enabled and hasControl = " +
+			// aec.hasControl());
+			// }
+			// }
+			// }
+			// } catch (Exception e) {
+			// }
+			// }
+			if (mAudiomanager_audio_source != record.getAudioSource()) {
+				Log.w("AudioInput", "AudioRecord is using " + record.getAudioSource() + " audio source instead of "
+						+ mAudiomanager_audio_source);
+			}
+		}
+		if (record == null) {
+			/* ressource not yet available? */
+			Log.w("AudioInput", "AudioRecord not yet available, retry later");
+			running = false;
+		} else {
+			running = true;
+			try {
+				record.startRecording();
+			} catch (Exception e) {
+				try {
+					record.stop();
+				} catch (Exception e1) {
+
+				}
+				record.release();
+				record = null;
+				// if (Build.VERSION.SDK_INT>=16) {
+				// if (agc!=null)
+				// agc.release();
+				// agc=null;
+				// if (aec!=null)
+				// aec.release();
+				// aec=null;
+				// }
+				running = false;
+			}
+		}
+	}
+
+	/** Stops running */
+	public int stop() {
+		if (record != null) {
+			running = false;
+			record.stop();
+			record.release();
+			record = null;
+			// if (Build.VERSION.SDK_INT>=16) {
+			// if (agc!=null)
+			// agc.release();
+			// agc=null;
+			// if (aec!=null)
+			// aec.release();
+			// aec=null;
+			// }
+		}
+		return 0;
+	}
+
+	int read_bytes(byte[] data, int len) {
+
+		if (beready==false) {
+			if (record != null) {
+				Log.i("AudioInput", "AudioRecord is now unused: stop");
+				running = false;
+				record.stop();
+				record.release();
+				record = null;
+				restart = false;
+				// if (Build.VERSION.SDK_INT>=16) {
+				// if (agc!=null)
+				// agc.release();
+				// agc=null;
+				// if (aec!=null)
+				// aec.release();
+				// aec=null;
+				// }
+			}
+			//Log.i("AudioInput", "AudioRecord is now unused: stopped");
+			
+			return 0;
+		}
+		
+		if (restart == true && Build.VERSION.SDK_INT >= 14) {
+			// let's consider restart is not required anymore for 4.0 and above.
+			restart = false;
+		}
+		if (record == null || restart == true) {
+			if (record != null) {
+				running = false;
+				record.stop();
+				record.release();
+				record = null;
+				// if (Build.VERSION.SDK_INT>=16) {
+				// if (agc!=null)
+				// agc.release();
+				// agc=null;
+				// if (aec!=null)
+				// aec.release();
+				// aec=null;
+				// }
+			}
+
+			int bufsize = AudioRecord.getMinBufferSize(mRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
+			if (bufsize < 2048)
+				bufsize = 2048;
+			bufsize = AudioCompatibility.getAudioRecord_getMinBufferSize(bufsize);
+			Log.i("AudioInput", "AudioRecord will use buffer = " + bufsize);
+
+			record = new AudioRecord(mAudiomanager_audio_source, mRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,
+					bufsize);
+			if (record != null) {
+				restart = false;
+				// if (Build.VERSION.SDK_INT>=16)
+				// {
+				// try {
+				// if (AutomaticGainControl.isAvailable()) {
+				// int session_id = record.getAudioSessionId();
+				// agc = AutomaticGainControl.create(session_id);
+				// if (agc!=null) {
+				// Log.w("AudioInput",
+				// "AudioRecord with AGC created / session id = " + session_id);
+				// if (agc.getEnabled()==false) {
+				// Log.w("AudioInput", "AudioRecord with AGC not yet enabled");
+				// agc.setEnabled(true);
+				// }
+				// if (agc.getEnabled()==true) {
+				// Log.w("AudioInput", "AudioRecord with AGC enabled");
+				// }
+				// }
+				// }
+				// } catch (Exception e) {
+				// }
+				// try {
+				// if (AcousticEchoCanceler.isAvailable()) {
+				// int session_id = record.getAudioSessionId();
+				// aec = AcousticEchoCanceler.create(session_id);
+				// Log.w("AudioInput",
+				// "AudioRecord with AEC created / session id = " + session_id);
+				// if (aec!=null) {
+				// if (aec.getEnabled()==false) {
+				// Log.w("AudioInput", "AudioRecord with AEC not yet enabled");
+				// aec.setEnabled(true);
+				// }
+				// if (aec.getEnabled()==true) {
+				// Log.w("AudioInput",
+				// "AudioRecord with AEC enabled and hasControl = " +
+				// aec.hasControl());
+				// }
+				// }
+				// }
+				// } catch (Exception e) {
+				// }
+				// }
+				if (mAudiomanager_audio_source != record.getAudioSource()) {
+					Log.w("AudioInput", "AudioRecord is using " + record.getAudioSource() + " audio source instead of "
+							+ mAudiomanager_audio_source);
+				}
+			}
+			if (record == null) {
+				/* resource not yet available? */
+				running = false;
+			} else {
+				Log.w("AudioInput", "AudioRecord finally available!");
+				running = true;
+
+				try {
+					record.startRecording();
+				} catch (Exception e) {
+					try {
+						record.stop();
+					} catch (Exception e1) {
+
+					}
+					record.release();
+					record = null;
+					// if (Build.VERSION.SDK_INT>=16) {
+					// if (agc!=null)
+					// agc.release();
+					// agc=null;
+					// if (aec!=null)
+					// aec.release();
+					// aec=null;
+					// }
+					running = false;
+				}
+			}
+		}
+
+		if (record != null) {
+			int num = record.read(data, 0, len);
+			
+			if (num==android.media.AudioRecord.ERROR_INVALID_OPERATION) {
+				try {
+					record.stop();
+				} catch (Exception e1) {
+	
+				}
+				record.release();
+				record = null;
+				running = false;
+			}
+			
+			if (muted == true) {
+				for (int k = 0; k < len; k++) {
+					data[k] = 0;
+				}
+			}
+			
+			offset += num;
+			if (num < len) {
+				Log.w("AudioInput", "AudioRecord return smaller data than expected!" + num + " asked:" + len);
+			}
+			return num;
+		}
+
+		return 0;
+	}
+}

+ 157 - 0
AmDemo_R/src/com/vvsip/ansip/AudioOutput.java

@@ -0,0 +1,157 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+ */
+
+package com.vvsip.ansip;
+
+import android.media.AudioFormat;
+import android.media.AudioTrack;
+import android.os.Build;
+import android.util.Log;
+
+/*
+ * 语音输出类,功能:播放语音
+ */
+public class AudioOutput {
+
+	public static boolean beready = false;
+	public static boolean restart = false;
+
+	public static final int BUFFER_SIZE = 640;
+
+	AudioTrack track;
+	boolean running = false;
+	// short[] lin;
+	int offset;
+	int mRate = 8000;
+
+	AudioOutput(int rate) {
+
+		mRate = rate;
+
+		if (beready == false)
+			return;
+
+		running = true;
+
+		int bufsize = AudioTrack.getMinBufferSize(rate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
+
+		int c = bufsize / BUFFER_SIZE;
+		bufsize = BUFFER_SIZE * c + BUFFER_SIZE;
+		if (bufsize < BUFFER_SIZE * 2 * 2)
+			bufsize = BUFFER_SIZE * 2 * 2;
+		android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
+		track = new AudioTrack(AudioCompatibility.mAudiomanager_stream_type, rate, AudioFormat.CHANNEL_OUT_MONO,
+				AudioFormat.ENCODING_PCM_16BIT, bufsize, AudioTrack.MODE_STREAM);
+		Log.i("AudioOutput", "new AudioTrack created!");
+		track.setStereoVolume(AudioTrack.getMaxVolume(), AudioTrack.getMaxVolume());
+
+		offset = 0;
+
+		try {
+			track.play();
+		} catch (Exception e) {
+			track.flush();
+			track.release();
+			track = null;
+		}
+	}
+
+	/** Stops running */
+	public int stop() {
+		running = false;
+		if (track == null)
+			return 0;
+
+		track.flush();
+		track.stop();
+		track.release();
+		track = null;
+		return 0;
+	}
+
+	public int write_bytes(byte[] data, int len) {
+		int size;
+		if (len > BUFFER_SIZE)
+			return 0;
+
+		if (beready == false) {
+			restart = false;
+			if (track != null) {
+				Log.i("AudioOutput", "AudioTrack is now unused: stop");
+				track.flush();
+				track.stop();
+				track.release();
+				track = null;
+			}
+			return 0;
+		}
+
+		if (restart == true && Build.VERSION.SDK_INT >= 14) {
+			// let's consider restart is not required anymore for 4.0 and above.
+			restart = false;
+		}
+		if (track == null || restart == true) {
+			if (AudioInput.restart == true) {
+				/* wait for INPUT to be ready... */
+				return 0;
+			}
+			restart = false;
+			if (track != null) {
+				track.flush();
+				track.stop();
+				track.release();
+				track = null;
+			}
+
+			int bufsize = AudioTrack.getMinBufferSize(mRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
+
+			int c = bufsize / BUFFER_SIZE;
+			bufsize = BUFFER_SIZE * c + BUFFER_SIZE;
+			if (bufsize < BUFFER_SIZE * 2 * 2)
+				bufsize = BUFFER_SIZE * 2 * 2;
+			android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
+			track = new AudioTrack(AudioCompatibility.mAudiomanager_stream_type, mRate, AudioFormat.CHANNEL_OUT_MONO,
+					AudioFormat.ENCODING_PCM_16BIT, bufsize, AudioTrack.MODE_STREAM);
+			Log.i("AudioOutput", "new(2) AudioTrack created!");
+			track.setStereoVolume(AudioTrack.getMaxVolume(), AudioTrack.getMaxVolume());
+			offset = 0;
+
+			try {
+				track.play();
+			} catch (Exception e) {
+				track.flush();
+				track.release();
+				track = null;
+				return len;
+			}
+		}
+
+		if (len == 0)
+			return 0; /*
+					 * len=0 is asked in order to allow beready to be checked,
+					 * in order to prepare the audiotrack before the call is
+					 * established
+					 */
+
+		int diff = 0;
+		try {
+			diff = offset - track.getPlaybackHeadPosition();
+		} catch (Exception e) {
+			// might be an IllegalStateException? happened once on galaxy S.
+			return len;
+		}
+		if (diff < 1024) {
+			Log.w("VvsipService", "inserting silence//diff = " + diff + " samples");
+			byte silence[] = new byte[BUFFER_SIZE];
+			track.write(silence, 0, BUFFER_SIZE);
+			offset += BUFFER_SIZE;
+		}
+		size = track.write(data, 0, len);
+		offset += size;
+		return size;
+	}
+
+}

+ 32 - 0
AmDemo_R/src/com/vvsip/ansip/CheckCpu.java

@@ -0,0 +1,32 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import android.util.Log;
+/*
+ * 检测CPU接口,增强系统兼容性
+ */
+public class CheckCpu {
+
+
+	public native int getcpufamily();
+	public native int getcpufeatures();
+
+	/* 
+	 */
+	static {
+		try {
+			System.loadLibrary("checkcpu");
+		} catch (UnsatisfiedLinkError e) {
+			Log.e("VvsipTask", "native library is missing // re-install the application...");
+			e.printStackTrace();
+		} catch (Exception e) {
+			Log.e("VvsipTask", "problem loading checkcpu.so?");
+			e.printStackTrace();
+		}
+	}	
+}

+ 392 - 0
AmDemo_R/src/com/vvsip/ansip/H264MediaCodecDecoder.java

@@ -0,0 +1,392 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+
+class OmxFormatInfo {
+	int omx_format;
+	int mediastreamer2_format;
+	int size_mul;
+	int line_mul;
+	int line_chroma_div;
+	
+	OmxFormatInfo(int _omx_format, int _mediastreamer2_format, int _size_mul, int _line_mul, int _line_chroma_div) {
+		omx_format=_omx_format;
+		mediastreamer2_format=_mediastreamer2_format;
+		size_mul=_size_mul;
+		line_mul=_line_mul;
+		line_chroma_div=_line_chroma_div;
+	}
+};
+
+
+/*
+ * H264硬解码类
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class H264MediaCodecDecoder  {
+
+	static final String mTag = "H264MediaCodecDecoder";
+	
+	MediaCodec mediaCodec;
+	MediaCodec.BufferInfo bufferInfo;
+    int ppssps_done;
+    int width;
+	int height;
+    int stride;
+    int slice_height;
+    int color_format;
+    int crop_left;
+    int crop_top;
+    int crop_right;
+    int crop_bottom;
+
+    public int getWidth() {
+		return width;
+	}
+
+	public int getHeight() {
+		return height;
+	}
+
+	public int getStride() {
+		return stride;
+	}
+
+	public int getSliceHeight() {
+		return slice_height;
+	}
+
+	public int getColorFormat() {
+		return color_format;
+	}
+
+	public int getCropLeft() {
+		return crop_left;
+	}
+
+	public int getCropTop() {
+		return crop_top;
+	}
+
+	public int getCropRight() {
+		return crop_right;
+	}
+
+	public int getCropBottom() {
+		return crop_bottom;
+	}
+    
+    
+	public static VvsipMediaCodecInfo mMediaCodecInfo = null;
+	
+	//static public int __get_ms_format() {
+	//	return mMediaCodecInfo.mMSColorFormat;
+	//}
+
+	public int getMSColorFormat() {
+		int ms_format = -1;
+		if (color_format==mMediaCodecInfo.mColorFormat)
+			return mMediaCodecInfo.mMSColorFormat;
+		
+		if (color_format==MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar)
+	        ms_format = 0; //MS_YUV420P;
+	      else if (color_format==MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar)
+	    	  ms_format = 0; //MS_YUV420P;
+	      else if (color_format==MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar)
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==0x7f000001) /* MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced */
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar)
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==2141391875) /* MediaCodecInfo.CodecCapabilities.QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka (supposed to be NV12MT?) */
+	        /* might be usefull?: */
+	        /* https://github.com/Owersun/xbmc/blob/8a2f587242eaedc03b8a0dfb0000eee3d0522db7/xbmc/cores/dvdplayer/DVDCodecs/Video/nv12mt_to_yuv420m.neon.S */
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==2141391876) /* MediaCodecInfo.CodecCapabilities.OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m (detected on nexus 5) */
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar) /*  */
+	    	  ms_format = 9; //MS_NV12;
+	      else if (color_format==842094169) /* YV12 (U and V reversed) */
+	    	  ms_format = 0; //MS_YUV420P;
+
+		return ms_format;
+	}
+	
+
+	private static Hashtable<Integer,OmxFormatInfo> omxFormatInfoList = new Hashtable<Integer,OmxFormatInfo>();
+
+	static {
+		Integer key;
+		OmxFormatInfo val;
+
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, 0, 3, 1, 2);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar);
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar, 0, 3, 1, 2);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar); //NV21 detected on samsung S3?
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 8 , 3, 1, 1);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar); //NV21
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, 8, 3, 1, 1);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar); //NV12
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar, 9, 3, 1, 2);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(0x7FA30C03); //NV12 //OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
+		val = new OmxFormatInfo(0x7FA30C03, 0, 3, 1, 1);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_FormatYCbYCr); //YUYV
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatYCbYCr, 1, 4, 2, 0);
+		omxFormatInfoList.put(key, val);
+		key = Integer.valueOf(MediaCodecInfo.CodecCapabilities.COLOR_FormatCbYCrY); //UYVY
+		val = new OmxFormatInfo(MediaCodecInfo.CodecCapabilities.COLOR_FormatCbYCrY, 5, 4, 2, 0);
+		omxFormatInfoList.put(key, val);
+    }
+
+	H264MediaCodecDecoder() {
+		
+		
+		mediaCodec = null;
+		bufferInfo = null;
+	}
+	
+	public void start() {
+		Log.d(mTag, "H264MediaCodecDecoder: start");
+		ppssps_done=0;
+		try {
+			Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: codec name: " + mMediaCodecInfo.info.getName());
+		    bufferInfo = new MediaCodec.BufferInfo();
+			mediaCodec = MediaCodec.createByCodecName(mMediaCodecInfo.info.getName());
+			MediaFormat mediaFormat = MediaFormat.createVideoFormat(mMediaCodecInfo.mMimeType, 352, 288);
+		    mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mMediaCodecInfo.mColorFormat);
+		    //mediaFormat.setByteBuffer("csd-0", bytes);
+		    mediaCodec.configure(mediaFormat, null, null, 0);
+		    mediaCodec.start();
+		} catch (Exception e) {
+	        e.printStackTrace();
+	        mediaCodec=null;
+	        bufferInfo=null;
+		}
+	}
+	
+	public int close() {
+		if (mediaCodec==null)
+			return 0;
+	    try {
+	        mediaCodec.stop();
+	        mediaCodec.release();
+	    } catch (Exception e){
+	        e.printStackTrace();
+	    }
+        mediaCodec=null;
+        bufferInfo=null;
+        return 0;
+	}
+
+	
+	public int decode_data(int flag, byte[] input, int input_len) {
+		
+		//Log.d(mTag, "H264MediaCodecDecoder: decode_data");
+		if (mediaCodec==null || bufferInfo==null) {
+			start();
+		}
+		if (mediaCodec==null || bufferInfo==null) {
+			return -1;
+		}
+		if (ppssps_done==0 && flag!=2) {
+            Log.i(mTag, "H264MediaCodecDecoder: missing sps/pps");
+			return -2;
+		}
+		
+	    try {
+	    	int inputBufferIndex;
+	        try {
+	        	inputBufferIndex = mediaCodec.dequeueInputBuffer(5000);
+	        }catch (Exception e) {
+	        	Log.e(mTag, "H264MediaCodecDecoder: dequeueInputBuffer" + e.getMessage());
+	        	close();
+	        	return -1;
+			} 
+	        
+	        if (inputBufferIndex >= 0) {
+	            ByteBuffer inputBuffer;
+	        	if (android.os.Build.VERSION.SDK_INT>=21)
+	        		inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
+	        	else {
+	    	        ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
+	        		inputBuffer = inputBuffers[inputBufferIndex];
+	        	}
+	            inputBuffer.clear();
+	            inputBuffer.put(input);
+	            mediaCodec.queueInputBuffer(inputBufferIndex, 0, input_len, 0, flag);
+	    		if (flag==2)
+	    			ppssps_done=1;
+	        } else {
+	            //Log.i(mTag, "H264MediaCodecDecoder: no input buffer");
+	            return -3;
+	        }
+
+	    } catch (Exception e) {
+	        e.printStackTrace();
+		    return -1;
+	    }
+
+	    //Log.d(mTag, "H264MediaCodecDecoder: end of decode_data");
+	    return 0;
+	}
+	
+	//private static List<String> nopadding_decoders2 = new ArrayList<String>() {{ add("OMX.SEC.avc.dec"); add("OMX.SEC.avcdec"); add("OMX.SEC.MPEG4.Decoder"); add("OMX.SEC.vc1.dec"); }};
+	private static List<String> nopadding_decoders = Collections.unmodifiableList(Arrays.asList(new String[] {
+			"OMX.SEC.avc.dec",
+			"OMX.SEC.avcdec",
+			"OMX.SEC.MPEG4.Decoder",
+			"OMX.SEC.mpeg4.dec",
+			"OMX.SEC.vc1.dec"}));
+	
+	public int get_raw_data(byte[] output, int max_output_len) {
+		
+		
+		int output_len=0;
+		//Log.d(mTag, "H264MediaCodecDecoder: get_h264_data");
+		if (mediaCodec==null || bufferInfo==null) {
+			return -1;
+		}
+		
+	    try {
+	        ByteBuffer[] outputBuffers;
+	        
+
+	        int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);
+	        if (outputBufferIndex >= 0) {
+	        	ByteBuffer outputBuffer;
+	        	if (android.os.Build.VERSION.SDK_INT>=21)
+	        		outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
+	        	else {
+	    	        try {
+	    	        	outputBuffers = mediaCodec.getOutputBuffers();
+	    	        }catch (Exception e) {
+	    	        	Log.e(mTag, "H264MediaCodecDecoder: getOutputBuffers" + e.getMessage());
+	    	        	close();
+	    	        	return -1;
+	    			} 
+		            outputBuffer = outputBuffers[outputBufferIndex];
+	        		
+	        	}
+	            //byte[] outData = new byte[bufferInfo.size];
+	            if (outputBuffer.remaining()>max_output_len) {
+		            Log.i(mTag, "output buffer too small outputBuffer.remaining()=" + outputBuffer.remaining() + " bufferInfo.size=" + bufferInfo.size + " max=" + max_output_len);
+		            output_len = -outputBuffer.remaining(); //return new required allocation size
+	            } else {
+	            	//Log.i(mTag, "remaining bytes in outputBuffer=" + outputBuffer.remaining() + " bufferInfo.size=" + bufferInfo.size + " bufferInfo.offset=" + bufferInfo.offset);
+		            //output_len = bufferInfo.offset+bufferInfo.size;
+	            	//outputBuffer.get(output, 0, bufferInfo.offset+bufferInfo.size);
+		            output_len = outputBuffer.remaining();
+	            	outputBuffer.get(output, 0, outputBuffer.remaining());
+	            }
+
+	            mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
+	        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+	            outputBuffers = mediaCodec.getOutputBuffers();
+	            return 0;
+	        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+	            // Subsequent data will conform to new format.
+	            MediaFormat format = mediaCodec.getOutputFormat();
+	            
+	            width        = format.getInteger("width");
+	            height       = format.getInteger("height");
+	            stride       = format.getInteger("stride");
+	            slice_height = format.getInteger("slice-height");
+	            color_format = format.getInteger("color-format");
+	            crop_left    = format.getInteger("crop-left");
+	            crop_top     = format.getInteger("crop-top");
+	            crop_right   = format.getInteger("crop-right");
+	            crop_bottom  = format.getInteger("crop-bottom");
+	            
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: width: " + width);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: height: " + height);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: stride: " + stride);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: slice-height: " + slice_height);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: color-format: " + color_format);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: crop-left: " + crop_left);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: crop-top: " + crop_top);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: crop-right: " + crop_right);
+	            Log.e(mTag, "INFO_OUTPUT_FORMAT_CHANGED: crop-bottom: " + crop_bottom);
+	            
+	            if (stride<=0)
+	            	stride=width;
+	            if (slice_height<=0)
+	            	slice_height=height;
+	            
+	            if (color_format == MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar) {
+	            	//ignore:
+	            	//slice_height -= crop_top/2;
+	            	//crop_top=0;
+	            	//crop_left=0;
+	            }
+	            int i_width=crop_right + 1 - crop_left;
+	            //int i_heigth=crop_bottom + 1 - crop_top;
+	            if (nopadding_decoders.contains(mMediaCodecInfo.info.getName())) {
+	            	slice_height=0; /* ? */
+	            	stride = i_width;
+	            }
+
+	            /* Align on macroblock boundary */
+	            //int aligned_width = (i_width + 15) & ~0xF;
+	            //int aligned_height = (i_heigth + 15) & ~0xF;
+	            
+	            
+	            OmxFormatInfo val = omxFormatInfoList.get(Integer.valueOf(color_format));
+	            if (val!=null) {
+		            //int size = aligned_width * aligned_height * val.size_mul / 2;
+		            //int pitch = aligned_width * aligned_height * val.line_mul;
+		            
+		            Log.d(mTag, "H264MediaCodecDecoder: =" + val.omx_format);
+		            Log.d(mTag, "H264MediaCodecDecoder: =" + val.size_mul);
+		            Log.d(mTag, "H264MediaCodecDecoder: =" + val.line_mul);
+		            Log.d(mTag, "H264MediaCodecDecoder: =" + val.line_chroma_div);
+	            }
+            	return -999;
+	        }
+	    } catch (Exception e) {
+	    	e.printStackTrace();
+		    return -1;
+	    }
+	    //Log.d(mTag, "H264MediaCodecDecoder: end of get_h264_data  output_len=" + output_len);
+	    return output_len;
+	}
+	
+	public static boolean TestDecoder() {
+		Log.d(mTag, "TestDecoder");
+		try {
+			MediaCodec mediaCodecTest = MediaCodec.createByCodecName(mMediaCodecInfo.info.getName());
+			MediaFormat mediaFormatTest = MediaFormat.createVideoFormat(mMediaCodecInfo.info.getName(), 320, 240);
+			mediaCodecTest.configure(mediaFormatTest, null, null, 0);
+			mediaCodecTest.start();
+			mediaCodecTest.stop();
+			mediaCodecTest.release();
+		} catch (Exception e) {
+	        e.printStackTrace();
+	        return false;
+		}
+		return true;
+	}
+}

+ 189 - 0
AmDemo_R/src/com/vvsip/ansip/H264MediaCodecEncoder.java

@@ -0,0 +1,189 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+ */
+
+package com.vvsip.ansip;
+
+import java.nio.ByteBuffer;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.os.Build;
+import android.util.Log;
+
+/*
+ * H264硬解码类
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class H264MediaCodecEncoder {
+
+	static final String mTag = "H264MediaCodecEncoder";
+
+	MediaCodec mediaCodec;
+	MediaCodec.BufferInfo bufferInfo;
+	int width;
+	int height;
+	int fps;
+	int bitrate;
+
+	public static VvsipMediaCodecInfo mMediaCodecInfo = null;
+
+	static public int get_format() {
+		return mMediaCodecInfo.mColorFormat;
+	}
+
+	static public int get_ms_format() {
+		return mMediaCodecInfo.mMSColorFormat;
+	}
+
+	H264MediaCodecEncoder() {
+		mediaCodec = null;
+		bufferInfo = null;
+	}
+
+	public void start(int _width, int _height, int _fps, int _bitrate) {
+		Log.d(mTag, "H264MediaCodecEncoder: start format=" + mMediaCodecInfo.mColorFormat);
+		try {
+			bufferInfo = new MediaCodec.BufferInfo();
+			mediaCodec = MediaCodec.createByCodecName(mMediaCodecInfo.info.getName());
+			MediaFormat mediaFormat = MediaFormat.createVideoFormat(mMediaCodecInfo.mMimeType, _width, _height);
+			mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, _bitrate);
+			mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, _fps);
+			mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mMediaCodecInfo.mColorFormat);
+			mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
+			mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+			mediaCodec.start();
+			width = _width;
+			height = _height;
+			fps = _fps;
+			bitrate = _bitrate;
+		} catch (Exception e) {
+			e.printStackTrace();
+			mediaCodec = null;
+			bufferInfo = null;
+		}
+	}
+
+	public int close() {
+		if (mediaCodec == null)
+			return 0;
+		try {
+			mediaCodec.stop();
+			mediaCodec.release();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		mediaCodec = null;
+		bufferInfo = null;
+		return 0;
+	}
+
+	public int encode_data(int _width, int _height, int _fps, int _bitrate, byte[] input, int input_len) {
+
+		long timeMs = System.currentTimeMillis();
+		if (width != _width || height != _height || fps != _fps || bitrate != _bitrate) {
+			close();
+		}
+		if (mediaCodec == null || bufferInfo == null) {
+			start(_width, _height, _fps, _bitrate);
+		}
+		if (mediaCodec == null || bufferInfo == null) {
+			return -1;
+		}
+
+		try {
+			int inputBufferIndex = mediaCodec.dequeueInputBuffer(0);
+			if (inputBufferIndex >= 0) {
+				ByteBuffer inputBuffer;
+				if (android.os.Build.VERSION.SDK_INT >= 21)
+					inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
+				else {
+					ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
+					inputBuffer = inputBuffers[inputBufferIndex];
+				}
+				inputBuffer.clear();
+				inputBuffer.put(input);
+				mediaCodec.queueInputBuffer(inputBufferIndex, 0, input_len, timeMs * 1000, 0);
+			} else {
+				Log.i(mTag, "H264MediaCodecEncoder: no input buffer");
+			}
+
+		} catch (Exception e) {
+			e.printStackTrace();
+			return -1;
+		}
+
+		// Log.d(mTag, "H264MediaCodecEncoder: end of encode_data");
+		return 0;
+	}
+
+	public int get_h264_data(byte[] output, int max_output_len) {
+
+		int output_len = 0;
+		// Log.d(mTag, "H264MediaCodecEncoder: get_h264_data");
+		if (mediaCodec == null || bufferInfo == null) {
+			return -1;
+		}
+
+		try {
+			int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
+			if (outputBufferIndex >= 0) {
+				ByteBuffer outputBuffer;
+				if (android.os.Build.VERSION.SDK_INT >= 21)
+					outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
+				else {
+					ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
+					outputBuffer = outputBuffers[outputBufferIndex];
+				}
+				if (bufferInfo.size > max_output_len) {
+					Log.i(mTag, "output buffer too small bufferInfo.size=" + bufferInfo.size + " max=" + max_output_len);
+				} else {
+					try {
+						outputBuffer.get(output, 0, bufferInfo.size);
+						output_len = bufferInfo.size;
+					} catch (Exception ex) {
+						ex.printStackTrace();
+						mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
+						output_len = 0;
+					}
+
+					// Log.i(mTag, output_len + " bytes written");
+				}
+
+				mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			return -1;
+		}
+
+		// Log.d(mTag,
+		// "H264MediaCodecEncoder: end of get_h264_data  output_len=" +
+		// output_len);
+		return output_len;
+	}
+
+	public static boolean TestEncoder() {
+		Log.d(mTag, "TestEncoder");
+		try {
+			MediaCodec mediaCodecTest = MediaCodec.createByCodecName(mMediaCodecInfo.info.getName());
+			MediaFormat mediaFormatTest = MediaFormat.createVideoFormat(mMediaCodecInfo.info.getName(), 320, 240);
+			mediaFormatTest.setInteger(MediaFormat.KEY_BIT_RATE, 256000);
+			mediaFormatTest.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
+			mediaFormatTest.setInteger(MediaFormat.KEY_COLOR_FORMAT, mMediaCodecInfo.mColorFormat);
+			mediaFormatTest.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
+			mediaCodecTest.configure(mediaFormatTest, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+			mediaCodecTest.start();
+			mediaCodecTest.stop();
+			mediaCodecTest.release();
+		} catch (Exception e) {
+			e.printStackTrace();
+			return false;
+		}
+		return true;
+	}
+
+}

+ 32 - 0
AmDemo_R/src/com/vvsip/ansip/IVvsipService.java

@@ -0,0 +1,32 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import java.util.List;
+
+import android.os.Handler;
+/*
+ * 服务接口
+ */
+public interface IVvsipService {
+	public VvsipTask getVvsipTask();
+	public int StartVvsipLayer();
+	public int StopVvsipLayer();
+	public void initiateOutgoingCall(String target,String macStr);
+    public void addListener(IVvsipServiceListener listener); 
+    public void removeListener(IVvsipServiceListener listener);
+    public void setAudioNormalMode();
+    public void setAudioInCallMode();
+    public void setSpeakerModeOff();
+    public void setSpeakerModeOn();
+	public void stopPlayer();
+	public void restartNetworkDetection();
+	public void setMessageHandler(Handler _mainActivityMessageHandler);
+	public void register(String domain,String username,String passwd);
+	public void setNeighbors();
+	public void sendDTMF(String dtmf);
+}

+ 18 - 0
AmDemo_R/src/com/vvsip/ansip/IVvsipServiceListener.java

@@ -0,0 +1,18 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+
+/*
+ * 服务监听接口
+ */
+public interface IVvsipServiceListener {
+	public void onNewVvsipCallEvent(VvsipCall call);
+	public void onRemoveVvsipCallEvent(VvsipCall call);
+	public void onStatusVvsipCallEvent(VvsipCall call);
+	public void onRegistrationEvent(int rid, String remote_uri, int code, String reason);
+}

+ 239 - 0
AmDemo_R/src/com/vvsip/ansip/VideoOrientationCompatibility.java

@@ -0,0 +1,239 @@
+package com.vvsip.ansip;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import android.annotation.SuppressLint;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.ActivityInfo;
+import android.text.TextUtils;
+/*
+ * 视频方向适配类,功能:增强兼容性
+ */
+public class VideoOrientationCompatibility {
+
+	final private static String KEY_PORTRAIT = "key_rotate_portrait";
+	final private static String KEY_LANDSCAPE = "key_rotate_landscape";
+	final private static String KEY_REVERSE_LANDSCAPE = "key_rotate_reverse_landscape";
+	final private static String KEY_REVERSE_PORTRAIT = "key_rotate_reverse_portrait";
+	
+	final private static List<Integer> possibleDisplayOrientations = Arrays.asList(0, 90, 180, 270);
+	final private static List<Integer> possibleImageOrientations = Arrays.asList(0, 1, 2, 3);
+	
+	private SharedPreferences configuration;
+	
+	private class Preset {
+		public Preset(Integer self, Integer remote) {
+			this.self = self;
+			this.remote = remote;
+		}
+		public Integer self;
+		public Integer remote;
+		
+		public List<Integer> getStorable() {
+			List<Integer> storable = Arrays.asList(self, remote);
+			return storable;
+		}
+		
+		public void fromStorable(Integer[] values) {
+			this.self = values[0];
+			this.remote = values[1];
+		}
+	}
+	
+	private class Settings {
+		public Preset frontCamera;
+		public Preset rearCamera;
+		
+		public Settings() {
+			this.frontCamera = new Preset(0, 0);
+			this.rearCamera = new Preset(0, 0);
+		}
+		public Settings(Preset front, Preset rear) {
+			this.frontCamera = front;
+			this.rearCamera = rear;
+		}
+		
+		
+		public List<Integer> getStorable() {
+			List<Integer> storable = new LinkedList<Integer>(frontCamera.getStorable());
+			storable.addAll(rearCamera.getStorable());
+			return storable;
+		}
+		
+		public void fromStorable(Integer[] values) {
+			Integer[] front = {values[0], values[1]};
+			frontCamera.fromStorable(front);
+			
+			Integer[] rear = {values[2], values[3]};
+			rearCamera.fromStorable(rear);
+		}
+	}
+	
+	@SuppressLint("UseSparseArrays")
+	private Map<Integer, Settings> orientationPresets =
+		new HashMap<Integer, Settings>();
+	
+	public VideoOrientationCompatibility(SharedPreferences configuration) {
+		this.configuration = configuration;
+		init();
+	}
+	
+	private void init() {
+		
+		if (hasSettingsStored()) {
+			load();
+			return;
+		}
+		
+		Settings portrait;
+		Settings landscape;
+		Settings reverseLandscape;
+		Settings reversePortrait;
+		
+		if (android.os.Build.MODEL.toUpperCase(Locale.US).startsWith("XOOM")) {
+			portrait 			= new Settings(new Preset(270, 3), new Preset(270, 3));
+			landscape 			= new Settings(new Preset(0,   0), new Preset(0,   0));
+			reverseLandscape 	= new Settings(new Preset(180, 2), new Preset(180, 2));
+			reversePortrait 	= new Settings(new Preset(90,  1), new Preset(90,  1));
+		}
+		else if (android.os.Build.MODEL.toUpperCase(Locale.US).startsWith("A500")) {
+			portrait 			= new Settings(new Preset(270, 1), new Preset(270, 3));
+			landscape 			= new Settings(new Preset(0,   0), new Preset(0,   0));
+			reverseLandscape 	= new Settings(new Preset(180, 2), new Preset(180, 2));
+			reversePortrait 	= new Settings(new Preset(90,  3), new Preset(90,  1));
+		}
+		else { // Default, for instance for Samsung Galaxy Nexus
+			portrait 			= new Settings(new Preset(90,  3), new Preset(90,  1));
+			landscape 			= new Settings(new Preset(0,   0), new Preset(0,   0));
+			reverseLandscape 	= new Settings(new Preset(180, 2), new Preset(180, 2));
+			reversePortrait 	= new Settings(new Preset(270, 1), new Preset(270, 3));
+		}
+		
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, portrait);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, landscape);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, reverseLandscape);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, reversePortrait);
+	}
+	
+	public Integer getDisplayRotation(Integer deviceOrientation, Boolean isFrontFacingCamera) {
+		return getPreset(deviceOrientation, isFrontFacingCamera).self;
+	}
+	
+	public Integer getImageRotation(Integer deviceOrientation, Boolean isFrontFacingCamera) {
+		return getPreset(deviceOrientation, isFrontFacingCamera).remote;
+	}
+	
+	public void setDisplayRotation(Integer deviceOrientation, Boolean isFrontFacingCamera, Integer displayOrientation) {
+		
+		if (!possibleDisplayOrientations.contains(displayOrientation))
+			return;
+		
+		Preset preset = getPresetOrNull(deviceOrientation, isFrontFacingCamera);
+		
+		if (preset != null) {
+			preset.self = displayOrientation;
+			setPreset(deviceOrientation, isFrontFacingCamera, preset);
+		}
+	}
+	
+	public void setImageRotation(Integer deviceOrientation, Boolean isFrontFacingCamera, Integer displayOrientation) {
+		
+		if (!possibleImageOrientations.contains(displayOrientation))
+			return;
+		
+		Preset preset = getPresetOrNull(deviceOrientation, isFrontFacingCamera);
+		
+		if (preset != null) {
+			preset.remote = displayOrientation;
+			setPreset(deviceOrientation, isFrontFacingCamera, preset);
+		}
+	}
+	
+	private Preset getPreset(Integer deviceOrientation, Boolean isFrontFacingCamera) {
+		Preset preset = getPresetOrNull(deviceOrientation, isFrontFacingCamera);
+		if (preset != null)
+			return preset;
+		// Return default 
+		return new Preset(0, 0);
+	}
+	
+	private Preset getPresetOrNull(Integer deviceOrientation, Boolean isFrontFacingCamera) {
+		Settings settings = orientationPresets.get(deviceOrientation);
+		
+		if (settings != null) {
+			if (isFrontFacingCamera)
+				return settings.frontCamera;
+			else 
+				return settings.rearCamera;
+		}
+		return null;
+	}
+	
+	private void setPreset(Integer deviceOrientation, Boolean isFrontFacingCamera, Preset preset) {
+		if (isFrontFacingCamera)
+			orientationPresets.get(deviceOrientation).frontCamera = preset;
+		else
+			orientationPresets.get(deviceOrientation).rearCamera = preset;
+		
+		store();
+	}
+	
+	private void store() {
+		String portrait = TextUtils.join(";", orientationPresets.get(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT).getStorable());
+		String landscape = TextUtils.join(";", orientationPresets.get(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE).getStorable());
+		String reverseLandscape = TextUtils.join(";", orientationPresets.get(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE).getStorable());
+		String reversePortrait = TextUtils.join(";", orientationPresets.get(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT).getStorable());
+		
+		Editor editor = configuration.edit();
+		editor.putString(KEY_PORTRAIT, portrait);
+		editor.putString(KEY_LANDSCAPE, landscape);
+		editor.putString(KEY_REVERSE_LANDSCAPE, reverseLandscape);
+		editor.putString(KEY_REVERSE_PORTRAIT, reversePortrait);
+		editor.commit();
+	}
+	
+	private boolean hasSettingsStored() {
+		return !configuration.getString(KEY_PORTRAIT, "NOSUCHSTRING").equals("NOSUCHSTRING");
+	}
+	
+	private void load() {
+		if (!hasSettingsStored())
+			return;
+		
+		Settings portrait = getSettingsFromString(configuration.getString(KEY_PORTRAIT, ""));
+		Settings landscape = getSettingsFromString(configuration.getString(KEY_LANDSCAPE, ""));
+		Settings reverseLandscape = getSettingsFromString(configuration.getString(KEY_REVERSE_LANDSCAPE, ""));
+		Settings reversePortrait = getSettingsFromString(configuration.getString(KEY_REVERSE_PORTRAIT, ""));
+		
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, portrait);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, landscape);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, reverseLandscape);
+		orientationPresets.put(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, reversePortrait);
+	}
+	
+	private Settings getSettingsFromString(String str) {
+		String[] arr = TextUtils.split(str, ";");
+		
+		if (arr.length != 4)
+			return null;
+		
+		Integer[] iarr = new Integer[4];
+		
+		for (int i = 0; i < 4; i++) {
+			Integer val = Integer.parseInt(arr[i]);
+			if (val == null)
+				return null;
+			iarr[i] = val;
+		}
+		
+		Settings settings = new Settings();
+		settings.fromStorable(iarr);
+		return settings;
+	}
+}

+ 163 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipAccount.java

@@ -0,0 +1,163 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+/*
+ * 帐号类,功能:存储帐号信息
+ */
+public class VvsipAccount {
+
+	private String domain;
+	private String userid;
+	private String passwd;
+	private String identity;
+	private String outboundProxy;
+	private String transport;
+	private int registerInterval;
+	private boolean echoCancellation;
+	
+	/**
+	 * @param domain the domain to set
+	 */
+	public void setDomain(String domain) {
+		this.domain = domain;
+	}
+	/**
+	 * @return the domain
+	 */
+	public String getDomain() {
+		return domain;
+	}
+	/**
+	 * @param userid the userid to set
+	 */
+	public void setUserid(String userid) {
+		this.userid = userid;
+	}
+	/**
+	 * @return the userid
+	 */
+	public String getUserid() {
+		return userid;
+	}
+	/**
+	 * @param passwd the passwd to set
+	 */
+	public void setPasswd(String passwd) {
+		this.passwd = passwd;
+	}
+	/**
+	 * @return the passwd
+	 */
+	public String getPasswd() {
+		return passwd;
+	}
+	/**
+	 * @param identity the identity to set
+	 */
+	public void setIdentity(String identity) {
+		this.identity = identity;
+	}
+	/**
+	 * @return the identity
+	 */
+	public String getIdentity() {
+		return identity;
+	}
+	/**
+	 * @param identity the identity to set
+	 */
+	public void setOutboundProxy(String outboundProxy) {
+		this.outboundProxy = outboundProxy;
+	}
+	/**
+	 * @return the identity
+	 */
+	public String getOutboundProxy() {
+		return outboundProxy;
+	}
+	/**
+	 * @param transport the transport to set
+	 */
+	public void setTransport(String transport) {
+		this.transport = transport;
+	}
+	/**
+	 * @return the transport
+	 */
+	public String getTransport() {
+		return transport;
+	}
+	
+	public boolean isDefined() {
+
+		if (domain!=null && domain.length()==0)
+			domain = null;
+		if (userid!=null && userid.length()==0)
+			userid = null;
+		if (passwd!=null && passwd.length()==0)
+			passwd = null;
+		if (identity!=null && identity.length()==0)
+			identity = null;
+		if (outboundProxy!=null && outboundProxy.length()==0)
+			outboundProxy = null;
+		if (transport!=null && transport.length()==0)
+			transport = null;
+		
+		
+		if (transport==null)
+			transport = "udp";
+		else if (transport.compareToIgnoreCase("udp")!=0
+				&&transport.compareToIgnoreCase("tcp")!=0
+				&&transport.compareToIgnoreCase("tls")!=0)
+			transport = "udp";
+		
+		if (registerInterval<=0)
+			registerInterval=600; //default!
+		
+		if (registerInterval<100)
+			registerInterval=100;
+		
+		
+		if (domain==null || domain.length()==0)
+			return false;
+		if (userid==null || userid.length()==0)
+			return false;
+		if (identity==null || identity.length()==0)
+		{
+			identity = "<sip:"+userid+"@"+domain+">";
+		}
+		
+		return true;
+	}
+	
+	/**
+	 * @param registerInterval the registerInterval to set
+	 */
+	public void setRegisterInterval(int registerInterval) {
+		this.registerInterval = registerInterval;
+	}
+	
+	/**
+	 * @return the registerInterval
+	 */
+	public int getRegisterInterval() {
+		return registerInterval;
+	}
+	/**
+	 * @param echoCancellation the echoCancellation to set
+	 */
+	public void setEchoCancellation(boolean echoCancellation) {
+		this.echoCancellation = echoCancellation;
+	}
+	/**
+	 * @return the echoCancellation
+	 */
+	public boolean isEchoCancellation() {
+		return echoCancellation;
+	}
+}

+ 165 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipCall.java

@@ -0,0 +1,165 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import com.vvsip.ansip.VvsipTask;
+import com.vvsip.ansip.AudioInput;
+import com.vvsip.ansip.AudioOutput;
+
+import android.graphics.drawable.Drawable;
+import android.os.SystemClock;
+
+/*
+ * 电话呼叫封装类,为主要功能类,功能:提供呼叫相关的功能,包括接电话,挂电话,保持,静音,视频,DTMF
+ */
+public class VvsipCall implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+	public long start_date;
+	public long established_date;
+	public long end_date;
+	public String description;
+	public String mRemoteUri;
+	public int tid;
+	public int cid;
+	public int did;
+	public boolean mIncomingCall;
+	public boolean mMuted;
+	public boolean mOnHold;
+	public int mState;
+	public String mDisplayName;
+	Drawable mContactImage;
+	public boolean mVideoStarted;
+	public String macStr;
+	
+	public VvsipCall()
+	{
+		Calendar cal = new GregorianCalendar();
+		start_date = cal.getTime().getTime();
+		description = "--";
+	}
+	
+	public boolean isIncomingCall()
+	{
+		return mIncomingCall;
+	}
+	
+	public int answer(int code, int enable_audio)
+	{
+    	IVvsipService _service = VvsipService.getService();
+    	if (_service==null)
+    		return -999;
+    	VvsipTask _vvsipTask = _service.getVvsipTask();
+    	if (_vvsipTask==null)
+    		return -998;
+    	int i;
+    	if (code<200)
+    	{
+    		i = _vvsipTask.vvsessionanswer(tid, did, code, 0);
+    		if (i>=0)
+    			mState=1;
+    	}
+    	else if (code<300)
+    	{
+    		i = _vvsipTask.vvsessionanswer(tid, did, code, 1);
+    		if (i>=0) {
+    			established_date = SystemClock.elapsedRealtime();
+    			mState=2;
+				AudioOutput.beready=true;
+	    		AudioInput.beready=true;
+    		}
+    	}
+    	else
+    	{
+			i = _vvsipTask.vvsessionanswer(tid, did, code, 0);
+    		if (i>=0)
+    		{
+    			if (mState<2 && isIncomingCall()) {
+        			description = ("未接来电");
+    			}
+    		}
+    		if (i>=0)
+    			mState=3;
+    	}
+		return i;
+	}
+	
+	public int stop()
+	{
+    	IVvsipService _service = VvsipService.getService();
+    	if (_service==null)
+    		return -999;
+    	VvsipTask _vvsipTask = _service.getVvsipTask();
+    	if (_vvsipTask==null)
+    		return -998;
+    	int i = _vvsipTask.vvsessionstop(cid, did, 486);
+    	if (i>=0)
+    	{
+    		if (mState==2)
+    		{
+        		Calendar cal = new GregorianCalendar();
+        		end_date = cal.getTime().getTime();
+    		} else if (mState<2 && isIncomingCall()) {
+    			description = "未接来电";
+    		} else if (mState<2) {
+    			description = "--";
+    		}
+    	}
+    	
+		if (i>=0)
+			mState = 3;
+		return i;
+	}
+
+	public int startvideo() {
+	   	IVvsipService _service = VvsipService.getService();
+    	if (_service==null)
+    		return -1;
+    	VvsipTask _vvsipTask = _service.getVvsipTask();
+    	if (_vvsipTask==null)
+    		return -1;
+    	int i = _vvsipTask.vvsessionaddvideo(did);
+    	if (i>=0)
+    	{    		
+    		mVideoStarted=true;
+    		return 0;
+    	}
+		return -1;
+	}
+
+	public void sendrtpdtmf(String dtmf) {
+    	if (cid>0 && mState==2)
+   		{
+			IVvsipService _service = VvsipService.getService();
+	    	if (_service==null)
+	    		return;
+	    	VvsipTask _vvsipTask = _service.getVvsipTask();
+	    	if (_vvsipTask==null)
+	    		return;
+	    	//_vvsipTask.vvsessionsenddtmfwithduration(pCall.did, "1", 480);
+	    	_vvsipTask.vvsessionsendrtpdtmf(did, dtmf);
+   		}
+	}
+
+	public void sendinfodtmf(String dtmf) {
+    	if (cid>0 && mState==2)
+   		{
+			IVvsipService _service = VvsipService.getService();
+	    	if (_service==null)
+	    		return;
+	    	VvsipTask _vvsipTask = _service.getVvsipTask();
+	    	if (_vvsipTask==null)
+	    		return;
+	    	_vvsipTask.vvsessionsenddtmfwithduration(did, dtmf, 480);
+   		}
+	}
+	
+}

+ 58 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipDTMF.java

@@ -0,0 +1,58 @@
+package com.vvsip.ansip;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class VvsipDTMF {
+	
+	private String mTag = "VvsipDTMF";
+	private static VvsipDTMF mVvsipTask;
+	public static int global_failure=0;
+	
+	private static Handler mainActivityMessageHandler;
+	
+	public static VvsipDTMF getVvsipDTMF()  {
+		if (mVvsipTask!=null)
+			return mVvsipTask;
+		return new VvsipDTMF();
+	}
+	
+	public VvsipDTMF() {
+		mVvsipTask = this;
+	}
+	
+	public int testdtmf(int dtmf){
+		Log.e(mTag, "printDTMF:"+dtmf);
+		
+		String strDTMF = null;
+		
+		if (mainActivityMessageHandler != null) {
+			Message m = new Message();
+			m.what = 88;
+			
+			if(dtmf==35){
+				strDTMF = "#";
+			}else if(dtmf==42){
+				strDTMF = "*";
+			}else if(dtmf>=48 && dtmf <=57){
+				strDTMF = String.valueOf(dtmf-48);
+			}else{
+				strDTMF = "unknown";
+			}
+			
+			
+			m.obj = "Received DTMF: " + strDTMF + "\n";
+
+			mainActivityMessageHandler.sendMessage(m);
+		} else {
+			Log.e(mTag, "mainActivityMessageHandler==null");
+		}
+		
+		return 0;
+	}
+	
+	public void setHandler(Handler _mainActivityEventHandler) {
+		mainActivityMessageHandler = _mainActivityEventHandler;
+	}
+}

+ 246 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipMediaCodecFinder.java

@@ -0,0 +1,246 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import java.util.ArrayList;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.os.Build;
+import android.util.Log;
+
+
+//Information on encoder, decoder, phone tested...
+
+/*
+HW-INFO:Galaxy Nexus
+HW-INFO:4.3
+HW-INFO:maguro
+HW-INFO:google
+Encoder: OMX.TI.DUCATI1.VIDEO.H264E Mimetype:video/avc supported with NV12 (COLOR_TI_FormatYUV420PackedSemiPlanar)
+Decoder: OMX.TI.DUCATI1.VIDEO.DECODER Mimetype:video/avc supported with NV12 (COLOR_TI_FormatYUV420PackedSemiPlanar)
+
+sidenote: was working with 4.2
+sidenote: MS_NV12 for both decoder/encoder
+sidenote: the decoded data(second plane) is shift by 16 octets?? (end of plane 1 + 16)
+          src_pic.planes[1]=d->data_nv12->b_rptr+d->stride*slice_height+(ysize)/2+16;
+          TODO: verify other received size
+sidenote: decoder tested with CIF and QCIF
+sidenote: encoder tested with 320x240 (and I think CIF and most probably other too...)
+
+HW-INFO:GT-I9305
+HW-INFO:4.1.2
+HW-INFO:m3
+HW-INFO:samsung
+
+Encoder: OMX.SEC.avc.enc Mimetype:video/avc supported with NV21 (COLOR_FormatYUV420SemiPlanar)
+Decoder: OMX.SEC.avc.dec Mimetype:video/avc supported with NV12 (COLOR_FormatYUV420SemiPlanar)
+
+sidenote: ENCODER ********MS_NV21*******
+          DECODER ********MS_NV12*******
+          -> WHY ARE THEY DIFFERENT???
+sidenote: example decoder:
+INFO_OUTPUT_FORMAT_CHANGED: codec name: OMX.SEC.avc.dec
+INFO_OUTPUT_FORMAT_CHANGED: width: 352
+INFO_OUTPUT_FORMAT_CHANGED: height: 288
+INFO_OUTPUT_FORMAT_CHANGED: stride: 352
+INFO_OUTPUT_FORMAT_CHANGED: slice-height: 288
+INFO_OUTPUT_FORMAT_CHANGED: color-format: 21
+INFO_OUTPUT_FORMAT_CHANGED: crop-left: 0
+INFO_OUTPUT_FORMAT_CHANGED: crop-top: 0
+INFO_OUTPUT_FORMAT_CHANGED: crop-right: 351
+INFO_OUTPUT_FORMAT_CHANGED: crop-bottom: 287
+sidenote: decoder tested with CIF and QCIF
+
+
+
+nexus7:
+
+09-04 14:35:32.218: D/VvsipMediaCodecFinder(4104): Encoder: OMX.Nvidia.h264.encoder Mimetype:video/avc supported with YUV420P (COLOR_FormatYUV420Planar)
+09-04 14:35:32.248: D/VvsipMediaCodecFinder(4104): Decoder: OMX.Nvidia.h264.decode Mimetype:video/avc supported with YUV420P (COLOR_FormatYUV420Planar)
+09-04 14:36:15.688: I/VvsipService(4104): HW-INFO:Nexus 7
+09-04 14:36:15.688: I/VvsipService(4104): HW-INFO:4.2.2
+09-04 14:36:15.688: I/VvsipService(4104): HW-INFO:tilapia
+09-04 14:36:15.688: I/VvsipService(4104): HW-INFO:google
+
+09-04 14:40:39.238: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: codec name: OMX.Nvidia.h264.decode
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: width: 352
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: height: 288
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: stride: 352
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: slice-height: 0
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: color-format: 19
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: crop-left: 0
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: crop-top: 0
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: crop-right: 351
+09-04 14:40:39.988: E/H264MediaCodecDecoder(4104): INFO_OUTPUT_FORMAT_CHANGED: crop-bottom: 287
+
+sidenote: decoder CIF and QCIF tested
+
+HW-INFO:POV_TAB-PROTAB25XXL8
+HW-INFO:4.1.1
+HW-INFO:POV_TAB-PROTAB25XXL
+HW-INFO:POV
+
+ Decoder: OMX.google.h264.decoder Mimetype:video/avc supported with YUV420P (COLOR_FormatYUV420Planar)
+ No usable Encoder
+ 
+sidenote: receiving QCIF -> crash
+sidenote: second decoder receiving QCIF -> crash (same as OMX.google.h264.decoder?)
+   it reports:  Decoder: video/avc supported with YUV420P (COLOR_FormatYUV420Planar)
+
+
+GT-N7000 and GT-I9100
+
+Encoder: NV12 with COLOR_FormatYUV420SemiPlanar
+
+*/
+/*
+ * 枚举硬编解码器
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class VvsipMediaCodecFinder {
+
+	static final String mTag = "VvsipMediaCodecFinder";
+	
+	static public ArrayList<VvsipMediaCodecInfo> AvcEncoders = new ArrayList<VvsipMediaCodecInfo>();
+	static public ArrayList<VvsipMediaCodecInfo> AvcDecoders = new ArrayList<VvsipMediaCodecInfo>();
+	static public boolean codec_loaded = false;
+    static public int codecCount = 0;
+    static public int totalSize = 0;
+
+    /*
+     * Find whether the given codec is supported
+     */
+    private static boolean isFormatSupported(MediaCodecInfo info, CodecCapabilities cap, int colorFormat) {
+
+        try {
+            for (int k = 0; k < cap.colorFormats.length; ++k) {
+                if (cap.colorFormats[k] == colorFormat) {
+                    //Log.d(mTag, "isFormatSupported: Found " + info.getName() + " // format: " + cap.colorFormats[k]);
+                	return true;
+                }
+            }
+    	}catch (Exception e) {
+            Log.d(mTag, "Codec: Skipping codec " + info.getName());
+            e.printStackTrace();
+		}
+    	return false;
+    }
+    
+	public static int ListAllMediaCodec(String mMimeType, int profile, boolean checkEncoder, boolean checkDecoder) {
+    	
+    	if (android.os.Build.VERSION.SDK_INT<16) {
+    		return totalSize;
+    	}
+    	if (AvcEncoders.size()>0)
+    		checkEncoder=false;
+    	if (AvcDecoders.size()>0)
+    		checkDecoder=false;
+    	/* already done or not required */
+    	if (checkEncoder==false && checkDecoder==false) {
+            codec_loaded=true;
+    		return totalSize;
+    	}
+
+		totalSize=0;
+        codecCount = MediaCodecList.getCodecCount();
+        for (int i = 0; i < codecCount; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+            String[] types = info.getSupportedTypes();
+
+        	if (info.isEncoder()==true && types.length>0)
+        		Log.d(mTag, "Codec: Found " + info.getName() + " // + " + types[0] + " // encoder");
+        	else if (info.isEncoder()==true)
+        		Log.d(mTag, "Codec: Found " + info.getName() + " // decoder");
+        	else if (types.length>0)
+        		Log.d(mTag, "Codec: Found " + info.getName() + " // + " + types[0] + " // decoder");
+        	else
+        		Log.d(mTag, "Codec: Found " + info.getName() + " // decoder");
+        	
+            totalSize += 1;
+            
+            if (checkEncoder==false && info.isEncoder())
+            	continue;
+            if (checkDecoder==false && info.isEncoder()==false)
+            	continue;
+            
+        	try {
+                for (int j = 0; j < types.length; ++j) {
+                	int profile_found=0;
+            		if (types[j].compareTo(mMimeType) != 0)
+            			continue;
+                    CodecCapabilities cap = info.getCapabilitiesForType(types[j]);
+                    CodecProfileLevel[] profileLevels = cap.profileLevels;
+                    for (int k = 0; k < profileLevels.length; ++k) {
+                        //Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // profile: " + profileLevels[k].profile + " level:" + profileLevels[k].level);
+                        if (profile==profileLevels[k].profile) {
+                        	profile_found=1;
+                        }
+                    }
+                	if (profile_found!=0) {
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_FormatYUV420SemiPlanar");
+                            VvsipMediaCodecInfo apci;
+                    		if (info.getName().equalsIgnoreCase("OMX.Intel.VideoDecoder.AVC"))
+                    			continue; //can't find the correct format...
+                    		else if (info.getName().equalsIgnoreCase("OMX.SEC.avc.enc") && android.os.Build.VERSION.SDK_INT<17)
+                    			apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 8); // NV21
+                    		else
+                    			apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar, 9); // NV12
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_FormatYUV420Planar");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar, 0); // YUV420P
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_FormatYUV420PackedPlanar");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar, 0); // YUV420P
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_FormatYUV420PackedSemiPlanar");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar, 9); // NV12
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_TI_FormatYUV420PackedSemiPlanar");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar, 9); // NV12
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, 0x7f000001)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, 0x7f000001, 9); // NV12
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                        if (isFormatSupported(info, cap, MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar)==true) {
+                            Log.d(mTag, "Codec: Found " + info.getName() + " // " + types[j] + " // COLOR_QCOM_FormatYUV420SemiPlanar");
+                    		VvsipMediaCodecInfo apci = new VvsipMediaCodecInfo(info, mMimeType, MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar, 9); // NV12
+                    		if (info.isEncoder()==true) AvcEncoders.add(apci);
+                    		else AvcDecoders.add(apci);
+                        }
+                    }
+                }
+        	}catch (Exception e) {
+                Log.d(mTag, "Codec: Skipping codec " + info.getName());
+                e.printStackTrace();
+			}
+        }
+        codec_loaded=true;
+        return totalSize;
+	}
+}

+ 29 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipMediaCodecInfo.java

@@ -0,0 +1,29 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import android.annotation.TargetApi;
+import android.media.MediaCodecInfo;
+import android.os.Build;
+/*
+ * 硬编解码器信息类
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class VvsipMediaCodecInfo  {
+
+	public MediaCodecInfo info;
+	public int mColorFormat;
+	int mMSColorFormat;
+	String mMimeType;
+	
+	VvsipMediaCodecInfo(MediaCodecInfo _info, String _mMimeType, int _mColorFormat, int _mMSColorFormat) {
+		info = _info;
+		mMimeType = _mMimeType;
+		mColorFormat = _mColorFormat;
+		mMSColorFormat = _mMSColorFormat;
+	}
+}

+ 6 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipNeighbor.java

@@ -0,0 +1,6 @@
+package com.vvsip.ansip;
+
+public class VvsipNeighbor {
+	public String location;
+	public String extension;
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2631 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipService.java


+ 23 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipServiceBinder.java

@@ -0,0 +1,23 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+
+package com.vvsip.ansip;
+
+import android.os.Binder;
+
+public class VvsipServiceBinder extends Binder {
+
+	private IVvsipService service = null; 
+	  
+    public VvsipServiceBinder(IVvsipService service) { 
+        super(); 
+        this.service = service; 
+    } 
+ 
+    public IVvsipService getService(){ 
+        return service; 
+    } 
+}

+ 413 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipTask.java

@@ -0,0 +1,413 @@
+/*
+  vvsip is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+*/
+package com.vvsip.ansip;
+
+
+import android.os.*;
+import android.util.*;
+/*
+ * JNI接口类,单例模式
+ */
+public class VvsipTask {
+
+	private static VvsipTask mVvsipTask;
+	public static int global_failure=0;
+	
+	public static VvsipTask getVvsipTask()  {
+		if (mVvsipTask!=null)
+			return mVvsipTask;
+		return new VvsipTask();
+	}
+	
+	public VvsipTask() {
+		mVvsipTask = this;
+	}
+	
+	/* REGISTER related events */
+	public static final int EXOSIP_REGISTRATION_SUCCESS=0;       /**< user is successfully registred.  */
+	public static final int EXOSIP_REGISTRATION_FAILURE=1;       /**< user is not registred.           */
+
+	/* INVITE related events within calls */
+	public static final int EXOSIP_CALL_INVITE=2;            /**< announce a new call                   */
+	public static final int EXOSIP_CALL_REINVITE=3;          /**< announce a new INVITE within call     */
+
+	public static final int EXOSIP_CALL_NOANSWER=4;          /**< announce no answer within the timeout */
+	public static final int EXOSIP_CALL_PROCEEDING=5;        /**< announce processing by a remote app   */
+	public static final int EXOSIP_CALL_RINGING=6;           /**< announce ringback                     */
+	public static final int EXOSIP_CALL_ANSWERED=7;          /**< announce start of call                */
+	public static final int EXOSIP_CALL_REDIRECTED=8;        /**< announce a redirection                */
+	public static final int EXOSIP_CALL_REQUESTFAILURE=9;    /**< announce a request failure            */
+	public static final int EXOSIP_CALL_SERVERFAILURE=10;     /**< announce a server failure             */
+	public static final int EXOSIP_CALL_GLOBALFAILURE=11;     /**< announce a global failure             */
+	public static final int EXOSIP_CALL_ACK=12;               /**< ACK received for 200ok to INVITE      */
+
+	public static final int EXOSIP_CALL_CANCELLED=13;         /**< announce that call has been cancelled */
+
+	/* request related events within calls (except INVITE) */
+	public static final int EXOSIP_CALL_MESSAGE_NEW=14;              /**< announce new incoming request. */
+	public static final int EXOSIP_CALL_MESSAGE_PROCEEDING=15;       /**< announce a 1xx for request. */
+	public static final int EXOSIP_CALL_MESSAGE_ANSWERED=16;         /**< announce a 200ok  */
+	public static final int EXOSIP_CALL_MESSAGE_REDIRECTED=17;       /**< announce a failure. */
+	public static final int EXOSIP_CALL_MESSAGE_REQUESTFAILURE=18;   /**< announce a failure. */
+	public static final int EXOSIP_CALL_MESSAGE_SERVERFAILURE=19;    /**< announce a failure. */
+	public static final int EXOSIP_CALL_MESSAGE_GLOBALFAILURE=20;    /**< announce a failure. */
+
+	public static final int EXOSIP_CALL_CLOSED=21;            /**< a BYE was received for this call      */
+
+	/* for both UAS & UAC events */
+	public static final int EXOSIP_CALL_RELEASED=22;             /**< call context is cleared.            */
+
+	/* response received for request outside calls */
+	public static final int EXOSIP_MESSAGE_NEW=23;              /**< announce new incoming request. */
+	public static final int EXOSIP_MESSAGE_PROCEEDING=24;       /**< announce a 1xx for request. */
+	public static final int EXOSIP_MESSAGE_ANSWERED=25;         /**< announce a 200ok  */
+	public static final int EXOSIP_MESSAGE_REDIRECTED=26;       /**< announce a failure. */
+	public static final int EXOSIP_MESSAGE_REQUESTFAILURE=27;   /**< announce a failure. */
+	public static final int EXOSIP_MESSAGE_SERVERFAILURE=28;    /**< announce a failure. */
+	public static final int EXOSIP_MESSAGE_GLOBALFAILURE=29;    /**< announce a failure. */
+
+    /* Presence and Instant Messaging */
+	public static final int EXOSIP_SUBSCRIPTION_NOANSWER=30;          /**< announce no answer              */
+	public static final int EXOSIP_SUBSCRIPTION_PROCEEDING=31;        /**< announce a 1xx                  */
+	public static final int EXOSIP_SUBSCRIPTION_ANSWERED=32;          /**< announce a 200ok                */
+	public static final int EXOSIP_SUBSCRIPTION_REDIRECTED=33;        /**< announce a redirection          */
+	public static final int EXOSIP_SUBSCRIPTION_REQUESTFAILURE=34;    /**< announce a request failure      */
+	public static final int EXOSIP_SUBSCRIPTION_SERVERFAILURE=35;     /**< announce a server failure       */
+	public static final int EXOSIP_SUBSCRIPTION_GLOBALFAILURE=36;     /**< announce a global failure       */
+	public static final int EXOSIP_SUBSCRIPTION_NOTIFY=37;            /**< announce new NOTIFY request     */
+
+	public static final int EXOSIP_IN_SUBSCRIPTION_NEW=38;            /**< announce new incoming SUBSCRIBE.*/
+
+	public static final int EXOSIP_NOTIFICATION_NOANSWER=39;          /**< announce no answer              */
+	public static final int EXOSIP_NOTIFICATION_PROCEEDING=40;        /**< announce a 1xx                  */
+	public static final int EXOSIP_NOTIFICATION_ANSWERED=41;          /**< announce a 200ok                */
+	public static final int EXOSIP_NOTIFICATION_REDIRECTED=42;        /**< announce a redirection          */
+	public static final int EXOSIP_NOTIFICATION_REQUESTFAILURE=43;    /**< announce a request failure      */
+	public static final int EXOSIP_NOTIFICATION_SERVERFAILURE=44;     /**< announce a server failure       */
+	public static final int EXOSIP_NOTIFICATION_GLOBALFAILURE=45;     /**< announce a global failure       */
+    
+	public boolean thread_started=false;
+	
+	private static Handler mainActivityEventHandler;
+	public boolean running=false;
+	private Thread taskThread;
+
+	public native int vvinit(int debug_level);
+	public native int vvreset(int debug_level);
+	public native int vvquit();
+	public native int vvcodecinfomodify(int pos, int enable, String codec_name, int mode, int cng, int vbr);
+	public native int vvvideocodecinfomodify(int pos, int enable, String codec_name, int mode, int cng, int vbr);
+	public native int vvvideocodecattrmodify(int uploadrate, int downloadrate);
+	 /* In 3G mode, if audio bitrate is <=30, the SDP will contain only the lower bitrate codec in SDP */
+	public native int vvcodecattrmodify(int ptime, int audio_bitrate);
+	
+	public native String vvoptiongetversion();
+	public native int vvoptionsetuseragent(String useragent);
+	public native int vvoptionsetinitialaudioport(int initialport);
+	public native int vvoptionenablestunserver(String stunserver, int usestunserver);
+	public native int vvoptionenableturnserver(String  turnserver, int useturnserver);
+	public native int vvoptionsetipv4forgateway(String ipv4forgateway);
+	public native int vvoptionenablerport(int enable);
+	public native int vvoptionsetdnscapabilities(int dnscapabilities);
+	public native int vvoptionenablekeepalive(int interval);
+	public native int vvoptionsetaudioprofile(String profile);
+	public native int vvoptionsetvideoprofile(String profile);
+	public native int vvoptionsettextprofile(String profile);
+	public native int vvoptionsetudpftpprofile(String profile);
+	public native int vvoptionenablesessiontimers(int sessionexpires);
+	public native int vvoptionenablesymmetricrtp(int enable);
+	//public native int vvoptionfindoutsoundcard(struct vvsndcard *sndcard);
+	//public native int vvoptionfindinsoundcard(struct vvsndcard *sndcard);
+	public native int vvoptionselectinsoundcard(int card);
+	public native int vvoptionselectoutsoundcard(int card);
+	//public native int vvoptionselectincustomsoundcard(MSSndCard *captcard);
+	//public native int vvoptionselectoutcustomsoundcard(MSSndCard *playcard);
+	public native int vvoptionsetvolumeoutsoundcard(int card, int mixer, int percent);
+	public native int vvoptiongetvolumeoutsoundcard(int card, int mixer);
+	public native int vvoptionsetvolumeinsoundcard(int card, int percent);
+	public native int vvoptiongetvolumeinsoundcard(int card);
+	public native int vvoptionsetmuteoutsoundcard(int card, int mixer, int val);
+	public native int vvoptionsetmuteinsoundcard(int card, int val);
+	public native int vvoptionenablewebrtcapm(int enable, int aecm, int aecm_comfort_noise, int aecm_routing_mode,
+                                        int ns, int ns_level,
+                                        int agc, int agc_mode, int agc_target_level_dbfs, int agc_compression_gain_db,
+                                        int high_pass_filter);
+	public native int vvoptionenableechocanceller(int enable, int framesize, int taillength);
+	public native int vvoptionenablehalfduplex(int enable, int vadprobstart, int vadprobcontinue);
+	public native int vvoptionenableagc(int enable, int agclevel, int maxgain);
+	public native int vvoptionsetjittermode(int mode);
+	public native int vvoptionvideosetjittermode(int mode);
+	public native int vvoptionsetpassword(String realm, String login, String passwd);
+	public native int vvoptionloadplugins(String directory);
+	public native int vvoptionenableoptionnalencryption(int optionnalencryption);
+	public native int vvoptionsetdscpvalue(int dscpvalue);
+	public native int vvoptionsetaudiodscp(int dscpvalue);
+	public native int vvoptionsetvideodscp(int dscpvalue);
+	public native int vvoptionsettextdscp(int dscpvalue);
+	public native int vvoptionsetudpftpdscp(int dscpvalue);
+	public native int vvoptionadddnscache(String host, String ip);
+	public native int vvoptionsetsupportedextensions(String supportedextensions);
+	public native int vvoptionsetacceptedtypes(String acceptedtypes);
+	public native int vvoptionsetallowedmethods(String allowedmethods);
+	public native int vvoptionsetrate(int rate);
+	public native int vvoptionsetvolumegain(float capturegain, float playbackgain);
+	public native int vvoptionsetecholimitation(int enabled,
+			float threshold,
+			float speed,
+			float force,
+			int sustain);
+
+	public native long vveventget();
+	public native long vveventwait(int tvs, int tvms);
+	public native void vveventrelease(long evt);
+	public native int vveventgettype(long evt);
+	public native int vveventgettid(long evt);
+	public native int vveventgetcid(long evt);
+	public native int vveventgetdid(long evt);
+	public native int vveventgetrid(long evt);
+	public native int vveventgetnid(long evt);
+	public native int vveventgetsid(long evt);
+	public native String vveventgetmethod(long evt);
+	public native String vveventgetreason(long evt);
+	public native int vveventgetstatuscode(long evt);
+	public native String vveventgetrequestheader(long evt, String hname, int n);
+	public native String vveventgetresponseheader(long evt, String hname, int n);
+	public native String vvurigetusername(String mSipUri);
+	public native String vvurigetdomain(String mSipUri);
+	public native String vvurigetdisplayname(String mSipUri);
+	
+	//For retreiving body in REQUEST (MESSAGE, INVITE, etc..)
+	public native byte[] vveventgetrequestbody(long evt, int n);
+
+	//public native int vvnetworkguessip(int family, String address, int size);
+	public native String vvnetworkgetnatinfo(String ip, int port);
+	public native int vvnetworkmasquerade(String ip, int port);
+	public native int vvoptionsettlscertificate(String certificate, String priv_key, String root_ca); 
+	public native int vvnetworkstart(String transport, int port);
+
+	public native int vvregisterstart(String identity, String proxy, String outboundproxy, int expires);
+	public native int vvregisterrefresh(int rid, int expires);
+	public native int vvregisterstop(int rid);
+
+	public native int vvsessionstart(String identity, String target, String proxy, String outboundproxy,String tags);
+	public native int vvsessionstartwithvideo(String identity, String target, String proxy, String outboundproxy,String tags);
+	
+/*	public native int vvsessionstart(String identity, String target, String proxy, String outboundproxy);
+	public native int vvsessionstartwithvideo(String identity, String target, String proxy, String outboundproxy);*/
+	public native int vvsessionaddvideo(int did);
+	public native int vvsessionstopvideo(int did);
+    public native int vvsessionadaptvideobitrate(int did, int percent);
+	public native int vvmessagegetrequestaudiortpdirection(long evt);
+	public native int vvmessagegetrequestvideortpdirection(long evt);
+	public native int vvmessagegetresponsevideortpdirection(long evt);
+	public native int vvsessionstop(int cid, int did, int code);
+	public native int vvsessionanswer(int cid, int did, int code, int enable_audio);
+
+	
+	public native float vvsessiongetaudiouploadbandwidth(int did);
+	public native float vvsessiongetaudiodownloadbandwidth(int did);
+	public native float vvsessiongetaudiopacketloss(int did);
+	public native float vvsessiongetaudioremotepacketloss(int did);
+	
+
+	public native float vvsessiongetvideouploadbandwidth(int did);
+	public native float vvsessiongetvideodownloadbandwidth(int did);
+	public native float vvsessiongetvideopacketloss(int did);    
+	public native float vvsessiongetvideoremotepacketloss(int did);
+	
+	public native int vvsessionanswerrequest(int cid, int did, int code);
+
+	public native int vvsessionsenddtmfwithduration(int did, String dtmf, int duration);
+	public native int vvsessionsendinbanddtmf(int did, String dtmf);
+	public native int vvsessionsendrtpdtmf(int did, String dtmf);
+	
+	public native int vvexecuteuri(String identity, String target,
+			String proxy, String outboundproxy, String body);
+	
+	public native int vvmessageanswer(int tid, int code);
+	
+	public native void registeraudio();
+	
+	//EXPERIMENTAL USAGE OF MEDIACODEC API FOR SDK>=16
+	//sidenote: validation of every device is NECESSARY.
+	//development device is galaxy nexus
+	public native int registermsh264mediaencoder(int version_sdk);
+	public native int registermsh264mediadecoder(int version_sdk);
+	
+	public native int vvoptionenablefilter(String filter_name);
+	public native int vvoptiondisablefilter(String filter_name);
+	
+	public native int setvideodisplay(Object lVideoDisplay);
+
+	/* load the 'vvsip' library on startup.
+	 * The library has been unpacked into
+	 * /data/data/com.vvsip.vvsip/lib/vvsip.so
+	 */
+	static {
+		CheckCpu ccpu;
+		int isArm = -1; 
+		int features = 0;
+		
+		try {
+			ccpu = new CheckCpu();
+			isArm = ccpu.getcpufamily();
+			features = ccpu.getcpufeatures();
+		} catch (UnsatisfiedLinkError e) {
+			Log.e("VvsipTask", "native library is missing // re-install the application...");
+			e.printStackTrace();
+			global_failure=1;
+		} catch (Exception e) {
+			Log.e("VvsipTask", "problem loading checkcpu.so?");
+			e.printStackTrace();
+			global_failure=1;
+		}
+		
+		if (isArm==1)
+		{
+			Log.i("VvsipTask", "CPU feature: " + features);
+			if ((features & 0x001) == 0x001)
+				Log.i("VvsipTask", "CPU feature: ANDROID_CPU_ARM_FEATURE_ARMv7");
+			if ((features & 0x002) == 0x002)
+				Log.i("VvsipTask", "CPU feature: ANDROID_CPU_ARM_FEATURE_VFPv3");
+			if ((features & 0x004) == 0x004)
+				Log.i("VvsipTask", "CPU feature: ANDROID_CPU_ARM_FEATURE_NEON");
+
+			try {
+				if ((features & 0x001) == 0x001)
+				{
+					if ((features & 0x004) == 0x004)
+						System.loadLibrary("vvsip-v7a-neon");
+					else
+						System.loadLibrary("vvsip-v7a");
+				} else {
+					System.loadLibrary("vvsip-v5");
+				}
+			} catch (UnsatisfiedLinkError e) {
+				Log.e("VvsipTask", "native library is missing // re-install the application...");
+				e.printStackTrace();
+				global_failure=1;
+			} catch (Exception e) {
+				Log.e("VvsipTask", "problem loading arm vvsip?");
+				e.printStackTrace();
+				global_failure=1;
+			}
+		} else if (isArm==2)
+			{
+				Log.i("VvsipTask", "CPU feature: " + features);
+				if ((features & 0x001) == 0x001)
+					Log.i("VvsipTask", "CPU feature: ANDROID_CPU_X86_FEATURE_SSSE3");
+				if ((features & 0x002) == 0x002)
+					Log.i("VvsipTask", "CPU feature: ANDROID_CPU_X86_FEATURE_POPCNT");
+				if ((features & 0x004) == 0x004)
+					Log.i("VvsipTask", "CPU feature: ANDROID_CPU_X86_FEATURE_MOVBE");
+				try {
+					System.loadLibrary("vvsip-x86");
+				} catch (UnsatisfiedLinkError e) {
+					Log.i("VvsipTask", "native library is missing // re-install the application...");
+					e.printStackTrace();
+					global_failure=1;
+				} catch (Exception e) {
+					Log.i("VvsipTask", "problem loading x86 vvsip?");
+					e.printStackTrace();
+					global_failure=1;
+				}
+		} else {
+			try {
+				System.loadLibrary("vvsip");
+			} catch (UnsatisfiedLinkError e) {
+				Log.e("VvsipTask", "native library is missing // re-install the application...");
+				e.printStackTrace();
+				global_failure=1;
+			} catch (Exception e) {
+				Log.e("VvsipTask", "problem loading arm vvsip?");
+				e.printStackTrace();
+				global_failure=1;
+			}
+		}
+		
+	}	
+
+	public void stop() {
+		
+		if (thread_started==false)
+			return;
+		running = false;
+
+		if (taskThread!=null)
+		{
+			try {
+				taskThread.join(1000);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			taskThread = null;
+		}
+   		
+		while (thread_started==true)
+		{
+
+		}
+	}
+
+	/*
+	 * 开始Handler,获得SIP信令消息与状态
+	 */
+	public void start(Handler _mainActivityEventHandler) {
+
+	   	if (running==true)
+    		return;
+
+	   	running=true;
+		thread_started = true;
+
+		mainActivityEventHandler = _mainActivityEventHandler;
+
+		taskThread = new Thread() {
+			@Override public void run() {
+				vvsipLoop();
+				thread_started = false;
+			}
+		};
+		taskThread.start();
+	}
+
+	private void vvsipLoop() {
+		Log.i(getClass().getSimpleName(), "background task - start");
+
+		int count=0;
+		while (running==true) {
+
+			count++;
+			if (count%(5*3)==0) /* each 3seconds */
+			{
+				Message m = Message.obtain(); //new Message(); 
+				m.what = -1;
+				m.arg1 = -1;
+				m.arg2 = -1;
+
+				mainActivityEventHandler.sendMessage(m);
+				count=0;
+			}
+			long evt = vveventwait(0, 200);
+			if (evt!=0)
+			{
+				int type = vveventgettype(evt);
+
+				//Send update to the main thread
+				Message m = Message.obtain(); //new Message();
+				m.what = type;
+				m.arg1 = vveventgetcid(evt);
+				m.arg2 = vveventgetdid(evt);
+				Long obj = Long.valueOf(evt);
+				m.obj = obj;
+
+				mainActivityEventHandler.sendMessage(m); 
+			}
+		}
+		Log.i(getClass().getSimpleName(), "background task - end");
+	}
+
+}

+ 591 - 0
AmDemo_R/src/com/vvsip/ansip/video/VideoCameraPreview.java

@@ -0,0 +1,591 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+ */
+
+package com.vvsip.ansip.video;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.ImageFormat;
+import android.hardware.Camera;
+import android.hardware.Camera.PreviewCallback;
+import android.hardware.Camera.Size;
+import android.os.Build;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+/**
+ *  Camera SurfaceView的封装
+ */
+public class VideoCameraPreview extends ViewGroup implements SurfaceHolder.Callback {
+	private final String TAG = "VideoCameraPreview";
+
+	SurfaceView mSurfaceView;
+	SurfaceHolder mHolder;
+	Size mPreviewSize;
+	List<Size> mSupportedPreviewSizes;
+	List<Integer> mSupportedFormats;
+	Camera mCamera;
+
+	private Camera.PreviewCallback mPreviewCallback = null;
+	private byte[] camera_preview_buffer = null;
+	DisplayMetrics metrics = new DisplayMetrics();
+
+	private Integer rotate_selfview_display = 0;
+
+	private boolean mHasActiveSurface=false;
+
+	public VideoCameraPreview(Context context, AttributeSet attributes) {
+		super(context, attributes);
+
+		mSurfaceView = new SurfaceView(context);
+		mSurfaceView.setZOrderOnTop(true);
+		addView(mSurfaceView);
+
+		// Install a SurfaceHolder.Callback so we get notified when the
+		// underlying surface is created and destroyed.
+		mHolder = mSurfaceView.getHolder();
+		mHolder.addCallback(this);
+		mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+	}
+
+	public void setPreviewCallback(PreviewCallback previewCallback) {
+		mPreviewCallback = previewCallback;
+	}
+
+	public void setCamera(Camera camera) {
+		mCamera = camera;
+		if (mCamera != null) {
+			Camera.Parameters params;
+			try {
+				params = mCamera.getParameters();
+			} catch (Exception e) {
+				// detected by report: java.lang.RuntimeException: getParameters
+				// failed (empty parameters)
+				Log.e(TAG, "Exception caused by mCamera.getParameters()", e);
+				mCamera = null;
+				return;
+			}
+
+			if (Build.VERSION.SDK_INT <= 4) {
+				String previewSizeValueString = params.get("preview-size-values");
+				Size lSize = params.getPreviewSize();
+				if (previewSizeValueString != null && previewSizeValueString.length() > 0) {
+					if (previewSizeValueString.contains("176x144")) {
+						lSize.width = 176;
+						lSize.height = 144;
+					} else if (previewSizeValueString.contains("320x240")) {
+						lSize.width = 320;
+						lSize.height = 240;
+					} else if (previewSizeValueString.contains("352x288")) {
+						lSize.width = 352;
+						lSize.height = 288;
+					} else if (previewSizeValueString.contains("640x480")) {
+						lSize.width = 640;
+						lSize.height = 480;
+					} else if (previewSizeValueString.contains("480x320")) {
+						lSize.width = 480;
+						lSize.height = 320;
+					}
+					// else, choose the current defined size...
+				}
+
+				int lFormat = params.getPreviewFormat();
+
+				mSupportedFormats = new ArrayList<Integer>();
+				mSupportedFormats.add(lFormat);
+
+				Log.i("VvsipVideoPreview", "using " + lSize.width + "x" + lSize.height + " for camera size");
+
+				mSupportedPreviewSizes = new ArrayList<Size>();
+				mSupportedPreviewSizes.add(lSize);
+			} else {
+				mSupportedPreviewSizes = params.getSupportedPreviewSizes();
+				Log.i("VvsipVideoPreview", "params.getSupportedPreviewSizes " + mSupportedPreviewSizes);
+
+				try {
+					mSupportedFormats = params.getSupportedPreviewFormats();
+				} catch (Exception e) {
+					mSupportedFormats = null;
+				}
+
+				if (mSupportedFormats == null) {
+					int lFormat = params.getPreviewFormat();
+					mSupportedFormats = new ArrayList<Integer>();
+					mSupportedFormats.add(lFormat);
+				}
+			}
+			requestLayout();
+		}
+	}
+
+	public void switchCamera(Camera camera) {
+		setCamera(camera);
+		try {
+			camera.setPreviewDisplay(mHolder);
+			if (android.os.Build.VERSION.SDK_INT < 8) {
+				camera.setPreviewCallback(mPreviewCallback);
+			} else {
+				camera.setPreviewCallbackWithBuffer(mPreviewCallback);
+			}
+		} catch (IOException exception) {
+			Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+		}
+
+		if (mSupportedFormats != null) {
+			getOptimalSupportedFormat(mSupportedFormats);
+		}
+
+		if (mSupportedPreviewSizes != null) {
+			SharedPreferences mConfiguration;
+			mConfiguration = PreferenceManager.getDefaultSharedPreferences(this.getContext());
+			String val = mConfiguration.getString("key_video_size", "default");
+			if (val == null || val.compareToIgnoreCase("0") == 0 || val.compareToIgnoreCase("1") == 0
+					|| val.compareToIgnoreCase("default") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 320, 240);
+			} else if (val.compareToIgnoreCase("small") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 240, 160);
+			} else if (val.compareToIgnoreCase("normal") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 320, 240);
+			} else if (val.compareToIgnoreCase("large") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 640, 480);
+			} else if (val.compareToIgnoreCase("hd") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 1280, 720);
+			} else {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 320, 240);
+			}
+
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
+			// width, heigth);
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 240,
+			// 160);
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 352,
+			// 288);
+		}
+
+		Camera.Parameters parameters = camera.getParameters();
+		parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+		requestLayout();
+
+		if (Build.VERSION.SDK_INT <= 4) {
+			parameters.set("preview-frame-rate", 1);
+			parameters.setPreviewFrameRate(1);
+		}
+
+		/* SIBO-Q899 failure? */
+		try  {
+			camera.setParameters(parameters);
+		} catch (Exception e) {
+			Log.e(TAG, "Exception for camera.setParameters(parameters)", e);
+			camera_preview_buffer = null;
+		}
+		
+		try {
+			if (android.os.Build.VERSION.SDK_INT >= 8) {
+				if (camera_preview_buffer == null)
+					camera_preview_buffer = new byte[1800000];
+				camera.addCallbackBuffer(camera_preview_buffer);
+			}
+		} catch (Exception e) {
+			Log.e(TAG, "Exception for allocation of camera_preview_buffer", e);
+			camera_preview_buffer = null;
+		}
+
+	}
+
+	@Override
+	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+		// We purposely disregard child measurements because act as a
+		// wrapper to a SurfaceView that centers the camera preview instead
+		// of stretching it.
+		// final int width = resolveSize(getSuggestedMinimumWidth(),
+		// widthMeasureSpec);
+		// final int height = resolveSize(getSuggestedMinimumHeight(),
+		// heightMeasureSpec);
+		// setMeasuredDimension(width, height);
+
+		WindowManager wm = (WindowManager) this.getContext().getSystemService(Context.WINDOW_SERVICE);
+		wm.getDefaultDisplay().getMetrics(metrics);
+
+		float screen_Xsize = metrics.widthPixels / metrics.xdpi;
+		float screen_Ysize = metrics.heightPixels / metrics.ydpi;
+		Log.i("VideoCameraPreview", "screen size = " + screen_Xsize + "x" + screen_Ysize + "inch " + metrics.widthPixels + "x"
+				+ metrics.heightPixels + "px");
+
+		// example on nexus S:
+		// 3.4120736x2.031496 //landscape nexus S
+		// 2.047244x3.3858268 //portait nexus S
+		// if (screen_Xsize>screen_Ysize) {
+		// if (screen_Xsize<4.5)
+		// setMeasuredDimension(160, 120);
+		// else if (metrics.widthPixels/320>2)
+		// setMeasuredDimension(320, 240);
+		// else
+		// setMeasuredDimension(160, 120);
+		// } else {
+		// if (screen_Ysize<4.5)
+		// setMeasuredDimension(160, 120);
+		// else if (metrics.heightPixels/240>2)
+		// setMeasuredDimension(320, 240);
+		// else
+		// setMeasuredDimension(160, 120);
+		// }
+
+		if (mSupportedFormats != null) {
+			getOptimalSupportedFormat(mSupportedFormats);
+		}
+
+		if (mSupportedPreviewSizes != null) {
+			SharedPreferences mConfiguration;
+			mConfiguration = PreferenceManager.getDefaultSharedPreferences(this.getContext());
+			String val = mConfiguration.getString("key_video_size", "default");
+			if (val == null || val.compareToIgnoreCase("0") == 0 || val.compareToIgnoreCase("1") == 0
+					|| val.compareToIgnoreCase("default") == 0) {
+				Log.w("VvsipService", "old config found");
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 320, 240);
+			} else if (val.compareToIgnoreCase("small") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 240, 160);
+			} else if (val.compareToIgnoreCase("normal") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 320, 240);
+			} else if (val.compareToIgnoreCase("large") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 640, 480);
+			} else if (val.compareToIgnoreCase("hd") == 0) {
+				mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 1280, 720);
+			}
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
+			// width, heigth);
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 240,
+			// 160);
+			// mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 352,
+			// 288);
+		}
+		if (mPreviewSize != null) {
+			// Log.i("VideoCameraPreview",
+			// "onMeasure done // rotate_selfview_display = " +
+			// rotate_selfview_display + " optimal size = " + mPreviewSize.width
+			// + "x" + mPreviewSize.height);
+
+			int mPreviewSize_width;
+			int mPreviewSize_height;
+			if (rotate_selfview_display == 90 || rotate_selfview_display == 270) {
+				mPreviewSize_width = mPreviewSize.height;
+				mPreviewSize_height = mPreviewSize.width;
+			} else {
+				mPreviewSize_width = mPreviewSize.width;
+				mPreviewSize_height = mPreviewSize.height;
+			}
+			float imageSideRatio = (float) mPreviewSize_width / (float) mPreviewSize_height;
+			float viewSideRatio = (float) MeasureSpec.getSize(widthMeasureSpec) / (float) MeasureSpec.getSize(heightMeasureSpec);
+
+			if (imageSideRatio >= viewSideRatio) {
+				// Image is wider than the display (ratio)
+				int width = MeasureSpec.getSize(widthMeasureSpec);
+				int height = (int) (width / imageSideRatio);
+				setMeasuredDimension(width, height);
+			} else {
+				// Image is taller than the display (ratio)
+				int height = MeasureSpec.getSize(heightMeasureSpec);
+				int width = (int) (height * imageSideRatio);
+				setMeasuredDimension(width, height);
+			}
+		} else {
+			setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+		}
+	}
+
+	@Override
+	protected void onLayout(boolean changed, int l, int t, int r, int b) {
+		if (changed && getChildCount() > 0) {
+			final View child = getChildAt(0);
+
+			final int width = r - l;
+			final int height = b - t;
+
+			int previewWidth = width;
+			int previewHeight = height;
+			if (mPreviewSize != null) {
+				if (rotate_selfview_display == 90 || rotate_selfview_display == 270) {
+					previewWidth = mPreviewSize.height;
+					previewHeight = mPreviewSize.width;
+				} else {
+					previewWidth = mPreviewSize.width;
+					previewHeight = mPreviewSize.height;
+				}
+			}
+
+			// Center the child SurfaceView within the parent.
+			if (width * previewHeight > height * previewWidth) {
+				final int scaledChildWidth = previewWidth * height / previewHeight;
+				child.layout((width - scaledChildWidth) / 2, 0, (width + scaledChildWidth) / 2, height);
+			} else {
+				final int scaledChildHeight = previewHeight * width / previewWidth;
+				child.layout(0, (height - scaledChildHeight) / 2, width, (height + scaledChildHeight) / 2);
+			}
+		}
+	}
+
+	public void surfaceCreated(SurfaceHolder holder) {
+		// The Surface has been created, acquire the camera and tell it where
+		// to draw.
+		try {
+			if (mCamera != null) {
+				mCamera.setPreviewDisplay(holder);
+				if (android.os.Build.VERSION.SDK_INT < 8) {
+					mCamera.setPreviewCallback(mPreviewCallback);
+				} else {
+					mCamera.setPreviewCallbackWithBuffer(mPreviewCallback);
+				}
+
+				try {
+					if (android.os.Build.VERSION.SDK_INT >= 8) {
+						if (camera_preview_buffer == null)
+							camera_preview_buffer = new byte[1800000];
+						mCamera.addCallbackBuffer(camera_preview_buffer);
+					}
+					Log.i(TAG, "camera_preview_buffer allocated");
+				} catch (Exception e) {
+					Log.e(TAG, "Exception for allocation of camera_preview_buffer", e);
+					camera_preview_buffer = null;
+				}
+			}
+		} catch (IOException exception) {
+			Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+		}
+	}
+
+	public void surfaceDestroyed(SurfaceHolder holder) {
+		// Surface will be destroyed when we return, so stop the preview.
+		mHasActiveSurface=false;
+		if (mCamera != null) {
+			if (android.os.Build.VERSION.SDK_INT < 8) {
+				mCamera.setPreviewCallback(null);
+			} else {
+				mCamera.setPreviewCallbackWithBuffer(null);
+			}
+			mCamera.stopPreview();
+		}
+	}
+
+	public int getOptimalSupportedFormat(List<Integer> formats) {
+		int format = -1;
+
+		for (Integer fmt : formats) {
+			if (fmt.intValue() == ImageFormat.NV21) {
+				Log.i(TAG, "format: ImageFormat.NV21");
+			} else if (fmt.intValue() == ImageFormat.YUY2) {
+				Log.i(TAG, "format: ImageFormat.YUY2");
+			} else if (fmt.intValue() == ImageFormat.NV16) { // YUV422P
+				Log.i(TAG, "format: ImageFormat.NV16");
+			} else {
+				Log.i(TAG, "format: -not supported-" + fmt);
+			}
+		}
+
+		for (Integer fmt : formats) {
+			if (fmt.intValue() == ImageFormat.NV21) {
+				format = ImageFormat.NV21;
+				return format;
+			}
+		}
+
+		for (Integer fmt : formats) {
+			if (fmt.intValue() == ImageFormat.YUY2) {
+				format = ImageFormat.YUY2;
+				return format;
+			}
+		}
+
+		return format;
+	}
+
+	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
+		final double ASPECT_TOLERANCE = 0.1;
+		double targetRatio = (double) w / h;
+		if (sizes == null)
+			return null;
+
+		Size optimalSize = null;
+		double minDiff = Double.MAX_VALUE;
+
+		int targetHeight = h;
+
+		// Try to find an size match aspect ratio and size
+		for (Size size : sizes) {
+			Log.i("VvsipVideoPreview", "size list " + size.width + "x" + size.height);
+			double ratio = (double) size.width / size.height;
+			if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
+				continue;
+			if (Math.abs(size.height - targetHeight) < minDiff) {
+				optimalSize = size;
+				minDiff = Math.abs(size.height - targetHeight);
+			}
+		}
+
+		// Cannot find the one match the aspect ratio, ignore the requirement
+		if (optimalSize == null) {
+			minDiff = Double.MAX_VALUE;
+			for (Size size : sizes) {
+				if (Math.abs(size.height - targetHeight) < minDiff) {
+					optimalSize = size;
+					minDiff = Math.abs(size.height - targetHeight);
+				}
+			}
+		}
+
+		if (optimalSize == null) {
+			for (Size size : sizes) {
+				optimalSize = size;
+			}
+		}
+
+		if (android.os.Build.DEVICE.toUpperCase(Locale.US).startsWith("GT-P1010") == true) {
+			optimalSize.height = 480;
+			optimalSize.width = 640;
+		}
+
+		Log.i("VvsipVideoPreview", "final choice " + optimalSize.width + "x" + optimalSize.height);
+		return optimalSize;
+	}
+
+	static public int find_range_above(List<int[]> fpslist, int higher_than) {
+		int max = 100000;
+		int best_index = -1;
+		for (int i = 0; i < fpslist.size(); i++) {
+			int tmp_maxfps = fpslist.get(i)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
+			if (tmp_maxfps >= higher_than && max > tmp_maxfps) {
+				max = tmp_maxfps;
+				best_index = i;
+			}
+		}
+		if (max == 0)
+			return -1;
+		return best_index;
+	}
+
+	static public int find_range_below(List<int[]> fpslist, int lower_than) {
+		int max = 0;
+		int best_index = -1;
+		for (int i = 0; i < fpslist.size(); i++) {
+			int tmp_maxfps = fpslist.get(i)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
+			if (tmp_maxfps <= lower_than && max < tmp_maxfps) {
+				max = tmp_maxfps;
+				best_index = i;
+			}
+		}
+		if (max == 0)
+			return -1;
+		return best_index;
+	}
+
+	@TargetApi(9)
+	public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+		// Now that the size is known, set up the camera parameters and begin
+		// the preview.
+		mHasActiveSurface=true;
+		if (mCamera != null) {
+			Camera.Parameters parameters;
+			try {
+				parameters = mCamera.getParameters();
+			} catch (Exception e) {
+				// detected by report: java.lang.RuntimeException: getParameters
+				// failed (empty parameters)
+				Log.e(TAG, "Exception caused by mCamera.getParameters()", e);
+				mCamera = null;
+				return;
+			}
+
+			// java.lang.NullPointerException
+			// at
+			// com.vvsip.ansip.video.VideoCameraPreview.surfaceChanged(VideoCameraPreview.java:437)
+			// -> means mPreviewSize is null? or parameters?
+
+			try {
+				parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+				Log.i("VvsipVideoPreview", "parameters.setPreviewSize " + mPreviewSize.width + "x" + mPreviewSize.height
+						+ " for camera size");
+			} catch (Exception e) {
+				Log.d(TAG, "Failed to call setPreviewSize");
+				if (mPreviewSize == null)
+					Log.d(TAG, "mPreviewSize is null");
+			}
+			if (Build.VERSION.SDK_INT <= 4) {
+				parameters.set("preview-frame-rate", 1);
+				parameters.setPreviewFrameRate(1);
+			} else if (Build.VERSION.SDK_INT < 9) {
+				parameters.setPreviewFrameRate(15);
+			} else {
+				int[] fpsrange = new int[2];
+				parameters.getPreviewFpsRange(fpsrange);
+				Log.d(TAG, "cur minfps= " + fpsrange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]);
+				Log.d(TAG, "cur maxfps= " + fpsrange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+
+				try {
+					// crash received on GT-N7000 with
+					// getSupportedPreviewFpsRange returning null
+					List<int[]> fpslist = parameters.getSupportedPreviewFpsRange();
+
+					Log.d(TAG, "size= " + fpslist.size());
+					for (int i = 0; i < fpslist.size(); i++) {
+						Log.d(TAG, i + "found fps= " + fpslist.get(i)[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]);
+						Log.d(TAG, i + "found fps= " + fpslist.get(i)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+					}
+					int index_1 = find_range_below(fpslist, 15000);
+					int index_2 = find_range_above(fpslist, 15000);
+					int index = -1;
+					if (index_1 >= 0 && index_2 >= 0) {
+						if (fpslist.get(index_1)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] >= 10000)
+							index = index_1;
+						else
+							index = index_2;
+					} else if (index < 0 && index_1 >= 0) {
+						index = index_1;
+					} else if (index < 0 && index_2 >= 0) {
+						index = index_2;
+					}
+
+					if (index >= 0) {
+						Log.d(TAG, " new fps= " + fpslist.get(index)[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]);
+						Log.d(TAG, " new fps= " + fpslist.get(index)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+						parameters.setPreviewFpsRange(fpslist.get(index)[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
+								fpslist.get(index)[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+					}
+				} catch (Exception e) {
+					Log.d(TAG, "Failed to get/set FPS");
+				}
+			}
+			requestLayout();
+
+			try {
+				mCamera.setParameters(parameters);
+				mCamera.startPreview();
+			} catch (Exception exception) {
+				Log.e(TAG, "Exception caused by startPreview()", exception);
+			}
+		}
+	}
+
+	public void setRotateValue(Integer _rotate_selfview_display) {
+		// TODO Auto-generated method stub
+		rotate_selfview_display = _rotate_selfview_display;
+	}
+
+	public boolean hasActiveSurface() {
+		// TODO Auto-generated method stub
+		return mHasActiveSurface;
+	}
+}

+ 293 - 0
AmDemo_R/src/com/vvsip/viewsip/VideoDisplay.java

@@ -0,0 +1,293 @@
+/*
+  vvphone is a SIP app for android.
+  vvsip is a SIP library for softphone (SIP -rfc3261-)
+  Copyright (C) 2003-2010  Bluegoby - <bluegoby@163.com>
+ */
+package com.vvsip.viewsip;
+
+
+import com.vvsip.amdemo.R;
+import com.vvsip.ansip.IVvsipService;
+import com.vvsip.ansip.VvsipService;
+import com.vvsip.ansip.VvsipTask;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * SurfaceView的封装,功能:显示对方视频
+ */
+public class VideoDisplay extends SurfaceView {
+	private final String mTag = "VideoDisplay";
+
+	private Bitmap mStaticImage;
+	private SurfaceHolder holder;
+
+	private Bitmap mIncomingImage;
+
+	private boolean running = false;
+
+    int mVideoViewWidth;
+    int mVideoViewHeight;
+
+	private int onscreen_width=0;
+	private int onscreen_height=0;
+	private int android_scaling=0;
+	Rect orig = null;
+	Rect dest = null;
+	
+	public VideoDisplay(Context context, AttributeSet attrset) {
+		super(context, attrset);
+		mStaticImage = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
+		holder = getHolder();
+		holder.addCallback(new SurfaceHolder.Callback() {
+
+			@Override
+			public void surfaceDestroyed(SurfaceHolder holder) {
+
+				IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+				if (_vvsipTask == null)
+					return;
+				running = false;
+				Log.i(mTag, "videoout: VideoDisplay removed");
+				_vvsipTask.setvideodisplay(null);
+				if (mIncomingImage!=null)
+					mIncomingImage.recycle();
+				mIncomingImage=null;
+			}
+
+			@SuppressLint("WrongCall")
+			@Override
+			public void surfaceCreated(SurfaceHolder holder) {
+
+				try {
+					Canvas c = holder.lockCanvas(null);
+					onDraw(c);
+					holder.unlockCanvasAndPost(c);
+				} catch (Exception e) {
+
+				}
+
+				IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+				if (_vvsipTask == null)
+					return;
+				_vvsipTask.setvideodisplay(VideoDisplay.this);
+				running = true;
+				Log.i(mTag, "videoout: VideoDisplay provided");
+			}
+
+			@Override
+			public void surfaceChanged(SurfaceHolder holder, int format,
+					int width, int height) {
+			}
+		});
+	}
+
+	public VideoDisplay(Context context) {
+		super(context);
+		mStaticImage = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
+		holder = getHolder();
+		holder.addCallback(new SurfaceHolder.Callback() {
+
+			@Override
+			public void surfaceDestroyed(SurfaceHolder holder) {
+
+				IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+				if (_vvsipTask == null)
+					return;
+				running = false;
+				Log.i(mTag, "videoout: VideoDisplay removed");
+				_vvsipTask.setvideodisplay(null);
+				if (mIncomingImage!=null)
+					mIncomingImage.recycle();
+				mIncomingImage=null;
+			}
+
+			@SuppressLint("WrongCall")
+			@Override
+			public void surfaceCreated(SurfaceHolder holder) {
+
+				try {
+					Canvas c = holder.lockCanvas(null);
+					onDraw(c);
+					holder.unlockCanvasAndPost(c);
+				} catch (Exception e) {
+
+				}
+
+				IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+				if (_vvsipTask == null)
+					return;
+				_vvsipTask.setvideodisplay(VideoDisplay.this);
+				running = true;
+				Log.i(mTag, "videoout: VideoDisplay provided (2)");
+			}
+
+			@Override
+			public void surfaceChanged(SurfaceHolder holder, int format,
+					int width, int height) {
+			}
+		});
+	}
+
+	static int gcd(int m, int n)
+	{
+	   if(n == 0)
+	     return m;
+	   else
+	     return gcd(n, m % n);
+	}
+
+	int ratiow=0;
+	int ratioh=0;
+
+	void reduce(int num, int denom)
+	{
+	   int divisor = gcd(num, denom);
+	   ratiow = num/divisor;
+	   ratioh = denom/divisor;
+	}
+
+	public Bitmap lockIncomingImage(int width, int height) {
+		if (running == false)
+			return null;
+
+		if (mIncomingImage == null || mIncomingImage.getWidth() != width
+				|| mIncomingImage.getHeight() != height) {
+			Log.i(mTag, "videoout: Creating bitmap");
+			
+			reduce(width, height);
+			Log.i(mTag, "videoout: transform " + width + "x" + height + " ratio " + ratiow +"x"+ ratioh);
+		    mVideoViewWidth = findViewById(R.id.video_view2).getWidth();
+		    mVideoViewHeight = findViewById(R.id.video_view2).getHeight();
+			Log.i(mTag, "videoout: transform " + width + "x" + height + " into " + mVideoViewWidth +"x"+ mVideoViewHeight);
+            int wtmp = mVideoViewWidth/ratiow;
+            wtmp = wtmp*ratiow;
+            int htmp = mVideoViewHeight/ratioh;
+            htmp = htmp*ratioh;
+            if (htmp*ratiow>wtmp*ratioh)
+            {
+                htmp = wtmp*ratioh/ratiow;
+            } else {
+                wtmp = htmp*ratiow/ratioh;
+            }
+			Log.i(mTag, "videoout: transform " + width + "x" + height + " final size " + wtmp +"x"+ htmp);
+			
+			if (wtmp>3*width && Build.VERSION.SDK_INT<11)
+			{
+				//refuse to have such bigger resizing
+				wtmp = width*3;
+				htmp = height*3;
+				Log.i(mTag, "videoout: transform " + width + "x" + height + " final size reduced to " + wtmp +"x"+ htmp);
+			}
+			
+			if (Build.VERSION.SDK_INT<=8) {
+				//keep good performance on device older than android 2.2 
+				onscreen_width=width;
+				onscreen_height=height;
+				if (wtmp>2*width)
+				{
+					//refuse to have such bigger resizing
+					wtmp = width*2;
+					htmp = height*2;
+					Log.i(mTag, "videoout: transform " + width + "x" + height + " final size reduced to " + wtmp +"x"+ htmp);
+				} else {
+					//refuse to have such bigger resizing
+					wtmp = width;
+					htmp = height;
+					Log.i(mTag, "videoout: transform " + width + "x" + height + " final size reduced to " + wtmp +"x"+ htmp);
+				}
+			}
+
+			try {
+				if (android_scaling==0) {
+					onscreen_width=wtmp;
+					onscreen_height=htmp;
+					mIncomingImage = Bitmap.createBitmap(width, height, Config.RGB_565);
+				} else {
+					mIncomingImage = Bitmap.createBitmap(wtmp, htmp, Config.RGB_565);
+				}
+			} catch (Exception e) {
+				mIncomingImage = null;
+				Log.e(mTag, "Bitmap.createBitmap failed -- Exception: " + e.getMessage());
+			}
+		}
+		return mIncomingImage;
+	}
+
+	@SuppressLint("WrongCall")
+	public synchronized void unlockIncomingImage() {
+		try {
+			if (running == false)
+				return;
+			Canvas c = holder.lockCanvas(null);
+			onDraw(c);
+			holder.unlockCanvasAndPost(c);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	protected void onDraw(Canvas canvas) {
+
+		if (mStaticImage==null) {
+			canvas.drawColor(Color.BLACK);
+			return;
+		}
+
+		if (mIncomingImage == null) {
+			int posx = (this.getWidth() - mStaticImage.getWidth()) / 2;
+			int posh = (this.getHeight() - mStaticImage.getHeight()) / 2;
+			canvas.drawColor(Color.BLACK);
+			canvas.drawBitmap(mStaticImage, posx, posh, null);
+		} else {
+			
+			if (android_scaling==0) {
+				int posx = (this.getWidth() - onscreen_width) / 2;
+				int post = (this.getHeight() - onscreen_height) / 2;
+				int posr = (this.getWidth() - onscreen_width) / 2 + onscreen_width;
+				int posb = (this.getHeight() - onscreen_height) / 2 + onscreen_height;
+				
+				if (orig==null || dest==null) {
+					orig = new Rect(0, 0, mIncomingImage.getWidth(), mIncomingImage.getHeight());
+					dest = new Rect(posx, post, posr, posb);
+				} else {
+					orig.set(0, 0, mIncomingImage.getWidth(), mIncomingImage.getHeight());
+					dest.set(posx, post, posr, posb);
+				}
+				canvas.drawColor(Color.BLACK);
+				canvas.drawBitmap (mIncomingImage, orig, dest, null);
+			} else {
+				int posx = (this.getWidth() - mIncomingImage.getWidth()) / 2;
+				int post = (this.getHeight() - mIncomingImage.getHeight()) / 2;
+				canvas.drawColor(Color.BLACK);
+				canvas.drawBitmap(mIncomingImage, posx, post, null);
+			}
+		}
+	}
+
+}

+ 1 - 0
README.md

@@ -0,0 +1 @@
+#CallingBed

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 94 - 0
app/build.gradle

@@ -0,0 +1,94 @@
+apply plugin: 'com.android.application'
+
+android {
+    // wuyq add for sign begin
+    signingConfigs {
+        release {
+            storeFile file("keystore/wdkl_bed.jks")
+            storePassword "111111"
+            keyAlias "wdkl_bed"
+            keyPassword "111111"
+        }
+        debug {
+            storeFile file("keystore/wdkl_bed.jks")
+            storePassword "111111"
+            keyAlias "wdkl_bed"
+            keyPassword "111111"
+        }
+    }
+    // wuyq add for sign end
+
+    compileSdkVersion 26
+    buildToolsVersion "26.0.1"
+    defaultConfig {
+        applicationId "com.wdkl.callingbed"
+        minSdkVersion 15
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.2"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        // wuyq add for sign begin
+        debug {
+            signingConfig signingConfigs.debug
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+        // wuyq add for sign end
+
+        release {
+            //wuyq add for sign begin
+            signingConfig signingConfigs.release
+            //wuyq add for sign end
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+
+    compile 'com.android.support:appcompat-v7:24.2.0'
+    compile 'com.android.support.constraint:constraint-layout:1.0.2'
+    testCompile 'junit:junit:4.12'
+    compile 'com.android.support:recyclerview-v7:24.2.0'
+    compile 'org.greenrobot:eventbus:3.0.0'
+    compile 'com.jakewharton:butterknife:7.0.1'
+
+    compile 'com.android.support:design:23.4.0'
+
+    // 适配
+    compile 'com.zhy:autolayout:1.4.3'
+    //hongyang okhttp
+    compile 'com.zhy:okhttputils:2.6.2'
+    //串口依赖库
+    compile project(path: ':bedlib')
+    //gson
+    compile 'com.google.code.gson:gson:2.7'
+    //图片框架
+    compile 'com.squareup.picasso:picasso:2.5.2'
+    //文字跳动
+    compile 'net.frakbot:jumpingbeans:1.3.0'
+    compile files('libs/core-3.2.1.jar')
+    compile project(':AmDemo_R')
+    compile 'com.android.support:cardview-v7:23.2.0'
+    compile 'com.github.anrwatchdog:anrwatchdog:1.3.+'
+//    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
+//    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
+
+}
+
+String SDK_DIR = System.getenv("ANDROID_SDK_HOME")
+if (SDK_DIR == null) {
+    Properties props = new Properties()
+    props.load(new FileInputStream(project.rootProject.file("local.properties")))
+    SDK_DIR = props.get('sdk.dir');
+}
+dependencies {
+    provided files("${SDK_DIR}/platforms/android-25/data/layoutlib.jar")
+}

BIN
app/keystore/callingbed.jks


BIN
app/keystore/wdkl_bed.jks


+ 139 - 0
app/keystore_wuyuqing_3128/keytool-importkeypair

@@ -0,0 +1,139 @@
+#! /bin/bash
+#
+# This file is part of keytool-importkeypair.
+#
+# keytool-importkeypair is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# keytool-importkeypair is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with keytool-importkeypair.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+DEFAULT_KEYSTORE=$HOME/.keystore
+keystore=$DEFAULT_KEYSTORE
+pk8=""
+cert=""
+alias=""
+passphrase=""
+tmpdir=""
+
+scriptname=`basename $0`
+
+usage() {
+cat << EOF
+usage: ${scriptname} [-k keystore] [-p storepass]
+-pk8 pk8 -cert cert -alias key_alias
+
+This script is used to import a key/certificate pair
+into a Java keystore.
+
+If a keystore is not specified then the key pair is imported into
+~/.keystore in the user's home directory.
+
+The passphrase can also be read from stdin.
+EOF
+}
+
+cleanup() {
+if [ ! -z "${tmpdir}" -a -d ${tmpdir} ]; then
+   rm -fr ${tmpdir}
+fi
+}
+
+while [ $# -gt 0 ]; do
+        case $1
+        in
+                -p | --passphrase | -passphrase)
+                        passphrase=$2
+                        shift 2
+        ;;
+                -h | --help)
+                        usage
+                        exit 0
+        ;;
+                -k | -keystore | --keystore)
+                        keystore=$2
+                        shift 2
+        ;;
+                -pk8 | --pk8 | -key | --key)
+                        pk8=$2
+                        shift 2
+        ;;
+                -cert | --cert | -pem | --pem)
+                        cert=$2
+                        shift 2
+        ;;
+                -a | -alias | --alias)
+                        alias=$2
+                        shift 2
+        ;;
+                *)
+                        echo "${scriptname}: Unknown option $1, exiting" 1>&2
+                        usage
+                        exit 1
+        ;;
+        esac
+done
+
+if [ -z "${pk8}" -o -z "${cert}" -o -z "${alias}" ]; then
+   echo "${scriptname}: Missing option, exiting..." 1>&2
+   usage
+   exit 1
+fi
+
+
+for f in "${pk8}" "${cert}"; do
+    if [ ! -f "$f" ]; then
+       echo "${scriptname}: Can't find file $f, exiting..." 1>&2
+       exit 1
+    fi
+done
+
+if [ ! -f "${keystore}" ]; then
+   storedir=`dirname "${keystore}"`
+   if [ ! -d "${storedir}" -o ! -w "${storedir}" ]; then
+      echo "${scriptname}: Can't access ${storedir}, exiting..." 1>&2
+      exit 1
+   fi
+fi
+
+# Create temp directory ofr key and pkcs12 bundle
+tmpdir=`mktemp -q -d "/tmp/${scriptname}.XXXX"`
+
+if [ $? -ne 0 ]; then
+   echo "${scriptname}: Can't create temp directory, exiting..." 1>&2
+   exit 1
+fi
+
+key="${tmpdir}/key"
+p12="${tmpdir}/p12"
+
+if [ -z "${passphrase}" ]; then
+   # Request a passphrase
+  read -p "Enter a passphrase: " -s passphrase
+  echo ""
+fi
+
+# Convert PK8 to PEM KEY
+openssl pkcs8 -inform DER -nocrypt -in "${pk8}" -out "${key}"
+
+# Bundle CERT and KEY
+openssl pkcs12 -export -in "${cert}" -inkey "${key}" -out "${p12}" -password pass:"${passphrase}" -name "${alias}"
+
+# Print cert
+echo -n "Importing \"${alias}\" with "
+openssl x509 -noout -fingerprint -in "${cert}"
+
+# Import P12 in Keystore
+keytool -importkeystore -deststorepass "${passphrase}" -destkeystore "${keystore}" -srckeystore "${p12}" -srcstoretype PKCS12 -srcstorepass "${passphrase}" 
+
+# Cleanup
+cleanup

+ 1 - 0
app/keystore_wuyuqing_3128/password.txt

@@ -0,0 +1 @@
+111111

BIN
app/keystore_wuyuqing_3128/platform.pk8


+ 24 - 0
app/keystore_wuyuqing_3128/platform.x509.pem

@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIJAP8GQTI8+VUSMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xNDEyMjMwNjQzNDFaFw00MjA1MTAwNjQzNDFaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
+hvcNAQEBBQADggENADCCAQgCggEBAKHY8Fl4XZzpJvgHoezYjhmKPvdq9DGYVc/X
+9NQO5oUlYIA/Ci5rzvljz13KbNve/KxuEu9HN8SzsLg9EBhghOko8JxEg7I8W6uP
+VOoRngNCMvXzjf6av77vxPqphlgq++Y4MIC+fiOxLd+gpYq0p6W7RWxEgrzLHnWi
+CX0dRmWDs+ey2t4f1WKzGoRQQS0Tn21CViThrVEe+zNwANnhErUcvoQB2m4/PQot
+uij7LZNccHJvUOUf5/4wIZd8JOgO3VLwzFO/HhrqUjafCvkpKTjW8oQmHLUz5m40
+ljETGEjqQ6AuAwmaeFT+Bwj1DUaYg+m7AzalJ2aAtHVX0FftRUkCAQOjUDBOMB0G
+A1UdDgQWBBQi+LgbyFfWSoWCbQ+NVDF4ZKTPCjAfBgNVHSMEGDAWgBQi+LgbyFfW
+SoWCbQ+NVDF4ZKTPCjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBH
+1kIQlSBjXRMuQdaDLytr8ZaJXIN1HApg2QA8azYQXOS/B16gwm6tBfh1dL86LL/7
+w09oM9LZv8WwtQyFNjM97vvQvkaOGW/ubhrKOk3+8HTHkEx4n7H6tYGOLdpmWepD
+fBSEFuLwq6yqG6wZFdd7IKO+sPlCxqUpqg40YAb4WOwzDbiuJnswDftP3wIaaJPh
+li6OIjRKyd3Sgw1MtffHOy+WSwqHLkGNgH6GAgvZlvhPA/yim+rjnE9oKV5G6Pyg
+QK7kJJjS/LdeqxE7M7pNRYPhcLT7qhE7MiuBuyqwAMTTBoU8u3lTdOZwNErbRT5t
+SXkgVMffkfN7wBNqpSSY
+-----END CERTIFICATE-----

BIN
app/keystore_wuyuqing_3128/rk3128.jks


+ 7 - 0
app/keystore_wuyuqing_3128/rk3128_generate_key.sh

@@ -0,0 +1,7 @@
+#!/bin/sh
+# 转换系统签名命令
+./keytool-importkeypair -k rk3128.jks -p 111111 -pk8 platform.pk8 -cert platform.x509.pem -alias rk3128
+# rk3128.jks : 签名文件
+# 111111 : 签名文件密码
+# platform.pk8、platform.x509.pem : 系统签名文件
+# rk3128 : 签名文件别名

+ 139 - 0
app/keystore_wuyuqing_3128/rk3128_signapk/keytool-importkeypair

@@ -0,0 +1,139 @@
+#! /bin/bash
+#
+# This file is part of keytool-importkeypair.
+#
+# keytool-importkeypair is free software: you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# keytool-importkeypair is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with keytool-importkeypair.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+DEFAULT_KEYSTORE=$HOME/.keystore
+keystore=$DEFAULT_KEYSTORE
+pk8=""
+cert=""
+alias=""
+passphrase=""
+tmpdir=""
+
+scriptname=`basename $0`
+
+usage() {
+cat << EOF
+usage: ${scriptname} [-k keystore] [-p storepass]
+-pk8 pk8 -cert cert -alias key_alias
+
+This script is used to import a key/certificate pair
+into a Java keystore.
+
+If a keystore is not specified then the key pair is imported into
+~/.keystore in the user's home directory.
+
+The passphrase can also be read from stdin.
+EOF
+}
+
+cleanup() {
+if [ ! -z "${tmpdir}" -a -d ${tmpdir} ]; then
+   rm -fr ${tmpdir}
+fi
+}
+
+while [ $# -gt 0 ]; do
+        case $1
+        in
+                -p | --passphrase | -passphrase)
+                        passphrase=$2
+                        shift 2
+        ;;
+                -h | --help)
+                        usage
+                        exit 0
+        ;;
+                -k | -keystore | --keystore)
+                        keystore=$2
+                        shift 2
+        ;;
+                -pk8 | --pk8 | -key | --key)
+                        pk8=$2
+                        shift 2
+        ;;
+                -cert | --cert | -pem | --pem)
+                        cert=$2
+                        shift 2
+        ;;
+                -a | -alias | --alias)
+                        alias=$2
+                        shift 2
+        ;;
+                *)
+                        echo "${scriptname}: Unknown option $1, exiting" 1>&2
+                        usage
+                        exit 1
+        ;;
+        esac
+done
+
+if [ -z "${pk8}" -o -z "${cert}" -o -z "${alias}" ]; then
+   echo "${scriptname}: Missing option, exiting..." 1>&2
+   usage
+   exit 1
+fi
+
+
+for f in "${pk8}" "${cert}"; do
+    if [ ! -f "$f" ]; then
+       echo "${scriptname}: Can't find file $f, exiting..." 1>&2
+       exit 1
+    fi
+done
+
+if [ ! -f "${keystore}" ]; then
+   storedir=`dirname "${keystore}"`
+   if [ ! -d "${storedir}" -o ! -w "${storedir}" ]; then
+      echo "${scriptname}: Can't access ${storedir}, exiting..." 1>&2
+      exit 1
+   fi
+fi
+
+# Create temp directory ofr key and pkcs12 bundle
+tmpdir=`mktemp -q -d "/tmp/${scriptname}.XXXX"`
+
+if [ $? -ne 0 ]; then
+   echo "${scriptname}: Can't create temp directory, exiting..." 1>&2
+   exit 1
+fi
+
+key="${tmpdir}/key"
+p12="${tmpdir}/p12"
+
+if [ -z "${passphrase}" ]; then
+   # Request a passphrase
+  read -p "Enter a passphrase: " -s passphrase
+  echo ""
+fi
+
+# Convert PK8 to PEM KEY
+openssl pkcs8 -inform DER -nocrypt -in "${pk8}" -out "${key}"
+
+# Bundle CERT and KEY
+openssl pkcs12 -export -in "${cert}" -inkey "${key}" -out "${p12}" -password pass:"${passphrase}" -name "${alias}"
+
+# Print cert
+echo -n "Importing \"${alias}\" with "
+openssl x509 -noout -fingerprint -in "${cert}"
+
+# Import P12 in Keystore
+keytool -importkeystore -deststorepass "${passphrase}" -destkeystore "${keystore}" -srckeystore "${p12}" -srcstoretype PKCS12 -srcstorepass "${passphrase}" 
+
+# Cleanup
+cleanup

BIN
app/keystore_wuyuqing_3128/rk3128_signapk/platform.pk8


+ 24 - 0
app/keystore_wuyuqing_3128/rk3128_signapk/platform.x509.pem

@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIJAP8GQTI8+VUSMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xNDEyMjMwNjQzNDFaFw00MjA1MTAwNjQzNDFaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
+hvcNAQEBBQADggENADCCAQgCggEBAKHY8Fl4XZzpJvgHoezYjhmKPvdq9DGYVc/X
+9NQO5oUlYIA/Ci5rzvljz13KbNve/KxuEu9HN8SzsLg9EBhghOko8JxEg7I8W6uP
+VOoRngNCMvXzjf6av77vxPqphlgq++Y4MIC+fiOxLd+gpYq0p6W7RWxEgrzLHnWi
+CX0dRmWDs+ey2t4f1WKzGoRQQS0Tn21CViThrVEe+zNwANnhErUcvoQB2m4/PQot
+uij7LZNccHJvUOUf5/4wIZd8JOgO3VLwzFO/HhrqUjafCvkpKTjW8oQmHLUz5m40
+ljETGEjqQ6AuAwmaeFT+Bwj1DUaYg+m7AzalJ2aAtHVX0FftRUkCAQOjUDBOMB0G
+A1UdDgQWBBQi+LgbyFfWSoWCbQ+NVDF4ZKTPCjAfBgNVHSMEGDAWgBQi+LgbyFfW
+SoWCbQ+NVDF4ZKTPCjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBH
+1kIQlSBjXRMuQdaDLytr8ZaJXIN1HApg2QA8azYQXOS/B16gwm6tBfh1dL86LL/7
+w09oM9LZv8WwtQyFNjM97vvQvkaOGW/ubhrKOk3+8HTHkEx4n7H6tYGOLdpmWepD
+fBSEFuLwq6yqG6wZFdd7IKO+sPlCxqUpqg40YAb4WOwzDbiuJnswDftP3wIaaJPh
+li6OIjRKyd3Sgw1MtffHOy+WSwqHLkGNgH6GAgvZlvhPA/yim+rjnE9oKV5G6Pyg
+QK7kJJjS/LdeqxE7M7pNRYPhcLT7qhE7MiuBuyqwAMTTBoU8u3lTdOZwNErbRT5t
+SXkgVMffkfN7wBNqpSSY
+-----END CERTIFICATE-----

BIN
app/keystore_wuyuqing_3128/rk3128_signapk/rk3128.jks


+ 7 - 0
app/keystore_wuyuqing_3128/rk3128_signapk/rk3128_generate_key.sh

@@ -0,0 +1,7 @@
+#!/bin/sh
+# 转换系统签名命令
+./keytool-importkeypair -k rk3128.jks -p 111111 -pk8 platform.pk8 -cert platform.x509.pem -alias rk3128
+# rk3128.jks : 签名文件
+# 111111 : 签名文件密码
+# platform.pk8、platform.x509.pem : 系统签名文件
+# rk3128 : 签名文件别名

BIN
app/keystore_wuyuqing_3128/rk3128_signapk/signapk.jar


BIN
app/keystore_wuyuqing_3128/signapk.jar


BIN
app/libs/core-3.2.1.jar


+ 25 - 0
app/proguard-rules.pro

@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in D:\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

BIN
app/sign_apk/platform.pk8


+ 27 - 0
app/sign_apk/platform.x509.pem

@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEqDCCA5CgAwIBAgIJALOZgIbQVs/6MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
+VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
+AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0wODA0MTUyMjQwNTBaFw0zNTA5MDEyMjQwNTBaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
+A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
+hvcNAQEBBQADggENADCCAQgCggEBAJx4BZKsDV04HN6qZezIpgBuNkgMbXIHsSAR
+vlCGOqvitV0Amt9xRtbyICKAx81Ne9smJDuKgGwms0sTdSOkkmgiSQTcAUk+fArP
+GgXIdPabA3tgMJ2QdNJCgOFrrSqHNDYZUer3KkgtCbIEsYdeEqyYwap3PWgAuer9
+5W1Yvtjo2hb5o2AJnDeoNKbf7be2tEoEngeiafzPLFSW8s821k35CjuNjzSjuqtM
+9TNxqydxmzulh1StDFP8FOHbRdUeI0+76TybpO35zlQmE1DsU1YHv2mi/0qgfbX3
+6iANCabBtJ4hQC+J7RGQiTqrWpGA8VLoL4WkV1PPX8GQccXuyCcCAQOjgfwwgfkw
+HQYDVR0OBBYEFE/koLPdnLop9x1yh8Tnw48ghsKZMIHJBgNVHSMEgcEwgb6AFE/k
+oLPdnLop9x1yh8Tnw48ghsKZoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
+CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
+QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
+CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJALOZgIbQVs/6MAwGA1Ud
+EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAFclUbjZOh9z3g9tRp+G2tZwFAAp
+PIigzXzXeLc9r8wZf6t25iEuVsHHYc/EL9cz3lLFCuCIFM78CjtaGkNGBU2Cnx2C
+tCsgSL+ItdFJKe+F9g7dEtctVWV+IuPoXQTIMdYT0Zk4u4mCJH+jISVroS0dao+S
+6h2xw3Mxe6DAN/DRr/ZFrvIkl5+6bnoUvAJccbmBOM7z3fwFlhfPJIRc97QNY4L3
+J17XOElatuWTG5QhdlxJG3L7aOCA29tYwgKdNHyLMozkPvaosVUz7fvpib1qSN1L
+IC7alMarjdW4OZID2q4u1EYjLk/pvZYTlMYwDlE448/Shebk5INTjLixs1c=
+-----END CERTIFICATE-----

BIN
app/sign_apk/signapk.jar


+ 1 - 0
app/sign_apk/签名方法.txt

@@ -0,0 +1 @@
+java -jar signapk.jar platform.x509.pem platform.pk8 app-release-unsigned.apk CallingBed_V10.0_20180929.apk

+ 26 - 0
app/src/androidTest/java/com/wdkl/callingbed/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.wdkl.callingbed;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.wdkl.callingbed", appContext.getPackageName());
+    }
+}

+ 105 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:sharedUserId="android.uid.system"
+    package="com.wdkl.callingbed"
+    >
+    <!--android:sharedUserId="android.uid.system"-->
+
+    <uses-permission android:name="android.permission.SHUTDOWN" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
+
+    <uses-permission
+        android:name="android.permission.INSTALL_PACKAGES"
+        tools:ignore="ProtectedPermissions" />
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.USE_SIP" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
+    <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
+    <uses-permission android:name="android.permission.CAMERA"></uses-permission>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
+    <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
+    <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+
+
+    <uses-feature
+        android:name="android.hardware.sip.voip"
+        android:required="true" />
+    <uses-feature
+        android:name="android.hardware.wifi"
+        android:required="true" />
+    <uses-feature
+        android:name="android.hardware.microphone"
+        android:required="true" />
+
+    <application
+        android:name=".MyApplication"
+        android:allowBackup="true"
+        android:icon="@mipmap/app_logo"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme"
+        tools:replace="android:icon">
+
+        <activity android:name=".ui.CallingBedActivity"
+            android:screenOrientation="landscape"></activity>
+
+        <activity android:name="com.wdkl.callingbed.ui.APPUpdateActivity"
+            android:screenOrientation="landscape"
+            android:launchMode="singleTop"></activity>
+
+        <activity android:name=".ui.InitActivity"
+            android:screenOrientation="landscape">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.MONKEY" />
+            </intent-filter>
+        </activity>
+
+        <receiver android:name=".receive.AlarmReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.ACTION_CALL" />
+                <action android:name="android.intent.action.SMS" />
+                <action android:name="android.intent.action.PHONE_STATE" />
+                <action android:name="android.intent.action.ANSWER" />
+                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
+            </intent-filter>
+        </receiver>
+
+        <!--系统重启自启APP-->
+        <!--SIP Service-->
+        <service
+            android:name="com.vvsip.ansip.VvsipService"
+            android:icon="@drawable/ic_launcher"></service>
+        <service
+            android:name="com.wdkl.callingbed.service.APPService"> </service>
+
+        <!-- 适配480 800 -->
+        <meta-data android:name="design_width" android:value="480"/>
+        <meta-data android:name="design_height" android:value="800"/>
+
+    </application>
+
+</manifest>

+ 26 - 0
app/src/main/aidl/android/content/pm/IPackageDataObserver.aidl

@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.content.pm;
+/**
+ * API for package data change related callbacks from the Package Manager.
+ * Some usage scenarios include deletion of cache directory, generate
+ * statistics related to code, data, cache usage(TODO)
+ * {@hide}
+ */
+oneway interface IPackageDataObserver {
+    void onRemoveCompleted(in String packageName, boolean succeeded);
+}

+ 0 - 0
app/src/main/aidl/android/content/pm/IPackageDeleteObserver.aidl


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels