Merge "1. Added OverlayFrame constuctor 2. Invalidate transitions when trimming video 3. Remove image file when removing an OverlayFrame 4. Bug fixes in the VideoEditor implementation"
diff --git a/api/current.xml b/api/current.xml
index 51315ab..5e57d80 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -46584,6 +46584,21 @@
<parameter name="cursor" type="android.database.Cursor">
</parameter>
</method>
+<method name="registerContentObserver"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cursor" type="android.database.Cursor">
+</parameter>
+<parameter name="observer" type="android.database.ContentObserver">
+</parameter>
+</method>
<method name="setProjection"
return="void"
abstract="false"
@@ -72506,6 +72521,146 @@
>
</field>
</class>
+<class name="BitmapRegionDecoder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="decodeRegion"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rect" type="android.graphics.Rect">
+</parameter>
+<parameter name="options" type="android.graphics.BitmapFactory.Options">
+</parameter>
+</method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isRecycled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="newInstance"
+ return="android.graphics.BitmapRegionDecoder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pathName" type="java.lang.String">
+</parameter>
+<parameter name="isShareable" type="boolean">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="recycle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
<class name="BitmapShader"
extends="android.graphics.Shader"
abstract="false"
@@ -89655,6 +89810,19 @@
visibility="public"
>
</method>
+<method name="onCurrentInputMethodSubtypeChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="newSubtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
<method name="onDisplayCompletions"
return="void"
abstract="false"
@@ -90258,6 +90426,19 @@
<parameter name="binding" type="android.view.inputmethod.InputBinding">
</parameter>
</method>
+<method name="changeInputMethodSubtype"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
<method name="hideSoftInput"
return="void"
abstract="false"
@@ -94480,1079 +94661,6 @@
>
</method>
</class>
-<class name="AudioEffect"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="AudioEffect"
- type="android.media.AudioEffect"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="type" type="java.util.UUID">
-</parameter>
-<parameter name="uuid" type="java.util.UUID">
-</parameter>
-<parameter name="priority" type="int">
-</parameter>
-<parameter name="audioSession" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="RuntimeException" type="java.lang.RuntimeException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</constructor>
-<method name="byteArrayToInt"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="valueBuf" type="byte[]">
-</parameter>
-</method>
-<method name="byteArrayToInt"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="valueBuf" type="byte[]">
-</parameter>
-<parameter name="offset" type="int">
-</parameter>
-</method>
-<method name="byteArrayToShort"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="valueBuf" type="byte[]">
-</parameter>
-</method>
-<method name="byteArrayToShort"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="valueBuf" type="byte[]">
-</parameter>
-<parameter name="offset" type="int">
-</parameter>
-</method>
-<method name="checkState"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="methodName" type="java.lang.String">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="checkStatus"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="status" type="int">
-</parameter>
-</method>
-<method name="command"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cmdCode" type="int">
-</parameter>
-<parameter name="command" type="byte[]">
-</parameter>
-<parameter name="reply" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="concatArrays"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="arrays" type="byte...">
-</parameter>
-</method>
-<method name="getDescriptor"
- return="android.media.AudioEffect.Descriptor"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getEnabled"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="byte[]">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="int[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="short[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="int[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="short[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="getParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="hasControl"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="intToByteArray"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="value" type="int">
-</parameter>
-</method>
-<method name="queryEffects"
- return="android.media.AudioEffect.Descriptor[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="release"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="setControlStatusListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.AudioEffect.OnControlStatusChangeListener">
-</parameter>
-</method>
-<method name="setEnableStatusListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.AudioEffect.OnEnableStatusChangeListener">
-</parameter>
-</method>
-<method name="setEnabled"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="enabled" type="boolean">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="byte[]">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="int">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="short">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="int[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="short[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameter"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="param" type="int[]">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-</method>
-<method name="setParameterListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.AudioEffect.OnParameterChangeListener">
-</parameter>
-</method>
-<method name="shortToByteArray"
- return="byte[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="value" type="short">
-</parameter>
-</method>
-<field name="ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ALREADY_EXISTS"
- type="int"
- transient="false"
- volatile="false"
- value="-2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="CONTENT_TYPE_GAME"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="CONTENT_TYPE_MOVIE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="CONTENT_TYPE_MUSIC"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="CONTENT_TYPE_VOICE"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_AUXILIARY"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""Auxiliary""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_INSERT"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""Insert""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_BASS_BOOST"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_ENV_REVERB"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_EQUALIZER"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_NULL"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_PRESET_REVERB"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_TYPE_VIRTUALIZER"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR"
- type="int"
- transient="false"
- volatile="false"
- value="-1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_BAD_VALUE"
- type="int"
- transient="false"
- volatile="false"
- value="-4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_DEAD_OBJECT"
- type="int"
- transient="false"
- volatile="false"
- value="-7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_INVALID_OPERATION"
- type="int"
- transient="false"
- volatile="false"
- value="-5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_NO_INIT"
- type="int"
- transient="false"
- volatile="false"
- value="-3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_NO_MEMORY"
- type="int"
- transient="false"
- volatile="false"
- value="-6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_AUDIO_SESSION"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.extra.AUDIO_SESSION""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_CONTENT_TYPE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.extra.CONTENT_TYPE""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_PACKAGE_NAME"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.media.extra.PACKAGE_NAME""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NATIVE_EVENT_CONTROL_STATUS"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NATIVE_EVENT_ENABLED_STATUS"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NATIVE_EVENT_PARAMETER_CHANGED"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATE_INITIALIZED"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATE_UNINITIALIZED"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="SUCCESS"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mListenerLock"
- type="java.lang.Object"
- transient="false"
- volatile="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mNativeEventHandler"
- type="android.media.AudioEffect.NativeEventHandler"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="AudioEffect.Descriptor"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="AudioEffect.Descriptor"
- type="android.media.AudioEffect.Descriptor"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="AudioEffect.Descriptor"
- type="android.media.AudioEffect.Descriptor"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="type" type="java.lang.String">
-</parameter>
-<parameter name="uuid" type="java.lang.String">
-</parameter>
-<parameter name="connectMode" type="java.lang.String">
-</parameter>
-<parameter name="name" type="java.lang.String">
-</parameter>
-<parameter name="implementor" type="java.lang.String">
-</parameter>
-</constructor>
-<field name="mConnectMode"
- type="java.lang.String"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mImplementor"
- type="java.lang.String"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mName"
- type="java.lang.String"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mType"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="mUuid"
- type="java.util.UUID"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="AudioEffect.NativeEventHandler"
- extends="android.os.Handler"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="private"
->
-<constructor name="AudioEffect.NativeEventHandler"
- type="android.media.AudioEffect.NativeEventHandler"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="ae" type="android.media.AudioEffect">
-</parameter>
-<parameter name="looper" type="android.os.Looper">
-</parameter>
-</constructor>
-</class>
-<interface name="AudioEffect.OnControlStatusChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onControlStatusChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.AudioEffect">
-</parameter>
-<parameter name="controlGranted" type="boolean">
-</parameter>
-</method>
-</interface>
-<interface name="AudioEffect.OnEnableStatusChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onEnableStatusChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.AudioEffect">
-</parameter>
-<parameter name="enabled" type="boolean">
-</parameter>
-</method>
-</interface>
-<interface name="AudioEffect.OnParameterChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onParameterChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.AudioEffect">
-</parameter>
-<parameter name="status" type="int">
-</parameter>
-<parameter name="param" type="byte[]">
-</parameter>
-<parameter name="value" type="byte[]">
-</parameter>
-</method>
-</interface>
<class name="AudioFormat"
extends="java.lang.Object"
abstract="false"
@@ -98394,217 +97502,6 @@
</parameter>
</method>
</interface>
-<class name="BassBoost"
- extends="android.media.AudioEffect"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="BassBoost"
- type="android.media.BassBoost"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="priority" type="int">
-</parameter>
-<parameter name="audioSession" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="RuntimeException" type="java.lang.RuntimeException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</constructor>
-<method name="getProperties"
- return="android.media.BassBoost.Settings"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getRoundedStrength"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getStrengthSupported"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="setParameterListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.BassBoost.OnParameterChangeListener">
-</parameter>
-</method>
-<method name="setProperties"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="android.media.BassBoost.Settings">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setStrength"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="strength" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<field name="PARAM_STRENGTH"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_STRENGTH_SUPPORTED"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<interface name="BassBoost.OnParameterChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onParameterChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.BassBoost">
-</parameter>
-<parameter name="status" type="int">
-</parameter>
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="short">
-</parameter>
-</method>
-</interface>
-<class name="BassBoost.Settings"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="BassBoost.Settings"
- type="android.media.BassBoost.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="BassBoost.Settings"
- type="android.media.BassBoost.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="java.lang.String">
-</parameter>
-</constructor>
-<field name="strength"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="CamcorderProfile"
extends="java.lang.Object"
abstract="false"
@@ -99022,1178 +97919,6 @@
>
</field>
</class>
-<class name="EnvironmentalReverb"
- extends="android.media.AudioEffect"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="EnvironmentalReverb"
- type="android.media.EnvironmentalReverb"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="priority" type="int">
-</parameter>
-<parameter name="audioSession" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="RuntimeException" type="java.lang.RuntimeException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</constructor>
-<method name="getDecayHFRatio"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getDecayTime"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getDensity"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getDiffusion"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getProperties"
- return="android.media.EnvironmentalReverb.Settings"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getReflectionsDelay"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getReflectionsLevel"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getReverbDelay"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getReverbLevel"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getRoomHFLevel"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getRoomLevel"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setDecayHFRatio"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="decayHFRatio" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setDecayTime"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="decayTime" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setDensity"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="density" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setDiffusion"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="diffusion" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setParameterListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.EnvironmentalReverb.OnParameterChangeListener">
-</parameter>
-</method>
-<method name="setProperties"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="android.media.EnvironmentalReverb.Settings">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setReflectionsDelay"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="reflectionsDelay" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setReflectionsLevel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="reflectionsLevel" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setReverbDelay"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="reverbDelay" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setReverbLevel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="reverbLevel" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setRoomHFLevel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="roomHF" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setRoomLevel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="room" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<field name="PARAM_DECAY_HF_RATIO"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_DECAY_TIME"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_DENSITY"
- type="int"
- transient="false"
- volatile="false"
- value="9"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_DIFFUSION"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_REFLECTIONS_DELAY"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_REFLECTIONS_LEVEL"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_REVERB_DELAY"
- type="int"
- transient="false"
- volatile="false"
- value="7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_REVERB_LEVEL"
- type="int"
- transient="false"
- volatile="false"
- value="6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_ROOM_HF_LEVEL"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_ROOM_LEVEL"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<interface name="EnvironmentalReverb.OnParameterChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onParameterChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.EnvironmentalReverb">
-</parameter>
-<parameter name="status" type="int">
-</parameter>
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="int">
-</parameter>
-</method>
-</interface>
-<class name="EnvironmentalReverb.Settings"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="EnvironmentalReverb.Settings"
- type="android.media.EnvironmentalReverb.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="EnvironmentalReverb.Settings"
- type="android.media.EnvironmentalReverb.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="java.lang.String">
-</parameter>
-</constructor>
-<field name="decayHFRatio"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="decayTime"
- type="int"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="density"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="diffusion"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="reflectionsDelay"
- type="int"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="reflectionsLevel"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="reverbDelay"
- type="int"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="reverbLevel"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="roomHFLevel"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="roomLevel"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="Equalizer"
- extends="android.media.AudioEffect"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Equalizer"
- type="android.media.Equalizer"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="priority" type="int">
-</parameter>
-<parameter name="audioSession" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="RuntimeException" type="java.lang.RuntimeException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</constructor>
-<method name="getBand"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="frequency" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getBandFreqRange"
- return="int[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="band" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getBandLevel"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="band" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getBandLevelRange"
- return="short[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getCenterFreq"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="band" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getCurrentPreset"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getNumberOfBands"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getNumberOfPresets"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getPresetName"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="preset" type="short">
-</parameter>
-</method>
-<method name="getProperties"
- return="android.media.Equalizer.Settings"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setBandLevel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="band" type="short">
-</parameter>
-<parameter name="level" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setParameterListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.Equalizer.OnParameterChangeListener">
-</parameter>
-</method>
-<method name="setProperties"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="android.media.Equalizer.Settings">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="usePreset"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="preset" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<field name="PARAM_BAND_FREQ_RANGE"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_BAND_LEVEL"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_CENTER_FREQ"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_CURRENT_PRESET"
- type="int"
- transient="false"
- volatile="false"
- value="6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_GET_BAND"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_GET_NUM_OF_PRESETS"
- type="int"
- transient="false"
- volatile="false"
- value="7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_GET_PRESET_NAME"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_LEVEL_RANGE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_NUM_BANDS"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PARAM_STRING_SIZE_MAX"
- type="int"
- transient="false"
- volatile="false"
- value="32"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<interface name="Equalizer.OnParameterChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onParameterChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.Equalizer">
-</parameter>
-<parameter name="status" type="int">
-</parameter>
-<parameter name="param1" type="int">
-</parameter>
-<parameter name="param2" type="int">
-</parameter>
-<parameter name="value" type="int">
-</parameter>
-</method>
-</interface>
-<class name="Equalizer.Settings"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="Equalizer.Settings"
- type="android.media.Equalizer.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="Equalizer.Settings"
- type="android.media.Equalizer.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="java.lang.String">
-</parameter>
-</constructor>
-<field name="bandLevels"
- type="short[]"
- transient="false"
- volatile="false"
- value="null"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="curPreset"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="numBands"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="ExifInterface"
extends="java.lang.Object"
abstract="false"
@@ -102897,270 +100622,6 @@
</parameter>
</method>
</interface>
-<class name="PresetReverb"
- extends="android.media.AudioEffect"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="PresetReverb"
- type="android.media.PresetReverb"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="priority" type="int">
-</parameter>
-<parameter name="audioSession" type="int">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="RuntimeException" type="java.lang.RuntimeException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</constructor>
-<method name="getPreset"
- return="short"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="getProperties"
- return="android.media.PresetReverb.Settings"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setParameterListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.PresetReverb.OnParameterChangeListener">
-</parameter>
-</method>
-<method name="setPreset"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="preset" type="short">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<method name="setProperties"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="android.media.PresetReverb.Settings">
-</parameter>
-<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
-</exception>
-<exception name="IllegalStateException" type="java.lang.IllegalStateException">
-</exception>
-<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
-</exception>
-</method>
-<field name="PARAM_PRESET"
- type="int"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_LARGEHALL"
- type="short"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_LARGEROOM"
- type="short"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_MEDIUMHALL"
- type="short"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_MEDIUMROOM"
- type="short"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_NONE"
- type="short"
- transient="false"
- volatile="false"
- value="0"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_PLATE"
- type="short"
- transient="false"
- volatile="false"
- value="6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="PRESET_SMALLROOM"
- type="short"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<interface name="PresetReverb.OnParameterChangeListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="onParameterChange"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="effect" type="android.media.PresetReverb">
-</parameter>
-<parameter name="status" type="int">
-</parameter>
-<parameter name="param" type="int">
-</parameter>
-<parameter name="value" type="short">
-</parameter>
-</method>
-</interface>
-<class name="PresetReverb.Settings"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="PresetReverb.Settings"
- type="android.media.PresetReverb.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="PresetReverb.Settings"
- type="android.media.PresetReverb.Settings"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="settings" type="java.lang.String">
-</parameter>
-</constructor>
-<field name="preset"
- type="short"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="Ringtone"
extends="java.lang.Object"
abstract="false"
@@ -105235,16 +102696,494 @@
>
</field>
</class>
-<class name="Virtualizer"
- extends="android.media.AudioEffect"
+</package>
+<package name="android.media.audiofx"
+>
+<class name="AudioEffect"
+ extends="java.lang.Object"
abstract="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
-<constructor name="Virtualizer"
- type="android.media.Virtualizer"
+<method name="getDescriptor"
+ return="android.media.audiofx.AudioEffect.Descriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="getEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="getId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="hasControl"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="queryEffects"
+ return="android.media.audiofx.AudioEffect.Descriptor[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="release"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setControlStatusListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.AudioEffect.OnControlStatusChangeListener">
+</parameter>
+</method>
+<method name="setEnableStatusListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.AudioEffect.OnEnableStatusChangeListener">
+</parameter>
+</method>
+<method name="setEnabled"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<field name="ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ALREADY_EXISTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_GAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MOVIE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MUSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_VOICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EFFECT_AUXILIARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Auxiliary""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EFFECT_INSERT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Insert""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_BAD_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_DEAD_OBJECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_INVALID_OPERATION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_NO_INIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_NO_MEMORY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_AUDIO_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.extra.AUDIO_SESSION""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CONTENT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.extra.CONTENT_TYPE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_PACKAGE_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.extra.PACKAGE_NAME""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SUCCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="AudioEffect.Descriptor"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AudioEffect.Descriptor"
+ type="android.media.audiofx.AudioEffect.Descriptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="AudioEffect.Descriptor"
+ type="android.media.audiofx.AudioEffect.Descriptor"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="java.lang.String">
+</parameter>
+<parameter name="uuid" type="java.lang.String">
+</parameter>
+<parameter name="connectMode" type="java.lang.String">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="implementor" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="connectMode"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="implementor"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="name"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="type"
+ type="java.util.UUID"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="uuid"
+ type="java.util.UUID"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="AudioEffect.OnControlStatusChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onControlStatusChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.AudioEffect">
+</parameter>
+<parameter name="controlGranted" type="boolean">
+</parameter>
+</method>
+</interface>
+<interface name="AudioEffect.OnEnableStatusChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onEnableStatusChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.AudioEffect">
+</parameter>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+</interface>
+<class name="BassBoost"
+ extends="android.media.audiofx.AudioEffect"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BassBoost"
+ type="android.media.audiofx.BassBoost"
static="false"
final="false"
deprecated="not deprecated"
@@ -105264,7 +103203,7 @@
</exception>
</constructor>
<method name="getProperties"
- return="android.media.Virtualizer.Settings"
+ return="android.media.audiofx.BassBoost.Settings"
abstract="false"
native="false"
synchronized="false"
@@ -105318,7 +103257,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="listener" type="android.media.Virtualizer.OnParameterChangeListener">
+<parameter name="listener" type="android.media.audiofx.BassBoost.OnParameterChangeListener">
</parameter>
</method>
<method name="setProperties"
@@ -105331,7 +103270,1654 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="settings" type="android.media.Virtualizer.Settings">
+<parameter name="settings" type="android.media.audiofx.BassBoost.Settings">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setStrength"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="strength" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<field name="PARAM_STRENGTH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_STRENGTH_SUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="BassBoost.OnParameterChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onParameterChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.BassBoost">
+</parameter>
+<parameter name="status" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+<parameter name="value" type="short">
+</parameter>
+</method>
+</interface>
+<class name="BassBoost.Settings"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="BassBoost.Settings"
+ type="android.media.audiofx.BassBoost.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="BassBoost.Settings"
+ type="android.media.audiofx.BassBoost.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="strength"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="EnvironmentalReverb"
+ extends="android.media.audiofx.AudioEffect"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="EnvironmentalReverb"
+ type="android.media.audiofx.EnvironmentalReverb"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="priority" type="int">
+</parameter>
+<parameter name="audioSession" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="RuntimeException" type="java.lang.RuntimeException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</constructor>
+<method name="getDecayHFRatio"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getDecayTime"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getDensity"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getDiffusion"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getProperties"
+ return="android.media.audiofx.EnvironmentalReverb.Settings"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getReflectionsDelay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getReflectionsLevel"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getReverbDelay"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getReverbLevel"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getRoomHFLevel"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getRoomLevel"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setDecayHFRatio"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="decayHFRatio" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setDecayTime"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="decayTime" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setDensity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="density" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setDiffusion"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="diffusion" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setParameterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener">
+</parameter>
+</method>
+<method name="setProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="android.media.audiofx.EnvironmentalReverb.Settings">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setReflectionsDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="reflectionsDelay" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setReflectionsLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="reflectionsLevel" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setReverbDelay"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="reverbDelay" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setReverbLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="reverbLevel" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setRoomHFLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="roomHF" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setRoomLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="room" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<field name="PARAM_DECAY_HF_RATIO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_DECAY_TIME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_DENSITY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="9"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_DIFFUSION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_REFLECTIONS_DELAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_REFLECTIONS_LEVEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_REVERB_DELAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_REVERB_LEVEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_ROOM_HF_LEVEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_ROOM_LEVEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="EnvironmentalReverb.OnParameterChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onParameterChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.EnvironmentalReverb">
+</parameter>
+<parameter name="status" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</interface>
+<class name="EnvironmentalReverb.Settings"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="EnvironmentalReverb.Settings"
+ type="android.media.audiofx.EnvironmentalReverb.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="EnvironmentalReverb.Settings"
+ type="android.media.audiofx.EnvironmentalReverb.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="decayHFRatio"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="decayTime"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="density"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="diffusion"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="reflectionsDelay"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="reflectionsLevel"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="reverbDelay"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="reverbLevel"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="roomHFLevel"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="roomLevel"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Equalizer"
+ extends="android.media.audiofx.AudioEffect"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Equalizer"
+ type="android.media.audiofx.Equalizer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="priority" type="int">
+</parameter>
+<parameter name="audioSession" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="RuntimeException" type="java.lang.RuntimeException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</constructor>
+<method name="getBand"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="frequency" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getBandFreqRange"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="band" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getBandLevel"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="band" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getBandLevelRange"
+ return="short[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getCenterFreq"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="band" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getCurrentPreset"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getNumberOfBands"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getNumberOfPresets"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getPresetName"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="preset" type="short">
+</parameter>
+</method>
+<method name="getProperties"
+ return="android.media.audiofx.Equalizer.Settings"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setBandLevel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="band" type="short">
+</parameter>
+<parameter name="level" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setParameterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.Equalizer.OnParameterChangeListener">
+</parameter>
+</method>
+<method name="setProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="android.media.audiofx.Equalizer.Settings">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="usePreset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="preset" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<field name="PARAM_BAND_FREQ_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_BAND_LEVEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_CENTER_FREQ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_CURRENT_PRESET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_GET_BAND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_GET_NUM_OF_PRESETS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_GET_PRESET_NAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_LEVEL_RANGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_NUM_BANDS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PARAM_STRING_SIZE_MAX"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="32"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="Equalizer.OnParameterChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onParameterChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.Equalizer">
+</parameter>
+<parameter name="status" type="int">
+</parameter>
+<parameter name="param1" type="int">
+</parameter>
+<parameter name="param2" type="int">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+</method>
+</interface>
+<class name="Equalizer.Settings"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Equalizer.Settings"
+ type="android.media.audiofx.Equalizer.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="Equalizer.Settings"
+ type="android.media.audiofx.Equalizer.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="bandLevels"
+ type="short[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="curPreset"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="numBands"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="PresetReverb"
+ extends="android.media.audiofx.AudioEffect"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PresetReverb"
+ type="android.media.audiofx.PresetReverb"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="priority" type="int">
+</parameter>
+<parameter name="audioSession" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="RuntimeException" type="java.lang.RuntimeException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</constructor>
+<method name="getPreset"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getProperties"
+ return="android.media.audiofx.PresetReverb.Settings"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setParameterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.PresetReverb.OnParameterChangeListener">
+</parameter>
+</method>
+<method name="setPreset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="preset" type="short">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="setProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="android.media.audiofx.PresetReverb.Settings">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<field name="PARAM_PRESET"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_LARGEHALL"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_LARGEROOM"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_MEDIUMHALL"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_MEDIUMROOM"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_NONE"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_PLATE"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PRESET_SMALLROOM"
+ type="short"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="PresetReverb.OnParameterChangeListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onParameterChange"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effect" type="android.media.audiofx.PresetReverb">
+</parameter>
+<parameter name="status" type="int">
+</parameter>
+<parameter name="param" type="int">
+</parameter>
+<parameter name="value" type="short">
+</parameter>
+</method>
+</interface>
+<class name="PresetReverb.Settings"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PresetReverb.Settings"
+ type="android.media.audiofx.PresetReverb.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="PresetReverb.Settings"
+ type="android.media.audiofx.PresetReverb.Settings"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="java.lang.String">
+</parameter>
+</constructor>
+<field name="preset"
+ type="short"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Virtualizer"
+ extends="android.media.audiofx.AudioEffect"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Virtualizer"
+ type="android.media.audiofx.Virtualizer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="priority" type="int">
+</parameter>
+<parameter name="audioSession" type="int">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="RuntimeException" type="java.lang.RuntimeException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</constructor>
+<method name="getProperties"
+ return="android.media.audiofx.Virtualizer.Settings"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getRoundedStrength"
+ return="short"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+<exception name="UnsupportedOperationException" type="java.lang.UnsupportedOperationException">
+</exception>
+</method>
+<method name="getStrengthSupported"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setParameterListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.audiofx.Virtualizer.OnParameterChangeListener">
+</parameter>
+</method>
+<method name="setProperties"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="settings" type="android.media.audiofx.Virtualizer.Settings">
</parameter>
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
</exception>
@@ -105399,7 +104985,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="effect" type="android.media.Virtualizer">
+<parameter name="effect" type="android.media.audiofx.Virtualizer">
</parameter>
<parameter name="status" type="int">
</parameter>
@@ -105418,7 +105004,7 @@
visibility="public"
>
<constructor name="Virtualizer.Settings"
- type="android.media.Virtualizer.Settings"
+ type="android.media.audiofx.Virtualizer.Settings"
static="false"
final="false"
deprecated="not deprecated"
@@ -105426,7 +105012,7 @@
>
</constructor>
<constructor name="Virtualizer.Settings"
- type="android.media.Virtualizer.Settings"
+ type="android.media.audiofx.Virtualizer.Settings"
static="false"
final="false"
deprecated="not deprecated"
@@ -105455,7 +105041,7 @@
visibility="public"
>
<constructor name="Visualizer"
- type="android.media.Visualizer"
+ type="android.media.audiofx.Visualizer"
static="false"
final="false"
deprecated="not deprecated"
@@ -105593,7 +105179,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="listener" type="android.media.Visualizer.OnDataCaptureListener">
+<parameter name="listener" type="android.media.audiofx.Visualizer.OnDataCaptureListener">
</parameter>
<parameter name="rate" type="int">
</parameter>
@@ -105756,7 +105342,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="visualizer" type="android.media.Visualizer">
+<parameter name="visualizer" type="android.media.audiofx.Visualizer">
</parameter>
<parameter name="fft" type="byte[]">
</parameter>
@@ -105773,7 +105359,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="visualizer" type="android.media.Visualizer">
+<parameter name="visualizer" type="android.media.audiofx.Visualizer">
</parameter>
<parameter name="waveform" type="byte[]">
</parameter>
@@ -106700,6 +106286,21 @@
<parameter name="uri" type="android.net.Uri">
</parameter>
</constructor>
+<method name="addRequestHeader"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="header" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
<method name="setAllowedNetworkTypes"
return="android.net.DownloadManager.Request"
abstract="false"
@@ -106736,7 +106337,39 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="description" type="java.lang.String">
+<parameter name="description" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setDestinationInExternalFilesDir"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="dirType" type="java.lang.String">
+</parameter>
+<parameter name="subPath" type="java.lang.String">
+</parameter>
+</method>
+<method name="setDestinationInExternalPublicDir"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dirType" type="java.lang.String">
+</parameter>
+<parameter name="subPath" type="java.lang.String">
</parameter>
</method>
<method name="setDestinationUri"
@@ -106752,7 +106385,7 @@
<parameter name="uri" type="android.net.Uri">
</parameter>
</method>
-<method name="setMediaType"
+<method name="setMimeType"
return="android.net.DownloadManager.Request"
abstract="false"
native="false"
@@ -106762,22 +106395,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="mediaType" type="java.lang.String">
-</parameter>
-</method>
-<method name="setRequestHeader"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="header" type="java.lang.String">
-</parameter>
-<parameter name="value" type="java.lang.String">
+<parameter name="mimeType" type="java.lang.String">
</parameter>
</method>
<method name="setShowRunningNotification"
@@ -106803,7 +106421,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="title" type="java.lang.String">
+<parameter name="title" type="java.lang.CharSequence">
</parameter>
</method>
<method name="setVisibleInDownloadsUi"
@@ -106841,17 +106459,6 @@
visibility="public"
>
</field>
-<field name="NETWORK_WIMAX"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="LocalServerSocket"
extends="java.lang.Object"
@@ -150134,6 +149741,28 @@
visibility="public"
>
</field>
+<field name="PHOTO_THUMBNAIL_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""photo_thumb_uri""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""photo_uri""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</interface>
<class name="ContactsContract.Data"
extends="java.lang.Object"
@@ -150665,6 +150294,61 @@
visibility="public"
>
</field>
+<field name="PHOTO_SUPPORT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""photoSupport""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_FULL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_FULL_SIZE_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PHOTO_SUPPORT_THUMBNAIL_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SHORTCUT_SUPPORT"
type="java.lang.String"
transient="false"
@@ -156547,6 +156231,17 @@
visibility="public"
>
</field>
+<field name="SELECTED_INPUT_METHOD_SUBTYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""selected_input_method_subtype""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SETTINGS_CLASSNAME"
type="java.lang.String"
transient="false"
@@ -157268,6 +156963,17 @@
visibility="public"
>
</field>
+<field name="AUTO_TIME_ZONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""auto_time_zone""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="BLUETOOTH_DISCOVERABILITY"
type="java.lang.String"
transient="false"
@@ -206715,17 +206421,6 @@
visibility="public"
>
</field>
-<field name="FEATURE_HARDWARE_ACCELERATED"
- type="int"
- transient="false"
- volatile="false"
- value="11"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="FEATURE_INDETERMINATE_PROGRESS"
type="int"
transient="false"
@@ -213522,6 +213217,19 @@
<parameter name="binding" type="android.view.inputmethod.InputBinding">
</parameter>
</method>
+<method name="changeInputMethodSubtype"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="subtype" type="android.view.inputmethod.InputMethodSubtype">
+</parameter>
+</method>
<method name="createSession"
return="void"
abstract="true"
@@ -213846,7 +213554,7 @@
>
</method>
<method name="getSubtypes"
- return="java.util.ArrayList<android.view.inputmethod.InputMethodInfo.InputMethodSubtype>"
+ return="java.util.ArrayList<android.view.inputmethod.InputMethodSubtype>"
abstract="false"
native="false"
synchronized="false"
@@ -213908,108 +213616,6 @@
>
</field>
</class>
-<class name="InputMethodInfo.InputMethodSubtype"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.Parcelable">
-</implements>
-<method name="describeContents"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getExtraValue"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getIconId"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getLocale"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getMode"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getName"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="writeToParcel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dest" type="android.os.Parcel">
-</parameter>
-<parameter name="parcelableFlags" type="int">
-</parameter>
-</method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="InputMethodManager"
extends="java.lang.Object"
abstract="false"
@@ -214230,6 +213836,17 @@
visibility="public"
>
</method>
+<method name="showInputMethodSubtypePicker"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="showSoftInput"
return="boolean"
abstract="false"
@@ -214644,6 +214261,108 @@
</parameter>
</method>
</interface>
+<class name="InputMethodSubtype"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getExtraValue"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIconResId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocale"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getModeResId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getNameResId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="parcelableFlags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
</package>
<package name="android.webkit"
>
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 42599ed..7776874 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -16,6 +16,7 @@
package android.content;
+import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -37,14 +38,22 @@
public Cursor loadInBackground() {
Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
mSelectionArgs, mSortOrder);
- // Ensure the cursor window is filled
if (cursor != null) {
+ // Ensure the cursor window is filled
cursor.getCount();
- cursor.registerContentObserver(mObserver);
+ registerContentObserver(cursor, mObserver);
}
return cursor;
}
+ /**
+ * Registers an observer to get notifications from the content provider
+ * when the cursor needs to be refreshed.
+ */
+ public void registerContentObserver(Cursor cursor, ContentObserver observer) {
+ cursor.registerContentObserver(mObserver);
+ }
+
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 3619653..27af013 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -177,6 +177,7 @@
* Implement this to handle {@link android.os.Binder#dump Binder.dump()}
* calls on your input method.
*/
+ @Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 35fd46f..24ea7d2 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -36,6 +36,7 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
+import android.view.inputmethod.InputMethodSubtype;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -64,6 +65,7 @@
private static final int DO_REVOKE_SESSION = 50;
private static final int DO_SHOW_SOFT_INPUT = 60;
private static final int DO_HIDE_SOFT_INPUT = 70;
+ private static final int DO_CHANGE_INPUTMETHOD_SUBTYPE = 80;
final WeakReference<AbstractInputMethodService> mTarget;
final HandlerCaller mCaller;
@@ -178,6 +180,9 @@
case DO_HIDE_SOFT_INPUT:
inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
return;
+ case DO_CHANGE_INPUTMETHOD_SUBTYPE:
+ inputMethod.changeInputMethodSubtype((InputMethodSubtype)msg.obj);
+ return;
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
@@ -267,4 +272,9 @@
mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_HIDE_SOFT_INPUT,
flags, resultReceiver));
}
+
+ public void changeInputMethodSubtype(InputMethodSubtype subtype) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CHANGE_INPUTMETHOD_SUBTYPE,
+ subtype));
+ }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 1a261d3..6089013 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -52,6 +52,7 @@
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.FrameLayout;
@@ -270,7 +271,7 @@
final Insets mTmpInsets = new Insets();
final int[] mTmpLocation = new int[2];
-
+
final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
new ViewTreeObserver.OnComputeInternalInsetsListener() {
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
@@ -394,8 +395,12 @@
: InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
}
}
+
+ public void changeInputMethodSubtype(InputMethodSubtype subtype) {
+ onCurrentInputMethodSubtypeChanged(subtype);
+ }
}
-
+
/**
* Concrete implementation of
* {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
@@ -541,6 +546,7 @@
* will typically call it in your constructor with the resource ID
* of your custom theme.
*/
+ @Override
public void setTheme(int theme) {
if (mWindow != null) {
throw new IllegalStateException("Must be called before onCreate()");
@@ -558,7 +564,7 @@
initViews();
mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
}
-
+
/**
* This is a hook that subclasses can use to perform initialization of
* their interface. It is called for you prior to any of your UI objects
@@ -567,14 +573,14 @@
*/
public void onInitializeInterface() {
}
-
+
void initialize() {
if (!mInitialized) {
mInitialized = true;
onInitializeInterface();
}
}
-
+
void initViews() {
mInitialized = false;
mWindowCreated = false;
@@ -610,7 +616,7 @@
mCandidatesFrame.setVisibility(mCandidatesVisibility);
mInputFrame.setVisibility(View.GONE);
}
-
+
@Override public void onDestroy() {
super.onDestroy();
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
@@ -677,6 +683,7 @@
* Implement to return our standard {@link InputMethodImpl}. Subclasses
* can override to provide their own customized version.
*/
+ @Override
public AbstractInputMethodImpl onCreateInputMethodInterface() {
return new InputMethodImpl();
}
@@ -685,6 +692,7 @@
* Implement to return our standard {@link InputMethodSessionImpl}. Subclasses
* can override to provide their own customized version.
*/
+ @Override
public AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface() {
return new InputMethodSessionImpl();
}
@@ -1656,6 +1664,7 @@
return doMovementKey(keyCode, event, MOVEMENT_UP);
}
+ @Override
public boolean onTrackballEvent(MotionEvent event) {
return false;
}
@@ -1694,7 +1703,7 @@
dy = count;
break;
}
- onExtractedCursorMovement(dx, dy);
+ onExtractedCursorMovement(dx, dy);
}
boolean doMovementKey(int keyCode, KeyEvent event, int count) {
@@ -2064,7 +2073,24 @@
}
}
}
-
+
+ // TODO: Handle the subtype change event
+ /**
+ * Called when the subtype was changed.
+ * @param newSubtype the subtype which is being changed to.
+ */
+ protected void onCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) {
+ if (DEBUG) {
+ int nameResId = newSubtype.getNameResId();
+ int modeResId = newSubtype.getModeResId();
+ String output = "changeInputMethodSubtype:"
+ + (nameResId == 0 ? "<none>" : getString(nameResId)) + ","
+ + (modeResId == 0 ? "<none>" : getString(modeResId)) + ","
+ + newSubtype.getLocale() + "," + newSubtype.getExtraValue();
+ Log.v(TAG, "--- " + output);
+ }
+ }
+
/**
* Performs a dump of the InputMethodService's internal state. Override
* to add your own information to the dump.
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index fc5ebb3..12c05cc 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -19,19 +19,21 @@
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
+import android.content.Context;
import android.database.Cursor;
import android.database.CursorWrapper;
+import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.Downloads;
+import android.util.Pair;
+import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -245,6 +247,7 @@
Downloads.COLUMN_LAST_MODIFICATION,
Downloads.COLUMN_DESTINATION,
Downloads.Impl.COLUMN_FILE_NAME_HINT,
+ Downloads.Impl._DATA,
};
private static final Set<String> LONG_COLUMNS = new HashSet<String>(
@@ -252,8 +255,12 @@
COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP));
/**
- * This class contains all the information necessary to request a new download. The URI is the
+ * This class contains all the information necessary to request a new download. The URI is the
* only required parameter.
+ *
+ * Note that the default download destination is a shared volume where the system might delete
+ * your file if it needs to reclaim space for system use. If this is a problem, use a location
+ * on external storage (see {@link #setDestinationUri(Uri)}.
*/
public static class Request {
/**
@@ -268,19 +275,13 @@
*/
public static final int NETWORK_WIFI = 1 << 1;
- /**
- * Bit flag for {@link #setAllowedNetworkTypes} corresponding to
- * {@link ConnectivityManager#TYPE_WIMAX}.
- */
- public static final int NETWORK_WIMAX = 1 << 2;
-
private Uri mUri;
private Uri mDestinationUri;
- private Map<String, String> mRequestHeaders = new HashMap<String, String>();
- private String mTitle;
- private String mDescription;
+ private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>();
+ private CharSequence mTitle;
+ private CharSequence mDescription;
private boolean mShowNotification = true;
- private String mMediaType;
+ private String mMimeType;
private boolean mRoamingAllowed = true;
private int mAllowedNetworkTypes = ~0; // default to all network types allowed
private boolean mIsVisibleInDownloadsUi = true;
@@ -300,12 +301,12 @@
}
/**
- * Set the local destination for the downloaded data. Must be a file URI to a path on
+ * Set the local destination for the downloaded file. Must be a file URI to a path on
* external storage, and the calling application must have the WRITE_EXTERNAL_STORAGE
* permission.
*
- * By default, downloads are saved to a generated file in the download cache and may be
- * deleted by the download manager at any time.
+ * By default, downloads are saved to a generated filename in the shared download cache and
+ * may be deleted by the system at any time to reclaim space.
*
* @return this object
*/
@@ -315,13 +316,62 @@
}
/**
- * Set an HTTP header to be included with the download request.
+ * Set the local destination for the downloaded file to a path within the application's
+ * external files directory (as returned by {@link Context#getExternalFilesDir(String)}.
+ *
+ * @param context the {@link Context} to use in determining the external files directory
+ * @param dirType the directory type to pass to {@link Context#getExternalFilesDir(String)}
+ * @param subPath the path within the external directory, including the destination filename
+ * @return this object
+ */
+ public Request setDestinationInExternalFilesDir(Context context, String dirType,
+ String subPath) {
+ setDestinationFromBase(context.getExternalFilesDir(dirType), subPath);
+ return this;
+ }
+
+ /**
+ * Set the local destination for the downloaded file to a path within the public external
+ * storage directory (as returned by
+ * {@link Environment#getExternalStoragePublicDirectory(String)}.
+ *
+ * @param dirType the directory type to pass to
+ * {@link Environment#getExternalStoragePublicDirectory(String)}
+ * @param subPath the path within the external directory, including the destination filename
+ * @return this object
+ */
+ public Request setDestinationInExternalPublicDir(String dirType, String subPath) {
+ setDestinationFromBase(Environment.getExternalStoragePublicDirectory(dirType), subPath);
+ return this;
+ }
+
+ private void setDestinationFromBase(File base, String subPath) {
+ if (subPath == null) {
+ throw new NullPointerException("subPath cannot be null");
+ }
+ mDestinationUri = Uri.withAppendedPath(Uri.fromFile(base), subPath);
+ }
+
+ /**
+ * Add an HTTP header to be included with the download request. The header will be added to
+ * the end of the list.
* @param header HTTP header name
* @param value header value
* @return this object
+ * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2">HTTP/1.1
+ * Message Headers</a>
*/
- public Request setRequestHeader(String header, String value) {
- mRequestHeaders.put(header, value);
+ public Request addRequestHeader(String header, String value) {
+ if (header == null) {
+ throw new NullPointerException("header cannot be null");
+ }
+ if (header.contains(":")) {
+ throw new IllegalArgumentException("header may not contain ':'");
+ }
+ if (value == null) {
+ value = "";
+ }
+ mRequestHeaders.add(Pair.create(header, value));
return this;
}
@@ -329,7 +379,7 @@
* Set the title of this download, to be displayed in notifications (if enabled)
* @return this object
*/
- public Request setTitle(String title) {
+ public Request setTitle(CharSequence title) {
mTitle = title;
return this;
}
@@ -338,19 +388,20 @@
* Set a description of this download, to be displayed in notifications (if enabled)
* @return this object
*/
- public Request setDescription(String description) {
+ public Request setDescription(CharSequence description) {
mDescription = description;
return this;
}
/**
- * Set the Internet Media Type of this download. This will override the media type declared
+ * Set the MIME content type of this download. This will override the content type declared
* in the server's response.
- * @see <a href="http://www.ietf.org/rfc/rfc1590.txt">RFC 1590, defining Media Types</a>
+ * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7">HTTP/1.1
+ * Media Types</a>
* @return this object
*/
- public Request setMediaType(String mediaType) {
- mMediaType = mediaType;
+ public Request setMimeType(String mimeType) {
+ mMimeType = mimeType;
return this;
}
@@ -428,7 +479,7 @@
putIfNonNull(values, Downloads.COLUMN_TITLE, mTitle);
putIfNonNull(values, Downloads.COLUMN_DESCRIPTION, mDescription);
- putIfNonNull(values, Downloads.COLUMN_MIME_TYPE, mMediaType);
+ putIfNonNull(values, Downloads.COLUMN_MIME_TYPE, mMimeType);
values.put(Downloads.COLUMN_VISIBILITY,
mShowNotification ? Downloads.VISIBILITY_VISIBLE
@@ -443,16 +494,16 @@
private void encodeHttpHeaders(ContentValues values) {
int index = 0;
- for (Map.Entry<String, String> entry : mRequestHeaders.entrySet()) {
- String headerString = entry.getKey() + ": " + entry.getValue();
+ for (Pair<String, String> header : mRequestHeaders) {
+ String headerString = header.first + ": " + header.second;
values.put(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX + index, headerString);
index++;
}
}
- private void putIfNonNull(ContentValues contentValues, String key, String value) {
+ private void putIfNonNull(ContentValues contentValues, String key, Object value) {
if (value != null) {
- contentValues.put(key, value);
+ contentValues.put(key, value.toString());
}
}
}
@@ -831,6 +882,11 @@
return getUnderlyingString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
}
+ if (destinationType == Downloads.Impl.DESTINATION_EXTERNAL) {
+ // return stored destination for legacy external download
+ return Uri.fromFile(new File(getUnderlyingString(Downloads.Impl._DATA))).toString();
+ }
+
// return content URI for cache download
long downloadId = getUnderlyingLong(Downloads.Impl._ID);
return ContentUris.withAppendedId(mBaseUri, downloadId).toString();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3876a3e..156da47 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -232,6 +232,8 @@
/**
* Sets whether this WakeLock is ref counted.
*
+ * <p>Wake locks are reference counted by default.
+ *
* @param value true for ref counted, false for not ref counted.
*/
public void setReferenceCounted(boolean value)
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index f571c42..3ddaad9 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -30,8 +30,59 @@
import java.util.HashMap;
/**
- * <p>StrictMode lets you impose stricter rules under which your
- * application runs.</p>
+ * <p>StrictMode is a developer tool which lets you impose stricter
+ * rules under which your application runs.
+ *
+ * <p>StrictMode is most commonly used to catch accidental disk or
+ * network access on the application's main thread, where UI
+ * operations are received and animations take place. Keeping disk
+ * and network operations off the main thread makes for much smoother,
+ * more responsive applications.
+ *
+ * <p class="note">Note that even though an Android device's disk is
+ * often on flash memory, many devices run a filesystem on top of that
+ * memory with very limited concurrency. It's often the case that
+ * almost all disk accesses are fast, but may in individual cases be
+ * dramatically slower when certain I/O is happening in the background
+ * from other processes. If possible, it's best to assume that such
+ * things are not fast.</p>
+ *
+ * <p>Example code to enable from early in your
+ * {@link android.app.Application}, {@link android.app.Activity}, or
+ * other application component's
+ * {@link android.app.Application#onCreate} method:
+ *
+ * <pre>
+ * public void onCreate() {
+ * if (DEVELOPER_MODE) {
+ * StrictMode.setThreadPolicy(StrictMode.DISALLOW_DISK_WRITE |
+ * StrictMode.DISALLOW_DISK_READ |
+ * StrictMode.DISALLOW_NETWORK |
+ * StrictMode.PENALTY_LOG);
+ * }
+ * super.onCreate();
+ * }
+ * </pre>
+ *
+ * <p>Then you can watch the output of <code>adb logcat</code> while you
+ * use your application.
+ *
+ * <p>If you find violations that you feel are problematic, there are
+ * a variety of tools to help solve them: threads, {@link android.os.Handler},
+ * {@link android.os.AsyncTask}, {@link android.app.IntentService}, etc.
+ * But don't feel compelled to fix everything that StrictMode finds. In particular,
+ * a lot of disk accesses are often necessary during the normal activity lifecycle. Use
+ * StrictMode to find things you did on accident. Network requests on the UI thread
+ * are almost always a problem, though.
+ *
+ * <p class="note">StrictMode is not a security mechanism and is not
+ * guaranteed to find all disk or network accesses. While it does
+ * propagate its state across process boundaries when doing
+ * {@link android.os.Binder} calls, it's still ultimately a best
+ * effort mechanism. Notably, disk or network access from JNI calls
+ * won't necessarily trigger it. Future versions of Android may catch
+ * more (or fewer) operations, so you should never leave StrictMode
+ * enabled in shipping applications on the Android Market.
*/
public final class StrictMode {
private static final String TAG = "StrictMode";
@@ -45,8 +96,22 @@
private StrictMode() {}
+ /**
+ * Flag for {@link #setThreadPolicy} to signal that you don't intend for this
+ * thread to write to disk.
+ */
public static final int DISALLOW_DISK_WRITE = 0x01;
+
+ /**
+ * Flag for {@link #setThreadPolicy} to signal that you don't intend for this
+ * thread to read from disk.
+ */
public static final int DISALLOW_DISK_READ = 0x02;
+
+ /**
+ * Flag for {@link #setThreadPolicy} to signal that you don't intend for this
+ * thread to access the network.
+ */
public static final int DISALLOW_NETWORK = 0x04;
/** @hide */
@@ -54,23 +119,30 @@
DISALLOW_DISK_WRITE | DISALLOW_DISK_READ | DISALLOW_NETWORK;
/**
- * Flag to log to the system log.
+ * Penalty flag for {@link #setThreadPolicy} to log violations to
+ * the system log, visible with <code>adb logcat</code>.
*/
public static final int PENALTY_LOG = 0x10; // normal android.util.Log
/**
- * Show an annoying dialog to the user. Will be rate-limited to be only
- * a little annoying.
+ * Penalty flag for {@link #setThreadPolicy} to show an annoying
+ * dialog to the developer, rate-limited to be only a little
+ * annoying.
*/
public static final int PENALTY_DIALOG = 0x20;
/**
- * Crash hard if policy is violated.
+ * Penalty flag for {@link #setThreadPolicy} to crash hard if
+ * policy is violated.
*/
public static final int PENALTY_DEATH = 0x40;
/**
- * Log a stacktrace to the DropBox on policy violation.
+ * Penalty flag for {@link #setThreadPolicy} to log a stacktrace
+ * and timing data to the
+ * {@link android.os.DropBoxManager DropBox} on policy violation.
+ * Intended mostly for platform integrators doing beta user field
+ * data collection.
*/
public static final int PENALTY_DROPBOX = 0x80;
@@ -109,10 +181,17 @@
};
/**
- * Sets the policy for what actions the current thread is denied,
- * as well as the penalty for violating the policy.
+ * Sets the policy for what actions the current thread isn't
+ * expected to do, as well as the penalty if it does.
*
- * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values.
+ * <p>Internally this sets a thread-local integer which is
+ * propagated across cross-process IPC calls, meaning you can
+ * catch violations when a system service or another process
+ * accesses the disk or network on your behalf.
+ *
+ * @param policyMask a bitmask of DISALLOW_* and PENALTY_* values,
+ * e.g. {@link #DISALLOW_DISK_READ}, {@link #DISALLOW_DISK_WRITE},
+ * {@link #DISALLOW_NETWORK}, {@link #PENALTY_LOG}.
*/
public static void setThreadPolicy(final int policyMask) {
// In addition to the Java-level thread-local in Dalvik's
@@ -160,7 +239,7 @@
}
/**
- * Returns the bitmask of the current thread's blocking policy.
+ * Returns the bitmask of the current thread's policy.
*
* @return the bitmask of all the DISALLOW_* and PENALTY_* bits currently enabled
*/
@@ -169,8 +248,10 @@
}
/**
- * Updates the current thread's policy mask to allow reading &
- * writing to disk.
+ * A convenience wrapper around {@link #getThreadPolicy} and
+ * {@link #setThreadPolicy}. Updates the current thread's policy
+ * mask to allow both reading & writing to disk, returning the
+ * old policy so you can restore it at the end of a block.
*
* @return the old policy mask, to be passed to setThreadPolicy to
* restore the policy.
@@ -185,8 +266,10 @@
}
/**
- * Updates the current thread's policy mask to allow reading from
- * disk.
+ * A convenience wrapper around {@link #getThreadPolicy} and
+ * {@link #setThreadPolicy}. Updates the current thread's policy
+ * mask to allow reading from disk, returning the old
+ * policy so you can restore it at the end of a block.
*
* @return the old policy mask, to be passed to setThreadPolicy to
* restore the policy.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b2c1c2d..36e2c56 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -445,7 +445,7 @@
/**
* One of {@link #SHORTCUT_SUPPORT_NONE}, {@link #SHORTCUT_SUPPORT_DATA_ITEMS_ONLY},
- * {@link #SHORTCUT_SUPPORT_FULL}, This is the expectation the directory
+ * {@link #SHORTCUT_SUPPORT_FULL}. This is the expectation the directory
* has for shortcuts created for its elements. Clients must obey this setting.
*/
public static final String SHORTCUT_SUPPORT = "shortcutSupport";
@@ -470,6 +470,37 @@
public static final int SHORTCUT_SUPPORT_FULL = 2;
/**
+ * One of {@link #PHOTO_SUPPORT_NONE}, {@link #PHOTO_SUPPORT_THUMBNAIL_ONLY},
+ * {@link #PHOTO_SUPPORT_FULL}. This is a feature flag indicating the extent
+ * to which the directory supports contact photos.
+ */
+ public static final String PHOTO_SUPPORT = "photoSupport";
+
+ /**
+ * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
+ * does not provide any photos.
+ */
+ public static final int PHOTO_SUPPORT_NONE = 0;
+
+ /**
+ * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
+ * can only produce small size thumbnails of contact photos.
+ */
+ public static final int PHOTO_SUPPORT_THUMBNAIL_ONLY = 1;
+
+ /**
+ * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
+ * has full-size contact photos, but cannot provide scaled thumbnails.
+ */
+ public static final int PHOTO_SUPPORT_FULL_SIZE_ONLY = 2;
+
+ /**
+ * An {@link #PHOTO_SUPPORT} setting that indicates that the directory
+ * can produce thumbnails as well as full-size contact photos.
+ */
+ public static final int PHOTO_SUPPORT_FULL = 3;
+
+ /**
* Notifies the system of a change in the list of directories handled by
* a particular directory provider. The Contacts provider will turn around
* and send a query to the directory provider for the full list of directories,
@@ -676,12 +707,42 @@
public static final String NAME_RAW_CONTACT_ID = "name_raw_contact_id";
/**
- * Reference to the row in the data table holding the photo.
+ * Reference to the row in the data table holding the photo. A photo can
+ * be referred to either by ID (this field) or by URI (see {@link #PHOTO_THUMBNAIL_URI}
+ * and {@link #PHOTO_URI}).
+ * If PHOTO_ID is null, consult {@link #PHOTO_URI} or {@link #PHOTO_THUMBNAIL_URI},
+ * which is a more generic mechanism for referencing the contact photo, especially for
+ * contacts returned by non-local directories (see {@link Directory}).
+ *
* <P>Type: INTEGER REFERENCES data(_id)</P>
*/
public static final String PHOTO_ID = "photo_id";
/**
+ * A URI that can be used to retrieve the contact's full-size photo.
+ * A photo can be referred to either by a URI (this field) or by ID
+ * (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
+ * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
+ * Thus using PHOTO_URI is a more robust method of retrieving contact photos.
+ *
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHOTO_URI = "photo_uri";
+
+ /**
+ * A URI that can be used to retrieve a thumbnail of the contact's photo.
+ * A photo can be referred to either by a URI (this field or {@link #PHOTO_URI})
+ * or by ID (see {@link #PHOTO_ID}). If PHOTO_ID is not null, PHOTO_URI and
+ * PHOTO_THUMBNAIL_URI shall not be null (but not necessarily vice versa).
+ * If the content provider does not differentiate between full-size photos
+ * and thumbnail photos, PHOTO_THUMBNAIL_URI and {@link #PHOTO_URI} can contain
+ * the same value, but either both shell be null or both not null.
+ *
+ * <P>Type: TEXT</P>
+ */
+ public static final String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
+
+ /**
* Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of
* any {@link CommonDataKinds.GroupMembership} for this contact.
*/
@@ -1032,6 +1093,20 @@
* that mime type.</td>
* </tr>
* <tr>
+ * <td>long</td>
+ * <td>{@link #PHOTO_URI}</td>
+ * <td>read-only</td>
+ * <td>A URI that can be used to retrieve the contact's full-size photo. This
+ * column is the preferred method of retrieving the contact photo.</td>
+ * </tr>
+ * <tr>
+ * <td>long</td>
+ * <td>{@link #PHOTO_THUMBNAIL_URI}</td>
+ * <td>read-only</td>
+ * <td>A URI that can be used to retrieve the thumbnail of contact's photo. This
+ * column is the preferred method of retrieving the contact photo.</td>
+ * </tr>
+ * <tr>
* <td>int</td>
* <td>{@link #IN_VISIBLE_GROUP}</td>
* <td>read-only</td>
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 1417ef5..da02845 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -255,13 +255,6 @@
public static final String MIME_TYPE = "mime_type";
/**
- * The row ID in the MTP object table corresponding to this media file.
- * <P>Type: INTEGER</P>
- * @hide
- */
- public static final String MTP_OBJECT_ID = "object_id";
-
- /**
* The MTP object handle of a newly transfered file.
* Used to pass the new file's object handle through the media scanner
* from MTP to the media provider
@@ -327,30 +320,33 @@
public static final String PARENT = "parent";
/**
- * Identifier for the media table containing the file.
- * Used internally by MediaProvider
- * <P>Type: INTEGER</P>
+ * The MIME type of the file
+ * <P>Type: TEXT</P>
*/
- public static final String MEDIA_TABLE = "media_table";
+ public static final String MIME_TYPE = "mime_type";
/**
- * The ID of the file in its media table.
- * <P>Type: INTEGER</P>
+ * The title of the content
+ * <P>Type: TEXT</P>
*/
- public static final String MEDIA_ID = "media_id";
+ public static final String TITLE = "title";
+
+ /**
+ * The media type (audio, video, image or playlist)
+ * of the file, or 0 for not a media file
+ * <P>Type: TEXT</P>
+ */
+ public static final String MEDIA_TYPE = "media_type";
+
+ /**
+ * Constants for MEDIA_TYPE
+ */
+ public static final int MEDIA_TYPE_NONE = 0;
+ public static final int MEDIA_TYPE_IMAGE = 1;
+ public static final int MEDIA_TYPE_AUDIO = 2;
+ public static final int MEDIA_TYPE_VIDEO = 3;
+ public static final int MEDIA_TYPE_PLAYLIST = 4;
}
-
- /**
- * The MIME type of the file
- * <P>Type: TEXT</P>
- */
- public static final String MIME_TYPE = "mime_type";
-
- /**
- * The title of the content
- * <P>Type: TEXT</P>
- */
- public static final String TITLE = "title";
}
/**
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index bba54e1..de161e7 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -75,7 +75,7 @@
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage");
}
- public static Uri getContentUri(int deviceID, int storageID) {
+ public static Uri getContentUri(int deviceID, long storageID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage/" + storageID);
}
@@ -97,17 +97,17 @@
*/
public static final class Object implements BaseColumns {
- public static Uri getContentUri(int deviceID, int objectID) {
+ public static Uri getContentUri(int deviceID, long objectID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/object/" + objectID);
}
- public static Uri getContentUriForObjectChildren(int deviceID, int objectID) {
+ public static Uri getContentUriForObjectChildren(int deviceID, long objectID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/object/" + objectID + "/child");
}
- public static Uri getContentUriForStorageChildren(int deviceID, int storageID) {
+ public static Uri getContentUriForStorageChildren(int deviceID, long storageID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/storage/" + storageID + "/child");
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4d87b79..e98fa26 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1494,6 +1494,12 @@
public static final String AUTO_TIME = "auto_time";
/**
+ * Value to specify if the user prefers the time zone
+ * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+ */
+ public static final String AUTO_TIME_ZONE = "auto_time_zone";
+
+ /**
* Display times as 12 or 24 hours
* 12
* 24
@@ -1775,6 +1781,7 @@
TEXT_AUTO_PUNCTUATE,
TEXT_SHOW_PASSWORD,
AUTO_TIME,
+ AUTO_TIME_ZONE,
TIME_12_24,
DATE_FORMAT,
ACCELEROMETER_ROTATION,
@@ -2349,6 +2356,13 @@
public static final String DEFAULT_INPUT_METHOD = "default_input_method";
/**
+ * Setting to record the input method subtype used by default, holding the ID
+ * of the desired method.
+ */
+ public static final String SELECTED_INPUT_METHOD_SUBTYPE =
+ "selected_input_method_subtype";
+
+ /**
* Whether the device has been provisioned (0 = false, 1 = true)
*/
public static final String DEVICE_PROVISIONED = "device_provisioned";
diff --git a/core/java/android/util/Base64InputStream.java b/core/java/android/util/Base64InputStream.java
index da3911d..e9dac24 100644
--- a/core/java/android/util/Base64InputStream.java
+++ b/core/java/android/util/Base64InputStream.java
@@ -112,7 +112,7 @@
if (outputStart >= outputEnd) {
return -1;
} else {
- return coder.output[outputStart++];
+ return coder.output[outputStart++] & 0xff;
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index e71b5b6..0321be0 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1584,11 +1584,7 @@
mAttachInfo.mRootView = null;
mAttachInfo.mSurface = null;
- if (mHwRenderer != null) {
- mHwRenderer.destroy(true);
- mHwRenderer = null;
- mAttachInfo.mHardwareAccelerated = false;
- }
+ destroyHardwareRenderer();
mSurface.release();
@@ -2542,6 +2538,8 @@
if (LOCAL_LOGV) Log.v(TAG, "DIE in " + this + " of " + mSurface);
synchronized (this) {
if (mAdded && !mFirst) {
+ destroyHardwareRenderer();
+
int viewVisibility = mView.getVisibility();
boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
if (mWindowAttributesChanged || viewVisibilityChanged) {
@@ -2566,6 +2564,14 @@
}
}
+ private void destroyHardwareRenderer() {
+ if (mHwRenderer != null) {
+ mHwRenderer.destroy(true);
+ mHwRenderer = null;
+ mAttachInfo.mHardwareAccelerated = false;
+ }
+ }
+
public void dispatchFinishedEvent(int seq, boolean handled) {
Message msg = obtainMessage(FINISHED_EVENT);
msg.arg1 = seq;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 6633367..9fadc58 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -78,10 +78,6 @@
* If overlay is enabled, the action mode UI will be allowed to cover existing window content.
*/
public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
- /**
- * Flag for requesting this window to be hardware accelerated, if possible.
- */
- public static final int FEATURE_HARDWARE_ACCELERATED = 11;
/** Flag for setting the progress bar's visibility to VISIBLE */
public static final int PROGRESS_VISIBILITY_ON = -1;
/** Flag for setting the progress bar's visibility to GONE */
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 55d11bb..8ffa158 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -214,9 +214,9 @@
// background.
// When device is near-vertical (screen approximately facing the horizon)
- private static final int DEFAULT_TIME_CONSTANT_MS = 50;
+ private static final int DEFAULT_TIME_CONSTANT_MS = 100;
// When device is partially tilted towards the sky or ground
- private static final int TILTED_TIME_CONSTANT_MS = 300;
+ private static final int TILTED_TIME_CONSTANT_MS = 500;
// When device is under external acceleration, i.e. not just gravity. We heavily distrust
// such readings.
private static final int ACCELERATING_TIME_CONSTANT_MS = 2000;
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 3801948..f7c869b 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -428,8 +428,12 @@
a = b;
b = tmp;
}
+ // Clip the end points to be within the content bounds.
+ final int length = content.length();
if (a < 0) a = 0;
- if (b > content.length()) b = content.length();
+ if (b < 0) b = 0;
+ if (a > length) a = length;
+ if (b > length) b = length;
ensureDefaultComposingSpans();
if (mDefaultComposingSpans != null) {
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index 2ddf5f8..5ab3d34 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -219,4 +219,10 @@
* {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
*/
public void hideSoftInput(int flags, ResultReceiver resultReceiver);
+
+ /**
+ * Notify that the input method subtype is being changed in the same input method.
+ * @param subtype New subtype of the notified input method
+ */
+ public void changeInputMethodSubtype(InputMethodSubtype subtype);
}
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 68e231c..54102f6 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -44,7 +44,7 @@
*/
public final class InputMethodInfo implements Parcelable {
static final String TAG = "InputMethodInfo";
-
+
/**
* The Service that implements this input method component.
*/
@@ -71,102 +71,6 @@
final int mIsDefaultResId;
/**
- * InputMethodSubtype is a subtype contained in the input method. Subtype can describe
- * locales (e.g. en_US, fr_FR...) and modes (e.g. voice, keyboard...), and is used for
- * IME switch. The subtype allows the system to call the specified subtype of IME directly.
- */
- public static class InputMethodSubtype implements Parcelable {
- private final String mSubtypeName;
- private final int mSubtypeIconId;
- private final String mSubtypeLocale;
- private final String mSubtypeMode;
- private final String mSubtypeExtraValue;
-
- /**
- * Constructor
- * @param name The name of the subtype
- * @param iconId The icon of the subtype
- * @param locale The locale supported by the subtype
- * @param mode The mode supported by the subtype
- * @param extraValue The extra value of the subtype
- */
- InputMethodSubtype(String name, int iconId, String locale, String mode,
- String extraValue) {
- mSubtypeName = name;
- mSubtypeIconId = iconId;
- mSubtypeLocale = locale;
- mSubtypeMode = mode;
- mSubtypeExtraValue = extraValue;
- }
-
- InputMethodSubtype(Parcel source) {
- mSubtypeName = source.readString();
- mSubtypeIconId = source.readInt();
- mSubtypeLocale = source.readString();
- mSubtypeMode = source.readString();
- mSubtypeExtraValue = source.readString();
- }
-
- /**
- * @return the name of the subtype
- */
- public String getName() {
- return mSubtypeName;
- }
-
- /**
- * @return the icon of the subtype
- */
- public int getIconId() {
- return mSubtypeIconId;
- }
-
- /**
- * @return the locale of the subtype
- */
- public String getLocale() {
- return mSubtypeLocale;
- }
-
- /**
- * @return the mode of the subtype
- */
- public String getMode() {
- return mSubtypeMode;
- }
-
- /**
- * @return the extra value of the subtype
- */
- public String getExtraValue() {
- return mSubtypeExtraValue;
- }
-
- public int describeContents() {
- return 0;
- }
-
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeString(mSubtypeName);
- dest.writeInt(mSubtypeIconId);
- dest.writeString(mSubtypeLocale);
- dest.writeString(mSubtypeMode);
- dest.writeString(mSubtypeExtraValue);
- }
-
- public static final Parcelable.Creator<InputMethodSubtype> CREATOR
- = new Parcelable.Creator<InputMethodSubtype>() {
- public InputMethodSubtype createFromParcel(Parcel source) {
- return new InputMethodSubtype(source);
- }
-
- public InputMethodSubtype[] newArray(int size) {
- return new InputMethodSubtype[size];
- }
- };
- }
-
- /**
* The array of the subtypes.
*/
private final ArrayList<InputMethodSubtype> mSubtypes = new ArrayList<InputMethodSubtype>();
@@ -223,24 +127,27 @@
// Parse all subtypes
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
&& type != XmlPullParser.END_DOCUMENT) {
- nodeName = parser.getName();
- if (!"subtype".equals(nodeName)) {
- throw new XmlPullParserException(
- "Meta-data in input-method does not start with subtype tag");
+ if (type == XmlPullParser.START_TAG) {
+ nodeName = parser.getName();
+ if (!"subtype".equals(nodeName)) {
+ throw new XmlPullParserException(
+ "Meta-data in input-method does not start with subtype tag");
+ }
+ final TypedArray a = res.obtainAttributes(
+ attrs, com.android.internal.R.styleable.InputMethod_Subtype);
+ InputMethodSubtype subtype = new InputMethodSubtype(
+ a.getResourceId(com.android.internal.R.styleable
+ .InputMethod_Subtype_label, 0),
+ a.getResourceId(com.android.internal.R.styleable
+ .InputMethod_Subtype_icon, 0),
+ a.getString(com.android.internal.R.styleable
+ .InputMethod_Subtype_imeSubtypeLocale),
+ a.getResourceId(com.android.internal.R.styleable
+ .InputMethod_Subtype_imeSubtypeMode, 0),
+ a.getString(com.android.internal.R.styleable
+ .InputMethod_Subtype_imeSubtypeExtraValue));
+ mSubtypes.add(subtype);
}
- final TypedArray a = res.obtainAttributes(
- attrs, com.android.internal.R.styleable.InputMethod_Subtype);
- InputMethodSubtype subtype = new InputMethodSubtype(
- a.getString(com.android.internal.R.styleable.InputMethod_Subtype_label),
- a.getResourceId(
- com.android.internal.R.styleable.InputMethod_Subtype_icon, 0),
- a.getString(com.android.internal.R.styleable
- .InputMethod_Subtype_imeSubtypeLocale),
- a.getString(com.android.internal.R.styleable
- .InputMethod_Subtype_imeSubtypeMode),
- a.getString(com.android.internal.R.styleable
- .InputMethod_Subtype_imeSubtypeExtraValue));
- mSubtypes.add(subtype);
}
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e30687f..8bd3298 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1380,7 +1380,7 @@
}
}
}
-
+
public void showInputMethodPicker() {
synchronized (mH) {
try {
@@ -1391,6 +1391,16 @@
}
}
+ public void showInputMethodSubtypePicker() {
+ synchronized (mH) {
+ try {
+ mService.showInputMethodSubtypePickerFromClient(mClient);
+ } catch (RemoteException e) {
+ Log.w(TAG, "IME died: " + mCurId, e);
+ }
+ }
+ }
+
void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
final Printer p = new PrintWriterPrinter(fout);
p.println("Input method client state for " + this + ":");
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.aidl b/core/java/android/view/inputmethod/InputMethodSubtype.aidl
new file mode 100644
index 0000000..ed82b84
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2010 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.view.inputmethod;
+
+parcelable InputMethodSubtype;
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
new file mode 100644
index 0000000..a1ed044
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2010 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.view.inputmethod;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * Information given to an {@link InputMethod} about a client connecting
+ * to it.
+ */
+/**
+ * InputMethodSubtype is a subtype contained in the input method. Subtype can describe
+ * locales (e.g. en_US, fr_FR...) and modes (e.g. voice, keyboard...), and is used for
+ * IME switch. The subtype allows the system to call the specified subtype of IME directly.
+ */
+public final class InputMethodSubtype implements Parcelable {
+ private final int mSubtypeNameResId;
+ private final int mSubtypeIconResId;
+ private final String mSubtypeLocale;
+ private final int mSubtypeModeResId;
+ private final String mSubtypeExtraValue;
+ private final int mSubtypeHashCode;
+
+ /**
+ * Constructor
+ * @param nameId The name of the subtype
+ * @param iconId The icon of the subtype
+ * @param locale The locale supported by the subtype
+ * @param modeId The mode supported by the subtype
+ * @param extraValue The extra value of the subtype
+ */
+ InputMethodSubtype(int nameId, int iconId, String locale, int modeId, String extraValue) {
+ mSubtypeNameResId = nameId;
+ mSubtypeIconResId = iconId;
+ mSubtypeLocale = locale;
+ mSubtypeModeResId = modeId;
+ mSubtypeExtraValue = extraValue;
+ mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
+ mSubtypeModeResId, mSubtypeExtraValue);
+ }
+
+ InputMethodSubtype(Parcel source) {
+ mSubtypeNameResId = source.readInt();
+ mSubtypeIconResId = source.readInt();
+ mSubtypeLocale = source.readString();
+ mSubtypeModeResId = source.readInt();
+ mSubtypeExtraValue = source.readString();
+ mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
+ mSubtypeModeResId, mSubtypeExtraValue);
+ }
+
+ /**
+ * @return the name of the subtype
+ */
+ public int getNameResId() {
+ return mSubtypeNameResId;
+ }
+
+ /**
+ * @return the icon of the subtype
+ */
+ public int getIconResId() {
+ return mSubtypeIconResId;
+ }
+
+ /**
+ * @return the locale of the subtype
+ */
+ public String getLocale() {
+ return mSubtypeLocale;
+ }
+
+ /**
+ * @return the mode of the subtype
+ */
+ public int getModeResId() {
+ return mSubtypeModeResId;
+ }
+
+ /**
+ * @return the extra value of the subtype
+ */
+ public String getExtraValue() {
+ return mSubtypeExtraValue;
+ }
+
+ @Override
+ public int hashCode() {
+ return mSubtypeHashCode;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof InputMethodSubtype) {
+ InputMethodSubtype subtype = (InputMethodSubtype) o;
+ return (subtype.getNameResId() == getNameResId())
+ && (subtype.getModeResId() == getModeResId())
+ && (subtype.getIconResId() == getIconResId())
+ && (subtype.getLocale().equals(getLocale()))
+ && (subtype.getExtraValue().equals(getExtraValue()));
+ }
+ return false;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int parcelableFlags) {
+ dest.writeInt(mSubtypeNameResId);
+ dest.writeInt(mSubtypeIconResId);
+ dest.writeString(mSubtypeLocale);
+ dest.writeInt(mSubtypeModeResId);
+ dest.writeString(mSubtypeExtraValue);
+ }
+
+ public static final Parcelable.Creator<InputMethodSubtype> CREATOR
+ = new Parcelable.Creator<InputMethodSubtype>() {
+ public InputMethodSubtype createFromParcel(Parcel source) {
+ return new InputMethodSubtype(source);
+ }
+
+ public InputMethodSubtype[] newArray(int size) {
+ return new InputMethodSubtype[size];
+ }
+ };
+
+ private static int hashCodeInternal(int nameResId, int iconResId, String locale,
+ int modeResId, String extraValue) {
+ return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, modeResId, extraValue});
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 61812ee..35cfbcb 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1037,15 +1037,16 @@
* We delegate the request to CallbackProxy, and route its response to
* {@link #nativeAuthenticationProceed(int, String, String)} or
* {@link #nativeAuthenticationCancel(int)}.
+ *
+ * We don't care what thread the callback is invoked on. All threading is
+ * handled on the C++ side, because the WebKit thread may be blocked on a
+ * synchronous call and unable to pump our MessageQueue.
*/
private void didReceiveAuthenticationChallenge(
final int handle, String host, String realm, final boolean useCachedCredentials) {
HttpAuthHandler handler = new HttpAuthHandler() {
- private static final int AUTH_PROCEED = 1;
- private static final int AUTH_CANCEL = 2;
-
@Override
public boolean useHttpAuthUsernamePassword() {
return useCachedCredentials;
@@ -1053,30 +1054,12 @@
@Override
public void proceed(String username, String password) {
- Message msg = obtainMessage(AUTH_PROCEED);
- msg.getData().putString("username", username);
- msg.getData().putString("password", password);
- sendMessage(msg);
+ nativeAuthenticationProceed(handle, username, password);
}
@Override
public void cancel() {
- sendMessage(obtainMessage(AUTH_CANCEL));
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case AUTH_PROCEED:
- String username = msg.getData().getString("username");
- String password = msg.getData().getString("password");
- nativeAuthenticationProceed(handle, username, password);
- break;
-
- case AUTH_CANCEL:
- nativeAuthenticationCancel(handle);
- break;
- }
+ nativeAuthenticationCancel(handle);
}
};
mCallbackProxy.onReceivedHttpAuthRequest(handler, host, realm);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 63fc008..20aafbd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -207,6 +207,7 @@
private RenderPriority mRenderPriority = RenderPriority.NORMAL;
private int mOverrideCacheMode = LOAD_DEFAULT;
private boolean mSaveFormData = true;
+ private boolean mAutoFillEnabled = false;
private boolean mSavePassword = true;
private boolean mLightTouchEnabled = false;
private boolean mNeedInitialFocus = true;
@@ -596,6 +597,20 @@
}
/**
+ * @hide
+ */
+ public void setAutoFillEnabled(boolean enabled) {
+ mAutoFillEnabled = enabled;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean getAutoFillEnabled() {
+ return mAutoFillEnabled;
+ }
+
+ /**
* Store whether the WebView is saving password.
*/
public void setSavePassword(boolean save) {
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index fca5ee1..1aff170 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -47,6 +47,7 @@
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputConnection;
import android.widget.AbsoluteLayout.LayoutParams;
+import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
@@ -116,15 +117,29 @@
private int mDelSelStart;
private int mDelSelEnd;
+ // Keep in sync with native constant in
+ // external/webkit/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp
+ /* package */ static final int FORM_NOT_AUTOFILLABLE = -1;
+
+ private boolean mAutoFillable; // Is this textview part of an autofillable form?
+ private int mQueryId;
+
/**
* Create a new WebTextView.
* @param context The Context for this WebTextView.
* @param webView The WebView that created this.
*/
- /* package */ WebTextView(Context context, WebView webView) {
+ /* package */ WebTextView(Context context, WebView webView, int autoFillQueryId) {
super(context, null, com.android.internal.R.attr.webTextViewStyle);
mWebView = webView;
mMaxLength = -1;
+ setAutoFillable(autoFillQueryId);
+ }
+
+ public void setAutoFillable(int queryId) {
+ mAutoFillable = mWebView.getSettings().getAutoFillEnabled()
+ && (queryId != FORM_NOT_AUTOFILLABLE);
+ mQueryId = queryId;
}
@Override
@@ -673,6 +688,22 @@
adapter.setTextView(this);
}
super.setAdapter(adapter);
+ if (mAutoFillable) {
+ setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (id == 0 && position == 0) {
+ // Blank out the text box while we wait for WebCore to fill the form.
+ replaceText("");
+ // Call a webview method to tell WebCore to autofill the form.
+ mWebView.autoFillForm(mQueryId);
+ }
+ }
+ });
+ } else {
+ setOnItemClickListener(null);
+ }
+ showDropDown();
}
/**
@@ -964,7 +995,7 @@
if (type != 2 /* PASSWORD */) {
String name = mWebView.nativeFocusCandidateName();
if (name != null && name.length() > 0) {
- mWebView.requestFormData(name, mNodePointer);
+ mWebView.requestFormData(name, mNodePointer, mAutoFillable);
}
}
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 127eae2..bca9b36 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -614,6 +614,8 @@
static final int SET_TOUCH_HIGHLIGHT_RECTS = 131;
static final int SAVE_WEBARCHIVE_FINISHED = 132;
+ static final int SET_AUTOFILLABLE = 133;
+
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;
@@ -662,7 +664,8 @@
"SET_SCROLLBAR_MODES", // = 129;
"SELECTION_STRING_CHANGED", // = 130;
"SET_TOUCH_HIGHLIGHT_RECTS", // = 131;
- "SAVE_WEBARCHIVE_FINISHED" // = 132;
+ "SAVE_WEBARCHIVE_FINISHED", // = 132;
+ "SET_AUTOFILLABLE" // = 133;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -735,6 +738,8 @@
// for event log
private long mLastTouchUpTime = 0;
+ private int mAutoFillQueryId = WebTextView.FORM_NOT_AUTOFILLABLE;
+
/**
* URI scheme for telephone number
*/
@@ -3868,7 +3873,7 @@
// At this point, we know we have found an input field, so go ahead
// and create the WebTextView if necessary.
if (mWebTextView == null) {
- mWebTextView = new WebTextView(mContext, WebView.this);
+ mWebTextView = new WebTextView(mContext, WebView.this, mAutoFillQueryId);
// Initialize our generation number.
mTextGeneration = 0;
}
@@ -3936,13 +3941,15 @@
* @param nodePointer Pointer to the node of the textfield, so it can be
* compared to the currently focused textfield when the data is
* retrieved.
+ * @param autoFillable true if WebKit has determined this field is part of
+ * a form that can be auto filled.
*/
- /* package */ void requestFormData(String name, int nodePointer) {
+ /* package */ void requestFormData(String name, int nodePointer, boolean autoFillable) {
if (mWebViewCore.getSettings().getSaveFormData()) {
Message update = mPrivateHandler.obtainMessage(REQUEST_FORM_DATA);
update.arg1 = nodePointer;
RequestFormData updater = new RequestFormData(name, getUrl(),
- update);
+ update, autoFillable);
Thread t = new Thread(updater);
t.start();
}
@@ -3968,15 +3975,28 @@
private String mName;
private String mUrl;
private Message mUpdateMessage;
+ private boolean mAutoFillable;
- public RequestFormData(String name, String url, Message msg) {
+ public RequestFormData(String name, String url, Message msg, boolean autoFillable) {
mName = name;
mUrl = url;
mUpdateMessage = msg;
+ mAutoFillable = autoFillable;
}
public void run() {
- ArrayList<String> pastEntries = mDatabase.getFormData(mUrl, mName);
+ ArrayList<String> pastEntries = new ArrayList();
+
+ if (mAutoFillable) {
+ // Note that code inside the adapter click handler in WebTextView depends
+ // on the AutoFill item being at the top of the drop down list. If you change
+ // the order, make sure to do it there too!
+ pastEntries.add(getResources().getText(
+ com.android.internal.R.string.autofill_this_form).toString());
+ }
+
+ pastEntries.addAll(mDatabase.getFormData(mUrl, mName));
+
if (pastEntries.size() > 0) {
AutoCompleteAdapter adapter = new
AutoCompleteAdapter(mContext, pastEntries);
@@ -6942,6 +6962,14 @@
}
break;
+ case SET_AUTOFILLABLE:
+ mAutoFillQueryId = msg.arg1;
+ if (mWebTextView != null) {
+ mWebTextView.setAutoFillable(mAutoFillQueryId);
+ rebuildWebTextView();
+ }
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -7475,6 +7503,10 @@
nativeUpdateCachedTextfield(updatedText, mTextGeneration);
}
+ /*package*/ void autoFillForm(int autoFillQueryId) {
+ mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
+ }
+
private native int nativeCacheHitFramePointer();
private native Rect nativeCacheHitNodeBounds();
private native int nativeCacheHitNodePointer();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index af7d95e..122cf6a 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -882,6 +882,8 @@
static final int USE_MOCK_DEVICE_ORIENTATION = 191;
+ static final int AUTOFILL_FORM = 192;
+
// private message ids
private static final int DESTROY = 200;
@@ -1417,6 +1419,10 @@
case USE_MOCK_DEVICE_ORIENTATION:
useMockDeviceOrientation();
break;
+
+ case AUTOFILL_FORM:
+ nativeAutoFillForm(msg.arg1);
+ break;
}
}
};
@@ -1829,9 +1835,11 @@
draw.mViewState = mInitialViewState;
if (mViewportWidth == -1 && mSettings.getUseFixedViewport() &&
mSettings.getUseWideViewPort()) {
+ final int fixedViewportMargin = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.fixed_viewport_margin);
// Use website's initial preferred width as the fixed viewport width.
mViewportWidth = Math.min(mSettings.getMaxFixedViewportWidth(),
- Math.max(draw.mWidthHeight.x, draw.mMinPrefWidth));
+ draw.mMinPrefWidth + 2 * fixedViewportMargin);
draw.mViewState.mViewportWidth = mViewportWidth;
}
mInitialViewState = null;
@@ -2364,6 +2372,13 @@
}
}
+ private void setWebTextViewAutoFillable(int queryId) {
+ if (mWebView != null) {
+ Message.obtain(mWebView.mPrivateHandler, WebView.SET_AUTOFILLABLE, queryId,
+ /* unused */0).sendToTarget();
+ }
+ }
+
// called by JNI
private Context getContext() {
return mContext;
@@ -2531,4 +2546,6 @@
private native ArrayList<Rect> nativeGetTouchHighlightRects(int x, int y,
int slop);
+
+ private native void nativeAutoFillForm(int queryId);
}
diff --git a/core/java/android/webruntime/WebRuntimeActivity.java b/core/java/android/webruntime/WebRuntimeActivity.java
deleted file mode 100644
index ec8c60c..0000000
--- a/core/java/android/webruntime/WebRuntimeActivity.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2010 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.webruntime;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.ComponentName;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.View;
-import android.view.Window;
-import android.webkit.GeolocationPermissions;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.android.internal.R;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-/**
- * The runtime used to display installed web applications.
- * @hide
- */
-public class WebRuntimeActivity extends Activity
-{
- private final static String LOGTAG = "WebRuntimeActivity";
-
- private WebView mWebView;
- private URL mBaseUrl;
- private ImageView mSplashScreen;
-
- public static class SensitiveFeatures {
- // All of the sensitive features
- private boolean mGeolocation;
- // On Android, the Browser doesn't prompt for database access, so we don't require an
- // explicit permission here in the WebRuntimeActivity, and there's no Android system
- // permission required for it either.
- //private boolean mDatabase;
-
- public boolean getGeolocation() {
- return mGeolocation;
- }
- public void setGeolocation(boolean geolocation) {
- mGeolocation = geolocation;
- }
- }
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
-
- // Can't get meta data using getApplicationInfo() as it doesn't pass GET_META_DATA
- PackageManager packageManager = getPackageManager();
- ComponentName componentName = new ComponentName(this, getClass());
- ActivityInfo activityInfo = null;
- try {
- activityInfo = packageManager.getActivityInfo(componentName, PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- Log.d(LOGTAG, "Failed to find component");
- return;
- }
- if (activityInfo == null) {
- Log.d(LOGTAG, "Failed to get activity info");
- return;
- }
-
- Bundle metaData = activityInfo.metaData;
- if (metaData == null) {
- Log.d(LOGTAG, "No meta data");
- return;
- }
-
- String url = metaData.getString("android.webruntime.url");
- if (url == null) {
- Log.d(LOGTAG, "No URL");
- return;
- }
-
- try {
- mBaseUrl = new URL(url);
- } catch (MalformedURLException e) {
- Log.d(LOGTAG, "Invalid URL");
- }
-
- // All false by default, and reading non-existent bundle properties gives false too.
- final SensitiveFeatures sensitiveFeatures = new SensitiveFeatures();
- sensitiveFeatures.setGeolocation(metaData.getBoolean("android.webruntime.SensitiveFeaturesGeolocation"));
-
- getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.web_runtime);
- mWebView = (WebView) findViewById(R.id.webview);
- mSplashScreen = (ImageView) findViewById(R.id.splashscreen);
- mSplashScreen.setImageResource(
- getResources().getIdentifier("splash_screen", "drawable", getPackageName()));
- mWebView.getSettings().setJavaScriptEnabled(true);
- mWebView.setWebViewClient(new WebViewClient() {
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- try {
- URL newOrigin = new URL(url);
- if (areSameOrigin(mBaseUrl, newOrigin)) {
- // If simple same origin test passes, load in the webview.
- return false;
- }
- } catch(MalformedURLException e) {
- // Don't load anything if this wasn't a proper URL.
- return true;
- }
-
- // Otherwise this is a URL that is not same origin so pass it to the
- // Browser to load.
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
- return true;
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- if (mSplashScreen != null && mSplashScreen.getVisibility() == View.VISIBLE) {
- mSplashScreen.setVisibility(View.GONE);
- mSplashScreen = null;
- }
- }
- });
-
- // Use a custom WebChromeClient with geolocation permissions handling.
- mWebView.setWebChromeClient(new WebChromeClient() {
- public void onGeolocationPermissionsShowPrompt(
- String origin, GeolocationPermissions.Callback callback) {
- // Allow this origin if it has Geolocation permissions, otherwise deny.
- boolean allowed = false;
- if (sensitiveFeatures.getGeolocation()) {
- try {
- URL originUrl = new URL(origin);
- allowed = areSameOrigin(mBaseUrl, originUrl);
- } catch(MalformedURLException e) {
- }
- }
- callback.invoke(origin, allowed, false);
- }
- });
-
- // Set the DB location. Optional. Geolocation works without DBs.
- mWebView.getSettings().setGeolocationDatabasePath(
- getDir("geolocation", MODE_PRIVATE).getPath());
-
- String title = metaData.getString("android.webruntime.title");
- // We turned off the title bar to go full screen so display the
- // webapp's title as a toast.
- if (title != null) {
- Toast.makeText(this, title, Toast.LENGTH_SHORT).show();
- }
-
- // Load the webapp's base URL.
- mWebView.loadUrl(url);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
- mWebView.goBack();
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, 0, 0, "Menu item 1");
- menu.add(0, 1, 0, "Menu item 2");
- return true;
- }
-
- private static boolean areSameOrigin(URL a, URL b) {
- int aPort = a.getPort() == -1 ? a.getDefaultPort() : a.getPort();
- int bPort = b.getPort() == -1 ? b.getDefaultPort() : b.getPort();
- return a.getProtocol().equals(b.getProtocol()) && aPort == bPort && a.getHost().equals(b.getHost());
- }
-}
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 176233e..8d58a6d 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -25,13 +25,13 @@
/**
- * <p>
- * <code>Button</code> represents a push-button widget. Push-buttons can be
- * pressed, or clicked, by the user to perform an action. A typical use of a
- * push-button in an activity would be the following:
+ * Represents a push-button widget. Push-buttons can be
+ * pressed, or clicked, by the user to perform an action.
+
+ * <p>A typical use of a push-button in an activity would be the following:
* </p>
*
- * <pre class="prettyprint">
+ * <pre>
* public class MyActivity extends Activity {
* protected void onCreate(Bundle icicle) {
* super.onCreate(icicle);
@@ -45,16 +45,52 @@
* }
* });
* }
- * }
- * </pre>
+ * }</pre>
*
- * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff
- * tutorial</a>.</p>
+ * <p>However, instead of applying an {@link android.view.View.OnClickListener OnClickListener} to
+ * the button in your activity, you can assign a method to your button in the XML layout,
+ * using the {@link android.R.attr#onClick android:onClick} attribute. For example:</p>
+ *
+ * <pre>
+ * <Button
+ * android:layout_height="wrap_content"
+ * android:layout_width="wrap_content"
+ * android:text="@string/self_destruct"
+ * android:onClick="selfDestruct" /></pre>
+ *
+ * <p>Now, when a user clicks the button, the Android system calls the activity's {@code
+ * selfDestruct(View)} method. In order for this to work, the method must be public and accept
+ * a {@link android.view.View} as its only parameter. For example:</p>
+ *
+ * <pre>
+ * public void selfDestruct(View view) {
+ * // Kabloey
+ * }</pre>
+ *
+ * <p>The {@link android.view.View} passed into the method is a reference to the widget
+ * that was clicked.</p>
+ *
+ * <h3>Button style</h3>
+ *
+ * <p>Every Button is styled using the system's default button background, which is often different
+ * from one device to another and from one version of the platform to another. If you're not
+ * satisfied with the default button style and want to customize it to match the design of your
+ * application, then you can replace the button's background image with a <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">state list drawable</a>.
+ * A state list drawable is a drawable resource defined in XML that changes its image based on
+ * the current state of the button. Once you've defined a state list drawable in XML, you can apply
+ * it to your Button with the {@link android.R.attr#background android:background}
+ * attribute. For more information and an example, see <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">State List
+ * Drawable</a>.</p>
+ *
+ * <p>Also see the <a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff
+ * tutorial</a> for an example implementation of a button.</p>
*
* <p><strong>XML attributes</strong></p>
- * <p>
- * See {@link android.R.styleable#Button Button Attributes},
- * {@link android.R.styleable#TextView TextView Attributes},
+ * <p>
+ * See {@link android.R.styleable#Button Button Attributes},
+ * {@link android.R.styleable#TextView TextView Attributes},
* {@link android.R.styleable#View View Attributes}
* </p>
*/
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 8ff18ed..c7fcab8 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -23,6 +23,7 @@
import android.view.MotionEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
@@ -52,4 +53,6 @@
void showSoftInput(int flags, in ResultReceiver resultReceiver);
void hideSoftInput(int flags, in ResultReceiver resultReceiver);
+
+ void changeInputMethodSubtype(in InputMethodSubtype subtype);
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index adec0a7..d012b0f 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -48,6 +48,7 @@
int softInputMode, boolean first, int windowFlags);
void showInputMethodPickerFromClient(in IInputMethodClient client);
+ void showInputMethodSubtypePickerFromClient(in IInputMethodClient client);
void setInputMethod(in IBinder token, String id);
void hideMySoftInput(in IBinder token, int flags);
void showMySoftInput(in IBinder token, int flags);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8310e56..fffd185 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -105,12 +105,13 @@
android_graphics_PixelFormat.cpp \
android/graphics/Picture.cpp \
android/graphics/PorterDuff.cpp \
- android/graphics/LargeBitmap.cpp \
+ android/graphics/BitmapRegionDecoder.cpp \
android/graphics/Rasterizer.cpp \
android/graphics/Region.cpp \
android/graphics/Shader.cpp \
android/graphics/TextLayout.cpp \
android/graphics/Typeface.cpp \
+ android/graphics/Utils.cpp \
android/graphics/Xfermode.cpp \
android/graphics/YuvToJpegEncoder.cpp \
android_media_AudioRecord.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4da73d7..ff62e0d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -53,7 +53,7 @@
extern int register_android_os_Process(JNIEnv* env);
extern int register_android_graphics_Bitmap(JNIEnv*);
extern int register_android_graphics_BitmapFactory(JNIEnv*);
-extern int register_android_graphics_LargeBitmap(JNIEnv*);
+extern int register_android_graphics_BitmapRegionDecoder(JNIEnv*);
extern int register_android_graphics_Camera(JNIEnv* env);
extern int register_android_graphics_Graphics(JNIEnv* env);
extern int register_android_graphics_Interpolator(JNIEnv* env);
@@ -1209,7 +1209,7 @@
REG_JNI(register_android_graphics_Bitmap),
REG_JNI(register_android_graphics_BitmapFactory),
- REG_JNI(register_android_graphics_LargeBitmap),
+ REG_JNI(register_android_graphics_BitmapRegionDecoder),
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_ColorFilter),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 6745b24..90a0243 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -10,6 +10,7 @@
#include "SkUtils.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include "AutoDecodeCancel.h"
+#include "Utils.h"
#include <android_runtime/AndroidRuntime.h>
#include <utils/Asset.h>
@@ -99,57 +100,6 @@
}
};
-class AssetStreamAdaptor : public SkStream {
-public:
- AssetStreamAdaptor(Asset* a) : fAsset(a) {}
-
- virtual bool rewind() {
- off_t pos = fAsset->seek(0, SEEK_SET);
- if (pos == (off_t)-1) {
- SkDebugf("----- fAsset->seek(rewind) failed\n");
- return false;
- }
- return true;
- }
-
- virtual size_t read(void* buffer, size_t size) {
- ssize_t amount;
-
- if (NULL == buffer) {
- if (0 == size) { // caller is asking us for our total length
- return fAsset->getLength();
- }
- // asset->seek returns new total offset
- // we want to return amount that was skipped
-
- off_t oldOffset = fAsset->seek(0, SEEK_CUR);
- if (-1 == oldOffset) {
- SkDebugf("---- fAsset->seek(oldOffset) failed\n");
- return 0;
- }
- off_t newOffset = fAsset->seek(size, SEEK_CUR);
- if (-1 == newOffset) {
- SkDebugf("---- fAsset->seek(%d) failed\n", size);
- return 0;
- }
- amount = newOffset - oldOffset;
- } else {
- amount = fAsset->read(buffer, size);
- if (amount <= 0) {
- SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
- }
- }
-
- if (amount < 0) {
- amount = 0;
- }
- return amount;
- }
-
-private:
- Asset* fAsset;
-};
-
///////////////////////////////////////////////////////////////////////////////
static inline int32_t validOrNeg1(bool isValid, int32_t value) {
@@ -201,12 +151,6 @@
!env->GetBooleanField(options, gOptions_nativeAllocFieldID);
}
-static jobject nullObjectReturn(const char msg[]) {
- if (msg) {
- SkDebugf("--- %s\n", msg);
- }
- return NULL;
-}
static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStream* stream,
int sampleSize, bool ditherImage) {
@@ -377,23 +321,6 @@
return size;
}
-/** Restore the file descriptor's offset in our destructor
- */
-class AutoFDSeek {
-public:
- AutoFDSeek(int fd) : fFD(fd) {
- fCurr = ::lseek(fd, 0, SEEK_CUR);
- }
- ~AutoFDSeek() {
- if (fCurr >= 0) {
- ::lseek(fFD, fCurr, SEEK_SET);
- }
- }
-private:
- int fFD;
- off_t fCurr;
-};
-
static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz,
jobject fileDescriptor,
jobject padding,
@@ -560,134 +487,6 @@
}
}
-static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
- size_t bufferSize = 4096;
- size_t streamLen = 0;
- size_t len;
- char* data = (char*)sk_malloc_throw(bufferSize);
-
- while ((len = stream->read(data + streamLen,
- bufferSize - streamLen)) != 0) {
- streamLen += len;
- if (streamLen == bufferSize) {
- bufferSize *= 2;
- data = (char*)sk_realloc_throw(data, bufferSize);
- }
- }
- data = (char*)sk_realloc_throw(data, streamLen);
- SkMemoryStream* streamMem = new SkMemoryStream();
- streamMem->setMemoryOwned(data, streamLen);
- return streamMem;
-}
-
-static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) {
- SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
- int width, height;
- if (NULL == decoder) {
- doThrowIOE(env, "Image format not supported");
- return nullObjectReturn("SkImageDecoder::Factory returned null");
- }
-
- JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true);
- decoder->setAllocator(javaAllocator);
- JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
- decoder->setReporter(javaMemoryReporter);
- javaAllocator->unref();
- javaMemoryReporter->unref();
-
- if (!decoder->buildTileIndex(stream, &width, &height)) {
- char msg[100];
- snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder",
- decoder->getFormatName());
- doThrowIOE(env, msg);
- return nullObjectReturn("decoder->buildTileIndex returned false");
- }
-
- SkLargeBitmap *bm = new SkLargeBitmap(decoder, width, height);
-
- return GraphicsJNI::createLargeBitmap(env, bm);
-}
-
-static jobject nativeCreateLargeBitmapFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
- int offset, int length, jboolean isShareable) {
- /* If isShareable we could decide to just wrap the java array and
- share it, but that means adding a globalref to the java array object
- For now we just always copy the array's data if isShareable.
- */
- AutoJavaByteArray ar(env, byteArray);
- SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
- return doBuildTileIndex(env, stream);
-}
-
-static jobject nativeCreateLargeBitmapFromFileDescriptor(JNIEnv* env, jobject clazz,
- jobject fileDescriptor, jboolean isShareable) {
- NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
-
- jint descriptor = env->GetIntField(fileDescriptor,
- gFileDescriptor_descriptor);
- SkStream *stream = NULL;
- struct stat fdStat;
- int newFD;
- if (fstat(descriptor, &fdStat) == -1) {
- doThrowIOE(env, "broken file descriptor");
- return nullObjectReturn("fstat return -1");
- }
-
- if (isShareable &&
- S_ISREG(fdStat.st_mode) &&
- (newFD = ::dup(descriptor)) != -1) {
- SkFDStream* fdStream = new SkFDStream(newFD, true);
- if (!fdStream->isValid()) {
- fdStream->unref();
- return NULL;
- }
- stream = fdStream;
- } else {
- SkFDStream* fdStream = new SkFDStream(descriptor, false);
- if (!fdStream->isValid()) {
- fdStream->unref();
- return NULL;
- }
- stream = buildSkMemoryStream(fdStream);
- fdStream->unref();
- }
-
- /* Restore our offset when we leave, so we can be called more than once
- with the same descriptor. This is only required if we didn't dup the
- file descriptor, but it is OK to do it all the time.
- */
- AutoFDSeek as(descriptor);
-
- return doBuildTileIndex(env, stream);
-}
-
-static jobject nativeCreateLargeBitmapFromStream(JNIEnv* env, jobject clazz,
- jobject is, // InputStream
- jbyteArray storage, // byte[]
- jboolean isShareable) {
- jobject largeBitmap = NULL;
- SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
-
- if (stream) {
- // for now we don't allow shareable with java inputstreams
- SkMemoryStream *mStream = buildSkMemoryStream(stream);
- largeBitmap = doBuildTileIndex(env, mStream);
- stream->unref();
- }
- return largeBitmap;
-}
-
-static jobject nativeCreateLargeBitmapFromAsset(JNIEnv* env, jobject clazz,
- jint native_asset, // Asset
- jboolean isShareable) {
- SkStream* stream, *assStream;
- Asset* asset = reinterpret_cast<Asset*>(native_asset);
- assStream = new AssetStreamAdaptor(asset);
- stream = buildSkMemoryStream(assStream);
- assStream->unref();
- return doBuildTileIndex(env, stream);
-}
-
///////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gMethods[] = {
@@ -717,26 +516,6 @@
},
{ "nativeSetDefaultConfig", "(I)V", (void*)nativeSetDefaultConfig },
-
- { "nativeCreateLargeBitmap",
- "([BIIZ)Landroid/graphics/LargeBitmap;",
- (void*)nativeCreateLargeBitmapFromByteArray
- },
-
- { "nativeCreateLargeBitmap",
- "(Ljava/io/InputStream;[BZ)Landroid/graphics/LargeBitmap;",
- (void*)nativeCreateLargeBitmapFromStream
- },
-
- { "nativeCreateLargeBitmap",
- "(Ljava/io/FileDescriptor;Z)Landroid/graphics/LargeBitmap;",
- (void*)nativeCreateLargeBitmapFromFileDescriptor
- },
-
- { "nativeCreateLargeBitmap",
- "(IZ)Landroid/graphics/LargeBitmap;",
- (void*)nativeCreateLargeBitmapFromAsset
- },
};
static JNINativeMethod gOptionsMethods[] = {
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
new file mode 100644
index 0000000..4503852
--- /dev/null
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "BitmapRegionDecoder"
+
+#include "SkBitmap.h"
+#include "SkImageEncoder.h"
+#include "GraphicsJNI.h"
+#include "SkUtils.h"
+#include "SkTemplates.h"
+#include "SkPixelRef.h"
+#include "SkStream.h"
+#include "BitmapFactory.h"
+#include "AutoDecodeCancel.h"
+#include "SkBitmapRegionDecoder.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+#include "Utils.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include "android_util_Binder.h"
+#include "android_nio_utils.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+#include <binder/Parcel.h>
+#include <jni.h>
+#include <utils/Asset.h>
+#include <sys/stat.h>
+
+static jclass gFileDescriptor_class;
+static jfieldID gFileDescriptor_descriptor;
+
+#if 0
+ #define TRACE_BITMAP(code) code
+#else
+ #define TRACE_BITMAP(code)
+#endif
+
+using namespace android;
+
+static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
+ size_t bufferSize = 4096;
+ size_t streamLen = 0;
+ size_t len;
+ char* data = (char*)sk_malloc_throw(bufferSize);
+
+ while ((len = stream->read(data + streamLen,
+ bufferSize - streamLen)) != 0) {
+ streamLen += len;
+ if (streamLen == bufferSize) {
+ bufferSize *= 2;
+ data = (char*)sk_realloc_throw(data, bufferSize);
+ }
+ }
+ data = (char*)sk_realloc_throw(data, streamLen);
+ SkMemoryStream* streamMem = new SkMemoryStream();
+ streamMem->setMemoryOwned(data, streamLen);
+ return streamMem;
+}
+
+static jobject doBuildTileIndex(JNIEnv* env, SkStream* stream) {
+ SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
+ int width, height;
+ if (NULL == decoder) {
+ doThrowIOE(env, "Image format not supported");
+ return nullObjectReturn("SkImageDecoder::Factory returned null");
+ }
+
+ JavaPixelAllocator *javaAllocator = new JavaPixelAllocator(env, true);
+ decoder->setAllocator(javaAllocator);
+ JavaMemoryUsageReporter *javaMemoryReporter = new JavaMemoryUsageReporter(env);
+ decoder->setReporter(javaMemoryReporter);
+ javaAllocator->unref();
+ javaMemoryReporter->unref();
+
+ if (!decoder->buildTileIndex(stream, &width, &height)) {
+ char msg[100];
+ snprintf(msg, sizeof(msg), "Image failed to decode using %s decoder",
+ decoder->getFormatName());
+ doThrowIOE(env, msg);
+ return nullObjectReturn("decoder->buildTileIndex returned false");
+ }
+
+ SkBitmapRegionDecoder *bm = new SkBitmapRegionDecoder(decoder, width, height);
+
+ return GraphicsJNI::createBitmapRegionDecoder(env, bm);
+}
+
+static jobject nativeNewInstanceFromByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
+ int offset, int length, jboolean isShareable) {
+ /* If isShareable we could decide to just wrap the java array and
+ share it, but that means adding a globalref to the java array object
+ For now we just always copy the array's data if isShareable.
+ */
+ AutoJavaByteArray ar(env, byteArray);
+ SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
+ return doBuildTileIndex(env, stream);
+}
+
+static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz,
+ jobject fileDescriptor, jboolean isShareable) {
+ NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
+
+ jint descriptor = env->GetIntField(fileDescriptor,
+ gFileDescriptor_descriptor);
+ SkStream *stream = NULL;
+ struct stat fdStat;
+ int newFD;
+ if (fstat(descriptor, &fdStat) == -1) {
+ doThrowIOE(env, "broken file descriptor");
+ return nullObjectReturn("fstat return -1");
+ }
+
+ if (isShareable &&
+ S_ISREG(fdStat.st_mode) &&
+ (newFD = ::dup(descriptor)) != -1) {
+ SkFDStream* fdStream = new SkFDStream(newFD, true);
+ if (!fdStream->isValid()) {
+ fdStream->unref();
+ return NULL;
+ }
+ stream = fdStream;
+ } else {
+ SkFDStream* fdStream = new SkFDStream(descriptor, false);
+ if (!fdStream->isValid()) {
+ fdStream->unref();
+ return NULL;
+ }
+ stream = buildSkMemoryStream(fdStream);
+ fdStream->unref();
+ }
+
+ /* Restore our offset when we leave, so we can be called more than once
+ with the same descriptor. This is only required if we didn't dup the
+ file descriptor, but it is OK to do it all the time.
+ */
+ AutoFDSeek as(descriptor);
+
+ return doBuildTileIndex(env, stream);
+}
+
+static jobject nativeNewInstanceFromStream(JNIEnv* env, jobject clazz,
+ jobject is, // InputStream
+ jbyteArray storage, // byte[]
+ jboolean isShareable) {
+ jobject largeBitmap = NULL;
+ SkStream* stream = CreateJavaInputStreamAdaptor(env, is, storage, 1024);
+
+ if (stream) {
+ // for now we don't allow shareable with java inputstreams
+ SkMemoryStream *mStream = buildSkMemoryStream(stream);
+ largeBitmap = doBuildTileIndex(env, mStream);
+ stream->unref();
+ }
+ return largeBitmap;
+}
+
+static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
+ jint native_asset, // Asset
+ jboolean isShareable) {
+ SkStream* stream, *assStream;
+ Asset* asset = reinterpret_cast<Asset*>(native_asset);
+ assStream = new AssetStreamAdaptor(asset);
+ stream = buildSkMemoryStream(assStream);
+ assStream->unref();
+ return doBuildTileIndex(env, stream);
+}
+
+/*
+ * nine patch not supported
+ *
+ * purgeable not supported
+ * reportSizeToVM not supported
+ */
+static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd,
+ int start_x, int start_y, int width, int height, jobject options) {
+ SkImageDecoder *decoder = brd->getDecoder();
+ int sampleSize = 1;
+ SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
+ bool doDither = true;
+
+ if (NULL != options) {
+ sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
+ // initialize these, in case we fail later on
+ env->SetIntField(options, gOptions_widthFieldID, -1);
+ env->SetIntField(options, gOptions_heightFieldID, -1);
+ env->SetObjectField(options, gOptions_mimeFieldID, 0);
+
+ jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
+ prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
+ doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
+ }
+
+ decoder->setDitherImage(doDither);
+ SkBitmap* bitmap = new SkBitmap;
+ SkAutoTDelete<SkBitmap> adb(bitmap);
+ AutoDecoderCancel adc(options, decoder);
+
+ // To fix the race condition in case "requestCancelDecode"
+ // happens earlier than AutoDecoderCancel object is added
+ // to the gAutoDecoderCancelMutex linked list.
+ if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
+ return nullObjectReturn("gOptions_mCancelID");;
+ }
+
+ SkIRect region;
+ region.fLeft = start_x;
+ region.fTop = start_y;
+ region.fRight = start_x + width;
+ region.fBottom = start_y + height;
+
+ if (!brd->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
+ return nullObjectReturn("decoder->decodeRegion returned false");
+ }
+
+ // update options (if any)
+ if (NULL != options) {
+ env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
+ env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
+ // TODO: set the mimeType field with the data from the codec.
+ // but how to reuse a set of strings, rather than allocating new one
+ // each time?
+ env->SetObjectField(options, gOptions_mimeFieldID,
+ getMimeTypeString(env, decoder->getFormat()));
+ }
+
+ // detach bitmap from its autotdeleter, since we want to own it now
+ adb.detach();
+
+ SkPixelRef* pr;
+ pr = bitmap->pixelRef();
+ // promise we will never change our pixels (great for sharing and pictures)
+ pr->setImmutable();
+ // now create the java bitmap
+ return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
+}
+
+static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
+ return brd->getHeight();
+}
+
+static int nativeGetWidth(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
+ return brd->getWidth();
+}
+
+static void nativeClean(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
+ delete brd;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <android_runtime/AndroidRuntime.h>
+
+static JNINativeMethod gBitmapRegionDecoderMethods[] = {
+ { "nativeDecodeRegion",
+ "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
+ (void*)nativeDecodeRegion},
+
+ { "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
+
+ { "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
+
+ { "nativeClean", "(I)V", (void*)nativeClean},
+
+ { "nativeNewInstance",
+ "([BIIZ)Landroid/graphics/BitmapRegionDecoder;",
+ (void*)nativeNewInstanceFromByteArray
+ },
+
+ { "nativeNewInstance",
+ "(Ljava/io/InputStream;[BZ)Landroid/graphics/BitmapRegionDecoder;",
+ (void*)nativeNewInstanceFromStream
+ },
+
+ { "nativeNewInstance",
+ "(Ljava/io/FileDescriptor;Z)Landroid/graphics/BitmapRegionDecoder;",
+ (void*)nativeNewInstanceFromFileDescriptor
+ },
+
+ { "nativeNewInstance",
+ "(IZ)Landroid/graphics/BitmapRegionDecoder;",
+ (void*)nativeNewInstanceFromAsset
+ },
+};
+
+#define kClassPathName "android/graphics/BitmapRegionDecoder"
+
+int register_android_graphics_BitmapRegionDecoder(JNIEnv* env);
+int register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
+{
+ return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+ gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
+}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 72cea65..1ebe14b 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -168,8 +168,8 @@
static jclass gBitmapConfig_class;
static jfieldID gBitmapConfig_nativeInstanceID;
-static jclass gLargeBitmap_class;
-static jmethodID gLargeBitmap_constructorMethodID;
+static jclass gBitmapRegionDecoder_class;
+static jmethodID gBitmapRegionDecoder_constructorMethodID;
static jclass gCanvas_class;
static jfieldID gCanvas_nativeInstanceID;
@@ -376,17 +376,18 @@
}
return obj;
}
-jobject GraphicsJNI::createLargeBitmap(JNIEnv* env, SkLargeBitmap* bitmap)
+
+jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap)
{
SkASSERT(bitmap != NULL);
- jobject obj = env->AllocObject(gLargeBitmap_class);
+ jobject obj = env->AllocObject(gBitmapRegionDecoder_class);
if (hasException(env)) {
obj = NULL;
return obj;
}
if (obj) {
- env->CallVoidMethod(obj, gLargeBitmap_constructorMethodID, (jint)bitmap);
+ env->CallVoidMethod(obj, gBitmapRegionDecoder_constructorMethodID, (jint)bitmap);
if (hasException(env)) {
obj = NULL;
}
@@ -612,8 +613,8 @@
gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
"(IZ[BI)V");
- gLargeBitmap_class = make_globalref(env, "android/graphics/LargeBitmap");
- gLargeBitmap_constructorMethodID = env->GetMethodID(gLargeBitmap_class, "<init>", "(I)V");
+ gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
+ gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V");
gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
@@ -651,4 +652,3 @@
return 0;
}
-
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 1a43a3e..d0f9125 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -4,7 +4,7 @@
#include "SkPoint.h"
#include "SkRect.h"
#include "SkBitmap.h"
-#include "../images/SkLargeBitmap.h"
+#include "../images/SkBitmapRegionDecoder.h"
#include "../images/SkImageDecoder.h"
#include <jni.h>
@@ -56,7 +56,7 @@
static jobject createRegion(JNIEnv* env, SkRegion* region);
- static jobject createLargeBitmap(JNIEnv* env, SkLargeBitmap* bitmap);
+ static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
/** Set a pixelref for the bitmap (needs setConfig to already be called)
Returns true on success. If it returns false, then it failed, and the
@@ -181,4 +181,3 @@
do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
#endif
-
diff --git a/core/jni/android/graphics/LargeBitmap.cpp b/core/jni/android/graphics/LargeBitmap.cpp
deleted file mode 100644
index 4cf5dfa..0000000
--- a/core/jni/android/graphics/LargeBitmap.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-#define LOG_TAG "LargeBitmap"
-
-#include "SkBitmap.h"
-#include "SkImageEncoder.h"
-#include "SkColorPriv.h"
-#include "GraphicsJNI.h"
-#include "SkDither.h"
-#include "SkUnPreMultiply.h"
-#include "SkUtils.h"
-#include "SkTemplates.h"
-#include "SkPixelRef.h"
-#include "BitmapFactory.h"
-#include "AutoDecodeCancel.h"
-#include "SkLargeBitmap.h"
-
-#include <binder/Parcel.h>
-#include "android_util_Binder.h"
-#include "android_nio_utils.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-
-#include <jni.h>
-
-#if 0
- #define TRACE_BITMAP(code) code
-#else
- #define TRACE_BITMAP(code)
-#endif
-
-static jobject nullObjectReturn(const char msg[]) {
- if (msg) {
- SkDebugf("--- %s\n", msg);
- }
- return NULL;
-}
-
-/*
- * nine patch not supported
- *
- * purgeable not supported
- * reportSizeToVM not supported
- */
-static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkLargeBitmap *bm,
- int start_x, int start_y, int width, int height, jobject options) {
- SkImageDecoder *decoder = bm->getDecoder();
- int sampleSize = 1;
- SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
- bool doDither = true;
-
- if (NULL != options) {
- sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
- // initialize these, in case we fail later on
- env->SetIntField(options, gOptions_widthFieldID, -1);
- env->SetIntField(options, gOptions_heightFieldID, -1);
- env->SetObjectField(options, gOptions_mimeFieldID, 0);
-
- jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
- prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
- doDither = env->GetBooleanField(options, gOptions_ditherFieldID);
- }
-
- decoder->setDitherImage(doDither);
- SkBitmap* bitmap = new SkBitmap;
- SkAutoTDelete<SkBitmap> adb(bitmap);
- AutoDecoderCancel adc(options, decoder);
-
- // To fix the race condition in case "requestCancelDecode"
- // happens earlier than AutoDecoderCancel object is added
- // to the gAutoDecoderCancelMutex linked list.
- if (NULL != options && env->GetBooleanField(options, gOptions_mCancelID)) {
- return nullObjectReturn("gOptions_mCancelID");;
- }
-
- SkIRect region;
- region.fLeft = start_x;
- region.fTop = start_y;
- region.fRight = start_x + width;
- region.fBottom = start_y + height;
-
- if (!bm->decodeRegion(bitmap, region, prefConfig, sampleSize)) {
- return nullObjectReturn("decoder->decodeRegion returned false");
- }
-
- // update options (if any)
- if (NULL != options) {
- env->SetIntField(options, gOptions_widthFieldID, bitmap->width());
- env->SetIntField(options, gOptions_heightFieldID, bitmap->height());
- // TODO: set the mimeType field with the data from the codec.
- // but how to reuse a set of strings, rather than allocating new one
- // each time?
- env->SetObjectField(options, gOptions_mimeFieldID,
- getMimeTypeString(env, decoder->getFormat()));
- }
-
- // detach bitmap from its autotdeleter, since we want to own it now
- adb.detach();
-
- SkPixelRef* pr;
- pr = bitmap->pixelRef();
- // promise we will never change our pixels (great for sharing and pictures)
- pr->setImmutable();
- // now create the java bitmap
- return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
-}
-
-static int nativeGetHeight(JNIEnv* env, jobject, SkLargeBitmap *bm) {
- return bm->getHeight();
-}
-
-static int nativeGetWidth(JNIEnv* env, jobject, SkLargeBitmap *bm) {
- return bm->getWidth();
-}
-
-static void nativeClean(JNIEnv* env, jobject, SkLargeBitmap *bm) {
- delete bm;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include <android_runtime/AndroidRuntime.h>
-
-static JNINativeMethod gLargeBitmapMethods[] = {
- { "nativeDecodeRegion",
- "(IIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
- (void*)nativeDecodeRegion},
- { "nativeGetHeight", "(I)I", (void*)nativeGetHeight},
- { "nativeGetWidth", "(I)I", (void*)nativeGetWidth},
- { "nativeClean", "(I)V", (void*)nativeClean},
-};
-
-#define kClassPathName "android/graphics/LargeBitmap"
-
-int register_android_graphics_LargeBitmap(JNIEnv* env);
-int register_android_graphics_LargeBitmap(JNIEnv* env)
-{
- return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
- gLargeBitmapMethods, SK_ARRAY_COUNT(gLargeBitmapMethods));
-}
-
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
new file mode 100644
index 0000000..b6ead19
--- /dev/null
+++ b/core/jni/android/graphics/Utils.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "Utils.h"
+#include "SkUtils.h"
+
+using namespace android;
+
+bool AssetStreamAdaptor::rewind() {
+ off_t pos = fAsset->seek(0, SEEK_SET);
+ if (pos == (off_t)-1) {
+ SkDebugf("----- fAsset->seek(rewind) failed\n");
+ return false;
+ }
+ return true;
+}
+
+size_t AssetStreamAdaptor::read(void* buffer, size_t size) {
+ ssize_t amount;
+
+ if (NULL == buffer) {
+ if (0 == size) { // caller is asking us for our total length
+ return fAsset->getLength();
+ }
+ // asset->seek returns new total offset
+ // we want to return amount that was skipped
+
+ off_t oldOffset = fAsset->seek(0, SEEK_CUR);
+ if (-1 == oldOffset) {
+ SkDebugf("---- fAsset->seek(oldOffset) failed\n");
+ return 0;
+ }
+ off_t newOffset = fAsset->seek(size, SEEK_CUR);
+ if (-1 == newOffset) {
+ SkDebugf("---- fAsset->seek(%d) failed\n", size);
+ return 0;
+ }
+ amount = newOffset - oldOffset;
+ } else {
+ amount = fAsset->read(buffer, size);
+ if (amount <= 0) {
+ SkDebugf("---- fAsset->read(%d) returned %d\n", size, amount);
+ }
+ }
+
+ if (amount < 0) {
+ amount = 0;
+ }
+ return amount;
+}
+
+jobject android::nullObjectReturn(const char msg[]) {
+ if (msg) {
+ SkDebugf("--- %s\n", msg);
+ }
+ return NULL;
+}
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
new file mode 100644
index 0000000..2de41a1
--- /dev/null
+++ b/core/jni/android/graphics/Utils.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#ifndef UTILS_DEFINED
+#define UTILS_DEFINED
+
+#include "SkStream.h"
+
+#include "android_util_Binder.h"
+
+#include <jni.h>
+#include <utils/Asset.h>
+
+namespace android {
+
+class AssetStreamAdaptor : public SkStream {
+public:
+ AssetStreamAdaptor(Asset* a) : fAsset(a) {}
+ virtual bool rewind();
+ virtual size_t read(void* buffer, size_t size);
+
+private:
+ Asset* fAsset;
+};
+
+
+/** Restore the file descriptor's offset in our destructor
+ */
+class AutoFDSeek {
+public:
+ AutoFDSeek(int fd) : fFD(fd) {
+ fCurr = ::lseek(fd, 0, SEEK_CUR);
+ }
+ ~AutoFDSeek() {
+ if (fCurr >= 0) {
+ ::lseek(fFD, fCurr, SEEK_SET);
+ }
+ }
+private:
+ int fFD;
+ off_t fCurr;
+};
+
+jobject nullObjectReturn(const char msg[]);
+
+}; // namespace android
+
+#endif
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index c5ccc43..defd0a0 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -30,6 +30,8 @@
static jboolean sScanModeActive = false;
+//TODO: check general errors in addition to overflow on snprintf
+
/*
* The following remembers the jfieldID's of the fields
* of the DhcpInfo Java object, so that we don't have
@@ -155,6 +157,36 @@
return doIntCommand("ADD_NETWORK");
}
+static jboolean android_net_wifi_wpsPbcCommand(JNIEnv* env, jobject clazz, jstring bssid)
+{
+ char cmdstr[50];
+ jboolean isCopy;
+
+ const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
+ int numWritten = snprintf(cmdstr, sizeof(cmdstr), "WPS_PBC %s", bssidStr);
+ env->ReleaseStringUTFChars(bssid, bssidStr);
+
+ if ((numWritten == -1) || (numWritten >= sizeof(cmdstr))) {
+ return false;
+ }
+ return doBooleanCommand(cmdstr, "OK");
+}
+
+static jboolean android_net_wifi_wpsPinCommand(JNIEnv* env, jobject clazz, jstring bssid, int apPin)
+{
+ char cmdstr[50];
+ jboolean isCopy;
+
+ const char *bssidStr = env->GetStringUTFChars(bssid, &isCopy);
+ int numWritten = snprintf(cmdstr, sizeof(cmdstr), "WPS_REG %s %d", bssidStr, apPin);
+ env->ReleaseStringUTFChars(bssid, bssidStr);
+
+ if ((numWritten == -1) || (numWritten >= (int)sizeof(cmdstr))) {
+ return false;
+ }
+ return doBooleanCommand(cmdstr, "OK");
+}
+
static jboolean android_net_wifi_setNetworkVariableCommand(JNIEnv* env,
jobject clazz,
jint netId,
@@ -603,7 +635,8 @@
{ "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
{ "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
{ "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
-
+ { "startWpsPbcCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_wpsPbcCommand },
+ { "startWpsPinCommand", "(Ljava/lang/String;I)Z", (void*) android_net_wifi_wpsPinCommand },
{ "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
};
diff --git a/core/res/res/values-rm/donottranslate-cldr.xml b/core/res/res/values-rm/donottranslate-cldr.xml
index 4b9f9db..ccdb17c 100644
--- a/core/res/res/values-rm/donottranslate-cldr.xml
+++ b/core/res/res/values-rm/donottranslate-cldr.xml
@@ -53,14 +53,6 @@
<string name="month_shortest_november">N</string>
<string name="month_shortest_december">D</string>
- <string name="sunday">dumengia</string>
- <string name="monday">glindesdi</string>
- <string name="tuesday">mardi</string>
- <string name="wednesday">mesemna</string>
- <string name="thursday">gievgia</string>
- <string name="friday">venderdi</string>
- <string name="saturday">sonda</string>
-
<string name="day_of_week_long_sunday">dumengia</string>
<string name="day_of_week_long_monday">glindesdi</string>
<string name="day_of_week_long_tuesday">mardi</string>
@@ -85,14 +77,6 @@
<string name="day_of_week_short_friday">ve</string>
<string name="day_of_week_short_saturday">so</string>
- <string name="day_of_week_shorter_sunday">D</string>
- <string name="day_of_week_shorter_monday">G</string>
- <string name="day_of_week_shorter_tuesday">M</string>
- <string name="day_of_week_shorter_wednesday">M</string>
- <string name="day_of_week_shorter_thursday">G</string>
- <string name="day_of_week_shorter_friday">V</string>
- <string name="day_of_week_shorter_saturday">S</string>
-
<string name="day_of_week_shortest_sunday">D</string>
<string name="day_of_week_shortest_monday">G</string>
<string name="day_of_week_shortest_tuesday">M</string>
@@ -114,12 +98,7 @@
<string name="numeric_date_format">dd.MM.yyyy</string>
<string name="numeric_date_template">"%s.%s.%s"</string>
<string name="month_day_year">%-e. %B %Y</string>
- <string name="full_date_month_first">d. MMMM y</string>
- <string name="full_date_day_first">d. MMMM y</string>
- <string name="medium_date_month_first">d. MMM y</string>
- <string name="medium_date_day_first">d. MMM y</string>
<string name="time_of_day">%H:%M:%S</string>
- <string name="status_bar_time_format">HH:mm</string>
<string name="date_and_time">%H:%M:%S %d.%m.%Y</string>
<string name="date_time">%1$s, %2$s</string>
<string name="time_date">%3$s, %1$s</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 539a986..171bb45 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -45,6 +45,8 @@
<dimen name="fastscroll_thumb_height">52dp</dimen>
<!-- Min width for a tablet device -->
<dimen name="min_xlarge_screen_width">800dp</dimen>
+ <!-- Fixed viewport margin for website content width change -->
+ <dimen name="fixed_viewport_margin">7dp</dimen>
<!-- Default height of a key in the password keyboard for alpha -->
<dimen name="password_keyboard_key_height_alpha">56dip</dimen>
<!-- Default height of a key in the password keyboard for numeric -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 95934d5..2d4de8b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1629,6 +1629,9 @@
<!-- Toast for double-tap -->
<string name="double_tap_toast">Tip: double-tap to zoom in and out.</string>
+ <!-- Text to show in the auto complete drop down list on a text view when the browser can auto fill the entire form -->
+ <string name="autofill_this_form">AutoFill this form</string>
+
<!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java
index 0f5b090..53368d4 100644
--- a/core/tests/coretests/src/android/util/Base64Test.java
+++ b/core/tests/coretests/src/android/util/Base64Test.java
@@ -16,6 +16,9 @@
package android.util;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
@@ -404,6 +407,14 @@
}
}
+ /** http://b/3026478 */
+ public void testSingleByteReads() throws IOException {
+ InputStream in = new Base64InputStream(
+ new ByteArrayInputStream("/v8=".getBytes()), Base64.DEFAULT);
+ assertEquals(254, in.read());
+ assertEquals(255, in.read());
+ }
+
/**
* Tests that Base64OutputStream produces exactly the same results
* as calling Base64.encode/.decode on an in-memory array.
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
index 0293ded..f21e7ac 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
@@ -241,7 +241,7 @@
Uri remoteUri = getExternalFileUri(filename);
Request request = new Request(remoteUri);
- request.setMediaType(getMimeMapping(DownloadFileType.APK));
+ request.setMimeType(getMimeMapping(DownloadFileType.APK));
dlRequest = mDownloadManager.enqueue(request);
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index 035ddb9..9ebed56 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -434,7 +434,7 @@
<h2 id="LayerList">Layer List</h2>
<p>A {@link android.graphics.drawable.LayerDrawable} is a drawable object
-that manages an array of other drawables. Each drawable in the list is drawn in the order of the
+that manages an array of other drawables. Each drawable in the list is drawn in the order of the
list—the last drawable in the list is drawn on top.</p>
<p>Each drawable is represented by an {@code <item>} element inside a single {@code
@@ -641,7 +641,7 @@
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
- android:state_window_focused=["true" | "false"] />
+ android:state_window_focused=["true" | "false"] />
</selector>
</pre>
</dd>
@@ -729,12 +729,12 @@
</selector>
</pre>
-<p>This layout XML applies the drawable to a View:</p>
+<p>This layout XML applies the state list drawable to a Button:</p>
<pre>
-<ImageView
+<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:src="@drawable/button" />
+ android:background="@drawable/button" />
</pre>
</dd> <!-- end example -->
@@ -1670,13 +1670,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <gradient
- android:startColor="#FFFF0000"
+ <gradient
+ android:startColor="#FFFF0000"
android:endColor="#80FF00FF"
android:angle="45"/>
- <padding android:left="7dp"
+ <padding android:left="7dp"
android:top="7dp"
- android:right="7dp"
+ android:right="7dp"
android:bottom="7dp" />
<corners android:radius="8dp" />
</shape>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index dc21a72..ea5ed6b 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -566,132 +566,6 @@
nativeSetDefaultConfig(config.nativeInt);
}
- /**
- * Create a LargeBitmap from the specified byte array.
- * Currently only the Jpeg format is supported.
- *
- * @param data byte array of compressed image data.
- * @param offset offset into data for where the decoder should begin
- * parsing.
- * @param length the number of bytes, beginning at offset, to parse
- * @param isShareable If this is true, then the LargeBitmap may keep a
- * shallow reference to the input. If this is false,
- * then the LargeBitmap will explicitly make a copy of the
- * input data, and keep that. Even if sharing is allowed,
- * the implementation may still decide to make a deep
- * copy of the input data. If an image is progressively encoded,
- * allowing sharing may degrade the decoding speed.
- * @return LargeBitmap, or null if the image data could not be decoded.
- * @throws IOException if the image format is not supported or can not be decoded.
- * @hide
- */
- public static LargeBitmap createLargeBitmap(byte[] data,
- int offset, int length, boolean isShareable) throws IOException {
- if ((offset | length) < 0 || data.length < offset + length) {
- throw new ArrayIndexOutOfBoundsException();
- }
- return nativeCreateLargeBitmap(data, offset, length, isShareable);
- }
-
- /**
- * Create a LargeBitmap from the file descriptor.
- * The position within the descriptor will not be changed when
- * this returns, so the descriptor can be used again as is.
- * Currently only the Jpeg format is supported.
- *
- * @param fd The file descriptor containing the data to decode
- * @param isShareable If this is true, then the LargeBitmap may keep a
- * shallow reference to the input. If this is false,
- * then the LargeBitmap will explicitly make a copy of the
- * input data, and keep that. Even if sharing is allowed,
- * the implementation may still decide to make a deep
- * copy of the input data. If an image is progressively encoded,
- * allowing sharing may degrade the decoding speed.
- * @return LargeBitmap, or null if the image data could not be decoded.
- * @throws IOException if the image format is not supported or can not be decoded.
- * @hide
- */
- public static LargeBitmap createLargeBitmap(
- FileDescriptor fd, boolean isShareable) throws IOException {
- return nativeCreateLargeBitmap(fd, isShareable);
- }
-
- /**
- * Create a LargeBitmap from an input stream.
- * The stream's position will be where ever it was after the encoded data
- * was read.
- * Currently only the Jpeg format is supported.
- *
- * @param is The input stream that holds the raw data to be decoded into a
- * LargeBitmap.
- * @param isShareable If this is true, then the LargeBitmap may keep a
- * shallow reference to the input. If this is false,
- * then the LargeBitmap will explicitly make a copy of the
- * input data, and keep that. Even if sharing is allowed,
- * the implementation may still decide to make a deep
- * copy of the input data. If an image is progressively encoded,
- * allowing sharing may degrade the decoding speed.
- * @return LargeBitmap, or null if the image data could not be decoded.
- * @throws IOException if the image format is not supported or can not be decoded.
- * @hide
- */
- public static LargeBitmap createLargeBitmap(InputStream is,
- boolean isShareable) throws IOException {
- // we need mark/reset to work properly in JNI
-
- if (!is.markSupported()) {
- is = new BufferedInputStream(is, 16 * 1024);
- }
-
- if (is instanceof AssetManager.AssetInputStream) {
- return nativeCreateLargeBitmap(
- ((AssetManager.AssetInputStream) is).getAssetInt(),
- isShareable);
- } else {
- // pass some temp storage down to the native code. 1024 is made up,
- // but should be large enough to avoid too many small calls back
- // into is.read(...).
- byte [] tempStorage = new byte[16 * 1024];
- return nativeCreateLargeBitmap(is, tempStorage, isShareable);
- }
- }
-
- /**
- * Create a LargeBitmap from a file path.
- * Currently only the Jpeg format is supported.
- *
- * @param pathName complete path name for the file to be decoded.
- * @param isShareable If this is true, then the LargeBitmap may keep a
- * shallow reference to the input. If this is false,
- * then the LargeBitmap will explicitly make a copy of the
- * input data, and keep that. Even if sharing is allowed,
- * the implementation may still decide to make a deep
- * copy of the input data. If an image is progressively encoded,
- * allowing sharing may degrade the decoding speed.
- * @return LargeBitmap, or null if the image data could not be decoded.
- * @throws IOException if the image format is not supported or can not be decoded.
- * @hide
- */
- public static LargeBitmap createLargeBitmap(String pathName, boolean isShareable)
- throws IOException {
- LargeBitmap bm = null;
- InputStream stream = null;
-
- try {
- stream = new FileInputStream(pathName);
- bm = createLargeBitmap(stream, isShareable);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- // do nothing here
- }
- }
- }
- return bm;
- }
-
private static native void nativeSetDefaultConfig(int nativeConfig);
private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage,
Rect padding, Options opts);
@@ -701,14 +575,4 @@
private static native Bitmap nativeDecodeByteArray(byte[] data, int offset,
int length, Options opts);
private static native byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad);
-
- private static native LargeBitmap nativeCreateLargeBitmap(
- byte[] data, int offset, int length, boolean isShareable);
- private static native LargeBitmap nativeCreateLargeBitmap(
- FileDescriptor fd, boolean isShareable);
- private static native LargeBitmap nativeCreateLargeBitmap(
- InputStream is, byte[] storage, boolean isShareable);
- private static native LargeBitmap nativeCreateLargeBitmap(
- int asset, boolean isShareable);
}
-
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
new file mode 100644
index 0000000..454eb4a
--- /dev/null
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -0,0 +1,263 @@
+/* Copyright (C) 2010 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.graphics;
+
+import android.content.res.AssetManager;
+
+import java.io.BufferedInputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * BitmapRegionDecoder can be used to decode a rectangle region from an image.
+ * BitmapRegionDecoder is particularly useful when an original image is large and
+ * you only need parts of the image.
+ *
+ * <p>To create a BitmapRegionDecoder, call newInstance(...).
+ * Given a BitmapRegionDecoder, users can call decodeRegion() repeatedly
+ * to get a decoded Bitmap of the specified region.
+ *
+ */
+public final class BitmapRegionDecoder {
+ private int mNativeBitmapRegionDecoder;
+ private boolean mRecycled;
+
+ /**
+ * Create a BitmapRegionDecoder from the specified byte array.
+ * Currently only the Jpeg format is supported.
+ *
+ * @param data byte array of compressed image data.
+ * @param offset offset into data for where the decoder should begin
+ * parsing.
+ * @param length the number of bytes, beginning at offset, to parse
+ * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
+ * shallow reference to the input. If this is false,
+ * then the BitmapRegionDecoder will explicitly make a copy of the
+ * input data, and keep that. Even if sharing is allowed,
+ * the implementation may still decide to make a deep
+ * copy of the input data. If an image is progressively encoded,
+ * allowing sharing may degrade the decoding speed.
+ * @return BitmapRegionDecoder, or null if the image data could not be decoded.
+ * @throws IOException if the image format is not supported or can not be decoded.
+ */
+ public static BitmapRegionDecoder newInstance(byte[] data,
+ int offset, int length, boolean isShareable) throws IOException {
+ if ((offset | length) < 0 || data.length < offset + length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ return nativeNewInstance(data, offset, length, isShareable);
+ }
+
+ /**
+ * Create a BitmapRegionDecoder from the file descriptor.
+ * The position within the descriptor will not be changed when
+ * this returns, so the descriptor can be used again as is.
+ * Currently only the Jpeg format is supported.
+ *
+ * @param fd The file descriptor containing the data to decode
+ * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
+ * shallow reference to the input. If this is false,
+ * then the BitmapRegionDecoder will explicitly make a copy of the
+ * input data, and keep that. Even if sharing is allowed,
+ * the implementation may still decide to make a deep
+ * copy of the input data. If an image is progressively encoded,
+ * allowing sharing may degrade the decoding speed.
+ * @return BitmapRegionDecoder, or null if the image data could not be decoded.
+ * @throws IOException if the image format is not supported or can not be decoded.
+ */
+ public static BitmapRegionDecoder newInstance(
+ FileDescriptor fd, boolean isShareable) throws IOException {
+ return nativeNewInstance(fd, isShareable);
+ }
+
+ /**
+ * Create a BitmapRegionDecoder from an input stream.
+ * The stream's position will be where ever it was after the encoded data
+ * was read.
+ * Currently only the Jpeg format is supported.
+ *
+ * @param is The input stream that holds the raw data to be decoded into a
+ * BitmapRegionDecoder.
+ * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
+ * shallow reference to the input. If this is false,
+ * then the BitmapRegionDecoder will explicitly make a copy of the
+ * input data, and keep that. Even if sharing is allowed,
+ * the implementation may still decide to make a deep
+ * copy of the input data. If an image is progressively encoded,
+ * allowing sharing may degrade the decoding speed.
+ * @return BitmapRegionDecoder, or null if the image data could not be decoded.
+ * @throws IOException if the image format is not supported or can not be decoded.
+ */
+ public static BitmapRegionDecoder newInstance(InputStream is,
+ boolean isShareable) throws IOException {
+ // we need mark/reset to work properly in JNI
+
+ if (!is.markSupported()) {
+ is = new BufferedInputStream(is, 16 * 1024);
+ }
+
+ if (is instanceof AssetManager.AssetInputStream) {
+ return nativeNewInstance(
+ ((AssetManager.AssetInputStream) is).getAssetInt(),
+ isShareable);
+ } else {
+ // pass some temp storage down to the native code. 1024 is made up,
+ // but should be large enough to avoid too many small calls back
+ // into is.read(...).
+ byte [] tempStorage = new byte[16 * 1024];
+ return nativeNewInstance(is, tempStorage, isShareable);
+ }
+ }
+
+ /**
+ * Create a BitmapRegionDecoder from a file path.
+ * Currently only the Jpeg format is supported.
+ *
+ * @param pathName complete path name for the file to be decoded.
+ * @param isShareable If this is true, then the BitmapRegionDecoder may keep a
+ * shallow reference to the input. If this is false,
+ * then the BitmapRegionDecoder will explicitly make a copy of the
+ * input data, and keep that. Even if sharing is allowed,
+ * the implementation may still decide to make a deep
+ * copy of the input data. If an image is progressively encoded,
+ * allowing sharing may degrade the decoding speed.
+ * @return BitmapRegionDecoder, or null if the image data could not be decoded.
+ * @throws IOException if the image format is not supported or can not be decoded.
+ */
+ public static BitmapRegionDecoder newInstance(String pathName,
+ boolean isShareable) throws IOException {
+ BitmapRegionDecoder decoder = null;
+ InputStream stream = null;
+
+ try {
+ stream = new FileInputStream(pathName);
+ decoder = newInstance(stream, isShareable);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // do nothing here
+ }
+ }
+ }
+ return decoder;
+ }
+
+ /* Private constructor that must receive an already allocated native
+ region decoder int (pointer).
+
+ This can be called from JNI code.
+ */
+ private BitmapRegionDecoder(int decoder) {
+ mNativeBitmapRegionDecoder = decoder;
+ mRecycled = false;
+ }
+
+ /**
+ * Decodes a rectangle region in the image specified by rect.
+ *
+ * @param rect The rectangle that specified the region to be decode.
+ * @param options null-ok; Options that control downsampling.
+ * inPurgeable is not supported.
+ * @return The decoded bitmap, or null if the image data could not be
+ * decoded.
+ */
+ public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
+ checkRecycled("decodeRegion called on recycled region decoder");
+ if (rect.left < 0 || rect.top < 0 || rect.right > getWidth()
+ || rect.bottom > getHeight())
+ throw new IllegalArgumentException("rectangle is not inside the image");
+ return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top, options);
+ }
+
+ /** Returns the original image's width */
+ public int getWidth() {
+ checkRecycled("getWidth called on recycled region decoder");
+ return nativeGetWidth(mNativeBitmapRegionDecoder);
+ }
+
+ /** Returns the original image's height */
+ public int getHeight() {
+ checkRecycled("getHeight called on recycled region decoder");
+ return nativeGetHeight(mNativeBitmapRegionDecoder);
+ }
+
+ /**
+ * Frees up the memory associated with this region decoder, and mark the
+ * region decoder as "dead", meaning it will throw an exception if decodeRegion(),
+ * getWidth() or getHeight() is called.
+ *
+ * <p>This operation cannot be reversed, so it should only be called if you are
+ * sure there are no further uses for the region decoder. This is an advanced call,
+ * and normally need not be called, since the normal GC process will free up this
+ * memory when there are no more references to this region decoder.
+ */
+ public void recycle() {
+ if (!mRecycled) {
+ nativeClean(mNativeBitmapRegionDecoder);
+ mRecycled = true;
+ }
+ }
+
+ /**
+ * Returns true if this region decoder has been recycled.
+ * If so, then it is an error to try use its method.
+ *
+ * @return true if the region decoder has been recycled
+ */
+ public final boolean isRecycled() {
+ return mRecycled;
+ }
+
+ /**
+ * Called by methods that want to throw an exception if the region decoder
+ * has already been recycled.
+ */
+ private void checkRecycled(String errorMessage) {
+ if (mRecycled) {
+ throw new IllegalStateException(errorMessage);
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ recycle();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private static native Bitmap nativeDecodeRegion(int lbm,
+ int start_x, int start_y, int width, int height,
+ BitmapFactory.Options options);
+ private static native int nativeGetWidth(int lbm);
+ private static native int nativeGetHeight(int lbm);
+ private static native void nativeClean(int lbm);
+
+ private static native BitmapRegionDecoder nativeNewInstance(
+ byte[] data, int offset, int length, boolean isShareable);
+ private static native BitmapRegionDecoder nativeNewInstance(
+ FileDescriptor fd, boolean isShareable);
+ private static native BitmapRegionDecoder nativeNewInstance(
+ InputStream is, byte[] storage, boolean isShareable);
+ private static native BitmapRegionDecoder nativeNewInstance(
+ int asset, boolean isShareable);
+}
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index b74c1f8..d36b2f1 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -69,7 +69,7 @@
int[] primitives = new int[idxCount];
mRS.nMeshGetVertices(mID, vtxIDs, vtxCount);
- mRS.nMeshGetIndices(mID, idxIDs, primitives, vtxCount);
+ mRS.nMeshGetIndices(mID, idxIDs, primitives, idxCount);
mVertexBuffers = new Allocation[vtxCount];
mIndexBuffers = new Allocation[idxCount];
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 9c67885..5ef66f3 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -31,6 +31,7 @@
#include "ProgramCache.h"
#include "PathCache.h"
#include "TextDropShadowCache.h"
+#include "Line.h"
namespace android {
namespace uirenderer {
@@ -64,6 +65,8 @@
PatchCache patchCache;
TextDropShadowCache dropShadowCache;
GammaFontRenderer fontRenderer;
+
+ Line line;
}; // class Caches
}; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index c527038..60523db 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -82,6 +82,10 @@
* Indicates whether this layer should be blended.
*/
bool blend;
+ /**
+ * Indicates that this layer has never been used before.
+ */
+ bool empty;
}; // struct Layer
}; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 39c3111..2770868 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -109,18 +109,16 @@
layer = new Layer;
layer->blend = true;
+ layer->empty = true;
glGenTextures(1, &layer->texture);
glBindTexture(GL_TEXTURE_2D, layer->texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
return layer;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 02b1425..e032085 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -133,6 +133,8 @@
OpenGLRenderer::~OpenGLRenderer() {
LOGD("Destroy OpenGLRenderer");
+ // The context has already been destroyed at this point, do not call
+ // GL APIs. All GL state should be kept in Caches.h
}
///////////////////////////////////////////////////////////////////////////////
@@ -379,8 +381,15 @@
// Copy the framebuffer into the layer
glBindTexture(GL_TEXTURE_2D, layer->texture);
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
- bounds.getWidth(), bounds.getHeight(), 0);
+
+ if (layer->empty) {
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
+ bounds.getWidth(), bounds.getHeight(), 0);
+ layer->empty = false;
+ } else {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, mHeight - bounds.bottom,
+ bounds.getWidth(), bounds.getHeight());
+ }
if (flags & SkCanvas::kClipToLayer_SaveFlag) {
if (mSnapshot->clipTransformed(bounds)) setScissorFromClip();
@@ -615,14 +624,14 @@
const bool isAA = paint->isAntiAlias();
if (isAA) {
GLuint textureUnit = 0;
- setupTextureAlpha8(mLine.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
- mode, false, true, mLine.getVertices(), mLine.getTexCoords());
+ setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
+ mode, false, true, mCaches.line.getVertices(), mCaches.line.getTexCoords());
} else {
setupColorRect(0.0f, 0.0f, 1.0f, 1.0f, r, g, b, a, mode, false);
}
const float strokeWidth = paint->getStrokeWidth();
- const GLsizei elementsCount = isAA ? mLine.getElementsCount() : gMeshCount;
+ const GLsizei elementsCount = isAA ? mCaches.line.getElementsCount() : gMeshCount;
const GLenum drawMode = isAA ? GL_TRIANGLES : GL_TRIANGLE_STRIP;
for (int i = 0; i < count; i += 4) {
@@ -630,7 +639,7 @@
float ty = 0.0f;
if (isAA) {
- mLine.update(points[i], points[i + 1], points[i + 2], points[i + 3],
+ mCaches.line.update(points[i], points[i + 1], points[i + 2], points[i + 3],
strokeWidth, tx, ty);
} else {
ty = strokeWidth <= 1.0f ? 0.0f : -strokeWidth * 0.5f;
@@ -647,7 +656,8 @@
}
mModelView.translate(tx, ty, 0.0f);
if (!isAA) {
- float length = mLine.getLength(points[i], points[i + 1], points[i + 2], points[i + 3]);
+ float length = mCaches.line.getLength(points[i], points[i + 1],
+ points[i + 2], points[i + 3]);
mModelView.scale(length, strokeWidth, 1.0f);
}
mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform);
@@ -659,7 +669,9 @@
glDrawArrays(drawMode, 0, elementsCount);
}
- glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
+ if (isAA) {
+ glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
+ }
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -956,25 +968,36 @@
}
if (underlineWidth > 0.0f) {
- float textSize = paint->getTextSize();
- float height = textSize * kStdUnderline_Thickness;
+ const float textSize = paint->getTextSize();
+ const float strokeWidth = textSize * kStdUnderline_Thickness;
- float left = x - offsetX;
+ const float left = x - offsetX;
float top = 0.0f;
- float right = left + underlineWidth;
- float bottom = 0.0f;
+
+ const int pointsCount = 4 * (flags & SkPaint::kStrikeThruText_Flag ? 2 : 1);
+ float points[pointsCount];
+ int currentPoint = 0;
if (flags & SkPaint::kUnderlineText_Flag) {
top = y + textSize * kStdUnderline_Offset;
- bottom = top + height;
- drawRect(left, top, right, bottom, paint);
+ points[currentPoint++] = left;
+ points[currentPoint++] = top;
+ points[currentPoint++] = left + underlineWidth;
+ points[currentPoint++] = top;
}
if (flags & SkPaint::kStrikeThruText_Flag) {
top = y + textSize * kStdStrikeThru_Offset;
- bottom = top + height;
- drawRect(left, top, right, bottom, paint);
+ points[currentPoint++] = left;
+ points[currentPoint++] = top;
+ points[currentPoint++] = left + underlineWidth;
+ points[currentPoint++] = top;
}
+
+ SkPaint linesPaint(*paint);
+ linesPaint.setStrokeWidth(strokeWidth);
+
+ drawLines(&points[0], pointsCount, &linesPaint);
}
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index eba0f41..f903505 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -40,7 +40,6 @@
#include "SkiaShader.h"
#include "SkiaColorFilter.h"
#include "Caches.h"
-#include "Line.h"
namespace android {
namespace uirenderer {
@@ -420,9 +419,6 @@
// List of rectangles to clear due to calls to saveLayer()
Vector<Rect*> mLayers;
- // Single object used to draw lines
- Line mLine;
-
// Misc
GLint mMaxTextureSize;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 9e1f6c2..165c0da 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -94,6 +94,11 @@
description.isBitmapNpot = true;
description.bitmapWrapS = gTileModes[mTileX];
description.bitmapWrapT = gTileModes[mTileY];
+ mWrapS = GL_CLAMP_TO_EDGE;
+ mWrapT = GL_CLAMP_TO_EDGE;
+ } else {
+ mWrapS = gTileModes[mTileX];
+ mWrapT = gTileModes[mTileY];
}
}
@@ -121,7 +126,7 @@
}
// Uniforms
- bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
+ bindTexture(texture->id, mWrapS, mWrapT, textureSlot);
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 0023c46..9f8778f 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -122,6 +122,8 @@
SkBitmap* mBitmap;
const Texture* mTexture;
+ GLenum mWrapS;
+ GLenum mWrapT;
}; // struct SkiaBitmapShader
/**
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 927070a..adf6ee2 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -159,32 +159,35 @@
return;
}
- if (!regenerate) {
- texture->generation = bitmap->getGenerationID();
- texture->width = bitmap->width();
- texture->height = bitmap->height();
+ const bool resize = !regenerate || bitmap->width() != int(texture->width) ||
+ bitmap->height() != int(texture->height);
+ if (!regenerate) {
glGenTextures(1, &texture->id);
}
+ texture->generation = bitmap->getGenerationID();
+ texture->width = bitmap->width();
+ texture->height = bitmap->height();
+
glBindTexture(GL_TEXTURE_2D, texture->id);
glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
switch (bitmap->getConfig()) {
case SkBitmap::kA8_Config:
- texture->blend = true;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, bitmap->getPixels());
+ uploadToTexture(resize, GL_ALPHA, bitmap->rowBytesAsPixels(), texture->height,
+ GL_UNSIGNED_BYTE, bitmap->getPixels());
+ texture->blend = true;
break;
case SkBitmap::kRGB_565_Config:
+ uploadToTexture(resize, GL_RGB, bitmap->rowBytesAsPixels(), texture->height,
+ GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
texture->blend = false;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
break;
case SkBitmap::kARGB_8888_Config:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
+ uploadToTexture(resize, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height,
+ GL_UNSIGNED_BYTE, bitmap->getPixels());
// Do this after calling getPixels() to make sure Skia's deferred
// decoding happened
texture->blend = !bitmap->isOpaque();
@@ -201,5 +204,14 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
+void TextureCache::uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height,
+ GLenum type, const GLvoid * data) {
+ if (resize) {
+ glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data);
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
+ }
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index a63789a..7cf66d9 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -79,6 +79,9 @@
*/
void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
+ void uploadToTexture(bool resize, GLenum format, GLsizei width, GLsizei height,
+ GLenum type, const GLvoid * data);
+
void init();
GenerationCache<SkBitmap*, Texture*> mCache;
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 31d70c7..21cbc50 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -354,10 +354,6 @@
}
-ScriptCSetScript {
- param void * codePtr
- }
-
ScriptCSetText {
param const char * text
param uint32_t length
diff --git a/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp
index 810e4ff..8e43f24 100644
--- a/libs/rs/rsMesh.cpp
+++ b/libs/rs/rsMesh.cpp
@@ -124,8 +124,6 @@
mPrimitives[ct]->mIndexBuffer->deferedUploadToBufferObject(rsc);
}
}
-
- rsc->checkError("Mesh::uploadAll");
}
void Mesh::updateGLPrimitives()
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 9817fca..8f5c653 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -78,8 +78,6 @@
mConstantColor[2] = 1.f;
mConstantColor[3] = 1.f;
- LOGE("Custom FP");
-
mTextureEnableMask = (1 << mTextureCount) -1;
init(rsc);
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index cbc5df9..4b484b1 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -67,12 +67,15 @@
ptr = mSlots[ct]->getPtr();
}
void **dest = ((void ***)mEnviroment.mFieldAddress)[ct];
- //LOGE("setupScript %i %p = %p %p %i", ct, dest, ptr, mSlots[ct]->getType(), mSlots[ct]->getType()->getDimX());
- //const uint32_t *p32 = (const uint32_t *)ptr;
- //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
- //LOGE(" %i = 0x%08x ", ct2, p32[ct2]);
- //}
+ if (rsc->props.mLogScripts) {
+ LOGV("%p ScriptC::setupScript slot=%i dst=%p src=%p type=%p", rsc, ct, dest, ptr, mSlots[ct]->getType());
+
+ //const uint32_t *p32 = (const uint32_t *)ptr;
+ //for (uint32_t ct2=0; ct2 < mSlots[ct]->getType()->getDimX(); ct2++) {
+ //LOGE(" %i = 0x%08x ", ct2, p32[ct2]);
+ //}
+ }
if (dest) {
*dest = ptr;
@@ -136,10 +139,18 @@
uint32_t ret = 0;
Script * oldTLS = setTLS(this);
- //LOGE("ScriptC::run %p", mProgram.mRoot);
+
+ if (rsc->props.mLogScripts) {
+ LOGV("%p ScriptC::run invoking root, ptr %p", rsc, mProgram.mRoot);
+ }
+
ret = mProgram.mRoot();
+
+ if (rsc->props.mLogScripts) {
+ LOGV("%p ScriptC::run invoking complete, ret=%i", rsc, ret);
+ }
+
setTLS(oldTLS);
- //LOGE("ScriptC::run ret %i", ret);
return ret;
}
@@ -325,8 +336,14 @@
setupScript(rsc);
Script * oldTLS = setTLS(this);
+ if (rsc->props.mLogScripts) {
+ LOGV("%p ScriptC::Invoke invoking slot %i, ptr %p", rsc, slot, mEnviroment.mInvokeFunctions[slot]);
+ }
((void (*)(const void *, uint32_t))
mEnviroment.mInvokeFunctions[slot])(data, len);
+ if (rsc->props.mLogScripts) {
+ LOGV("%p ScriptC::Invoke complete", rsc);
+ }
setTLS(oldTLS);
}
@@ -377,7 +394,7 @@
void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
{
- LOGV("ScriptCState::runCompiler ");
+ LOGV("%p ScriptCState::runCompiler ", rsc);
s->mBccScript = bccCreateScript();
s->mEnviroment.mIsThreadable = true;
@@ -386,7 +403,7 @@
bccCompileScript(s->mBccScript);
bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
- LOGV("root %p, init %p", s->mProgram.mRoot, s->mProgram.mInit);
+ LOGV("%p ScriptCState::runCompiler root %p, init %p", rsc, s->mProgram.mRoot, s->mProgram.mInit);
if (s->mProgram.mInit) {
s->mProgram.mInit();
@@ -407,9 +424,6 @@
s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
bccGetExportVars(s->mBccScript, NULL, s->mEnviroment.mFieldCount, (BCCvoid **) s->mEnviroment.mFieldAddress);
}
- //for (int ct2=0; ct2 < s->mEnviroment.mFieldCount; ct2++ ) {
- //LOGE("Script field %i = %p", ct2, s->mEnviroment.mFieldAddress[ct2]);
- //}
s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
@@ -491,13 +505,6 @@
ss->clear();
}
-void rsi_ScriptCSetScript(Context * rsc, void *vp)
-{
- rsAssert(0);
- //ScriptCState *ss = &rsc->mScriptC;
- //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
-}
-
void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
{
ScriptCState *ss = &rsc->mScriptC;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7469133..b97c3c4 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -963,14 +963,17 @@
//--------------------
/**
- * Attaches an auxiliary effect to the audio track. A typical auxiliary effect is a
- * reverberation effect which can be applied on any sound source that directs a certain
- * amount of its energy to this effect. This amount is defined by setAuxEffectSendLevel().
+ * Attaches an auxiliary effect to the audio track. A typical auxiliary
+ * effect is a reverberation effect which can be applied on any sound source
+ * that directs a certain amount of its energy to this effect. This amount
+ * is defined by setAuxEffectSendLevel().
* {@see #setAuxEffectSendLevel(float)}.
- * <p>After creating an auxiliary effect (e.g. {@link android.media.EnvironmentalReverb}),
- * retrieve its ID with {@link android.media.AudioEffect#getId()} and use it when calling
+ * <p>After creating an auxiliary effect (e.g.
+ * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
+ * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling
* this method to attach the audio track to the effect.
- * <p>To detach the effect from the audio track, call this method with a null effect id.
+ * <p>To detach the effect from the audio track, call this method with a
+ * null effect id.
*
* @param effectId system wide unique id of the effect to attach
* @return error code or success, see {@link #SUCCESS},
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 280def9..cb46a29 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1210,9 +1210,10 @@
* effect which can be applied on any sound source that directs a certain amount of its
* energy to this effect. This amount is defined by setAuxEffectSendLevel().
* {@see #setAuxEffectSendLevel(float)}.
- * <p>After creating an auxiliary effect (e.g. {@link android.media.EnvironmentalReverb}),
- * retrieve its ID with {@link android.media.AudioEffect#getId()} and use it when calling
- * this method to attach the player to the effect.
+ * <p>After creating an auxiliary effect (e.g.
+ * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
+ * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling this method
+ * to attach the player to the effect.
* <p>To detach the effect from the player, call this method with a null effect id.
* <p>This method must be called after one of the overloaded <code> setDataSource </code>
* methods.
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index b2a0a46..f72eaa4 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -644,8 +644,9 @@
} else if (MediaFile.isAudioFileType(mFileType)) {
map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0) ?
mArtist : MediaStore.UNKNOWN_STRING);
- map.put(Audio.Media.ALBUM_ARTIST, (mAlbumArtist != null &&
- mAlbumArtist.length() > 0) ? mAlbumArtist : null);
+// disable album artist support until MediaProvider really supports it
+// map.put(Audio.Media.ALBUM_ARTIST, (mAlbumArtist != null &&
+// mAlbumArtist.length() > 0) ? mAlbumArtist : null);
map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0) ?
mAlbum : MediaStore.UNKNOWN_STRING);
map.put(Audio.Media.COMPOSER, mComposer);
@@ -695,7 +696,7 @@
}
}
long rowId = entry.mRowId;
- if (MediaFile.isAudioFileType(mFileType) && rowId == 0) {
+ if (MediaFile.isAudioFileType(mFileType) && (rowId == 0 || mMtpObjectHandle != 0)) {
// Only set these for new entries. For existing entries, they
// may have been modified later, and we want to keep the current
// values so that custom ringtones still show up in the ringtone
@@ -927,136 +928,6 @@
c = null;
}
}
-
- // Read existing files from the audio table and update FileCacheEntry
- c = mMediaProvider.query(mAudioUri, MEDIA_PRESCAN_PROJECTION,
- where, selectionArgs, null);
- if (c != null) {
- while (c.moveToNext()) {
- long rowId = c.getLong(MEDIA_PRESCAN_ID_COLUMN_INDEX);
- String path = c.getString(MEDIA_PRESCAN_PATH_COLUMN_INDEX);
- long lastModified = c.getLong(MEDIA_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
- // Only consider entries with absolute path names.
- // This allows storing URIs in the database without the
- // media scanner removing them.
- if (path.startsWith("/")) {
- String key = path;
- if (mCaseInsensitivePaths) {
- key = path.toLowerCase();
- }
- FileCacheEntry entry = mFileCache.get(path);
- if (entry == null) {
- mFileCache.put(key, new FileCacheEntry(mAudioUri, rowId, path,
- lastModified, 0));
- } else {
- // update the entry
- entry.mTableUri = mAudioUri;
- entry.mRowId = rowId;
- }
- }
- }
- c.close();
- c = null;
- }
-
- // Read existing files from the video table and update FileCacheEntry
- c = mMediaProvider.query(mVideoUri, MEDIA_PRESCAN_PROJECTION,
- where, selectionArgs, null);
- if (c != null) {
- while (c.moveToNext()) {
- long rowId = c.getLong(MEDIA_PRESCAN_ID_COLUMN_INDEX);
- String path = c.getString(MEDIA_PRESCAN_PATH_COLUMN_INDEX);
- long lastModified = c.getLong(MEDIA_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
- // Only consider entries with absolute path names.
- // This allows storing URIs in the database without the
- // media scanner removing them.
- if (path.startsWith("/")) {
- String key = path;
- if (mCaseInsensitivePaths) {
- key = path.toLowerCase();
- }
- FileCacheEntry entry = mFileCache.get(path);
- if (entry == null) {
- mFileCache.put(key, new FileCacheEntry(mVideoUri, rowId, path,
- lastModified, 0));
- } else {
- // update the entry
- entry.mTableUri = mVideoUri;
- entry.mRowId = rowId;
- }
- }
- }
- c.close();
- c = null;
- }
-
- // Read existing files from the video table and update FileCacheEntry
- c = mMediaProvider.query(mImagesUri, MEDIA_PRESCAN_PROJECTION,
- where, selectionArgs, null);
- if (c != null) {
- while (c.moveToNext()) {
- long rowId = c.getLong(MEDIA_PRESCAN_ID_COLUMN_INDEX);
- String path = c.getString(MEDIA_PRESCAN_PATH_COLUMN_INDEX);
- long lastModified = c.getLong(MEDIA_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
- // Only consider entries with absolute path names.
- // This allows storing URIs in the database without the
- // media scanner removing them.
- if (path.startsWith("/")) {
- String key = path;
- if (mCaseInsensitivePaths) {
- key = path.toLowerCase();
- }
- FileCacheEntry entry = mFileCache.get(path);
- if (entry == null) {
- mFileCache.put(key, new FileCacheEntry(mImagesUri, rowId, path,
- lastModified, 0));
- } else {
- // update the entry
- entry.mTableUri = mImagesUri;
- entry.mRowId = rowId;
- }
- }
- }
- c.close();
- c = null;
- }
-
- if (mProcessPlaylists) {
- // Read existing files from the playlists table and update FileCacheEntry
- c = mMediaProvider.query(mPlaylistsUri, MEDIA_PRESCAN_PROJECTION,
- where, selectionArgs, null);
- if (c != null) {
- while (c.moveToNext()) {
- long rowId = c.getLong(MEDIA_PRESCAN_ID_COLUMN_INDEX);
- String path = c.getString(MEDIA_PRESCAN_PATH_COLUMN_INDEX);
- long lastModified = c.getLong(MEDIA_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
- // Only consider entries with absolute path names.
- // This allows storing URIs in the database without the
- // media scanner removing them.
- if (path.startsWith("/")) {
- String key = path;
- if (mCaseInsensitivePaths) {
- key = path.toLowerCase();
- }
- FileCacheEntry entry = mFileCache.get(path);
- if (entry == null) {
- mFileCache.put(key, new FileCacheEntry(mPlaylistsUri, rowId, path,
- lastModified, 0));
- } else {
- // update the entry
- entry.mTableUri = mPlaylistsUri;
- entry.mRowId = rowId;
- }
- }
- }
- c.close();
- c = null;
- }
- }
}
finally {
if (c != null) {
diff --git a/media/java/android/media/MtpClient.java b/media/java/android/media/MtpClient.java
index f7c0ce2..98da1f6 100644
--- a/media/java/android/media/MtpClient.java
+++ b/media/java/android/media/MtpClient.java
@@ -57,20 +57,20 @@
native_stop();
}
- public boolean deleteObject(int deviceID, int objectID) {
+ public boolean deleteObject(int deviceID, long objectID) {
return native_delete_object(deviceID, objectID);
}
- public int getParent(int deviceID, int objectID) {
+ public long getParent(int deviceID, long objectID) {
return native_get_parent(deviceID, objectID);
}
- public int getStorageID(int deviceID, int objectID) {
+ public long getStorageID(int deviceID, long objectID) {
return native_get_storage_id(deviceID, objectID);
}
// create a file descriptor for reading the contents of an object over MTP
- public ParcelFileDescriptor openFile(int deviceID, int objectID) {
+ public ParcelFileDescriptor openFile(int deviceID, long objectID) {
return native_open_file(deviceID, objectID);
}
@@ -101,8 +101,8 @@
private native final void native_finalize();
private native boolean native_start();
private native void native_stop();
- private native boolean native_delete_object(int deviceID, int objectID);
- private native int native_get_parent(int deviceID, int objectID);
- private native int native_get_storage_id(int deviceID, int objectID);
- private native ParcelFileDescriptor native_open_file(int deviceID, int objectID);
+ private native boolean native_delete_object(int deviceID, long objectID);
+ private native long native_get_parent(int deviceID, long objectID);
+ private native long native_get_storage_id(int deviceID, long objectID);
+ private native ParcelFileDescriptor native_open_file(int deviceID, long objectID);
}
diff --git a/media/java/android/media/MtpCursor.java b/media/java/android/media/MtpCursor.java
index d4142d8..b9dd03e 100644
--- a/media/java/android/media/MtpCursor.java
+++ b/media/java/android/media/MtpCursor.java
@@ -43,8 +43,8 @@
private int mQueryType;
private int mDeviceID;
- private int mStorageID;
- private int mQbjectID;
+ private long mStorageID;
+ private long mQbjectID;
/** The names of the columns in the projection */
private String[] mColumns;
@@ -54,7 +54,7 @@
private final MtpClient mClient;
- public MtpCursor(MtpClient client, int queryType, int deviceID, int storageID, int objectID,
+ public MtpCursor(MtpClient client, int queryType, int deviceID, long storageID, long objectID,
String[] projection) {
mClient = client;
@@ -220,7 +220,7 @@
private int mNativeContext;
private native final void native_setup(MtpClient client, int queryType,
- int deviceID, int storageID, int objectID, int[] columns);
+ int deviceID, long storageID, long objectID, int[] columns);
private native final void native_finalize();
private native void native_wait_for_event();
private native int native_fill_window(CursorWindow window, int startPos);
diff --git a/media/java/android/media/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
similarity index 89%
rename from media/java/android/media/AudioEffect.java
rename to media/java/android/media/audiofx/AudioEffect.java
index ed7601e..3e54627 100644
--- a/media/java/android/media/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -29,22 +29,35 @@
import java.util.UUID;
/**
- * AudioEffect is the base class for implementing audio effect control in Java
- * applications.
- * <p>Creating an AudioEffect object will create the effect engine in
- * audio framework if no instance of the same effect type exists in the
- * specified audio session. If one exists, this instance will be used.
- * <p>The application creating the AudioEffect object (or a derived class) will either
- * receive control of the effect engine or not depending on the priority
- * parameter. If priority is higher than the priority used by the current effect
- * engine owner, the control will be transfered to the new object. Otherwise
- * control will remain with the previous object. In this case, the new
- * application will be notified of changes in effect engine state or control
- * ownership by the appropiate listener.
- * <p>If the effect is to be applied to a specific AudioTrack or MediaPlayer instance,
- * the application must specify the audio session ID of that instance when calling the AudioEffect
- * constructor.
+ * AudioEffect is the base class for controlling audio effects provided by the android audio
+ * framework.
+ * <p>Applications should not use the AudioEffect class directly but one of its derived classes to
+ * control specific effects:
+ * <ul>
+ * <li> {@link android.media.audiofx.Equalizer}</li>
+ * <li> {@link android.media.audiofx.Virtualizer}</li>
+ * <li> {@link android.media.audiofx.BassBoost}</li>
+ * <li> {@link android.media.audiofx.PresetReverb}</li>
+ * <li> {@link android.media.audiofx.EnvironmentalReverb}</li>
+ * </ul>
+ * <p>If the audio effect is to be applied to a specific AudioTrack or MediaPlayer instance,
+ * the application must specify the audio session ID of that instance when creating the AudioEffect.
+ * (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions).
+ * To apply an effect to the global audio output mix, session 0 must be specified when creating the
+ * AudioEffect.
+ * <p>Creating an effect on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>Creating an AudioEffect object will create the corresponding effect engine in the audio
+ * framework if no instance of the same effect type exists in the specified audio session.
+ * If one exists, this instance will be used.
+ * <p>The application creating the AudioEffect object (or a derived class) will either receive
+ * control of the effect engine or not depending on the priority parameter. If priority is higher
+ * than the priority used by the current effect engine owner, the control will be transfered to the
+ * new object. Otherwise control will remain with the previous object. In this case, the new
+ * application will be notified of changes in effect engine state or control ownership by the
+ * appropiate listener.
*/
+
public class AudioEffect {
static {
System.loadLibrary("audioeffect_jni");
@@ -62,32 +75,38 @@
/**
* UUID for environmental reverb effect
+ * @hide
*/
public static final UUID EFFECT_TYPE_ENV_REVERB = UUID
.fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
/**
* UUID for preset reverb effect
+ * @hide
*/
public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID
.fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
/**
* UUID for equalizer effect
+ * @hide
*/
public static final UUID EFFECT_TYPE_EQUALIZER = UUID
.fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
/**
* UUID for bass boost effect
+ * @hide
*/
public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
.fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
/**
* UUID for virtualizer effect
+ * @hide
*/
public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID
.fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
/**
* Null effect UUID. Used when the UUID for effect type of
+ * @hide
*/
public static final UUID EFFECT_TYPE_NULL = UUID
.fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
@@ -95,10 +114,12 @@
/**
* State of an AudioEffect object that was not successfully initialized upon
* creation
+ * @hide
*/
public static final int STATE_UNINITIALIZED = 0;
/**
* State of an AudioEffect object that is ready to be used.
+ * @hide
*/
public static final int STATE_INITIALIZED = 1;
@@ -106,14 +127,17 @@
// frameworks/base/include/media/AudioEffect.h
/**
* Event id for engine control ownership change notification.
+ * @hide
*/
public static final int NATIVE_EVENT_CONTROL_STATUS = 0;
/**
* Event id for engine state change notification.
+ * @hide
*/
public static final int NATIVE_EVENT_ENABLED_STATUS = 1;
/**
* Event id for engine parameter change notification.
+ * @hide
*/
public static final int NATIVE_EVENT_PARAMETER_CHANGED = 2;
@@ -151,15 +175,17 @@
public static final int ERROR_DEAD_OBJECT = -7;
/**
- * The effect descriptor contains necessary information to facilitate
- * effects enumeration:<br>
+ * The effect descriptor contains information on a particular effect implemented in the
+ * audio framework:<br>
* <ul>
- * <li>mType: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
- * <li>mUuid: UUID for this particular implementation</li>
- * <li>mConnectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
- * <li>mName: human readable effect name</li>
- * <li>mImplementor: human readable effect implementor name</li>
+ * <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
+ * <li>uuid: UUID for this particular implementation</li>
+ * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
+ * <li>name: human readable effect name</li>
+ * <li>implementor: human readable effect implementor name</li>
* </ul>
+ * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects
+ * enumeration.
*/
public static class Descriptor {
@@ -168,18 +194,39 @@
public Descriptor(String type, String uuid, String connectMode,
String name, String implementor) {
- mType = UUID.fromString(type);
- mUuid = UUID.fromString(uuid);
- mConnectMode = connectMode;
- mName = name;
- mImplementor = implementor;
+ this.type = UUID.fromString(type);
+ this.uuid = UUID.fromString(uuid);
+ this.connectMode = connectMode;
+ this.name = name;
+ this.implementor = implementor;
}
- public UUID mType;
- public UUID mUuid;
- public String mConnectMode;
- public String mName;
- public String mImplementor;
+ /**
+ * Indicates the generic type of the effect (Equalizer, Bass boost ...). The UUID
+ * corresponds to the OpenSL ES Interface ID for this type of effect.
+ */
+ public UUID type;
+ /**
+ * Indicates the particular implementation of the effect in that type. Several effects
+ * can have the same type but this uuid is unique to a given implementation.
+ */
+ public UUID uuid;
+ /**
+ * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
+ * category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied
+ * to the entire audio source and usually not shared by several sources. Auxiliary effects
+ * (typically a reverberator) are applied to part of the signal (wet) and the effect output
+ * is added to the original signal (dry).
+ */
+ public String connectMode;
+ /**
+ * Human readable effect name
+ */
+ public String name;
+ /**
+ * Human readable effect implementor name
+ */
+ public String implementor;
};
/**
@@ -242,10 +289,12 @@
private OnParameterChangeListener mParameterChangeListener = null;
/**
* Lock to protect listeners updates against event notifications
+ * @hide
*/
public final Object mListenerLock = new Object();
/**
* Handler for events coming from the native code
+ * @hide
*/
public NativeEventHandler mNativeEventHandler = null;
@@ -283,6 +332,7 @@
* @throws java.lang.IllegalArgumentException
* @throws java.lang.UnsupportedOperationException
* @throws java.lang.RuntimeException
+ * @hide
*/
public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
@@ -337,7 +387,7 @@
/**
* Get the effect descriptor.
*
- * @see android.media.AudioEffect.Descriptor
+ * @see android.media.audiofx.AudioEffect.Descriptor
* @throws IllegalStateException
*/
public Descriptor getDescriptor() throws IllegalStateException {
@@ -351,7 +401,7 @@
/**
* Query all effects available on the platform. Returns an array of
- * {@link android.media.AudioEffect.Descriptor} objects
+ * {@link android.media.audiofx.AudioEffect.Descriptor} objects
*
* @throws IllegalStateException
*/
@@ -365,7 +415,11 @@
// --------------------
/**
- * Enable or disable effect engine.
+ * Enable or disable the effect.
+ * Creating an audio effect does not automatically apply this effect on the audio source. It
+ * creates the resources necessary to process this effect but the audio signal is still bypassed
+ * through the effect engine. Calling this method will make that the effect is actually applied
+ * or not to the audio content being played in the corresponding audio session.
*
* @param enabled the requested enable state
* @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
@@ -392,6 +446,7 @@
* {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or
* {@link #ERROR_DEAD_OBJECT} in case of failure
* @throws IllegalStateException
+ * @hide
*/
public int setParameter(byte[] param, byte[] value)
throws IllegalStateException {
@@ -403,6 +458,7 @@
* Set effect parameter. The parameter and its value are integers.
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int param, int value) throws IllegalStateException {
byte[] p = intToByteArray(param);
@@ -415,6 +471,7 @@
* short integer.
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int param, short value)
throws IllegalStateException {
@@ -428,6 +485,7 @@
* array of bytes.
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int param, byte[] value)
throws IllegalStateException {
@@ -440,6 +498,7 @@
* the value is also an array of 1 or 2 integers
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int[] param, int[] value)
throws IllegalStateException {
@@ -464,6 +523,7 @@
* the value is an array of 1 or 2 short integers
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int[] param, short[] value)
throws IllegalStateException {
@@ -489,6 +549,7 @@
* the value is an array of bytes
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int[] param, byte[] value)
throws IllegalStateException {
@@ -519,6 +580,7 @@
* returning, value.length is updated with the actual size of the
* returned value.
* @throws IllegalStateException
+ * @hide
*/
public int getParameter(byte[] param, byte[] value)
throws IllegalStateException {
@@ -539,6 +601,7 @@
* array of bytes.
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int param, byte[] value)
throws IllegalStateException {
@@ -552,6 +615,7 @@
* array of 1 or 2 integers
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int param, int[] value)
throws IllegalStateException {
@@ -576,6 +640,7 @@
* array of 1 or 2 short integers
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int param, short[] value)
throws IllegalStateException {
@@ -600,6 +665,7 @@
* the value is also an array of 1 or 2 integers
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int[] param, int[] value)
throws IllegalStateException {
@@ -627,6 +693,7 @@
* the value is an array of 1 or 2 short integers
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int[] param, short[] value)
throws IllegalStateException {
@@ -654,6 +721,7 @@
* the value is an array of bytes
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int[] param, byte[] value)
throws IllegalStateException {
@@ -673,6 +741,7 @@
* Send a command to the effect engine. This method is intended to send
* proprietary commands to a particular effect implementation.
*
+ * @hide
*/
public int command(int cmdCode, byte[] command, byte[] reply)
throws IllegalStateException {
@@ -709,7 +778,7 @@
}
/**
- * Returns effect engine enable state
+ * Returns effect enabled state
*
* @return true if the effect is enabled, false otherwise.
* @throws IllegalStateException
@@ -768,6 +837,7 @@
* Sets the listener AudioEffect notifies when a parameter is changed.
*
* @param listener
+ * @hide
*/
public void setParameterListener(OnParameterChangeListener listener) {
synchronized (mListenerLock) {
@@ -828,6 +898,7 @@
/**
* The OnParameterChangeListener interface defines a method called by the AudioEffect
* when a parameter is changed in the effect engine by the controlling application.
+ * @hide
*/
public interface OnParameterChangeListener {
/**
@@ -914,8 +985,7 @@
* {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
* {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
* <p>The extra value is of type int and is the audio session ID.
- *
- * @see android.media.MediaPlayer#setAudioSessionId(int)
+ * @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions.
*/
public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
@@ -1086,6 +1156,9 @@
// Utility methods
// ------------------
+ /**
+ * @hide
+ */
public void checkState(String methodName) throws IllegalStateException {
synchronized (mStateLock) {
if (mState != STATE_INITIALIZED) {
@@ -1095,6 +1168,9 @@
}
}
+ /**
+ * @hide
+ */
public void checkStatus(int status) {
switch (status) {
case AudioEffect.SUCCESS:
@@ -1110,11 +1186,17 @@
}
}
+ /**
+ * @hide
+ */
public int byteArrayToInt(byte[] valueBuf) {
return byteArrayToInt(valueBuf, 0);
}
+ /**
+ * @hide
+ */
public int byteArrayToInt(byte[] valueBuf, int offset) {
ByteBuffer converter = ByteBuffer.wrap(valueBuf);
converter.order(ByteOrder.nativeOrder());
@@ -1122,6 +1204,9 @@
}
+ /**
+ * @hide
+ */
public byte[] intToByteArray(int value) {
ByteBuffer converter = ByteBuffer.allocate(4);
converter.order(ByteOrder.nativeOrder());
@@ -1129,10 +1214,16 @@
return converter.array();
}
+ /**
+ * @hide
+ */
public short byteArrayToShort(byte[] valueBuf) {
return byteArrayToShort(valueBuf, 0);
}
+ /**
+ * @hide
+ */
public short byteArrayToShort(byte[] valueBuf, int offset) {
ByteBuffer converter = ByteBuffer.wrap(valueBuf);
converter.order(ByteOrder.nativeOrder());
@@ -1140,6 +1231,9 @@
}
+ /**
+ * @hide
+ */
public byte[] shortToByteArray(short value) {
ByteBuffer converter = ByteBuffer.allocate(2);
converter.order(ByteOrder.nativeOrder());
@@ -1148,6 +1242,9 @@
return converter.array();
}
+ /**
+ * @hide
+ */
public byte[] concatArrays(byte[]... arrays) {
int len = 0;
for (byte[] a : arrays) {
@@ -1162,5 +1259,4 @@
}
return b;
}
-
}
diff --git a/media/java/android/media/BassBoost.java b/media/java/android/media/audiofx/BassBoost.java
similarity index 94%
rename from media/java/android/media/BassBoost.java
rename to media/java/android/media/audiofx/BassBoost.java
index 476b056..ca55f0f 100644
--- a/media/java/android/media/BassBoost.java
+++ b/media/java/android/media/audiofx/BassBoost.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.util.Log;
@@ -32,15 +32,19 @@
/**
* Bass boost is an audio effect to boost or amplify low frequencies of the sound. It is comparable
* to a simple equalizer but limited to one band amplification in the low frequency range.
- * <p>An application creates a BassBoost object to instantiate and control a bass boost engine
- * in the audio framework.
+ * <p>An application creates a BassBoost object to instantiate and control a bass boost engine in
+ * the audio framework.
* <p>The methods, parameter types and units exposed by the BassBoost implementation are directly
* mapping those defined by the OpenSL ES 1.0.1 Specification (http://www.khronos.org/opensles/)
* for the SLBassBoostItf interface. Please refer to this specification for more details.
* <p>To attach the BassBoost to a particular AudioTrack or MediaPlayer, specify the audio session
- * ID of this AudioTrack or MediaPlayer when constructing the BassBoost. If the audio session ID 0
- * is specified, the BassBoost applies to the main audio output mix.
- * <p> See {@link android.media.AudioEffect} class for more details on controlling audio effects.
+ * ID of this AudioTrack or MediaPlayer when constructing the BassBoost.
+ * If the audio session ID 0 is specified, the BassBoost applies to the main audio output mix.
+ * <p>Creating a BassBoost on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
*/
public class BassBoost extends AudioEffect {
@@ -55,7 +59,7 @@
public static final int PARAM_STRENGTH_SUPPORTED = 0;
/**
* Bass boost effect strength. Parameter ID for
- * {@link android.media.BassBoost.OnParameterChangeListener}
+ * {@link android.media.audiofx.BassBoost.OnParameterChangeListener}
*/
public static final int PARAM_STRENGTH = 1;
@@ -155,7 +159,6 @@
* BassBoost engine.
* @param effect the BassBoost on which the interface is registered.
* @param status status of the set parameter operation.
- * See {@link android.media.AudioEffect#setParameter(byte[], byte[])}.
* @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ...
* @param value the new parameter value.
*/
diff --git a/media/java/android/media/EnvironmentalReverb.java b/media/java/android/media/audiofx/EnvironmentalReverb.java
similarity index 96%
rename from media/java/android/media/EnvironmentalReverb.java
rename to media/java/android/media/audiofx/EnvironmentalReverb.java
index b50febc..f1f582e 100644
--- a/media/java/android/media/EnvironmentalReverb.java
+++ b/media/java/android/media/audiofx/EnvironmentalReverb.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.util.Log;
@@ -28,18 +28,18 @@
import java.util.StringTokenizer;
/**
- * A sound generated within a room travels in many directions. The listener first hears the
- * direct sound from the source itself. Later, he or she hears discrete echoes caused by sound
- * bouncing off nearby walls, the ceiling and the floor. As sound waves arrive after
- * undergoing more and more reflections, individual reflections become indistinguishable and
- * the listener hears continuous reverberation that decays over time.
+ * A sound generated within a room travels in many directions. The listener first hears the direct
+ * sound from the source itself. Later, he or she hears discrete echoes caused by sound bouncing off
+ * nearby walls, the ceiling and the floor. As sound waves arrive after undergoing more and more
+ * reflections, individual reflections become indistinguishable and the listener hears continuous
+ * reverberation that decays over time.
* Reverb is vital for modeling a listener's environment. It can be used in music applications
* to simulate music being played back in various environments, or in games to immerse the
* listener within the game's environment.
* The EnvironmentalReverb class allows an application to control each reverb engine property in a
* global reverb environment and is more suitable for games. For basic control, more suitable for
* music applications, it is recommended to use the
- * {@link android.media.PresetReverb} class.
+ * {@link android.media.audiofx.PresetReverb} class.
* <p>An application creates a EnvironmentalReverb object to instantiate and control a reverb engine
* in the audio framework.
* <p>The methods, parameter types and units exposed by the EnvironmentalReverb implementation are
@@ -51,7 +51,9 @@
* they must be explicitely attached to it and a send level must be specified. Use the effect ID
* returned by getId() method to designate this particular effect when attaching it to the
* MediaPlayer or AudioTrack.
- * <p> See {@link android.media.AudioEffect} class for more details on controlling
+ * <p>Creating a reverb on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling
* audio effects.
*/
@@ -76,7 +78,7 @@
public static final int PARAM_DECAY_TIME = 2;
/**
* Decay HF ratio. Parameter ID for
- * {@link android.media.EnvironmentalReverb.OnParameterChangeListener}
+ * {@link android.media.audiofx.EnvironmentalReverb.OnParameterChangeListener}
*/
public static final int PARAM_DECAY_HF_RATIO = 3;
/**
@@ -444,7 +446,6 @@
* EnvironmentalReverb engine.
* @param effect the EnvironmentalReverb on which the interface is registered.
* @param status status of the set parameter operation.
- * See {@link android.media.AudioEffect#setParameter(byte[], byte[])}.
* @param param ID of the modified parameter. See {@link #PARAM_ROOM_LEVEL} ...
* @param value the new parameter value.
*/
diff --git a/media/java/android/media/Equalizer.java b/media/java/android/media/audiofx/Equalizer.java
similarity index 97%
rename from media/java/android/media/Equalizer.java
rename to media/java/android/media/audiofx/Equalizer.java
index 6fa48c5..b3bafa9 100644
--- a/media/java/android/media/Equalizer.java
+++ b/media/java/android/media/audiofx/Equalizer.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.util.Log;
@@ -41,7 +41,11 @@
* <p>To attach the Equalizer to a particular AudioTrack or MediaPlayer, specify the audio session
* ID of this AudioTrack or MediaPlayer when constructing the Equalizer. If the audio session ID 0
* is specified, the Equalizer applies to the main audio output mix.
- * <p> See {@link android.media.AudioEffect} class for more details on controlling audio effects.
+ * <p>Creating an Equalizer on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling audio
+ * effects.
*/
public class Equalizer extends AudioEffect {
@@ -68,7 +72,7 @@
public static final int PARAM_CENTER_FREQ = 3;
/**
* Band frequency range. Parameter ID for
- * {@link android.media.Equalizer.OnParameterChangeListener}
+ * {@link android.media.audiofx.Equalizer.OnParameterChangeListener}
*/
public static final int PARAM_BAND_FREQ_RANGE = 4;
/**
@@ -380,7 +384,6 @@
* Equalizer engine.
* @param effect the Equalizer on which the interface is registered.
* @param status status of the set parameter operation.
- * See {@link android.media.AudioEffect#setParameter(byte[], byte[])}.
* @param param1 ID of the modified parameter. See {@link #PARAM_BAND_LEVEL} ...
* @param param2 additional parameter qualifier (e.g the band for band level parameter).
* @param value the new parameter value.
diff --git a/media/java/android/media/PresetReverb.java b/media/java/android/media/audiofx/PresetReverb.java
similarity index 96%
rename from media/java/android/media/PresetReverb.java
rename to media/java/android/media/audiofx/PresetReverb.java
index 65175ff..7a89ae7 100644
--- a/media/java/android/media/PresetReverb.java
+++ b/media/java/android/media/audiofx/PresetReverb.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.util.Log;
@@ -40,7 +40,7 @@
* The PresetReverb class allows an application to configure the global reverb using a reverb preset.
* This is primarily used for adding some reverb in a music playback context. Applications
* requiring control over a more advanced environmental reverb are advised to use the
- * {@link android.media.EnvironmentalReverb} class.
+ * {@link android.media.audiofx.EnvironmentalReverb} class.
* <p>An application creates a PresetReverb object to instantiate and control a reverb engine in the
* audio framework.
* <p>The methods, parameter types and units exposed by the PresetReverb implementation are
@@ -52,7 +52,10 @@
* they must be explicitely attached to it and a send level must be specified. Use the effect ID
* returned by getId() method to designate this particular effect when attaching it to the
* MediaPlayer or AudioTrack.
- * <p> See {@link android.media.AudioEffect} class for more details on controlling audio effects.
+ * <p>Creating a reverb on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling
+ * audio effects.
*/
public class PresetReverb extends AudioEffect {
@@ -64,7 +67,7 @@
/**
* Preset. Parameter ID for
- * {@link android.media.PresetReverb.OnParameterChangeListener}
+ * {@link android.media.audiofx.PresetReverb.OnParameterChangeListener}
*/
public static final int PARAM_PRESET = 0;
@@ -174,7 +177,6 @@
* PresetReverb engine.
* @param effect the PresetReverb on which the interface is registered.
* @param status status of the set parameter operation.
- * See {@link android.media.AudioEffect#setParameter(byte[], byte[])}.
* @param param ID of the modified parameter. See {@link #PARAM_PRESET} ...
* @param value the new parameter value.
*/
diff --git a/media/java/android/media/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
similarity index 95%
rename from media/java/android/media/Virtualizer.java
rename to media/java/android/media/audiofx/Virtualizer.java
index b08f36e..a682a45 100644
--- a/media/java/android/media/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.util.Log;
@@ -42,7 +42,11 @@
* <p>To attach the Virtualizer to a particular AudioTrack or MediaPlayer, specify the audio session
* ID of this AudioTrack or MediaPlayer when constructing the Virtualizer. If the audio session ID 0
* is specified, the Virtualizer applies to the main audio output mix.
- * <p> See {@link android.media.AudioEffect} class for more details on controlling audio effects.
+ * <p>Creating a Virtualizer on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
+ * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling
+ * audio effects.
*/
public class Virtualizer extends AudioEffect {
@@ -56,7 +60,7 @@
public static final int PARAM_STRENGTH_SUPPORTED = 0;
/**
* Virtualizer effect strength. Parameter ID for
- * {@link android.media.Virtualizer.OnParameterChangeListener}
+ * {@link android.media.audiofx.Virtualizer.OnParameterChangeListener}
*/
public static final int PARAM_STRENGTH = 1;
@@ -156,7 +160,6 @@
* Virtualizer engine.
* @param effect the Virtualizer on which the interface is registered.
* @param status status of the set parameter operation.
- * See {@link android.media.AudioEffect#setParameter(byte[], byte[])}.
* @param param ID of the modified parameter. See {@link #PARAM_STRENGTH} ...
* @param value the new parameter value.
*/
diff --git a/media/java/android/media/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
similarity index 98%
rename from media/java/android/media/Visualizer.java
rename to media/java/android/media/audiofx/Visualizer.java
index 33222ff..0c48556 100755
--- a/media/java/android/media/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media;
+package android.media.audiofx;
import android.util.Log;
import java.lang.ref.WeakReference;
@@ -32,8 +32,8 @@
* visualized:<br>
* <ul>
* <li>If the session is 0, the audio output mix is visualized</li>
- * <li>If the session is not 0, the audio from a particular {@link MediaPlayer} or
- * {@link AudioTrack}
+ * <li>If the session is not 0, the audio from a particular {@link android.media.MediaPlayer} or
+ * {@link android.media.AudioTrack}
* using this audio session is visualized </li>
* </ul>
* <p>Two types of representation of audio content can be captured: <br>
@@ -57,6 +57,8 @@
* When data capture is not needed any more, the Visualizer should be disabled.
* <p>It is good practice to call the {@link #release()} method when the Visualizer is not used
* anymore to free up native resources associated to the Visualizer instance.
+ * <p>Creating a Visualizer on the output mix (audio session 0) requires permission
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}
*/
public class Visualizer {
diff --git a/media/java/android/media/audiofx/package.html b/media/java/android/media/audiofx/package.html
new file mode 100644
index 0000000..c6e4892
--- /dev/null
+++ b/media/java/android/media/audiofx/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Provides classes that manage audio effects implemented in the media framework.
+</BODY>
+</HTML>
diff --git a/media/jni/android_media_MtpClient.cpp b/media/jni/android_media_MtpClient.cpp
index 67740bc..d23185b 100644
--- a/media/jni/android_media_MtpClient.cpp
+++ b/media/jni/android_media_MtpClient.cpp
@@ -161,7 +161,7 @@
static jboolean
android_media_MtpClient_delete_object(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -173,9 +173,9 @@
return NULL;
}
-static jint
+static jlong
android_media_MtpClient_get_parent(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -187,9 +187,9 @@
return -1;
}
-static jint
+static jlong
android_media_MtpClient_get_storage_id(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -203,7 +203,7 @@
static jobject
android_media_MtpClient_open_file(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -240,10 +240,10 @@
{"native_finalize", "()V", (void *)android_media_MtpClient_finalize},
{"native_start", "()Z", (void *)android_media_MtpClient_start},
{"native_stop", "()V", (void *)android_media_MtpClient_stop},
- {"native_delete_object", "(II)Z", (void *)android_media_MtpClient_delete_object},
- {"native_get_parent", "(II)I", (void *)android_media_MtpClient_get_parent},
- {"native_get_storage_id", "(II)I", (void *)android_media_MtpClient_get_storage_id},
- {"native_open_file", "(II)Landroid/os/ParcelFileDescriptor;",
+ {"native_delete_object", "(IJ)Z", (void *)android_media_MtpClient_delete_object},
+ {"native_get_parent", "(IJ)J", (void *)android_media_MtpClient_get_parent},
+ {"native_get_storage_id", "(IJ)J", (void *)android_media_MtpClient_get_storage_id},
+ {"native_open_file", "(IJ)Landroid/os/ParcelFileDescriptor;",
(void *)android_media_MtpClient_open_file},
};
diff --git a/media/jni/android_media_MtpCursor.cpp b/media/jni/android_media_MtpCursor.cpp
index 6228b5d..6a65ffd 100644
--- a/media/jni/android_media_MtpCursor.cpp
+++ b/media/jni/android_media_MtpCursor.cpp
@@ -49,7 +49,7 @@
static void
android_media_MtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
- jint queryType, jint deviceID, jint storageID, jint objectID, jintArray javaColumns)
+ jint queryType, jint deviceID, jlong storageID, jlong objectID, jintArray javaColumns)
{
#ifdef HAVE_ANDROID_OS
LOGD("android_media_MtpCursor_setup queryType: %d deviceID: %d storageID: %d objectID: %d\n",
@@ -104,7 +104,7 @@
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"native_setup", "(Landroid/media/MtpClient;IIII[I)V",
+ {"native_setup", "(Landroid/media/MtpClient;IIJJ[I)V",
(void *)android_media_MtpCursor_setup},
{"native_finalize", "()V", (void *)android_media_MtpCursor_finalize},
{"native_fill_window", "(Landroid/database/CursorWindow;I)I",
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 8d9f4fe..b16372d 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -37,7 +37,7 @@
#define AUDIOEFFECT_ERROR_DEAD_OBJECT -7
// ----------------------------------------------------------------------------
-static const char* const kClassPathName = "android/media/AudioEffect";
+static const char* const kClassPathName = "android/media/audiofx/AudioEffect";
struct fields_t {
// these fields provide access from C++ to the...
@@ -228,9 +228,9 @@
return;
}
- clazz = env->FindClass("android/media/AudioEffect$Descriptor");
+ clazz = env->FindClass("android/media/audiofx/AudioEffect$Descriptor");
if (clazz == NULL) {
- LOGE("Can't find android/media/AudioEffect$Descriptor class");
+ LOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class");
return;
}
fields.clazzDesc = (jclass)env->NewGlobalRef(clazz);
@@ -241,7 +241,7 @@
"<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (fields.midDescCstor == NULL) {
- LOGE("Can't find android/media/AudioEffect$Descriptor class constructor");
+ LOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class constructor");
return;
}
}
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 31119f8..7b271ce 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -40,7 +40,7 @@
#define NATIVE_EVENT_FFT_CAPTURE 1
// ----------------------------------------------------------------------------
-static const char* const kClassPathName = "android/media/Visualizer";
+static const char* const kClassPathName = "android/media/audiofx/Visualizer";
struct fields_t {
// these fields provide access from C++ to the...
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1b2be41..7a29bd2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -999,7 +999,10 @@
status_t err = mOMX->getParameter(
mNode, OMX_IndexParamVideoErrorCorrection,
&errorCorrectionType, sizeof(errorCorrectionType));
- CHECK_EQ(err, OK);
+ if (err != OK) {
+ LOGW("Error correction param query is not supported");
+ return OK; // Optional feature. Ignore this failure
+ }
errorCorrectionType.bEnableHEC = OMX_FALSE;
errorCorrectionType.bEnableResync = OMX_TRUE;
@@ -1010,7 +1013,11 @@
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoErrorCorrection,
&errorCorrectionType, sizeof(errorCorrectionType));
- CHECK_EQ(err, OK);
+ if (err != OK) {
+ LOGW("Error correction param configuration is not supported");
+ }
+
+ // Optional feature. Ignore the failure.
return OK;
}
@@ -1108,8 +1115,8 @@
// Check profile and level parameters
CodecProfileLevel defaultProfileLevel, profileLevel;
- defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline;
- defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45;
+ defaultProfileLevel.mProfile = h263type.eProfile;
+ defaultProfileLevel.mLevel = h263type.eLevel;
err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
if (err != OK) return err;
h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
@@ -1165,8 +1172,8 @@
// Check profile and level parameters
CodecProfileLevel defaultProfileLevel, profileLevel;
- defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple;
- defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2;
+ defaultProfileLevel.mProfile = mpeg4type.eProfile;
+ defaultProfileLevel.mLevel = mpeg4type.eLevel;
err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
if (err != OK) return err;
mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 7483d60..3c0b736 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -232,6 +232,53 @@
}
}
+MediaBuffer *AVCDecoder::drainOutputBuffer() {
+ int32_t index;
+ int32_t Release;
+ AVCFrameIO Output;
+ Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
+ AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
+
+ if (status != AVCDEC_SUCCESS) {
+ LOGV("PVAVCDecGetOutput returned error %d", status);
+ return NULL;
+ }
+
+ CHECK(index >= 0);
+ CHECK(index < (int32_t)mFrames.size());
+
+ MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (!skipFrame) {
+ mbuf->set_range(0, mbuf->size());
+ mbuf->add_ref();
+
+ return mbuf;
+ }
+
+ return new MediaBuffer(0);
+}
+
status_t AVCDecoder::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
@@ -279,7 +326,8 @@
seekOptions.clearSeekTo();
if (err != OK) {
- return err;
+ *out = drainOutputBuffer();
+ return (*out == NULL) ? err : (status_t)OK;
}
if (mInputBuffer->range_length() > 0) {
@@ -415,51 +463,12 @@
fragSize);
if (res == AVCDEC_PICTURE_OUTPUT_READY) {
- int32_t index;
- int32_t Release;
- AVCFrameIO Output;
- Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-
- AVCDec_Status status =
- PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
- if (status != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecGetOutput returned error %d", status);
+ MediaBuffer *mbuf = drainOutputBuffer();
+ if (mbuf == NULL) {
break;
}
- CHECK(index >= 0);
- CHECK(index < (int32_t)mFrames.size());
-
- MediaBuffer *mbuf = mFrames.editItemAt(index);
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- int64_t timeUs;
- CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (!skipFrame) {
- *out = mbuf;
- (*out)->set_range(0, (*out)->size());
- (*out)->add_ref();
- } else {
- *out = new MediaBuffer(0);
- }
+ *out = mbuf;
// Do _not_ release input buffer yet.
@@ -496,6 +505,7 @@
case AVC_NALTYPE_AUD:
case AVC_NALTYPE_FILL:
+ case AVC_NALTYPE_EOSEQ:
{
*out = new MediaBuffer(0);
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 898c90a..eb3b142 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -82,6 +82,8 @@
void releaseFrames();
+ MediaBuffer *drainOutputBuffer();
+
AVCDecoder(const AVCDecoder &);
AVCDecoder &operator=(const AVCDecoder &);
};
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index fcf506d..4f28855 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
+ sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
IOMX::node_id node;
status_t err =
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
index 33d2976..1d81129 100644
--- a/media/tests/CameraBrowser/Android.mk
+++ b/media/tests/CameraBrowser/Android.mk
@@ -1,6 +1,8 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := CameraBrowser
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
index 329aa40..6d34fd4 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
@@ -44,8 +44,8 @@
private Cursor mCursor;
private ObjectCursorAdapter mAdapter;
private int mDeviceID;
- private int mStorageID;
- private int mObjectID;
+ private long mStorageID;
+ private long mObjectID;
private static final String[] OBJECT_COLUMNS =
new String[] { Mtp.Object._ID, Mtp.Object.NAME, Mtp.Object.FORMAT, Mtp.Object.THUMB };
@@ -65,8 +65,8 @@
super.onResume();
mDeviceID = getIntent().getIntExtra("device", 0);
- mStorageID = getIntent().getIntExtra("storage", 0);
- mObjectID = getIntent().getIntExtra("object", 0);
+ mStorageID = getIntent().getLongExtra("storage", 0);
+ mObjectID = getIntent().getLongExtra("object", 0);
if (mDeviceID != 0 && mStorageID != 0) {
Cursor c;
Uri uri;
@@ -88,7 +88,7 @@
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
- int rowID = (int)mAdapter.getItemId(position);
+ long rowID = mAdapter.getItemId(position);
Cursor c = getContentResolver().query(
Mtp.Object.getContentUri(mDeviceID, rowID),
OBJECT_COLUMNS, null, null, null);
@@ -111,7 +111,7 @@
Intent intent = new Intent(this, ObjectViewer.class);
intent.putExtra("device", mDeviceID);
intent.putExtra("storage", mStorageID);
- intent.putExtra("object",rowID);
+ intent.putExtra("object", rowID);
startActivity(intent);
}
}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
index 408f15e..5899bc1 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
@@ -51,8 +51,8 @@
private static final String TAG = "ObjectViewer";
private int mDeviceID;
- private int mStorageID;
- private int mObjectID;
+ private long mStorageID;
+ private long mObjectID;
private static final String[] OBJECT_COLUMNS =
new String[] { Mtp.Object._ID,
@@ -84,8 +84,8 @@
super.onResume();
mDeviceID = getIntent().getIntExtra("device", 0);
- mStorageID = getIntent().getIntExtra("storage", 0);
- mObjectID = getIntent().getIntExtra("object", 0);
+ mStorageID = getIntent().getLongExtra("storage", 0);
+ mObjectID = getIntent().getLongExtra("object", 0);
if (mDeviceID != 0 && mObjectID != 0) {
Cursor c = getContentResolver().query(
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
index 6ddf4e7..63e036e 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
@@ -70,7 +70,7 @@
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, ObjectBrowser.class);
intent.putExtra("device", mDeviceID);
- intent.putExtra("storage", (int)mAdapter.getItemId(position));
+ intent.putExtra("storage", mAdapter.getItemId(position));
startActivity(intent);
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
index d339e06..4e4df3b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
@@ -16,7 +16,7 @@
package com.android.mediaframeworktest.functional;
-import android.media.Visualizer;
+import android.media.audiofx.Visualizer;
import android.util.Log;
/**
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java
index fd939ae..34025f69e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java
@@ -19,12 +19,12 @@
import com.android.mediaframeworktest.MediaFrameworkTest;
import com.android.mediaframeworktest.MediaNames;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
-import android.media.EnvironmentalReverb;
-import android.media.Equalizer;
+import android.media.audiofx.EnvironmentalReverb;
+import android.media.audiofx.Equalizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -103,14 +103,14 @@
boolean hasEnvReverb = false;
for (int i = 0; i < desc.length; i++) {
- if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
+ if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
hasEQ = true;
- } if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
+ } if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
hasBassBoost = true;
- } else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
+ } else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
hasVirtualizer = true;
}
- else if (desc[i].mType.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
+ else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
hasEnvReverb = true;
}
}
@@ -132,7 +132,7 @@
AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
assertTrue(msg+": no effects found", (desc.length != 0));
try {
- AudioEffect effect = new AudioEffect(desc[0].mType,
+ AudioEffect effect = new AudioEffect(desc[0].type,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
@@ -146,7 +146,7 @@
effect.release();
}
} catch (IllegalArgumentException e) {
- msg = msg.concat(": Effect not found: "+desc[0].mName);
+ msg = msg.concat(": Effect not found: "+desc[0].name);
result = false;
} catch (UnsupportedOperationException e) {
msg = msg.concat(": Effect library not loaded");
@@ -164,13 +164,13 @@
assertTrue(msg+"no effects found", (desc.length != 0));
try {
AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_NULL,
- desc[0].mUuid,
+ desc[0].uuid,
0,
0);
assertNotNull(msg + ": could not create AudioEffect", effect);
effect.release();
} catch (IllegalArgumentException e) {
- msg = msg.concat(": Effect not found: "+desc[0].mName);
+ msg = msg.concat(": Effect not found: "+desc[0].name);
result = false;
} catch (UnsupportedOperationException e) {
msg = msg.concat(": Effect library not loaded");
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
index aca729e..aa5c4d7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
@@ -20,10 +20,10 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.BassBoost;
-import android.media.Visualizer;
+import android.media.audiofx.BassBoost;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -45,6 +45,7 @@
private String TAG = "MediaBassBoostTest";
private final static int MIN_ENERGY_RATIO_2 = 3;
private final static short TEST_STRENGTH = 500;
+ private final static int TEST_VOLUME = 4;
private BassBoost mBassBoost = null;
private int mSession = -1;
@@ -192,7 +193,7 @@
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
- am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ TEST_VOLUME,
0);
try {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
index db0db70..ba202a7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -20,10 +20,10 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.EnvironmentalReverb;
-import android.media.Visualizer;
+import android.media.audiofx.EnvironmentalReverb;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -414,13 +414,13 @@
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -433,11 +433,24 @@
mp = new MediaPlayer();
mp.setDataSource(MediaNames.SINE_200_1000);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
- getReverb(mp.getAudioSessionId());
- mReverb.setRoomLevel((short)0);
- mReverb.setReverbLevel((short)0);
- mReverb.setDecayTime(2000);
- mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of EnvironmentalReverb constructor otherwise an
+ // auxiliary reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(EnvironmentalReverb.PARAM_ROOM_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_REVERB_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_DECAY_TIME, 2000);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -460,13 +473,15 @@
loge(msg, "sleep() interrupted");
}
finally {
- releaseReverb();
if (mp != null) {
mp.release();
}
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
index 7b3945d..9146fb8 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
@@ -20,10 +20,10 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.Equalizer;
-import android.media.Visualizer;
+import android.media.audiofx.Equalizer;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -48,6 +48,7 @@
private final static int MAX_BAND_LEVEL = 1500;
private final static int TEST_FREQUENCY_MILLIHERTZ = 1000000;
private final static int MIN_NUMBER_OF_PRESETS = 4;
+ private final static int TEST_VOLUME = 4;
private Equalizer mEqualizer = null;
private int mSession = -1;
@@ -259,7 +260,7 @@
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
- am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ TEST_VOLUME,
0);
try {
probe = new EnergyProbe(0);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
index c14319a..242e6bb 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -20,10 +20,10 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.PresetReverb;
-import android.media.Visualizer;
+import android.media.audiofx.PresetReverb;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -257,13 +257,13 @@
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -279,6 +279,22 @@
getReverb(mp.getAudioSessionId());
mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
+ // reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -308,6 +324,9 @@
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
index 517d575..7a35429 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
@@ -20,10 +20,10 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.Virtualizer;
-import android.media.Visualizer;
+import android.media.audiofx.Virtualizer;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
@@ -45,6 +45,7 @@
private String TAG = "MediaVirtualizerTest";
private final static int MIN_ENERGY_RATIO_2 = 3;
private final static short TEST_STRENGTH = 500;
+ private final static int TEST_VOLUME = 4;
private Virtualizer mVirtualizer = null;
private int mSession = -1;
@@ -193,7 +194,7 @@
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
- am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+ TEST_VOLUME,
0);
try {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java
index 26fdbfe..542ca8d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java
@@ -20,9 +20,9 @@
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.AudioEffect;
+import android.media.audiofx.AudioEffect;
import android.media.AudioManager;
-import android.media.Visualizer;
+import android.media.audiofx.Visualizer;
import android.media.MediaPlayer;
import android.os.Looper;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 66f9e2d..d99fc1e 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -453,6 +453,12 @@
}
}
+// Always return GL_INVALID_OPERATION from glGetError() when called from
+// a thread without a bound context.
+static GLenum gl_no_context_glGetError() {
+ return GL_INVALID_OPERATION;
+}
+
static void early_egl_init(void)
{
#if !USE_FAST_TLS_KEY
@@ -463,6 +469,9 @@
(uint32_t*)(void*)&gHooksNoContext,
addr,
sizeof(gHooksNoContext));
+
+ gHooksNoContext.gl.glGetError = gl_no_context_glGetError;
+
setGlThreadSpecific(&gHooksNoContext);
}
@@ -1365,16 +1374,18 @@
EGLint eglGetError(void)
{
EGLint result = EGL_SUCCESS;
+ EGLint err;
for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) {
- EGLint err = EGL_SUCCESS;
+ err = EGL_SUCCESS;
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso)
err = cnx->egl.eglGetError();
if (err!=EGL_SUCCESS && result==EGL_SUCCESS)
result = err;
}
+ err = getError();
if (result == EGL_SUCCESS)
- result = getError();
+ result = err;
return result;
}
@@ -1816,16 +1827,16 @@
{
EGLContext ctx = eglGetCurrentContext();
ContextRef _c(ctx);
- if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+ if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR);
if (!validate_display_context(dpy, ctx))
- return EGL_NO_IMAGE_KHR;
+ return EGL_NO_SYNC_KHR;
egl_display_t const * const dp = get_display(dpy);
egl_context_t * const c = get_context(ctx);
- EGLSyncKHR result = EGL_NO_IMAGE_KHR;
+ EGLSyncKHR result = EGL_NO_SYNC_KHR;
if (c->cnx->egl.eglCreateSyncKHR) {
EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR(
dp->disp[c->impl].dpy, type, attrib_list);
- if (sync == EGL_NO_IMAGE_KHR)
+ if (sync == EGL_NO_SYNC_KHR)
return sync;
result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync);
}
diff --git a/opengl/tests/testLatency/Android.mk b/opengl/tests/testLatency/Android.mk
new file mode 100644
index 0000000..96417c7
--- /dev/null
+++ b/opengl/tests/testLatency/Android.mk
@@ -0,0 +1,20 @@
+#########################################################################
+# Test end-to-end latency.
+#########################################################################
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SDK_VERSION := 8
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := TestLatency
+
+include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testLatency/AndroidManifest.xml b/opengl/tests/testLatency/AndroidManifest.xml
new file mode 100644
index 0000000..741266e
--- /dev/null
+++ b/opengl/tests/testLatency/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.testlatency">
+ <uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8" />
+
+ <application
+ android:label="@string/testLatency_activity">
+ <activity android:name="TestLatencyActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:launchMode="singleTask"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/opengl/tests/testLatency/res/values/strings.xml b/opengl/tests/testLatency/res/values/strings.xml
new file mode 100644
index 0000000..0309991
--- /dev/null
+++ b/opengl/tests/testLatency/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, 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.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="testLatency_activity">TestLatency</string>
+
+</resources>
+
diff --git a/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java
new file mode 100644
index 0000000..ed993cb
--- /dev/null
+++ b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package com.android.testlatency;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.io.File;
+
+
+public class TestLatencyActivity extends Activity {
+
+ TestLatencyView mView;
+
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mView = new TestLatencyView(getApplication());
+ setContentView(mView);
+ mView.setFocusableInTouchMode(true);
+ }
+
+ @Override protected void onPause() {
+ super.onPause();
+ mView.onPause();
+ }
+
+ @Override protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+}
diff --git a/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java
new file mode 100644
index 0000000..d62bf17
--- /dev/null
+++ b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2009 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 com.android.testlatency;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying an OpenGL animation. This allows the animation to run in a
+ * separate thread, without requiring that it be driven by the update mechanism
+ * of the view hierarchy.
+ *
+ * The application-specific rendering code is delegated to a GLView.Renderer
+ * instance.
+ */
+class TestLatencyView extends GLSurfaceView {
+ private static String TAG = "TestLatencyiew";
+ private float mX;
+ private float mY;
+ private float mDX;
+ private float mDY;
+ private long mT;
+ private long mDT;
+
+ public TestLatencyView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ setRenderer(new Renderer());
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ float x = event.getX();
+ float y = event.getY();
+ long t = event.getEventTime();
+ synchronized(this) {
+ mDT = t - mT;
+ mT = t;
+ mDX = x - mX;
+ mX = x;
+ mDY = y - mY;
+ mY = y;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ private class Renderer implements GLSurfaceView.Renderer {
+ private float mScaleX, mScaleY, mOffsetX, mOffsetY;
+ private final float MS_PER_FRAME = 1000 / 60;
+ public Renderer() {
+ mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ }
+
+
+ public void onDrawFrame(GL10 gl) {
+ GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
+ GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+ GLES20.glUseProgram(mProgram);
+ checkGlError("glUseProgram");
+
+ float x, y, dx, dy;
+ long t, dt;
+ synchronized(TestLatencyView.this) {
+ x = mX;
+ y = mY;
+ dx = mDX;
+ dy = mDY;
+ dt = mDT;
+ }
+
+ if (dt > 0) {
+ dx = dx * MS_PER_FRAME / dt;
+ dy = dy * MS_PER_FRAME / dt;
+ }
+
+ GLES20.glEnableVertexAttribArray(mvPositionHandle);
+ checkGlError("glEnableVertexAttribArray");
+ GLES20.glEnableVertexAttribArray(mvColorHandle);
+ checkGlError("glEnableVertexAttribArray");
+ for(int step = 0; step < 8; step++) {
+ float sx = (x + dx * step) * mScaleX + mOffsetX;
+ float sy = (y + dy * step) * mScaleY + mOffsetY;
+ int cbase = step * 4;
+
+ for (int i = 0; i < mTriangleVerticesData.length; i += 6) {
+ mTriangleVerticesData2[i] = sx + mTriangleVerticesData[i];
+ mTriangleVerticesData2[i+1] = -sy + mTriangleVerticesData[i+1];
+ mTriangleVerticesData2[i+2] = mColors[cbase];
+ mTriangleVerticesData2[i+3] = mColors[cbase+1];
+ mTriangleVerticesData2[i+4] = mColors[cbase+2];
+ mTriangleVerticesData2[i+5] = mColors[cbase+3];
+ }
+ mTriangleVertices.position(0);
+ mTriangleVertices.put(mTriangleVerticesData2).position(0);
+
+ GLES20.glVertexAttribPointer(mvPositionHandle, 2, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
+ checkGlError("glVertexAttribPointer mvPosition");
+ mTriangleVertices.put(mTriangleVerticesData2).position(2);
+ GLES20.glVertexAttribPointer(mvColorHandle, 4, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
+ checkGlError("glVertexAttribPointer mvColor");
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
+ checkGlError("glDrawArrays");
+ }
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ GLES20.glViewport(0, 0, width, height);
+ mScaleX = 2.0f / width;
+ mScaleY = 2.0f / height;
+ mOffsetX = -1f;
+ mOffsetY = -1f;
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mProgram = createProgram(mVertexShader, mFragmentShader);
+ if (mProgram == 0) {
+ return;
+ }
+ mvPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+ checkGlError("glGetAttribLocation");
+ if (mvPositionHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for vPosition");
+ }
+ mvColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
+ checkGlError("glGetAttribLocation");
+ if (mvColorHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for vColor");
+ }
+ }
+
+ private int loadShader(int shaderType, String source) {
+ int shader = GLES20.glCreateShader(shaderType);
+ if (shader != 0) {
+ GLES20.glShaderSource(shader, source);
+ GLES20.glCompileShader(shader);
+ int[] compiled = new int[1];
+ GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+ if (compiled[0] == 0) {
+ Log.e(TAG, "Could not compile shader " + shaderType + ":");
+ Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+ GLES20.glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ return shader;
+ }
+
+ private int createProgram(String vertexSource, String fragmentSource) {
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+ if (vertexShader == 0) {
+ return 0;
+ }
+
+ int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+ if (pixelShader == 0) {
+ return 0;
+ }
+
+ int program = GLES20.glCreateProgram();
+ if (program != 0) {
+ GLES20.glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader vertexShader");
+ GLES20.glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader pixelShader");
+ GLES20.glLinkProgram(program);
+ int[] linkStatus = new int[1];
+ GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+ if (linkStatus[0] != GLES20.GL_TRUE) {
+ Log.e(TAG, "Could not link program: ");
+ Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+ GLES20.glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+ }
+
+ private void checkGlError(String op) {
+ int error;
+ while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+ Log.e(TAG, op + ": glError " + error);
+ throw new RuntimeException(op + ": glError " + error);
+ }
+ }
+
+ // X, Y, R G B A
+ private final float[] mTriangleVerticesData = {
+ -0.025f, 0.3f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.025f, 0.3f, 1.0f, 1.0f, 255.0f, 1.0f
+ };
+
+ // Color cascade:
+ private final float[] mColors = {
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.5f, 0.0f, 1.0f,
+ 0.5f, 0.5f, 0.0f, 1.0f,
+
+ 0.0f, 0.0f, 0.5f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f
+ };
+
+ private float[] mTriangleVerticesData2 = new float[mTriangleVerticesData.length];
+ private FloatBuffer mTriangleVertices;
+
+ private final String mVertexShader = "attribute vec4 aPosition;\n"
+ + "attribute vec4 aColor;\n"
+ + "varying vec4 vColor;\n"
+ + "void main() {\n"
+ + " gl_Position = aPosition;\n"
+ + " vColor = aColor;\n"
+ + "}\n";
+
+ private final String mFragmentShader = "precision mediump float;\n"
+ + "varying vec4 vColor;\n"
+ + "void main() {\n"
+ + " gl_FragColor = vColor;\n"
+ + "}\n";
+
+ private int mProgram;
+ private int mvPositionHandle;
+ private int mvColorHandle;
+
+ }
+}
+
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 43bb26a..3980189 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -3,16 +3,16 @@
/**
* Copyright (c) 2009, 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
+ * 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
+ * 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
+ * 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.
*/
-->
@@ -24,6 +24,7 @@
<string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string>
<string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi</string>
<bool name="def_auto_time">true</bool>
+ <bool name="def_auto_time_zone">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
<integer name="def_screen_brightness">102</integer>
@@ -31,12 +32,12 @@
<fraction name="def_window_animation_scale">100%</fraction>
<fraction name="def_window_transition_scale">100%</fraction>
<bool name="def_haptic_feedback">true</bool>
-
+
<bool name="def_bluetooth_on">false</bool>
<bool name="def_install_non_market_apps">false</bool>
- <!-- Comma-separated list of location providers.
+ <!-- Comma-separated list of location providers.
Network location is off by default because it requires
- user opt-in via Setup Wizard or Settings.
+ user opt-in via Setup Wizard or Settings.
-->
<string name="def_location_providers_allowed" translatable="false">gps</string>
<bool name="assisted_gps_enabled">true</bool>
@@ -45,11 +46,11 @@
<bool name="def_usb_mass_storage_enabled">true</bool>
<bool name="def_wifi_on">false</bool>
<bool name="def_networks_available_notification_on">true</bool>
-
+
<bool name="def_backup_enabled">false</bool>
<string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string>
- <!-- Default value for whether or not to pulse the notification LED when there is a
+ <!-- Default value for whether or not to pulse the notification LED when there is a
pending notification -->
<bool name="def_notification_pulse">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 8eb3fe6..9ac832b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,6 +16,15 @@
package com.android.providers.settings;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@@ -36,14 +45,6 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
@@ -60,7 +61,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 58;
+ private static final int DATABASE_VERSION = 59;
private Context mContext;
@@ -757,6 +758,23 @@
upgradeVersion = 58;
}
+ if (upgradeVersion == 58) {
+ /* Add default for new Auto Time Zone */
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 59;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1067,7 +1085,10 @@
loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
R.bool.def_auto_time); // Sync time to NITZ
-
+
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+
loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
R.integer.def_screen_brightness);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index 0fc092e..0309430 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -844,7 +844,7 @@
int[] iconList;
// Display signal strength while in "emergency calls only" mode
- if (!hasService() && !mServiceState.isEmergencyOnly()) {
+ if (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly())) {
//Slog.d(TAG, "updateSignalStrength: no service");
if (Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) == 1) {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 886c25b..56de765 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -4656,13 +4656,25 @@
{
Mutex::Autolock _l(mLock);
+ // check audio settings permission for global effects
+ if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
+ // that can only be created by audio policy manager (running in same process)
+ if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE && getpid() != pid) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
// check recording permission for visualizer
- if (memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
- memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) {
- if (!recordingAllowed()) {
- lStatus = PERMISSION_DENIED;
- goto Exit;
- }
+ if ((memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
+ memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) &&
+ !recordingAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
}
if (!EffectIsNullUuid(&pDesc->uuid)) {
@@ -4727,14 +4739,6 @@
goto Exit;
}
- // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
- // that can only be created by audio policy manager (running in same process)
- if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE &&
- getpid() != pid) {
- lStatus = INVALID_OPERATION;
- goto Exit;
- }
-
// return effect descriptor
memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java
index 14b7d3e..9829f9a 100644
--- a/services/java/com/android/server/DropBoxManagerService.java
+++ b/services/java/com/android/server/DropBoxManagerService.java
@@ -36,6 +36,7 @@
import com.android.internal.os.IDropBoxManagerService;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -179,7 +180,10 @@
// the data in uncompressed form.
temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
- output = new FileOutputStream(temp);
+ int bufferSize = mBlockSize;
+ if (bufferSize > 4096) bufferSize = 4096;
+ if (bufferSize < 512) bufferSize = 512;
+ output = new BufferedOutputStream(new FileOutputStream(temp), bufferSize);
if (read == buffer.length && ((flags & DropBoxManager.IS_GZIPPED) == 0)) {
output = new GZIPOutputStream(output);
flags = flags | DropBoxManager.IS_GZIPPED;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 9efc708..675760f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -61,18 +61,21 @@
import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Settings.Secure;
+import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.EventLog;
+import android.util.Pair;
import android.util.Slog;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.view.IWindowManager;
import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodSubtype;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -93,6 +96,7 @@
static final String TAG = "InputManagerService";
static final int MSG_SHOW_IM_PICKER = 1;
+ static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
static final int MSG_UNBIND_INPUT = 1000;
static final int MSG_BIND_INPUT = 1010;
@@ -109,6 +113,8 @@
static final long TIME_TO_RECONNECT = 10*1000;
+ private static final int NOT_A_SUBTYPE_ID = -1;
+
final Context mContext;
final Handler mHandler;
final SettingsObserver mSettingsObserver;
@@ -224,6 +230,12 @@
String mCurId;
/**
+ * The current subtype of the current input method.
+ */
+ private InputMethodSubtype mCurrentSubtype;
+
+
+ /**
* Set to true if our ServiceConnection is currently actively bound to
* a service (whether or not we have gotten its IBinder back yet).
*/
@@ -292,6 +304,7 @@
AlertDialog mSwitchingDialog;
InputMethodInfo[] mIms;
CharSequence[] mItems;
+ int[] mSubtypeIds;
class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler) {
@@ -299,6 +312,8 @@
ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
}
@Override public void onChange(boolean selfChange) {
@@ -351,9 +366,9 @@
if (!doit) {
return true;
}
-
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD, "");
+ resetSelectedInputMethodSubtype();
chooseNewDefaultIMELocked();
return true;
}
@@ -409,16 +424,15 @@
if (!chooseNewDefaultIMELocked()) {
changed = true;
curIm = null;
- curInputMethodId = "";
Slog.i(TAG, "Unsetting current input method");
Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD,
- curInputMethodId);
+ Settings.Secure.DEFAULT_INPUT_METHOD, "");
+ resetSelectedInputMethodSubtype();
}
}
}
}
-
+
if (curIm == null) {
// We currently don't have a default input method... is
// one now available?
@@ -509,6 +523,7 @@
if (defIm != null) {
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD, defIm.getId());
+ putSelectedInputMethodSubtype(defIm, NOT_A_SUBTYPE_ID);
}
}
@@ -964,10 +979,10 @@
// sync, so we will never have a DEFAULT_INPUT_METHOD that is not
// enabled.
String id = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD);
+ Settings.Secure.DEFAULT_INPUT_METHOD);
if (id != null && id.length() > 0) {
try {
- setInputMethodLocked(id);
+ setInputMethodLocked(id, getSelectedInputMethodSubtypeId(id));
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Unknown input method from prefs: " + id, e);
mCurMethodId = null;
@@ -980,21 +995,44 @@
}
}
- void setInputMethodLocked(String id) {
+ /* package */ void setInputMethodLocked(String id, int subtypeId) {
InputMethodInfo info = mMethodMap.get(id);
if (info == null) {
throw new IllegalArgumentException("Unknown id: " + id);
}
if (id.equals(mCurMethodId)) {
+ if (subtypeId != NOT_A_SUBTYPE_ID) {
+ InputMethodSubtype subtype = info.getSubtypes().get(subtypeId);
+ if (subtype != mCurrentSubtype) {
+ synchronized (mMethodMap) {
+ if (mCurMethod != null) {
+ try {
+ putSelectedInputMethodSubtype(info, subtypeId);
+ mCurMethod.changeInputMethodSubtype(subtype);
+ } catch (RemoteException e) {
+ return;
+ }
+ }
+ }
+ }
+ }
return;
}
final long ident = Binder.clearCallingIdentity();
try {
mCurMethodId = id;
+ // Set a subtype to this input method.
+ // subtypeId the name of a subtype which will be set.
+ if (putSelectedInputMethodSubtype(info, subtypeId)) {
+ mCurrentSubtype = info.getSubtypes().get(subtypeId);
+ } else {
+ mCurrentSubtype = null;
+ }
+
Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD, id);
+ Settings.Secure.DEFAULT_INPUT_METHOD, id);
if (ActivityManagerNative.isSystemReady()) {
Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
@@ -1226,7 +1264,22 @@
}
}
+ public void showInputMethodSubtypePickerFromClient(IInputMethodClient client) {
+ synchronized (mMethodMap) {
+ if (mCurClient == null || client == null
+ || mCurClient.client.asBinder() != client.asBinder()) {
+ Slog.w(TAG, "Ignoring showInputSubtypeMethodDialogFromClient of: " + client);
+ }
+
+ mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
+ }
+ }
+
public void setInputMethod(IBinder token, String id) {
+ setInputMethodWithSubtype(token, id, NOT_A_SUBTYPE_ID);
+ }
+
+ private void setInputMethodWithSubtype(IBinder token, String id, int subtypeId) {
synchronized (mMethodMap) {
if (token == null) {
if (mContext.checkCallingOrSelfPermission(
@@ -1243,7 +1296,7 @@
long ident = Binder.clearCallingIdentity();
try {
- setInputMethodLocked(id);
+ setInputMethodLocked(id, subtypeId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1307,6 +1360,10 @@
showInputMethodMenu();
return true;
+ case MSG_SHOW_IM_SUBTYPE_PICKER:
+ showInputMethodSubtypeMenu();
+ return true;
+
// ---------------------------------------------------------
case MSG_UNBIND_INPUT:
@@ -1417,9 +1474,10 @@
break;
}
}
+ InputMethodInfo imi = enabled.get(i);
Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD,
- enabled.get(i).getId());
+ Settings.Secure.DEFAULT_INPUT_METHOD, imi.getId());
+ putSelectedInputMethodSubtype(imi, NOT_A_SUBTYPE_ID);
return true;
}
@@ -1490,7 +1548,15 @@
// ----------------------------------------------------------------------
- void showInputMethodMenu() {
+ private void showInputMethodMenu() {
+ showInputMethodMenuInternal(false);
+ }
+
+ private void showInputMethodSubtypeMenu() {
+ showInputMethodMenuInternal(true);
+ }
+
+ private void showInputMethodMenuInternal(boolean showSubtypes) {
if (DEBUG) Slog.v(TAG, "Show switching menu");
final Context context = mContext;
@@ -1499,42 +1565,78 @@
String lastInputMethodId = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+ int lastInputMethodSubtypeId = getSelectedInputMethodSubtypeId(lastInputMethodId);
if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
final List<InputMethodInfo> immis = getEnabledInputMethodList();
+ ArrayList<Integer> subtypeIds = new ArrayList<Integer>();
if (immis == null) {
return;
}
-
+
synchronized (mMethodMap) {
hideInputMethodMenuLocked();
int N = immis.size();
- final Map<CharSequence, InputMethodInfo> imMap =
- new TreeMap<CharSequence, InputMethodInfo>(Collator.getInstance());
+ final Map<CharSequence, Pair<InputMethodInfo, Integer>> imMap =
+ new TreeMap<CharSequence, Pair<InputMethodInfo, Integer>>(Collator.getInstance());
for (int i = 0; i < N; ++i) {
InputMethodInfo property = immis.get(i);
if (property == null) {
continue;
}
- imMap.put(property.loadLabel(pm), property);
+ // TODO: Show only enabled subtypes
+ ArrayList<InputMethodSubtype> subtypes = property.getSubtypes();
+ CharSequence label = property.loadLabel(pm);
+ if (showSubtypes && subtypes.size() > 0) {
+ for (int j = 0; j < subtypes.size(); ++j) {
+ InputMethodSubtype subtype = subtypes.get(j);
+ CharSequence title;
+ int nameResId = subtype.getNameResId();
+ int modeResId = subtype.getModeResId();
+ if (nameResId != 0) {
+ title = pm.getText(property.getPackageName(), nameResId,
+ property.getServiceInfo().applicationInfo);
+ } else {
+ CharSequence language = subtype.getLocale();
+ CharSequence mode = modeResId == 0 ? null
+ : pm.getText(property.getPackageName(), modeResId,
+ property.getServiceInfo().applicationInfo);
+ // TODO: Use more friendly Title and UI
+ title = label + "," + (mode == null ? "" : mode) + ","
+ + (language == null ? "" : language);
+ }
+ imMap.put(title, new Pair<InputMethodInfo, Integer>(property, j));
+ }
+ } else {
+ imMap.put(label,
+ new Pair<InputMethodInfo, Integer>(property, NOT_A_SUBTYPE_ID));
+ subtypeIds.add(0);
+ }
}
N = imMap.size();
mItems = imMap.keySet().toArray(new CharSequence[N]);
- mIms = imMap.values().toArray(new InputMethodInfo[N]);
-
+ mIms = new InputMethodInfo[N];
+ mSubtypeIds = new int[N];
int checkedItem = 0;
for (int i = 0; i < N; ++i) {
+ Pair<InputMethodInfo, Integer> value = imMap.get(mItems[i]);
+ mIms[i] = value.first;
+ mSubtypeIds[i] = value.second;
if (mIms[i].getId().equals(lastInputMethodId)) {
- checkedItem = i;
- break;
+ int subtypeId = mSubtypeIds[i];
+ if ((subtypeId == NOT_A_SUBTYPE_ID)
+ || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
+ || (subtypeId == lastInputMethodSubtypeId)) {
+ checkedItem = i;
+ }
}
}
-
+
AlertDialog.OnClickListener adocl = new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
hideInputMethodMenu();
@@ -1559,13 +1661,19 @@
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
synchronized (mMethodMap) {
- if (mIms == null || mIms.length <= which) {
+ if (mIms == null || mIms.length <= which
+ || mSubtypeIds == null || mSubtypeIds.length <= which) {
return;
}
InputMethodInfo im = mIms[which];
+ int subtypeId = mSubtypeIds[which];
hideInputMethodMenu();
if (im != null) {
- setInputMethodLocked(im.getId());
+ if ((subtypeId < 0)
+ || (subtypeId >= im.getSubtypes().size())) {
+ subtypeId = NOT_A_SUBTYPE_ID;
+ }
+ setInputMethodLocked(im.getId(), subtypeId);
}
}
}
@@ -1679,6 +1787,7 @@
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD,
firstId != null ? firstId : "");
+ resetSelectedInputMethodSubtype();
}
// Previous state was enabled.
return true;
@@ -1698,6 +1807,53 @@
return false;
}
+ private void resetSelectedInputMethodSubtype() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, NOT_A_SUBTYPE_ID);
+ }
+
+ private boolean putSelectedInputMethodSubtype(InputMethodInfo imi, int subtypeId) {
+ ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
+ if (subtypeId >= 0 && subtypeId < subtypes.size()) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+ subtypes.get(subtypeId).hashCode());
+ return true;
+ } else {
+ resetSelectedInputMethodSubtype();
+ return false;
+ }
+ }
+
+ private int getSelectedInputMethodSubtypeId(String id) {
+ InputMethodInfo imi = mMethodMap.get(id);
+ if (imi == null) {
+ return NOT_A_SUBTYPE_ID;
+ }
+ ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
+ int subtypeId;
+ try {
+ subtypeId = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE);
+ } catch (SettingNotFoundException e) {
+ return NOT_A_SUBTYPE_ID;
+ }
+ for (int i = 0; i < subtypes.size(); ++i) {
+ InputMethodSubtype ims = subtypes.get(i);
+ if (subtypeId == ims.hashCode()) {
+ return i;
+ }
+ }
+ return NOT_A_SUBTYPE_ID;
+ }
+
+ /**
+ * @return Return the current subtype of this input method.
+ */
+ public InputMethodSubtype getCurrentInputMethodSubtype() {
+ return mCurrentSubtype;
+ }
+
// ----------------------------------------------------------------------
@Override
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 03f8dae..cf87a9d 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -181,7 +181,8 @@
}
}
- private void sendCommand(String command) {
+ private void sendCommand(String command)
+ throws NativeDaemonConnectorException {
sendCommand(command, null);
}
@@ -191,11 +192,13 @@
* @param command The command to send to the daemon
* @param argument The argument to send with the command (or null)
*/
- private void sendCommand(String command, String argument) {
+ private void sendCommand(String command, String argument)
+ throws NativeDaemonConnectorException {
synchronized (this) {
if (LOCAL_LOGD) Slog.d(TAG, String.format("SND -> {%s} {%s}", command, argument));
if (mOutputStream == null) {
Slog.e(TAG, "No connection to daemon", new IllegalStateException());
+ throw new NativeDaemonConnectorException("No output stream!");
} else {
StringBuilder builder = new StringBuilder(command);
if (argument != null) {
@@ -226,6 +229,7 @@
while (!complete) {
try {
+ // TODO - this should not block forever
String line = mResponseQueue.take();
if (LOCAL_LOGD) Slog.d(TAG, String.format("RSP <- {%s}", line));
String[] tokens = line.split(" ");
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index de459ab..05abd99 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -47,6 +47,7 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.concurrent.CountDownLatch;
/**
* @hide
@@ -54,7 +55,7 @@
class NetworkManagementService extends INetworkManagementService.Stub {
private static final String TAG = "NetworkManagmentService";
-
+ private static final boolean DBG = true;
private static final String NETD_TAG = "NetdConnector";
class NetdResponseCode {
@@ -86,6 +87,9 @@
*/
private NativeDaemonConnector mConnector;
+ private Thread mThread;
+ private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
+
private ArrayList<INetworkManagementEventObserver> mObservers;
/**
@@ -93,9 +97,8 @@
*
* @param context Binder context for this service
*/
- public NetworkManagementService(Context context) {
+ private NetworkManagementService(Context context) {
mContext = context;
-
mObservers = new ArrayList<INetworkManagementEventObserver>();
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
@@ -104,8 +107,17 @@
mConnector = new NativeDaemonConnector(
new NetdCallbackReceiver(), "netd", 10, NETD_TAG);
- Thread thread = new Thread(mConnector, NETD_TAG);
- thread.start();
+ mThread = new Thread(mConnector, NETD_TAG);
+ }
+
+ public static NetworkManagementService create(Context context) throws InterruptedException {
+ NetworkManagementService service = new NetworkManagementService(context);
+ if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
+ service.mThread.start();
+ if (DBG) Slog.d(TAG, "Awaiting socket connection");
+ service.mConnectedSignal.await();
+ if (DBG) Slog.d(TAG, "Connected");
+ return service;
}
public void registerObserver(INetworkManagementEventObserver obs) {
@@ -157,6 +169,14 @@
}
}
+ /**
+ * Let us know the daemon is connected
+ */
+ protected void onConnected() {
+ if (DBG) Slog.d(TAG, "onConnected");
+ mConnectedSignal.countDown();
+ }
+
//
// Netd Callback handling
@@ -164,6 +184,7 @@
class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
public void onDaemonConnected() {
+ NetworkManagementService.this.onConnected();
new Thread() {
public void run() {
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 023da46..9401ff8 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -25,6 +25,7 @@
import android.content.BroadcastReceiver;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -36,6 +37,7 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Environment;
@@ -109,6 +111,9 @@
// Cached secure settings; see updateSettingsValues()
private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
+ // Default timeout for screen off, if not found in settings database = 15 seconds.
+ private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15000;
+
// flags for setPowerState
private static final int SCREEN_ON_BIT = 0x00000001;
private static final int SCREEN_BRIGHT_BIT = 0x00000002;
@@ -411,24 +416,28 @@
}
private class SettingsObserver implements Observer {
- private int getInt(String name) {
- return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
+ private int getInt(String name, int defValue) {
+ ContentValues values = mSettings.getValues(name);
+ Integer iVal = values != null ? values.getAsInteger(Settings.System.VALUE) : null;
+ return iVal != null ? iVal : defValue;
}
public void update(Observable o, Object arg) {
synchronized (mLocks) {
- // STAY_ON_WHILE_PLUGGED_IN
- mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN);
+ // STAY_ON_WHILE_PLUGGED_IN, default to when plugged into AC
+ mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN,
+ BatteryManager.BATTERY_PLUGGED_AC);
updateWakeLockLocked();
- // SCREEN_OFF_TIMEOUT
- mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT);
+ // SCREEN_OFF_TIMEOUT, default to 15 seconds
+ mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
// DIM_SCREEN
//mDimScreen = getInt(DIM_SCREEN) != 0;
- // SCREEN_BRIGHTNESS_MODE
- setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE));
+ // SCREEN_BRIGHTNESS_MODE, default to manual
+ setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL));
// recalculate everything
setScreenOffTimeoutsLocked();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4f05007..5ca386b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -255,7 +255,8 @@
try {
Slog.i(TAG, "NetworkManagement Service");
ServiceManager.addService(
- Context.NETWORKMANAGEMENT_SERVICE, new NetworkManagementService(context));
+ Context.NETWORKMANAGEMENT_SERVICE,
+ NetworkManagementService.create(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting NetworkManagement Service", e);
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index c52567a..7b2a570 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -804,6 +804,16 @@
mWifiStateMachine.forgetNetwork(netId);
}
+ public void startWpsPbc(String bssid) {
+ enforceChangePermission();
+ mWifiStateMachine.startWpsPbc(bssid);
+ }
+
+ public void startWpsPin(String bssid, int apPin) {
+ enforceChangePermission();
+ mWifiStateMachine.startWpsPin(bssid, apPin);
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3bf6ee4..39ce0b6 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1171,7 +1171,10 @@
private void reportAGpsStatus(int type, int status) {
switch (status) {
case GPS_REQUEST_AGPS_DATA_CONN:
- int result = mConnMgr.startUsingNetworkFeature(
+ // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
+ // to avoid a race condition with handleUpdateNetworkState()
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ int result = mConnMgr.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
if (result == Phone.APN_ALREADY_ACTIVE) {
if (mAGpsApn != null) {
@@ -1179,11 +1182,13 @@
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else {
Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
} else if (result == Phone.APN_REQUEST_STARTED) {
- mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ // Nothing to do here
} else {
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
break;
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index a2ebc69..f1dcd5a 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -172,7 +172,7 @@
SipSessionGroupExt group = mSipGroups.remove(localProfileUri);
if (group != null) {
notifyProfileRemoved(group.getLocalProfile());
- group.closeToNotReceiveCalls();
+ group.close();
if (isWifiOn() && !anyOpened()) releaseWifiLock();
}
}
@@ -449,9 +449,9 @@
}
}
- public void closeToNotReceiveCalls() {
+ public void close() {
mOpened = false;
- mSipGroup.closeToNotReceiveCalls();
+ mSipGroup.close();
mAutoRegistration.stop();
if (DEBUG) Log.d(TAG, " close: " + getUri() + ": "
+ mIncomingCallBroadcastAction);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b45f6fe..06c86dd 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -85,6 +85,7 @@
mFreezeDisplayTime(0),
mDebugRegion(0),
mDebugBackground(0),
+ mDebugDisableHWC(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
@@ -768,6 +769,10 @@
hwc_layer_t* const cur(hwc.getLayers());
for (size_t i=0 ; cur && i<count ; i++) {
currentLayers[i]->setGeometry(&cur[i]);
+ if (mDebugDisableHWC) {
+ cur[i].compositionType = HWC_FRAMEBUFFER;
+ cur[i].flags |= HWC_SKIP_LAYER;
+ }
}
}
}
@@ -901,6 +906,7 @@
continue;
}
}
+
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
@@ -1522,6 +1528,12 @@
result.append(buffer);
}
+ HWComposer& hwc(hw.getHwComposer());
+ snprintf(buffer, SIZE, " h/w composer %s and %s\n",
+ hwc.initCheck()==NO_ERROR ? "present" : "not present",
+ mDebugDisableHWC ? "disabled" : "enabled");
+ result.append(buffer);
+
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
alloc.dump(result);
@@ -1580,6 +1592,11 @@
n = data.readInt32();
mDebugBackground = n ? 1 : 0;
return NO_ERROR;
+ case 1008: // toggle use of hw composer
+ n = data.readInt32();
+ mDebugDisableHWC = n ? 1 : 0;
+ mHwWorkListDirty = true;
+ // fall-through...
case 1004:{ // repaint everything
Mutex::Autolock _l(mStateLock);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8e286e5..551e8e7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -382,6 +382,7 @@
// don't use a lock for these, we don't care
int mDebugRegion;
int mDebugBackground;
+ int mDebugDisableHWC;
volatile nsecs_t mDebugInSwapBuffers;
nsecs_t mLastSwapBufferTime;
volatile nsecs_t mDebugInTransaction;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 5d4dc58..b71cf13 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,6 +16,16 @@
package com.android.internal.telephony.cdma;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,19 +48,8 @@
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
-import android.util.Config;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -987,7 +986,7 @@
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1439,7 +1438,7 @@
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1529,6 +1528,14 @@
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index b639eea..83ad552 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,6 +16,17 @@
package com.android.internal.telephony.gsm;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -47,17 +58,6 @@
import android.util.Log;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -995,7 +995,7 @@
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1476,7 +1476,7 @@
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1546,6 +1546,15 @@
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(phone.getContext().getContentResolver(),
+ Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index c0ba9e5..30d255a 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -43,9 +43,10 @@
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
+import android.webkit.WebStorage;
+import android.webkit.WebStorage.QuotaUpdater;
import android.webkit.WebView;
import android.webkit.WebViewClient;
-import android.webkit.WebStorage.QuotaUpdater;
import java.io.File;
import java.lang.Thread.UncaughtExceptionHandler;
@@ -327,6 +328,13 @@
mCurrentAdditionalTextOutput = null;
mCurrentWebView = createWebViewWithJavascriptInterfaces();
+ // When we create the first WebView, we need to pause to wait for the WebView thread to spin
+ // and up and for it to register its message handlers.
+ if (previousWebView == null) {
+ try {
+ Thread.currentThread().sleep(1000);
+ } catch (Exception e) {}
+ }
setupWebView(mCurrentWebView);
mEventSender.reset(mCurrentWebView);
@@ -386,6 +394,9 @@
// This is asynchronous, but it gets processed by WebCore before it starts loading pages.
mCurrentWebView.useMockDeviceOrientation();
+
+ // Must do this after setting the AppCache path.
+ WebStorage.getInstance().deleteAllData();
}
private void startTests() {
diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java
index 89e6aa9..4851a46 100644
--- a/voip/java/android/net/rtp/AudioCodec.java
+++ b/voip/java/android/net/rtp/AudioCodec.java
@@ -16,41 +16,133 @@
package android.net.rtp;
-/** @hide */
+import java.util.Arrays;
+
+/**
+ * This class defines a collection of audio codecs to be used with
+ * {@link AudioStream}s. Their parameters are designed to be exchanged using
+ * Session Description Protocol (SDP). Most of the values listed here can be
+ * found in RFC 3551, while others are described in separated standards.
+ *
+ * <p>Few simple configurations are defined as public static instances for the
+ * convenience of direct uses. More complicated ones could be obtained using
+ * {@link #getCodec(int, String, String)}. For example, one can use the
+ * following snippet to create a mode-1-only AMR codec.</p>
+ * <pre>
+ * AudioCodec codec = AudioCodec.getCodec(100, "AMR/8000", "mode-set=1");
+ * </pre>
+ *
+ * @see AudioStream
+ * @hide
+ */
public class AudioCodec {
- public static final AudioCodec ULAW = new AudioCodec("PCMU", 8000, 160, 0);
- public static final AudioCodec ALAW = new AudioCodec("PCMA", 8000, 160, 8);
+ /**
+ * The RTP payload type of the encoding.
+ */
+ public final int type;
/**
- * Returns system supported codecs.
+ * The encoding parameters to be used in the corresponding SDP attribute.
*/
- public static AudioCodec[] getSystemSupportedCodecs() {
- return new AudioCodec[] {AudioCodec.ULAW, AudioCodec.ALAW};
+ public final String rtpmap;
+
+ /**
+ * The format parameters to be used in the corresponding SDP attribute.
+ */
+ public final String fmtp;
+
+ /**
+ * G.711 u-law audio codec.
+ */
+ public static final AudioCodec PCMU = new AudioCodec(0, "PCMU/8000", null);
+
+ /**
+ * G.711 a-law audio codec.
+ */
+ public static final AudioCodec PCMA = new AudioCodec(8, "PCMA/8000", null);
+
+ /**
+ * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or
+ * simply FR.
+ */
+ public static final AudioCodec GSM = new AudioCodec(3, "GSM/8000", null);
+
+ /**
+ * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or
+ * simply EFR.
+ */
+ public static final AudioCodec GSM_EFR = new AudioCodec(96, "GSM-EFR/8000", null);
+
+ /**
+ * Adaptive Multi-Rate narrowband audio codec, also known as AMR or AMR-NB.
+ * Currently CRC, robust sorting, and interleaving are not supported. See
+ * more details about these features in RFC 4867.
+ */
+ public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null);
+
+ // TODO: add rest of the codecs when the native part is done.
+ private static final AudioCodec[] sCodecs = {PCMU, PCMA};
+
+ private AudioCodec(int type, String rtpmap, String fmtp) {
+ this.type = type;
+ this.rtpmap = rtpmap;
+ this.fmtp = fmtp;
}
/**
- * Returns the codec instance if it is supported by the system.
+ * Returns system supported audio codecs.
+ */
+ public static AudioCodec[] getCodecs() {
+ return Arrays.copyOf(sCodecs, sCodecs.length);
+ }
+
+ /**
+ * Creates an AudioCodec according to the given configuration.
*
- * @param name name of the codec
- * @return the matched codec or null if the codec name is not supported by
- * the system
+ * @param type The payload type of the encoding defined in RTP/AVP.
+ * @param rtpmap The encoding parameters specified in the corresponding SDP
+ * attribute, or null if it is not available.
+ * @param fmtp The format parameters specified in the corresponding SDP
+ * attribute, or null if it is not available.
+ * @return The configured AudioCodec or {@code null} if it is not supported.
*/
- public static AudioCodec getSystemSupportedCodec(String name) {
- for (AudioCodec codec : getSystemSupportedCodecs()) {
- if (codec.name.equals(name)) return codec;
+ public static AudioCodec getCodec(int type, String rtpmap, String fmtp) {
+ if (type < 0 || type > 127) {
+ return null;
}
- return null;
- }
- public final String name;
- public final int sampleRate;
- public final int sampleCount;
- public final int defaultType;
+ AudioCodec hint = null;
+ if (rtpmap != null) {
+ String clue = rtpmap.trim().toUpperCase();
+ for (AudioCodec codec : sCodecs) {
+ if (clue.startsWith(codec.rtpmap)) {
+ String channels = clue.substring(codec.rtpmap.length());
+ if (channels.length() == 0 || channels.equals("/1")) {
+ hint = codec;
+ }
+ break;
+ }
+ }
+ } else if (type < 96) {
+ for (AudioCodec codec : sCodecs) {
+ if (type == codec.type) {
+ hint = codec;
+ rtpmap = codec.rtpmap;
+ break;
+ }
+ }
+ }
- private AudioCodec(String name, int sampleRate, int sampleCount, int defaultType) {
- this.name = name;
- this.sampleRate = sampleRate;
- this.sampleCount = sampleCount;
- this.defaultType = defaultType;
+ if (hint == null) {
+ return null;
+ }
+ if (hint == AMR && fmtp != null) {
+ String clue = fmtp.toLowerCase();
+ if (clue.contains("crc=1") || clue.contains("robust-sorting=1") ||
+ clue.contains("interleaving=")) {
+ return null;
+ }
+ }
+ return new AudioCodec(type, rtpmap, fmtp);
}
}
diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java
index 37cc121..43a3827 100644
--- a/voip/java/android/net/rtp/AudioGroup.java
+++ b/voip/java/android/net/rtp/AudioGroup.java
@@ -20,13 +20,63 @@
import java.util.Map;
/**
+ * An AudioGroup acts as a router connected to the speaker, the microphone, and
+ * {@link AudioStream}s. Its pipeline has four steps. First, for each
+ * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming
+ * packets and stores in its buffer. Then, if the microphone is enabled,
+ * processes the recorded audio and stores in its buffer. Third, if the speaker
+ * is enabled, mixes and playbacks buffers of all AudioStreams. Finally, for
+ * each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other
+ * buffers and sends back the encoded packets. An AudioGroup does nothing if
+ * there is no AudioStream in it.
+ *
+ * <p>Few things must be noticed before using these classes. The performance is
+ * highly related to the system load and the network bandwidth. Usually a
+ * simpler {@link AudioCodec} costs fewer CPU cycles but requires more network
+ * bandwidth, and vise versa. Using two AudioStreams at the same time not only
+ * doubles the load but also the bandwidth. The condition varies from one device
+ * to another, and developers must choose the right combination in order to get
+ * the best result.
+ *
+ * <p>It is sometimes useful to keep multiple AudioGroups at the same time. For
+ * example, a Voice over IP (VoIP) application might want to put a conference
+ * call on hold in order to make a new call but still allow people in the
+ * previous call to talk to each other. This can be done easily using two
+ * AudioGroups, but there are some limitations. Since the speaker and the
+ * microphone are shared globally, only one AudioGroup is allowed to run in
+ * modes other than {@link #MODE_ON_HOLD}. In addition, before adding an
+ * AudioStream into an AudioGroup, one should always put all other AudioGroups
+ * into {@link #MODE_ON_HOLD}. That will make sure the audio driver correctly
+ * initialized.
+ * @hide
*/
-/** @hide */
public class AudioGroup {
+ /**
+ * This mode is similar to {@link #MODE_NORMAL} except the speaker and
+ * the microphone are disabled.
+ */
public static final int MODE_ON_HOLD = 0;
+
+ /**
+ * This mode is similar to {@link #MODE_NORMAL} except the microphone is
+ * muted.
+ */
public static final int MODE_MUTED = 1;
+
+ /**
+ * This mode indicates that the speaker, the microphone, and all
+ * {@link AudioStream}s in the group are enabled. First, the packets
+ * received from the streams are decoded and mixed with the audio recorded
+ * from the microphone. Then, the results are played back to the speaker,
+ * encoded and sent back to each stream.
+ */
public static final int MODE_NORMAL = 2;
- public static final int MODE_EC_ENABLED = 3;
+
+ /**
+ * This mode is similar to {@link #MODE_NORMAL} except the echo suppression
+ * is enabled. It should be only used when the speaker phone is on.
+ */
+ public static final int MODE_ECHO_SUPPRESSION = 3;
private final Map<AudioStream, Integer> mStreams;
private int mMode = MODE_ON_HOLD;
@@ -36,23 +86,42 @@
System.loadLibrary("rtp_jni");
}
+ /**
+ * Creates an empty AudioGroup.
+ */
public AudioGroup() {
mStreams = new HashMap<AudioStream, Integer>();
}
+ /**
+ * Returns the current mode.
+ */
public int getMode() {
return mMode;
}
+ /**
+ * Changes the current mode. It must be one of {@link #MODE_ON_HOLD},
+ * {@link #MODE_MUTED}, {@link #MODE_NORMAL}, and
+ * {@link #MODE_ECHO_SUPPRESSION}.
+ *
+ * @param mode The mode to change to.
+ * @throws IllegalArgumentException if the mode is invalid.
+ */
public synchronized native void setMode(int mode);
- synchronized void add(AudioStream stream, AudioCodec codec, int codecType, int dtmfType) {
+ private native void add(int mode, int socket, String remoteAddress,
+ int remotePort, String codecSpec, int dtmfType);
+
+ synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) {
if (!mStreams.containsKey(stream)) {
try {
int socket = stream.dup();
+ String codecSpec = String.format("%d %s %s", codec.type,
+ codec.rtpmap, codec.fmtp);
add(stream.getMode(), socket,
- stream.getRemoteAddress().getHostAddress(), stream.getRemotePort(),
- codec.name, codec.sampleRate, codec.sampleCount, codecType, dtmfType);
+ stream.getRemoteAddress().getHostAddress(),
+ stream.getRemotePort(), codecSpec, dtmfType);
mStreams.put(stream, socket);
} catch (NullPointerException e) {
throw new IllegalStateException(e);
@@ -60,8 +129,7 @@
}
}
- private native void add(int mode, int socket, String remoteAddress, int remotePort,
- String codecName, int sampleRate, int sampleCount, int codecType, int dtmfType);
+ private native void remove(int socket);
synchronized void remove(AudioStream stream) {
Integer socket = mStreams.remove(stream);
@@ -70,8 +138,6 @@
}
}
- private native void remove(int socket);
-
/**
* Sends a DTMF digit to every {@link AudioStream} in this group. Currently
* only event {@code 0} to {@code 15} are supported.
@@ -80,13 +146,16 @@
*/
public native synchronized void sendDtmf(int event);
- public synchronized void reset() {
+ /**
+ * Removes every {@link AudioStream} in this group.
+ */
+ public synchronized void clear() {
remove(-1);
}
@Override
protected void finalize() throws Throwable {
- reset();
+ clear();
super.finalize();
}
}
diff --git a/voip/java/android/net/rtp/AudioStream.java b/voip/java/android/net/rtp/AudioStream.java
index a955fd2..e5197ce 100644
--- a/voip/java/android/net/rtp/AudioStream.java
+++ b/voip/java/android/net/rtp/AudioStream.java
@@ -20,12 +20,27 @@
import java.net.SocketException;
/**
- * AudioStream represents a RTP stream carrying audio payloads.
+ * An AudioStream is a {@link RtpStream} which carrys audio payloads over
+ * Real-time Transport Protocol (RTP). Two different classes are developed in
+ * order to support various usages such as audio conferencing. An AudioStream
+ * represents a remote endpoint which consists of a network mapping and a
+ * configured {@link AudioCodec}. On the other side, An {@link AudioGroup}
+ * represents a local endpoint which mixes all the AudioStreams and optionally
+ * interacts with the speaker and the microphone at the same time. The simplest
+ * usage includes one for each endpoints. For other combinations, users should
+ * be aware of the limitations described in {@link AudioGroup}.
+ *
+ * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most
+ * of the setter methods are disabled. This is designed to ease the task of
+ * managing native resources. One can always make an AudioStream leave its
+ * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it
+ * back after the modification is done.
+ *
+ * @see AudioGroup
+ * @hide
*/
-/** @hide */
public class AudioStream extends RtpStream {
private AudioCodec mCodec;
- private int mCodecType = -1;
private int mDtmfType = -1;
private AudioGroup mGroup;
@@ -42,7 +57,8 @@
}
/**
- * Returns {@code true} if the stream already joined an {@link AudioGroup}.
+ * Returns {@code true} if the stream has already joined an
+ * {@link AudioGroup}.
*/
@Override
public final boolean isBusy() {
@@ -52,7 +68,7 @@
/**
* Returns the joined {@link AudioGroup}.
*/
- public AudioGroup getAudioGroup() {
+ public AudioGroup getGroup() {
return mGroup;
}
@@ -74,35 +90,45 @@
mGroup = null;
}
if (group != null) {
- group.add(this, mCodec, mCodecType, mDtmfType);
+ group.add(this, mCodec, mDtmfType);
mGroup = group;
}
}
/**
- * Sets the {@link AudioCodec} and its RTP payload type. According to RFC
- * 3551, the type must be in the range of 0 and 127, where 96 and above are
- * dynamic types. For codecs with static mappings (non-negative
- * {@link AudioCodec#defaultType}), assigning a different non-dynamic type
- * is disallowed.
+ * Returns the {@link AudioCodec}, or {@code null} if it is not set.
+ *
+ * @see #setCodec(AudioCodec)
+ */
+ public AudioCodec getCodec() {
+ return mCodec;
+ }
+
+ /**
+ * Sets the {@link AudioCodec}.
*
* @param codec The AudioCodec to be used.
- * @param type The RTP payload type.
- * @throws IllegalArgumentException if the type is invalid or used by DTMF.
+ * @throws IllegalArgumentException if its type is used by DTMF.
* @throws IllegalStateException if the stream is busy.
*/
- public void setCodec(AudioCodec codec, int type) {
+ public void setCodec(AudioCodec codec) {
if (isBusy()) {
throw new IllegalStateException("Busy");
}
- if (type < 0 || type > 127 || (type != codec.defaultType && type < 96)) {
- throw new IllegalArgumentException("Invalid type");
- }
- if (type == mDtmfType) {
+ if (codec.type == mDtmfType) {
throw new IllegalArgumentException("The type is used by DTMF");
}
mCodec = codec;
- mCodecType = type;
+ }
+
+ /**
+ * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits,
+ * or {@code -1} if it is not enabled.
+ *
+ * @see #setDtmfType(int)
+ */
+ public int getDtmfType() {
+ return mDtmfType;
}
/**
@@ -111,7 +137,7 @@
* certain tasks, such as second-stage dialing. According to RFC 2833, the
* RTP payload type for DTMF is assigned dynamically, so it must be in the
* range of 96 and 127. One can use {@code -1} to disable DTMF and free up
- * the previous assigned value. This method cannot be called when the stream
+ * the previous assigned type. This method cannot be called when the stream
* already joined an {@link AudioGroup}.
*
* @param type The RTP payload type to be used or {@code -1} to disable it.
@@ -127,7 +153,7 @@
if (type < 96 || type > 127) {
throw new IllegalArgumentException("Invalid type");
}
- if (type == mCodecType) {
+ if (type == mCodec.type) {
throw new IllegalArgumentException("The type is used by codec");
}
}
diff --git a/voip/java/android/net/rtp/RtpStream.java b/voip/java/android/net/rtp/RtpStream.java
index ef5ca17..23fb258 100644
--- a/voip/java/android/net/rtp/RtpStream.java
+++ b/voip/java/android/net/rtp/RtpStream.java
@@ -22,13 +22,25 @@
import java.net.SocketException;
/**
- * RtpStream represents a base class of media streams running over
- * Real-time Transport Protocol (RTP).
+ * RtpStream represents the base class of streams which send and receive network
+ * packets with media payloads over Real-time Transport Protocol (RTP).
+ * @hide
*/
-/** @hide */
public class RtpStream {
+ /**
+ * This mode indicates that the stream sends and receives packets at the
+ * same time. This is the initial mode for new streams.
+ */
public static final int MODE_NORMAL = 0;
+
+ /**
+ * This mode indicates that the stream only sends packets.
+ */
public static final int MODE_SEND_ONLY = 1;
+
+ /**
+ * This mode indicates that the stream only receives packets.
+ */
public static final int MODE_RECEIVE_ONLY = 2;
private final InetAddress mLocalAddress;
@@ -89,15 +101,16 @@
}
/**
- * Returns {@code true} if the stream is busy. This method is intended to be
- * overridden by subclasses.
+ * Returns {@code true} if the stream is busy. In this case most of the
+ * setter methods are disabled. This method is intended to be overridden
+ * by subclasses.
*/
public boolean isBusy() {
return false;
}
/**
- * Returns the current mode. The initial mode is {@link #MODE_NORMAL}.
+ * Returns the current mode.
*/
public int getMode() {
return mMode;
@@ -123,7 +136,8 @@
}
/**
- * Associates with a remote host.
+ * Associates with a remote host. This defines the destination of the
+ * outgoing packets.
*
* @param address The network address of the remote host.
* @param port The network port of the remote host.
diff --git a/voip/java/android/net/sip/SimpleSessionDescription.java b/voip/java/android/net/sip/SimpleSessionDescription.java
new file mode 100644
index 0000000..29166dc
--- /dev/null
+++ b/voip/java/android/net/sip/SimpleSessionDescription.java
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2010 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.net.sip;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * An object used to manipulate messages of Session Description Protocol (SDP).
+ * It is mainly designed for the uses of Session Initiation Protocol (SIP).
+ * Therefore, it only handles connection addresses ("c="), bandwidth limits,
+ * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this
+ * implementation does not support multicast sessions.
+ *
+ * <p>Here is an example code to create a session description.</p>
+ * <pre>
+ * SimpleSessionDescription description = new SimpleSessionDescription(
+ * System.currentTimeMillis(), "1.2.3.4");
+ * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP");
+ * media.setRtpPayload(0, "PCMU/8000", null);
+ * media.setRtpPayload(8, "PCMA/8000", null);
+ * media.setRtpPayload(127, "telephone-event/8000", "0-15");
+ * media.setAttribute("sendrecv", "");
+ * </pre>
+ * <p>Invoking <code>description.encode()</code> will produce a result like the
+ * one below.</p>
+ * <pre>
+ * v=0
+ * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4
+ * s=-
+ * c=IN IP4 1.2.3.4
+ * t=0 0
+ * m=audio 56789 RTP/AVP 0 8 127
+ * a=rtpmap:0 PCMU/8000
+ * a=rtpmap:8 PCMA/8000
+ * a=rtpmap:127 telephone-event/8000
+ * a=fmtp:127 0-15
+ * a=sendrecv
+ * </pre>
+ * @hide
+ */
+public class SimpleSessionDescription {
+ private final Fields mFields = new Fields("voscbtka");
+ private final ArrayList<Media> mMedia = new ArrayList<Media>();
+
+ /**
+ * Creates a minimal session description from the given session ID and
+ * unicast address. The address is used in the origin field ("o=") and the
+ * connection field ("c="). See {@link SimpleSessionDescription} for an
+ * example of its usage.
+ */
+ public SimpleSessionDescription(long sessionId, String address) {
+ address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address;
+ mFields.parse("v=0");
+ mFields.parse(String.format("o=- %d %d %s", sessionId,
+ System.currentTimeMillis(), address));
+ mFields.parse("s=-");
+ mFields.parse("t=0 0");
+ mFields.parse("c=" + address);
+ }
+
+ /**
+ * Creates a session description from the given message.
+ *
+ * @throws IllegalArgumentException if message is invalid.
+ */
+ public SimpleSessionDescription(String message) {
+ String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+");
+ Fields fields = mFields;
+
+ for (String line : lines) {
+ try {
+ if (line.charAt(1) != '=') {
+ throw new IllegalArgumentException();
+ }
+ if (line.charAt(0) == 'm') {
+ String[] parts = line.substring(2).split(" ", 4);
+ String[] ports = parts[1].split("/", 2);
+ Media media = newMedia(parts[0], Integer.parseInt(ports[0]),
+ (ports.length < 2) ? 1 : Integer.parseInt(ports[1]),
+ parts[2]);
+ for (String format : parts[3].split(" ")) {
+ media.setFormat(format, null);
+ }
+ fields = media;
+ } else {
+ fields.parse(line);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid SDP: " + line);
+ }
+ }
+ }
+
+ /**
+ * Creates a new media description in this session description.
+ *
+ * @param type The media type, e.g. {@code "audio"}.
+ * @param port The first transport port used by this media.
+ * @param portCount The number of contiguous ports used by this media.
+ * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}.
+ */
+ public Media newMedia(String type, int port, int portCount,
+ String protocol) {
+ Media media = new Media(type, port, portCount, protocol);
+ mMedia.add(media);
+ return media;
+ }
+
+ /**
+ * Returns all the media descriptions in this session description.
+ */
+ public Media[] getMedia() {
+ return mMedia.toArray(new Media[mMedia.size()]);
+ }
+
+ /**
+ * Encodes the session description and all its media descriptions in a
+ * string. Note that the result might be incomplete if a required field
+ * has never been added before.
+ */
+ public String encode() {
+ StringBuilder buffer = new StringBuilder();
+ mFields.write(buffer);
+ for (Media media : mMedia) {
+ media.write(buffer);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Returns the connection address or {@code null} if it is not present.
+ */
+ public String getAddress() {
+ return mFields.getAddress();
+ }
+
+ /**
+ * Sets the connection address. The field will be removed if the address
+ * is {@code null}.
+ */
+ public void setAddress(String address) {
+ mFields.setAddress(address);
+ }
+
+ /**
+ * Returns the encryption method or {@code null} if it is not present.
+ */
+ public String getEncryptionMethod() {
+ return mFields.getEncryptionMethod();
+ }
+
+ /**
+ * Returns the encryption key or {@code null} if it is not present.
+ */
+ public String getEncryptionKey() {
+ return mFields.getEncryptionKey();
+ }
+
+ /**
+ * Sets the encryption method and the encryption key. The field will be
+ * removed if the method is {@code null}.
+ */
+ public void setEncryption(String method, String key) {
+ mFields.setEncryption(method, key);
+ }
+
+ /**
+ * Returns the types of the bandwidth limits.
+ */
+ public String[] getBandwidthTypes() {
+ return mFields.getBandwidthTypes();
+ }
+
+ /**
+ * Returns the bandwidth limit of the given type or {@code -1} if it is not
+ * present.
+ */
+ public int getBandwidth(String type) {
+ return mFields.getBandwidth(type);
+ }
+
+ /**
+ * Sets the bandwith limit for the given type. The field will be removed if
+ * the value is negative.
+ */
+ public void setBandwidth(String type, int value) {
+ mFields.setBandwidth(type, value);
+ }
+
+ /**
+ * Returns the names of all the attributes.
+ */
+ public String[] getAttributeNames() {
+ return mFields.getAttributeNames();
+ }
+
+ /**
+ * Returns the attribute of the given name or {@code null} if it is not
+ * present.
+ */
+ public String getAttribute(String name) {
+ return mFields.getAttribute(name);
+ }
+
+ /**
+ * Sets the attribute for the given name. The field will be removed if
+ * the value is {@code null}. To set a binary attribute, use an empty
+ * string as the value.
+ */
+ public void setAttribute(String name, String value) {
+ mFields.setAttribute(name, value);
+ }
+
+ /**
+ * This class represents a media description of a session description. It
+ * can only be created by {@link SimpleSessionDescription#newMedia}. Since
+ * the syntax is more restricted for RTP based protocols, two sets of access
+ * methods are implemented. See {@link SimpleSessionDescription} for an
+ * example of its usage.
+ */
+ public static class Media extends Fields {
+ private final String mType;
+ private final int mPort;
+ private final int mPortCount;
+ private final String mProtocol;
+ private ArrayList<String> mFormats = new ArrayList<String>();
+
+ private Media(String type, int port, int portCount, String protocol) {
+ super("icbka");
+ mType = type;
+ mPort = port;
+ mPortCount = portCount;
+ mProtocol = protocol;
+ }
+
+ /**
+ * Returns the media type.
+ */
+ public String getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the first transport port used by this media.
+ */
+ public int getPort() {
+ return mPort;
+ }
+
+ /**
+ * Returns the number of contiguous ports used by this media.
+ */
+ public int getPortCount() {
+ return mPortCount;
+ }
+
+ /**
+ * Returns the transport protocol.
+ */
+ public String getProtocol() {
+ return mProtocol;
+ }
+
+ /**
+ * Returns the media formats.
+ */
+ public String[] getFormats() {
+ return mFormats.toArray(new String[mFormats.size()]);
+ }
+
+ /**
+ * Returns the {@code fmtp} attribute of the given format or
+ * {@code null} if it is not present.
+ */
+ public String getFmtp(String format) {
+ return super.get("a=fmtp:" + format, ' ');
+ }
+
+ /**
+ * Sets a format and its {@code fmtp} attribute. If the attribute is
+ * {@code null}, the corresponding field will be removed.
+ */
+ public void setFormat(String format, String fmtp) {
+ mFormats.remove(format);
+ mFormats.add(format);
+ super.set("a=rtpmap:" + format, ' ', null);
+ super.set("a=fmtp:" + format, ' ', fmtp);
+ }
+
+ /**
+ * Removes a format and its {@code fmtp} attribute.
+ */
+ public void removeFormat(String format) {
+ mFormats.remove(format);
+ super.set("a=rtpmap:" + format, ' ', null);
+ super.set("a=fmtp:" + format, ' ', null);
+ }
+
+ /**
+ * Returns the RTP payload types.
+ */
+ public int[] getRtpPayloadTypes() {
+ int[] types = new int[mFormats.size()];
+ int length = 0;
+ for (String format : mFormats) {
+ try {
+ types[length] = Integer.parseInt(format);
+ ++length;
+ } catch (NumberFormatException e) { }
+ }
+ return Arrays.copyOf(types, length);
+ }
+
+ /**
+ * Returns the {@code rtpmap} attribute of the given RTP payload type
+ * or {@code null} if it is not present.
+ */
+ public String getRtpmap(int type) {
+ return super.get("a=rtpmap:" + type, ' ');
+ }
+
+ /**
+ * Returns the {@code fmtp} attribute of the given RTP payload type or
+ * {@code null} if it is not present.
+ */
+ public String getFmtp(int type) {
+ return super.get("a=fmtp:" + type, ' ');
+ }
+
+ /**
+ * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp}
+ * attributes. If any of the attributes is {@code null}, the
+ * corresponding field will be removed. See
+ * {@link SimpleSessionDescription} for an example of its usage.
+ */
+ public void setRtpPayload(int type, String rtpmap, String fmtp) {
+ String format = String.valueOf(type);
+ mFormats.remove(format);
+ mFormats.add(format);
+ super.set("a=rtpmap:" + format, ' ', rtpmap);
+ super.set("a=fmtp:" + format, ' ', fmtp);
+ }
+
+ /**
+ * Removes a RTP payload and its {@code rtpmap} and {@code fmtp}
+ * attributes.
+ */
+ public void removeRtpPayload(int type) {
+ removeFormat(String.valueOf(type));
+ }
+
+ private void write(StringBuilder buffer) {
+ buffer.append("m=").append(mType).append(' ').append(mPort);
+ if (mPortCount != 1) {
+ buffer.append('/').append(mPortCount);
+ }
+ buffer.append(' ').append(mProtocol);
+ for (String format : mFormats) {
+ buffer.append(' ').append(format);
+ }
+ buffer.append("\r\n");
+ super.write(buffer);
+ }
+ }
+
+ /**
+ * This class acts as a set of fields, and the size of the set is expected
+ * to be small. Therefore, it uses a simple list instead of maps. Each field
+ * has three parts: a key, a delimiter, and a value. Delimiters are special
+ * because they are not included in binary attributes. As a result, the
+ * private methods, which are the building blocks of this class, all take
+ * the delimiter as an argument.
+ */
+ private static class Fields {
+ private final String mOrder;
+ private final ArrayList<String> mLines = new ArrayList<String>();
+
+ Fields(String order) {
+ mOrder = order;
+ }
+
+ /**
+ * Returns the connection address or {@code null} if it is not present.
+ */
+ public String getAddress() {
+ String address = get("c", '=');
+ if (address == null) {
+ return null;
+ }
+ String[] parts = address.split(" ");
+ if (parts.length != 3) {
+ return null;
+ }
+ int slash = parts[2].indexOf('/');
+ return (slash < 0) ? parts[2] : parts[2].substring(0, slash);
+ }
+
+ /**
+ * Sets the connection address. The field will be removed if the address
+ * is {@code null}.
+ */
+ public void setAddress(String address) {
+ if (address != null) {
+ address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") +
+ address;
+ }
+ set("c", '=', address);
+ }
+
+ /**
+ * Returns the encryption method or {@code null} if it is not present.
+ */
+ public String getEncryptionMethod() {
+ String encryption = get("k", '=');
+ if (encryption == null) {
+ return null;
+ }
+ int colon = encryption.indexOf(':');
+ return (colon == -1) ? encryption : encryption.substring(0, colon);
+ }
+
+ /**
+ * Returns the encryption key or {@code null} if it is not present.
+ */
+ public String getEncryptionKey() {
+ String encryption = get("k", '=');
+ if (encryption == null) {
+ return null;
+ }
+ int colon = encryption.indexOf(':');
+ return (colon == -1) ? null : encryption.substring(0, colon + 1);
+ }
+
+ /**
+ * Sets the encryption method and the encryption key. The field will be
+ * removed if the method is {@code null}.
+ */
+ public void setEncryption(String method, String key) {
+ set("k", '=', (method == null || key == null) ?
+ method : method + ':' + key);
+ }
+
+ /**
+ * Returns the types of the bandwidth limits.
+ */
+ public String[] getBandwidthTypes() {
+ return cut("b=", ':');
+ }
+
+ /**
+ * Returns the bandwidth limit of the given type or {@code -1} if it is
+ * not present.
+ */
+ public int getBandwidth(String type) {
+ String value = get("b=" + type, ':');
+ if (value != null) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) { }
+ setBandwidth(type, -1);
+ }
+ return -1;
+ }
+
+ /**
+ * Sets the bandwith limit for the given type. The field will be removed
+ * if the value is negative.
+ */
+ public void setBandwidth(String type, int value) {
+ set("b=" + type, ':', (value < 0) ? null : String.valueOf(value));
+ }
+
+ /**
+ * Returns the names of all the attributes.
+ */
+ public String[] getAttributeNames() {
+ return cut("a=", ':');
+ }
+
+ /**
+ * Returns the attribute of the given name or {@code null} if it is not
+ * present.
+ */
+ public String getAttribute(String name) {
+ return get("a=" + name, ':');
+ }
+
+ /**
+ * Sets the attribute for the given name. The field will be removed if
+ * the value is {@code null}. To set a binary attribute, use an empty
+ * string as the value.
+ */
+ public void setAttribute(String name, String value) {
+ set("a=" + name, ':', value);
+ }
+
+ private void write(StringBuilder buffer) {
+ for (int i = 0; i < mOrder.length(); ++i) {
+ char type = mOrder.charAt(i);
+ for (String line : mLines) {
+ if (line.charAt(0) == type) {
+ buffer.append(line).append("\r\n");
+ }
+ }
+ }
+ }
+
+ /**
+ * Invokes {@link #set} after splitting the line into three parts.
+ */
+ private void parse(String line) {
+ char type = line.charAt(0);
+ if (mOrder.indexOf(type) == -1) {
+ return;
+ }
+ char delimiter = '=';
+ if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) {
+ delimiter = ' ';
+ } else if (type == 'b' || type == 'a') {
+ delimiter = ':';
+ }
+ int i = line.indexOf(delimiter);
+ if (i == -1) {
+ set(line, delimiter, "");
+ } else {
+ set(line.substring(0, i), delimiter, line.substring(i + 1));
+ }
+ }
+
+ /**
+ * Finds the key with the given prefix and returns its suffix.
+ */
+ private String[] cut(String prefix, char delimiter) {
+ String[] names = new String[mLines.size()];
+ int length = 0;
+ for (String line : mLines) {
+ if (line.startsWith(prefix)) {
+ int i = line.indexOf(delimiter);
+ if (i == -1) {
+ i = line.length();
+ }
+ names[length] = line.substring(prefix.length(), i);
+ ++length;
+ }
+ }
+ return Arrays.copyOf(names, length);
+ }
+
+ /**
+ * Returns the index of the key.
+ */
+ private int find(String key, char delimiter) {
+ int length = key.length();
+ for (int i = mLines.size() - 1; i >= 0; --i) {
+ String line = mLines.get(i);
+ if (line.startsWith(key) && (line.length() == length ||
+ line.charAt(length) == delimiter)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Sets the key with the value or removes the key if the value is
+ * {@code null}.
+ */
+ private void set(String key, char delimiter, String value) {
+ int index = find(key, delimiter);
+ if (value != null) {
+ if (value.length() != 0) {
+ key = key + delimiter + value;
+ }
+ if (index == -1) {
+ mLines.add(key);
+ } else {
+ mLines.set(index, key);
+ }
+ } else if (index != -1) {
+ mLines.remove(index);
+ }
+ }
+
+ /**
+ * Returns the value of the key.
+ */
+ private String get(String key, char delimiter) {
+ int index = find(key, delimiter);
+ if (index == -1) {
+ return null;
+ }
+ String line = mLines.get(index);
+ int length = key.length();
+ return (line.length() == length) ? "" : line.substring(length + 1);
+ }
+ }
+}
diff --git a/voip/java/android/net/sip/SipAudioCallImpl.java b/voip/java/android/net/sip/SipAudioCallImpl.java
index 8cd41db..5eecc05 100644
--- a/voip/java/android/net/sip/SipAudioCallImpl.java
+++ b/voip/java/android/net/sip/SipAudioCallImpl.java
@@ -16,8 +16,6 @@
package android.net.sip;
-import gov.nist.javax.sdp.fields.SDPKeywords;
-
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
@@ -28,6 +26,7 @@
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
import android.net.rtp.RtpStream;
+import android.net.sip.SimpleSessionDescription.Media;
import android.net.wifi.WifiManager;
import android.os.Message;
import android.os.RemoteException;
@@ -38,15 +37,13 @@
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.sdp.SdpException;
/**
- * Class that handles an audio call over SIP.
+ * Class that handles an audio call over SIP.
*/
/** @hide */
public class SipAudioCallImpl extends SipSessionAdapter
@@ -54,20 +51,19 @@
private static final String TAG = SipAudioCallImpl.class.getSimpleName();
private static final boolean RELEASE_SOCKET = true;
private static final boolean DONT_RELEASE_SOCKET = false;
- private static final String AUDIO = "audio";
- private static final int DTMF = 101;
private static final int SESSION_TIMEOUT = 5; // in seconds
private Context mContext;
private SipProfile mLocalProfile;
private SipAudioCall.Listener mListener;
private ISipSession mSipSession;
- private SdpSessionDescription mPeerSd;
+
+ private long mSessionId = System.currentTimeMillis();
+ private String mPeerSd;
private AudioStream mAudioStream;
private AudioGroup mAudioGroup;
- private SdpSessionDescription.AudioCodec mCodec;
- private long mSessionId = -1L; // SDP session ID
+
private boolean mInCall = false;
private boolean mMuted = false;
private boolean mHold = false;
@@ -146,7 +142,7 @@
mInCall = false;
mHold = false;
- mSessionId = -1L;
+ mSessionId = System.currentTimeMillis();
mErrorCode = SipErrorCode.NO_ERROR;
mErrorMessage = null;
@@ -226,8 +222,8 @@
// session changing request
try {
- mPeerSd = new SdpSessionDescription(sessionDescription);
- answerCall(SESSION_TIMEOUT);
+ String answer = createAnswer(sessionDescription).encode();
+ mSipSession.answerCall(answer, SESSION_TIMEOUT);
} catch (Throwable e) {
Log.e(TAG, "onRinging()", e);
session.endCall();
@@ -242,12 +238,8 @@
String sessionDescription) {
stopRingbackTone();
stopRinging();
- try {
- mPeerSd = new SdpSessionDescription(sessionDescription);
- Log.d(TAG, "sip call established: " + mPeerSd);
- } catch (SdpException e) {
- Log.e(TAG, "createSessionDescription()", e);
- }
+ mPeerSd = sessionDescription;
+ Log.v(TAG, "onCallEstablished()" + mPeerSd);
Listener listener = mListener;
if (listener != null) {
@@ -332,10 +324,10 @@
public synchronized void attachCall(ISipSession session,
String sessionDescription) throws SipException {
mSipSession = session;
+ mPeerSd = sessionDescription;
+ Log.v(TAG, "attachCall()" + mPeerSd);
try {
- mPeerSd = new SdpSessionDescription(sessionDescription);
session.setListener(this);
-
if (getState() == SipSessionState.INCOMING_CALL) startRinging();
} catch (Throwable e) {
Log.e(TAG, "attachCall()", e);
@@ -351,8 +343,8 @@
throw new SipException(
"Failed to create SipSession; network available?");
}
- mSipSession.makeCall(peerProfile, createOfferSessionDescription(),
- timeout);
+ mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
+ mSipSession.makeCall(peerProfile, createOffer().encode(), timeout);
} catch (Throwable e) {
if (e instanceof SipException) {
throw (SipException) e;
@@ -365,7 +357,7 @@
public synchronized void endCall() throws SipException {
try {
stopRinging();
- stopCall(true);
+ stopCall(RELEASE_SOCKET);
mInCall = false;
// perform the above local ops first and then network op
@@ -375,123 +367,131 @@
}
}
- public synchronized void holdCall(int timeout) throws SipException {
- if (mHold) return;
- try {
- mSipSession.changeCall(createHoldSessionDescription(), timeout);
- mHold = true;
- } catch (Throwable e) {
- throwSipException(e);
- }
-
- AudioGroup audioGroup = getAudioGroup();
- if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
- }
-
public synchronized void answerCall(int timeout) throws SipException {
try {
stopRinging();
- mSipSession.answerCall(createAnswerSessionDescription(), timeout);
+ mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
+ mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
} catch (Throwable e) {
Log.e(TAG, "answerCall()", e);
throwSipException(e);
}
}
- public synchronized void continueCall(int timeout) throws SipException {
- if (!mHold) return;
+ public synchronized void holdCall(int timeout) throws SipException {
+ if (mHold) return;
try {
- mHold = false;
- mSipSession.changeCall(createContinueSessionDescription(), timeout);
+ mSipSession.changeCall(createHoldOffer().encode(), timeout);
} catch (Throwable e) {
throwSipException(e);
}
+ mHold = true;
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ }
+ public synchronized void continueCall(int timeout) throws SipException {
+ if (!mHold) return;
+ try {
+ mSipSession.changeCall(createContinueOffer().encode(), timeout);
+ } catch (Throwable e) {
+ throwSipException(e);
+ }
+ mHold = false;
AudioGroup audioGroup = getAudioGroup();
if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_NORMAL);
}
- private String createOfferSessionDescription() {
- AudioCodec[] codecs = AudioCodec.getSystemSupportedCodecs();
- return createSdpBuilder(true, convert(codecs)).build();
- }
-
- private String createAnswerSessionDescription() {
- try {
- // choose an acceptable media from mPeerSd to answer
- SdpSessionDescription.AudioCodec codec = getCodec(mPeerSd);
- SdpSessionDescription.Builder sdpBuilder =
- createSdpBuilder(false, codec);
- if (mPeerSd.isSendOnly(AUDIO)) {
- sdpBuilder.addMediaAttribute(AUDIO, "recvonly", (String) null);
- } else if (mPeerSd.isReceiveOnly(AUDIO)) {
- sdpBuilder.addMediaAttribute(AUDIO, "sendonly", (String) null);
- }
- return sdpBuilder.build();
- } catch (SdpException e) {
- throw new RuntimeException(e);
+ private SimpleSessionDescription createOffer() {
+ SimpleSessionDescription offer =
+ new SimpleSessionDescription(mSessionId, getLocalIp());
+ AudioCodec[] codecs = AudioCodec.getCodecs();
+ Media media = offer.newMedia(
+ "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP");
+ for (AudioCodec codec : AudioCodec.getCodecs()) {
+ media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp);
}
+ media.setRtpPayload(127, "telephone-event/8000", "0-15");
+ return offer;
}
- private String createHoldSessionDescription() {
- try {
- return createSdpBuilder(false, mCodec)
- .addMediaAttribute(AUDIO, "sendonly", (String) null)
- .build();
- } catch (SdpException e) {
- throw new RuntimeException(e);
- }
- }
+ private SimpleSessionDescription createAnswer(String offerSd) {
+ SimpleSessionDescription offer =
+ new SimpleSessionDescription(offerSd);
+ SimpleSessionDescription answer =
+ new SimpleSessionDescription(mSessionId, getLocalIp());
+ AudioCodec codec = null;
+ for (Media media : offer.getMedia()) {
+ if ((codec == null) && (media.getPort() > 0)
+ && "audio".equals(media.getType())
+ && "RTP/AVP".equals(media.getProtocol())) {
+ // Find the first audio codec we supported.
+ for (int type : media.getRtpPayloadTypes()) {
+ codec = AudioCodec.getCodec(type, media.getRtpmap(type),
+ media.getFmtp(type));
+ if (codec != null) {
+ break;
+ }
+ }
+ if (codec != null) {
+ Media reply = answer.newMedia(
+ "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP");
+ reply.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp);
- private String createContinueSessionDescription() {
- return createSdpBuilder(true, mCodec).build();
- }
+ // Check if DTMF is supported in the same media.
+ for (int type : media.getRtpPayloadTypes()) {
+ String rtpmap = media.getRtpmap(type);
+ if ((type != codec.type) && (rtpmap != null)
+ && rtpmap.startsWith("telephone-event")) {
+ reply.setRtpPayload(
+ type, rtpmap, media.getFmtp(type));
+ }
+ }
- private String getMediaDescription(SdpSessionDescription.AudioCodec codec) {
- return String.format("%d %s/%d", codec.payloadType, codec.name,
- codec.sampleRate);
- }
-
- private long getSessionId() {
- if (mSessionId < 0) {
- mSessionId = System.currentTimeMillis();
- }
- return mSessionId;
- }
-
- private SdpSessionDescription.Builder createSdpBuilder(
- boolean addTelephoneEvent,
- SdpSessionDescription.AudioCodec... codecs) {
- String localIp = getLocalIp();
- SdpSessionDescription.Builder sdpBuilder;
- try {
- long sessionVersion = System.currentTimeMillis();
- sdpBuilder = new SdpSessionDescription.Builder("SIP Call")
- .setOrigin(mLocalProfile, getSessionId(), sessionVersion,
- SDPKeywords.IN, SDPKeywords.IPV4, localIp)
- .setConnectionInfo(SDPKeywords.IN, SDPKeywords.IPV4,
- localIp);
- List<Integer> codecIds = new ArrayList<Integer>();
- for (SdpSessionDescription.AudioCodec codec : codecs) {
- codecIds.add(codec.payloadType);
+ // Handle recvonly and sendonly.
+ if (media.getAttribute("recvonly") != null) {
+ answer.setAttribute("sendonly", "");
+ } else if(media.getAttribute("sendonly") != null) {
+ answer.setAttribute("recvonly", "");
+ } else if(offer.getAttribute("recvonly") != null) {
+ answer.setAttribute("sendonly", "");
+ } else if(offer.getAttribute("sendonly") != null) {
+ answer.setAttribute("recvonly", "");
+ }
+ continue;
+ }
}
- if (addTelephoneEvent) codecIds.add(DTMF);
- sdpBuilder.addMedia(AUDIO, getLocalMediaPort(), 1, "RTP/AVP",
- codecIds.toArray(new Integer[codecIds.size()]));
- for (SdpSessionDescription.AudioCodec codec : codecs) {
- sdpBuilder.addMediaAttribute(AUDIO, "rtpmap",
- getMediaDescription(codec));
+ // Reject the media.
+ Media reply = answer.newMedia(
+ media.getType(), 0, 1, media.getProtocol());
+ for (String format : media.getFormats()) {
+ reply.setFormat(format, null);
}
- if (addTelephoneEvent) {
- sdpBuilder.addMediaAttribute(AUDIO, "rtpmap",
- DTMF + " telephone-event/8000");
- }
- // FIXME: deal with vbr codec
- sdpBuilder.addMediaAttribute(AUDIO, "ptime", "20");
- } catch (SdpException e) {
- throw new RuntimeException(e);
}
- return sdpBuilder;
+ if (codec == null) {
+ throw new IllegalStateException("Reject SDP: no suitable codecs");
+ }
+ return answer;
+ }
+
+ private SimpleSessionDescription createHoldOffer() {
+ SimpleSessionDescription offer = createContinueOffer();
+ offer.setAttribute("sendonly", "");
+ return offer;
+ }
+
+ private SimpleSessionDescription createContinueOffer() {
+ SimpleSessionDescription offer =
+ new SimpleSessionDescription(mSessionId, getLocalIp());
+ Media media = offer.newMedia(
+ "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP");
+ AudioCodec codec = mAudioStream.getCodec();
+ media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp);
+ int dtmfType = mAudioStream.getDtmfType();
+ if (dtmfType != -1) {
+ media.setRtpPayload(dtmfType, "telephone-event/8000", "0-15");
+ }
+ return offer;
}
public synchronized void toggleMute() {
@@ -532,49 +532,16 @@
public synchronized AudioGroup getAudioGroup() {
if (mAudioGroup != null) return mAudioGroup;
- return ((mAudioStream == null) ? null : mAudioStream.getAudioGroup());
+ return ((mAudioStream == null) ? null : mAudioStream.getGroup());
}
public synchronized void setAudioGroup(AudioGroup group) {
- if ((mAudioStream != null) && (mAudioStream.getAudioGroup() != null)) {
+ if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
mAudioStream.join(group);
}
mAudioGroup = group;
}
- private SdpSessionDescription.AudioCodec getCodec(SdpSessionDescription sd) {
- HashMap<String, AudioCodec> acceptableCodecs =
- new HashMap<String, AudioCodec>();
- for (AudioCodec codec : AudioCodec.getSystemSupportedCodecs()) {
- acceptableCodecs.put(codec.name, codec);
- }
- for (SdpSessionDescription.AudioCodec codec : sd.getAudioCodecs()) {
- AudioCodec matchedCodec = acceptableCodecs.get(codec.name);
- if (matchedCodec != null) return codec;
- }
- Log.w(TAG, "no common codec is found, use PCM/0");
- return convert(AudioCodec.ULAW);
- }
-
- private AudioCodec convert(SdpSessionDescription.AudioCodec codec) {
- AudioCodec c = AudioCodec.getSystemSupportedCodec(codec.name);
- return ((c == null) ? AudioCodec.ULAW : c);
- }
-
- private SdpSessionDescription.AudioCodec convert(AudioCodec codec) {
- return new SdpSessionDescription.AudioCodec(codec.defaultType,
- codec.name, codec.sampleRate, codec.sampleCount);
- }
-
- private SdpSessionDescription.AudioCodec[] convert(AudioCodec[] codecs) {
- SdpSessionDescription.AudioCodec[] copies =
- new SdpSessionDescription.AudioCodec[codecs.length];
- for (int i = 0, len = codecs.length; i < len; i++) {
- copies[i] = convert(codecs[i]);
- }
- return copies;
- }
-
public void startAudio() {
try {
startAudioInternal();
@@ -588,41 +555,75 @@
}
private synchronized void startAudioInternal() throws UnknownHostException {
+ if (mPeerSd == null) {
+ Log.v(TAG, "startAudioInternal() mPeerSd = null");
+ throw new IllegalStateException("mPeerSd = null");
+ }
+
stopCall(DONT_RELEASE_SOCKET);
mInCall = true;
- SdpSessionDescription peerSd = mPeerSd;
- String peerMediaAddress = peerSd.getPeerMediaAddress(AUDIO);
- // TODO: handle multiple media fields
- int peerMediaPort = peerSd.getPeerMediaPort(AUDIO);
- Log.i(TAG, "start audiocall " + peerMediaAddress + ":" + peerMediaPort);
- int localPort = getLocalMediaPort();
- int sampleRate = 8000;
- int frameSize = sampleRate / 50; // 160
+ // Run exact the same logic in createAnswer() to setup mAudioStream.
+ SimpleSessionDescription offer =
+ new SimpleSessionDescription(mPeerSd);
+ AudioStream stream = mAudioStream;
+ AudioCodec codec = null;
+ for (Media media : offer.getMedia()) {
+ if ((codec == null) && (media.getPort() > 0)
+ && "audio".equals(media.getType())
+ && "RTP/AVP".equals(media.getProtocol())) {
+ // Find the first audio codec we supported.
+ for (int type : media.getRtpPayloadTypes()) {
+ codec = AudioCodec.getCodec(
+ type, media.getRtpmap(type), media.getFmtp(type));
+ if (codec != null) {
+ break;
+ }
+ }
- // TODO: get sample rate from sdp
- mCodec = getCodec(peerSd);
+ if (codec != null) {
+ // Associate with the remote host.
+ String address = media.getAddress();
+ if (address == null) {
+ address = offer.getAddress();
+ }
+ stream.associate(InetAddress.getByName(address),
+ media.getPort());
- AudioStream audioStream = mAudioStream;
- audioStream.associate(InetAddress.getByName(peerMediaAddress),
- peerMediaPort);
- audioStream.setCodec(convert(mCodec), mCodec.payloadType);
- audioStream.setDtmfType(DTMF);
- Log.d(TAG, "start media: localPort=" + localPort + ", peer="
- + peerMediaAddress + ":" + peerMediaPort);
+ stream.setDtmfType(-1);
+ stream.setCodec(codec);
+ // Check if DTMF is supported in the same media.
+ for (int type : media.getRtpPayloadTypes()) {
+ String rtpmap = media.getRtpmap(type);
+ if ((type != codec.type) && (rtpmap != null)
+ && rtpmap.startsWith("telephone-event")) {
+ stream.setDtmfType(type);
+ }
+ }
- audioStream.setMode(RtpStream.MODE_NORMAL);
+ // Handle recvonly and sendonly.
+ if (mHold) {
+ stream.setMode(RtpStream.MODE_NORMAL);
+ } else if (media.getAttribute("recvonly") != null) {
+ stream.setMode(RtpStream.MODE_SEND_ONLY);
+ } else if(media.getAttribute("sendonly") != null) {
+ stream.setMode(RtpStream.MODE_RECEIVE_ONLY);
+ } else if(offer.getAttribute("recvonly") != null) {
+ stream.setMode(RtpStream.MODE_SEND_ONLY);
+ } else if(offer.getAttribute("sendonly") != null) {
+ stream.setMode(RtpStream.MODE_RECEIVE_ONLY);
+ } else {
+ stream.setMode(RtpStream.MODE_NORMAL);
+ }
+ break;
+ }
+ }
+ }
+ if (codec == null) {
+ throw new IllegalStateException("Reject SDP: no suitable codecs");
+ }
+
if (!mHold) {
- // FIXME: won't work if peer is not sending nor receiving
- if (!peerSd.isSending(AUDIO)) {
- Log.d(TAG, " not receiving");
- audioStream.setMode(RtpStream.MODE_SEND_ONLY);
- }
- if (!peerSd.isReceiving(AUDIO)) {
- Log.d(TAG, " not sending");
- audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY);
- }
-
/* The recorder volume will be very low if the device is in
* IN_CALL mode. Therefore, we have to set the mode to NORMAL
* in order to have the normal microphone level.
@@ -642,7 +643,7 @@
// there's another AudioGroup out there that's active
} else {
if (audioGroup == null) audioGroup = new AudioGroup();
- audioStream.join(audioGroup);
+ mAudioStream.join(audioGroup);
if (mMuted) {
audioGroup.setMode(AudioGroup.MODE_MUTED);
} else {
@@ -663,24 +664,11 @@
}
}
- private int getLocalMediaPort() {
- if (mAudioStream != null) return mAudioStream.getLocalPort();
- try {
- AudioStream s = mAudioStream =
- new AudioStream(InetAddress.getByName(getLocalIp()));
- return s.getLocalPort();
- } catch (IOException e) {
- Log.w(TAG, "getLocalMediaPort(): " + e);
- throw new RuntimeException(e);
- }
- }
-
private String getLocalIp() {
try {
return mSipSession.getLocalIp();
} catch (RemoteException e) {
- // FIXME
- return "127.0.0.1";
+ throw new IllegalStateException(e);
}
}
diff --git a/voip/jni/rtp/AudioCodec.cpp b/voip/jni/rtp/AudioCodec.cpp
index ddd07fc..4d8d36c 100644
--- a/voip/jni/rtp/AudioCodec.cpp
+++ b/voip/jni/rtp/AudioCodec.cpp
@@ -36,9 +36,9 @@
class UlawCodec : public AudioCodec
{
public:
- bool set(int sampleRate, int sampleCount) {
- mSampleCount = sampleCount;
- return sampleCount > 0;
+ int set(int sampleRate, const char *fmtp) {
+ mSampleCount = sampleRate / 50;
+ return mSampleCount;
}
int encode(void *payload, int16_t *samples);
int decode(int16_t *samples, void *payload, int length);
@@ -89,9 +89,9 @@
class AlawCodec : public AudioCodec
{
public:
- bool set(int sampleRate, int sampleCount) {
- mSampleCount = sampleCount;
- return sampleCount > 0;
+ int set(int sampleRate, const char *fmtp) {
+ mSampleCount = sampleRate / 50;
+ return mSampleCount;
}
int encode(void *payload, int16_t *samples);
int decode(int16_t *samples, void *payload, int length);
@@ -152,8 +152,10 @@
{
AudioCodecType *type = gAudioCodecTypes;
while (type->name != NULL) {
- if (strcmp(codecName, type->name) == 0) {
- return type->create();
+ if (strcasecmp(codecName, type->name) == 0) {
+ AudioCodec *codec = type->create();
+ codec->name = type->name;
+ return codec;
}
++type;
}
diff --git a/voip/jni/rtp/AudioCodec.h b/voip/jni/rtp/AudioCodec.h
index 797494c..e389255 100644
--- a/voip/jni/rtp/AudioCodec.h
+++ b/voip/jni/rtp/AudioCodec.h
@@ -22,9 +22,11 @@
class AudioCodec
{
public:
+ const char *name;
+ // Needed by destruction through base class pointers.
virtual ~AudioCodec() {}
- // Returns true if initialization succeeds.
- virtual bool set(int sampleRate, int sampleCount) = 0;
+ // Returns sampleCount or non-positive value if unsupported.
+ virtual int set(int sampleRate, const char *fmtp) = 0;
// Returns the length of payload in bytes.
virtual int encode(void *payload, int16_t *samples) = 0;
// Returns the number of decoded samples.
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 3433dcf..7cf06137 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -77,7 +77,7 @@
AudioStream();
~AudioStream();
bool set(int mode, int socket, sockaddr_storage *remote,
- const char *codecName, int sampleRate, int sampleCount,
+ AudioCodec *codec, int sampleRate, int sampleCount,
int codecType, int dtmfType);
void sendDtmf(int event);
@@ -104,6 +104,7 @@
int mSampleRate;
int mSampleCount;
int mInterval;
+ int mLogThrottle;
int16_t *mBuffer;
int mBufferMask;
@@ -140,7 +141,7 @@
}
bool AudioStream::set(int mode, int socket, sockaddr_storage *remote,
- const char *codecName, int sampleRate, int sampleCount,
+ AudioCodec *codec, int sampleRate, int sampleCount,
int codecType, int dtmfType)
{
if (mode < 0 || mode > LAST_MODE) {
@@ -148,14 +149,6 @@
}
mMode = mode;
- if (codecName) {
- mRemote = *remote;
- mCodec = newAudioCodec(codecName);
- if (!mCodec || !mCodec->set(sampleRate, sampleCount)) {
- return false;
- }
- }
-
mCodecMagic = (0x8000 | codecType) << 16;
mDtmfMagic = (dtmfType == -1) ? 0 : (0x8000 | dtmfType) << 16;
@@ -181,11 +174,15 @@
mDtmfEvent = -1;
mDtmfStart = 0;
- // Only take over the socket when succeeded.
+ // Only take over these things when succeeded.
mSocket = socket;
+ if (codec) {
+ mRemote = *remote;
+ mCodec = codec;
+ }
LOGD("stream[%d] is configured as %s %dkHz %dms", mSocket,
- (codecName ? codecName : "RAW"), mSampleRate, mInterval);
+ (codec ? codec->name : "RAW"), mSampleRate, mInterval);
return true;
}
@@ -282,7 +279,10 @@
chain = chain->mNext;
}
if (!mixed) {
- LOGD("stream[%d] no data", mSocket);
+ if ((mTick ^ mLogThrottle) >> 10) {
+ mLogThrottle = mTick;
+ LOGD("stream[%d] no data", mSocket);
+ }
return;
}
@@ -831,10 +831,9 @@
void add(JNIEnv *env, jobject thiz, jint mode,
jint socket, jstring jRemoteAddress, jint remotePort,
- jstring jCodecName, jint sampleRate, jint sampleCount,
- jint codecType, jint dtmfType)
+ jstring jCodecSpec, jint dtmfType)
{
- const char *codecName = NULL;
+ AudioCodec *codec = NULL;
AudioStream *stream = NULL;
AudioGroup *group = NULL;
@@ -842,33 +841,42 @@
sockaddr_storage remote;
if (parse(env, jRemoteAddress, remotePort, &remote) < 0) {
// Exception already thrown.
- goto error;
+ return;
}
- if (sampleRate < 0 || sampleCount < 0 || codecType < 0 || codecType > 127) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- goto error;
+ if (!jCodecSpec) {
+ jniThrowNullPointerException(env, "codecSpec");
+ return;
}
- if (!jCodecName) {
- jniThrowNullPointerException(env, "codecName");
- goto error;
- }
- codecName = env->GetStringUTFChars(jCodecName, NULL);
- if (!codecName) {
+ const char *codecSpec = env->GetStringUTFChars(jCodecSpec, NULL);
+ if (!codecSpec) {
// Exception already thrown.
+ return;
+ }
+
+ // Create audio codec.
+ int codecType = -1;
+ char codecName[16];
+ int sampleRate = -1;
+ sscanf(codecSpec, "%d %[^/]%*c%d", &codecType, codecName, &sampleRate);
+ codec = newAudioCodec(codecName);
+ int sampleCount = (codec ? codec->set(sampleRate, codecSpec) : -1);
+ env->ReleaseStringUTFChars(jCodecSpec, codecSpec);
+ if (sampleCount <= 0) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot initialize audio codec");
goto error;
}
// Create audio stream.
stream = new AudioStream;
- if (!stream->set(mode, socket, &remote, codecName, sampleRate, sampleCount,
+ if (!stream->set(mode, socket, &remote, codec, sampleRate, sampleCount,
codecType, dtmfType)) {
jniThrowException(env, "java/lang/IllegalStateException",
"cannot initialize audio stream");
- env->ReleaseStringUTFChars(jCodecName, codecName);
goto error;
}
- env->ReleaseStringUTFChars(jCodecName, codecName);
socket = -1;
+ codec = NULL;
// Create audio group.
group = (AudioGroup *)env->GetIntField(thiz, gNative);
@@ -896,6 +904,7 @@
error:
delete group;
delete stream;
+ delete codec;
close(socket);
env->SetIntField(thiz, gNative, NULL);
}
@@ -930,7 +939,7 @@
}
JNINativeMethod gMethods[] = {
- {"add", "(IILjava/lang/String;ILjava/lang/String;IIII)V", (void *)add},
+ {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add},
{"remove", "(I)V", (void *)remove},
{"setMode", "(I)V", (void *)setMode},
{"sendDtmf", "(I)V", (void *)sendDtmf},
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index e73bca0..f760d27 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -105,5 +105,9 @@
void saveNetwork(in WifiConfiguration wifiConfig);
void forgetNetwork(int networkId);
+
+ void startWpsPbc(String bssid);
+
+ void startWpsPin(String bssid, int apPin);
}
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index dfa9f75..7ea4872 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -23,6 +23,7 @@
import android.net.wifi.WifiConfiguration.IpAssignment;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.Status;
+import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
@@ -95,9 +96,9 @@
* and enable all stored networks in supplicant.
*/
static void initialize(Context context) {
- Log.d(TAG, "Updating config and enabling all networks");
+ Log.d(TAG, "Loading config and enabling all networks");
sContext = context;
- updateConfiguredNetworks();
+ loadConfiguredNetworks();
enableAllNetworks();
}
@@ -150,7 +151,7 @@
static void selectNetwork(WifiConfiguration config) {
if (config != null) {
int netId = addOrUpdateNetworkNative(config);
- if (netId != -1) {
+ if (netId != INVALID_NETWORK_ID) {
selectNetwork(netId);
} else {
Log.e(TAG, "Failed to update network " + config);
@@ -174,7 +175,7 @@
if (sLastPriority == -1 || sLastPriority > 1000000) {
synchronized (sConfiguredNetworks) {
for(WifiConfiguration config : sConfiguredNetworks.values()) {
- if (config.networkId != -1) {
+ if (config.networkId != INVALID_NETWORK_ID) {
config.priority = 0;
addOrUpdateNetworkNative(config);
}
@@ -204,10 +205,10 @@
* @param config WifiConfiguration to be saved
*/
static void saveNetwork(WifiConfiguration config) {
- boolean newNetwork = (config.networkId == -1);
+ boolean newNetwork = (config.networkId == INVALID_NETWORK_ID);
int netId = addOrUpdateNetworkNative(config);
/* enable a new network */
- if (newNetwork && netId >= 0) {
+ if (newNetwork && netId != INVALID_NETWORK_ID) {
WifiNative.enableNetworkCommand(netId, false);
synchronized (sConfiguredNetworks) {
sConfiguredNetworks.get(netId).status = Status.ENABLED;
@@ -288,13 +289,7 @@
}
if (disableOthers) {
- synchronized (sConfiguredNetworks) {
- for(WifiConfiguration config : sConfiguredNetworks.values()) {
- if(config != null && config.networkId != netId) {
- config.status = Status.DISABLED;
- }
- }
- }
+ markAllNetworksDisabledExcept(netId);
}
return ret;
}
@@ -321,6 +316,32 @@
}
/**
+ * Start WPS pin method configuration
+ */
+ static boolean startWpsPin(String bssid, int apPin) {
+ if (WifiNative.startWpsPinCommand(bssid, apPin)) {
+ /* WPS leaves all networks disabled */
+ markAllNetworksDisabled();
+ return true;
+ }
+ Log.e(TAG, "Failed to start WPS pin method configuration");
+ return false;
+ }
+
+ /**
+ * Start WPS push button configuration
+ */
+ static boolean startWpsPbc(String bssid) {
+ if (WifiNative.startWpsPbcCommand(bssid)) {
+ /* WPS leaves all networks disabled */
+ markAllNetworksDisabled();
+ return true;
+ }
+ Log.e(TAG, "Failed to start WPS push button configuration");
+ return false;
+ }
+
+ /**
* Fetch the IP configuration for a given network id
*/
static DhcpInfo getIpConfiguration(int netId) {
@@ -350,7 +371,7 @@
sContext.sendBroadcast(intent);
}
- private static void updateConfiguredNetworks() {
+ static void loadConfiguredNetworks() {
String listStr = WifiNative.listNetworksCommand();
sLastPriority = 0;
@@ -391,6 +412,22 @@
}
}
readIpConfigurations();
+ sendConfigChangeBroadcast();
+ }
+
+ /* Mark all networks except specified netId as disabled */
+ private static void markAllNetworksDisabledExcept(int netId) {
+ synchronized (sConfiguredNetworks) {
+ for(WifiConfiguration config : sConfiguredNetworks.values()) {
+ if(config != null && config.networkId != netId) {
+ config.status = Status.DISABLED;
+ }
+ }
+ }
+ }
+
+ private static void markAllNetworksDisabled() {
+ markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
}
private static void writeIpConfigurations() {
@@ -513,20 +550,20 @@
private static int addOrUpdateNetworkNative(WifiConfiguration config) {
/*
- * If the supplied networkId is -1, we create a new empty
+ * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty
* network configuration. Otherwise, the networkId should
* refer to an existing configuration.
*/
int netId = config.networkId;
boolean updateFailed = true;
- boolean newNetwork = netId == -1;
- // networkId of -1 means we want to create a new network
+ boolean newNetwork = (netId == INVALID_NETWORK_ID);
+ // networkId of INVALID_NETWORK_ID means we want to create a new network
if (newNetwork) {
netId = WifiNative.addNetworkCommand();
if (netId < 0) {
Log.e(TAG, "Failed to add a network!");
- return -1;
+ return INVALID_NETWORK_ID;
}
}
@@ -700,7 +737,7 @@
"Failed to set a network variable, removed network: "
+ netId);
}
- return -1;
+ return INVALID_NETWORK_ID;
}
/* An update of the network variables requires reading them
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 8971bdd..57e9bad 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -43,6 +43,8 @@
public static final String priorityVarName = "priority";
/** {@hide} */
public static final String hiddenSSIDVarName = "scan_ssid";
+ /** {@hide} */
+ public static final int INVALID_NETWORK_ID = -1;
/** {@hide} */
public class EnterpriseField {
@@ -313,7 +315,7 @@
public DhcpInfo ipConfig;
public WifiConfiguration() {
- networkId = -1;
+ networkId = INVALID_NETWORK_ID;
SSID = null;
BSSID = null;
priority = 0;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4435110..0b3a782 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1037,6 +1037,32 @@
}
/**
+ * Start Wi-fi protected setup push button Configuration
+ *
+ * @param bssid BSSID of the access point
+ * @hide
+ */
+ public void startWpsPbc(String bssid) {
+ try {
+ mService.startWpsPbc(bssid);
+ } catch (RemoteException e) { }
+ }
+
+ /**
+ * Start Wi-fi Protected Setup pin method configuration
+ *
+ * @param bssid BSSID of the access point
+ * @param apPin PIN issued by the access point
+ *
+ * @hide
+ */
+ public void startWpsPin(String bssid, int apPin) {
+ try {
+ mService.startWpsPin(bssid, apPin);
+ } catch (RemoteException e) { }
+ }
+
+ /**
* Allows an application to keep the Wi-Fi radio awake.
* Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
* Acquiring a WifiLock will keep the radio on until the lock is released. Multiple
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 862a61b..1251a25 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -151,6 +151,10 @@
public native static boolean clearBlacklistCommand();
+ public native static boolean startWpsPbcCommand(String bssid);
+
+ public native static boolean startWpsPinCommand(String bssid, int apPin);
+
public native static boolean doDhcpRequest(DhcpInfo results);
public native static String getDhcpError();
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 6fe7529..7e26028 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -151,7 +151,9 @@
/* Connection to a specific network involves disabling all networks,
* this flag tracks if networks need to be re-enabled */
private boolean mEnableAllNetworks = false;
-
+ /* Track if WPS was started since we need to re-enable networks
+ * and load configuration afterwards */
+ private boolean mWpsStarted = false;
// Event log tags (must be in sync with event-log-tags)
private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021;
@@ -299,7 +301,8 @@
* supplicant config.
*/
private static final int CMD_FORGET_NETWORK = 92;
-
+ /* Start Wi-Fi protected setup */
+ private static final int CMD_START_WPS = 93;
/**
@@ -406,7 +409,7 @@
* Keep track of whether WIFI is running.
*/
private boolean mIsRunning = false;
-
+
/**
* Keep track of whether we last told the battery stats we had started.
*/
@@ -765,6 +768,14 @@
sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0));
}
+ public void startWpsPbc(String bssid) {
+ sendMessage(obtainMessage(CMD_START_WPS, bssid));
+ }
+
+ public void startWpsPin(String bssid, int apPin) {
+ sendMessage(obtainMessage(CMD_START_WPS, apPin, 0, bssid));
+ }
+
public void enableRssiPolling(boolean enabled) {
sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0));
}
@@ -1597,6 +1608,7 @@
case CMD_CONNECT_NETWORK:
case CMD_SAVE_NETWORK:
case CMD_FORGET_NETWORK:
+ case CMD_START_WPS:
break;
default:
Log.e(TAG, "Error! unhandled message" + message);
@@ -2355,6 +2367,33 @@
/* Expect a disconnection from the old connection */
transitionTo(mDisconnectingState);
break;
+ case CMD_START_WPS:
+ String bssid = (String) message.obj;
+ int apPin = message.arg1;
+ boolean success;
+ if (apPin != 0) {
+ /* WPS pin method configuration */
+ success = WifiConfigStore.startWpsPin(bssid, apPin);
+ } else {
+ /* WPS push button configuration */
+ success = WifiConfigStore.startWpsPbc(bssid);
+ }
+ /* During WPS setup, all other networks are disabled. After
+ * a successful connect a new config is created in the supplicant.
+ *
+ * We need to enable all networks after a successful connection
+ * or when supplicant goes inactive due to failure. Enabling all
+ * networks after a disconnect is observed as done with connectNetwork
+ * does not lead to a successful WPS setup.
+ *
+ * Upon success, the configuration list needs to be reloaded
+ */
+ if (success) {
+ mWpsStarted = true;
+ /* Expect a disconnection from the old connection */
+ transitionTo(mDisconnectingState);
+ }
+ break;
case SCAN_RESULTS_EVENT:
/* Set the scan setting back to "connect" mode */
WifiNative.setScanResultHandlingCommand(CONNECT_MODE);
@@ -2581,6 +2620,12 @@
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
+ /* A successful WPS connection */
+ if (mWpsStarted) {
+ WifiConfigStore.enableAllNetworks();
+ WifiConfigStore.loadConfiguredNetworks();
+ mWpsStarted = false;
+ }
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
}
@Override
@@ -2911,6 +2956,14 @@
@Override
public void enter() {
if (DBG) Log.d(TAG, getName() + "\n");
+
+ /* A failed WPS connection */
+ if (mWpsStarted) {
+ Log.e(TAG, "WPS set up failed, enabling other networks");
+ WifiConfigStore.enableAllNetworks();
+ mWpsStarted = false;
+ }
+
Message message = getCurrentMessage();
StateChangeResult stateChangeResult = (StateChangeResult) message.obj;