summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml4941
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java215
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java21
-rw-r--r--core/java/android/app/ActivityThread.java13
-rw-r--r--core/java/android/app/IActivityController.aidl5
-rw-r--r--core/java/android/net/DownloadManager.java116
-rw-r--r--core/java/android/os/BatteryStats.java24
-rw-r--r--core/java/android/preference/PreferenceFragment.java1
-rw-r--r--core/java/android/preference/PreferenceManager.java30
-rw-r--r--core/java/android/preference/RingtonePreference.java8
-rw-r--r--core/java/android/view/HardwareRenderer.java10
-rw-r--r--core/java/android/view/ViewGroup.java6
-rw-r--r--core/java/android/view/ViewRoot.java63
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java6
-rw-r--r--core/java/android/widget/Button.java60
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java78
-rw-r--r--core/java/com/android/internal/widget/DrawableHolder.java232
-rw-r--r--core/java/com/android/internal/widget/WaveView.java573
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp35
-rw-r--r--core/res/res/drawable-xlarge/unlock_default.pngbin0 -> 4691 bytes
-rw-r--r--core/res/res/drawable-xlarge/unlock_halo.pngbin0 -> 23133 bytes
-rw-r--r--core/res/res/drawable-xlarge/unlock_ring.pngbin0 -> 112512 bytes
-rw-r--r--core/res/res/drawable-xlarge/unlock_wave.pngbin0 -> 112482 bytes
-rw-r--r--core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml9
-rw-r--r--core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml7
-rw-r--r--core/res/res/values-rm/donottranslate-cldr.xml21
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java56
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java2
-rw-r--r--data/fonts/fonts.xml4
-rw-r--r--docs/html/guide/topics/resources/drawable-resource.jd18
-rw-r--r--docs/html/guide/tutorials/notepad/notepad-ex2.jd4
-rw-r--r--docs/html/resources/tutorials/notepad/notepad-ex2.jd4
-rw-r--r--docs/html/sdk/adt_download.jd11
-rw-r--r--docs/html/sdk/eclipse-adt.jd45
-rw-r--r--docs/html/sdk/requirements.jd2
-rw-r--r--docs/html/sdk/sdk_toc.cs2
-rw-r--r--libs/rs/java/Samples/src/com/android/samples/RsList.java4
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java89
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/RSTestView.java44
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java39
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java41
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/UnitTest.java61
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs9
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/primitives.rs25
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/rslist.rs86
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/shared.rsh5
-rw-r--r--media/java/android/media/AudioTrack.java15
-rw-r--r--media/java/android/media/MediaPlayer.java7
-rw-r--r--media/java/android/media/MtpDatabase.java31
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java (renamed from media/java/android/media/AudioEffect.java)176
-rw-r--r--media/java/android/media/audiofx/BassBoost.java (renamed from media/java/android/media/BassBoost.java)21
-rw-r--r--media/java/android/media/audiofx/EnvironmentalReverb.java (renamed from media/java/android/media/EnvironmentalReverb.java)23
-rw-r--r--media/java/android/media/audiofx/Equalizer.java (renamed from media/java/android/media/Equalizer.java)13
-rw-r--r--media/java/android/media/audiofx/PresetReverb.java (renamed from media/java/android/media/PresetReverb.java)14
-rw-r--r--media/java/android/media/audiofx/Virtualizer.java (renamed from media/java/android/media/Virtualizer.java)13
-rwxr-xr-xmedia/java/android/media/audiofx/Visualizer.java (renamed from media/java/android/media/Visualizer.java)8
-rw-r--r--media/java/android/media/audiofx/package.html5
-rwxr-xr-xmedia/java/android/media/videoeditor/Effect.java2
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaItem.java35
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaVideoItem.java15
-rwxr-xr-xmedia/java/android/media/videoeditor/OverlayFrame.java86
-rwxr-xr-xmedia/java/android/media/videoeditor/TransitionAlpha.java14
-rw-r--r--media/java/android/media/videoeditor/VideoEditorTestImpl.java186
-rw-r--r--media/jni/android_media_MtpDatabase.cpp17
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp8
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp2
-rw-r--r--media/libstagefright/MPEG4Writer.cpp10
-rw-r--r--media/mtp/MtpCursor.cpp6
-rw-r--r--media/mtp/MtpCursor.h20
-rw-r--r--media/mtp/MtpServer.cpp7
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaAudioEffectTest.java22
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVisualizerTest.java4
-rw-r--r--opengl/libs/EGL/egl.cpp4
-rw-r--r--opengl/libs/GLES2/gl2.cpp1
-rw-r--r--opengl/libs/GLES_CM/gl.cpp1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java7
-rw-r--r--policy/src/com/android/internal/policy/impl/LockScreen.java231
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java50
-rw-r--r--services/java/com/android/server/ProcessStats.java148
-rw-r--r--services/java/com/android/server/WifiService.java10
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java573
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java28
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java4
-rw-r--r--services/java/com/android/server/sip/SipService.java25
-rw-r--r--services/java/com/android/server/sip/SipSessionGroup.java105
-rw-r--r--services/java/com/android/server/sip/SipSessionListenerProxy.java2
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp21
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h5
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp18
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h1
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhone.java24
-rw-r--r--tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java28
-rw-r--r--tools/aapt/Bundle.h5
-rw-r--r--tools/aapt/Main.cpp13
-rw-r--r--tools/aapt/ResourceTable.cpp82
-rw-r--r--voip/java/android/net/sip/SdpSessionDescription.java428
-rw-r--r--voip/java/android/net/sip/SessionDescription.aidl19
-rw-r--r--voip/java/android/net/sip/SessionDescription.java83
-rw-r--r--voip/java/android/net/sip/SipAudioCall.java957
-rw-r--r--voip/java/android/net/sip/SipAudioCallImpl.java738
-rw-r--r--voip/java/android/net/sip/SipManager.java169
-rw-r--r--voip/java/android/net/sip/SipProfile.java5
-rw-r--r--voip/java/android/net/sip/SipSession.java531
-rw-r--r--voip/java/android/net/sip/SipSessionState.java94
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl4
-rw-r--r--wifi/java/android/net/wifi/WifiConfigStore.java75
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java4
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java26
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java4
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java59
116 files changed, 7123 insertions, 5276 deletions
diff --git a/api/current.xml b/api/current.xml
index 07aabed..80428bd 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21741,6 +21741,17 @@
visibility="public"
>
</method>
+<method name="removeAllUpdateListeners"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="removeUpdateListener"
return="void"
abstract="false"
@@ -94661,1079 +94672,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="&quot;android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION&quot;"
- 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="&quot;android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL&quot;"
- 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="&quot;android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION&quot;"
- 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="&quot;Auxiliary&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EFFECT_INSERT"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;Insert&quot;"
- 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="&quot;android.media.extra.AUDIO_SESSION&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_CONTENT_TYPE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.media.extra.CONTENT_TYPE&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_PACKAGE_NAME"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.media.extra.PACKAGE_NAME&quot;"
- 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"
@@ -98575,217 +97513,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"
@@ -99203,1178 +97930,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"
@@ -103078,270 +100633,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"
@@ -105416,8 +102707,2133 @@
>
</field>
</class>
+</package>
+<package name="android.media.audiofx"
+>
+<class name="AudioEffect"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<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="&quot;android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ 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="&quot;android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL&quot;"
+ 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="&quot;android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ 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="&quot;Auxiliary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EFFECT_INSERT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;Insert&quot;"
+ 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="&quot;android.media.extra.AUDIO_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CONTENT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.CONTENT_TYPE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_PACKAGE_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.PACKAGE_NAME&quot;"
+ 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"
+ 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.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.audiofx.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.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.AudioEffect"
+ extends="android.media.audiofx.AudioEffect"
abstract="false"
static="false"
final="false"
@@ -105425,7 +104841,7 @@
visibility="public"
>
<constructor name="Virtualizer"
- type="android.media.Virtualizer"
+ type="android.media.audiofx.Virtualizer"
static="false"
final="false"
deprecated="not deprecated"
@@ -105445,7 +104861,7 @@
</exception>
</constructor>
<method name="getProperties"
- return="android.media.Virtualizer.Settings"
+ return="android.media.audiofx.Virtualizer.Settings"
abstract="false"
native="false"
synchronized="false"
@@ -105499,7 +104915,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="listener" type="android.media.Virtualizer.OnParameterChangeListener">
+<parameter name="listener" type="android.media.audiofx.Virtualizer.OnParameterChangeListener">
</parameter>
</method>
<method name="setProperties"
@@ -105512,7 +104928,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="settings" type="android.media.Virtualizer.Settings">
+<parameter name="settings" type="android.media.audiofx.Virtualizer.Settings">
</parameter>
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
</exception>
@@ -105580,7 +104996,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>
@@ -105599,7 +105015,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"
@@ -105607,7 +105023,7 @@
>
</constructor>
<constructor name="Virtualizer.Settings"
- type="android.media.Virtualizer.Settings"
+ type="android.media.audiofx.Virtualizer.Settings"
static="false"
final="false"
deprecated="not deprecated"
@@ -105636,7 +105052,7 @@
visibility="public"
>
<constructor name="Visualizer"
- type="android.media.Visualizer"
+ type="android.media.audiofx.Visualizer"
static="false"
final="false"
deprecated="not deprecated"
@@ -105774,7 +105190,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>
@@ -105937,7 +105353,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>
@@ -105954,7 +105370,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>
@@ -106881,6 +106297,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"
@@ -106917,10 +106348,10 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="description" type="java.lang.String">
+<parameter name="description" type="java.lang.CharSequence">
</parameter>
</method>
-<method name="setDestinationUri"
+<method name="setDestinationInExternalFilesDir"
return="android.net.DownloadManager.Request"
abstract="false"
native="false"
@@ -106930,10 +106361,14 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="uri" type="android.net.Uri">
+<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="setMediaType"
+<method name="setDestinationInExternalPublicDir"
return="android.net.DownloadManager.Request"
abstract="false"
native="false"
@@ -106943,10 +106378,12 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="mediaType" type="java.lang.String">
+<parameter name="dirType" type="java.lang.String">
+</parameter>
+<parameter name="subPath" type="java.lang.String">
</parameter>
</method>
-<method name="setRequestHeader"
+<method name="setDestinationUri"
return="android.net.DownloadManager.Request"
abstract="false"
native="false"
@@ -106956,9 +106393,20 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="header" type="java.lang.String">
+<parameter name="uri" type="android.net.Uri">
</parameter>
-<parameter name="value" type="java.lang.String">
+</method>
+<method name="setMimeType"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
</parameter>
</method>
<method name="setShowRunningNotification"
@@ -106984,7 +106432,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"
@@ -107022,17 +106470,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"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index f901bfb..4dee350 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -19,6 +19,7 @@
package com.android.commands.am;
import android.app.ActivityManagerNative;
+import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
import android.app.Instrumentation;
@@ -28,12 +29,18 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.AndroidException;
import android.view.IWindowManager;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.util.Iterator;
@@ -99,6 +106,8 @@ public class Am {
runProfile();
} else if (op.equals("dumpheap")) {
runDumpHeap();
+ } else if (op.equals("monitor")) {
+ runMonitor();
} else {
throw new IllegalArgumentException("Unknown command: " + op);
}
@@ -472,6 +481,210 @@ public class Am {
}
}
+ class MyActivityController extends IActivityController.Stub {
+ static final int STATE_NORMAL = 0;
+ static final int STATE_CRASHED = 1;
+ static final int STATE_EARLY_ANR = 2;
+ static final int STATE_ANR = 3;
+
+ int mState;
+
+ static final int RESULT_DEFAULT = 0;
+
+ static final int RESULT_CRASH_DIALOG = 0;
+ static final int RESULT_CRASH_KILL = 1;
+
+ static final int RESULT_EARLY_ANR_CONTINUE = 0;
+ static final int RESULT_EARLY_ANR_KILL = 1;
+
+ static final int RESULT_ANR_DIALOG = 0;
+ static final int RESULT_ANR_KILL = 1;
+ static final int RESULT_ANR_WAIT = 1;
+
+ int mResult;
+
+ @Override
+ public boolean activityResuming(String pkg) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** Activity resuming: " + pkg);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** Activity starting: " + pkg);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
+ long timeMillis, String stackTrace) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: PROCESS CRASHED");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("shortMsg: " + shortMsg);
+ System.out.println("longMsg: " + longMsg);
+ System.out.println("timeMillis: " + timeMillis);
+ System.out.println("stack:");
+ System.out.print(stackTrace);
+ System.out.println("#");
+ int result = waitControllerLocked(STATE_CRASHED);
+ return result == RESULT_CRASH_KILL ? false : true;
+ }
+ }
+
+ @Override
+ public int appEarlyNotResponding(String processName, int pid, String annotation)
+ throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("annotation: " + annotation);
+ int result = waitControllerLocked(STATE_EARLY_ANR);
+ if (result == RESULT_EARLY_ANR_KILL) return -1;
+ return 0;
+ }
+ }
+
+ @Override
+ public int appNotResponding(String processName, int pid, String processStats)
+ throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: PROCESS NOT RESPONDING");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("processStats:");
+ System.out.print(processStats);
+ System.out.println("#");
+ int result = waitControllerLocked(STATE_ANR);
+ if (result == RESULT_ANR_KILL) return -1;
+ if (result == RESULT_ANR_WAIT) return 1;
+ return 0;
+ }
+ }
+
+ int waitControllerLocked(int state) {
+ mState = state;
+ System.out.println("");
+ printMessageForState();
+
+ while (mState != STATE_NORMAL) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ return mResult;
+ }
+
+ void resumeController(int result) {
+ synchronized (this) {
+ mState = STATE_NORMAL;
+ mResult = result;
+ notifyAll();
+ }
+ }
+
+ void printMessageForState() {
+ switch (mState) {
+ case STATE_NORMAL:
+ System.out.println("Monitoring activity manager... available commands:");
+ break;
+ case STATE_CRASHED:
+ System.out.println("Waiting after crash... available commands:");
+ System.out.println("(c)ontinue: show crash dialog");
+ System.out.println("(k)ill: immediately kill app");
+ break;
+ case STATE_EARLY_ANR:
+ System.out.println("Waiting after early ANR... available commands:");
+ System.out.println("(c)ontinue: standard ANR processing");
+ System.out.println("(k)ill: immediately kill app");
+ break;
+ case STATE_ANR:
+ System.out.println("Waiting after ANR... available commands:");
+ System.out.println("(c)ontinue: show ANR dialog");
+ System.out.println("(k)ill: immediately kill app");
+ System.out.println("(w)ait: wait some more");
+ break;
+ }
+ System.out.println("(q)uit: finish monitoring");
+ }
+
+ void run() throws RemoteException {
+ try {
+ printMessageForState();
+
+ mAm.setActivityController(this);
+ mState = STATE_NORMAL;
+
+ InputStreamReader converter = new InputStreamReader(System.in);
+ BufferedReader in = new BufferedReader(converter);
+ String line;
+
+ while ((line = in.readLine()) != null) {
+ boolean addNewline = true;
+ if (line.length() <= 0) {
+ addNewline = false;
+ } else if ("q".equals(line) || "quit".equals(line)) {
+ resumeController(RESULT_DEFAULT);
+ break;
+ } else if (mState == STATE_CRASHED) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_CRASH_DIALOG);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_CRASH_KILL);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else if (mState == STATE_ANR) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_ANR_DIALOG);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_ANR_KILL);
+ } else if ("w".equals(line) || "wait".equals(line)) {
+ resumeController(RESULT_ANR_WAIT);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else if (mState == STATE_EARLY_ANR) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_EARLY_ANR_CONTINUE);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_EARLY_ANR_KILL);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+
+ synchronized (this) {
+ if (addNewline) {
+ System.out.println("");
+ }
+ printMessageForState();
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mAm.setActivityController(null);
+ }
+ }
+ }
+
+ private void runMonitor() throws Exception {
+ MyActivityController controller = new MyActivityController();
+ controller.run();
+ }
+
private class IntentReceiver extends IIntentReceiver.Stub {
private boolean mFinished = false;
@@ -649,6 +862,8 @@ public class Am {
" dump heap: am dumpheap [flags] <PROCESS> <FILE>\n" +
" -n: dump native heap instead of managed heap\n" +
"\n" +
+ " start monitoring: am monitor\n" +
+ "\n" +
" <INTENT> specifications include these flags:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 1e2bbcc..02b2dce 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -614,6 +614,17 @@ public class ValueAnimator<T> extends Animator {
}
/**
+ * Removes all listeners from the set listening to frame updates for this animation.
+ */
+ public void removeAllUpdateListeners() {
+ if (mUpdateListeners == null) {
+ return;
+ }
+ mUpdateListeners.clear();
+ mUpdateListeners = null;
+ }
+
+ /**
* Removes a listener from the set listening to frame updates for this animation.
*
* @param listener the listener to be removed from the current set of update listeners
@@ -685,7 +696,15 @@ public class ValueAnimator<T> extends Animator {
*/
private void start(boolean playBackwards) {
mPlayingBackwards = playBackwards;
- if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
+ Looper looper = Looper.getMainLooper();
+ final boolean isUiThread;
+ if (looper != null) {
+ isUiThread = Thread.currentThread() == looper.getThread();
+ } else {
+ // ignore check if we don't have a Looper (this isn't an Activity)
+ isUiThread = true;
+ }
+ if ((mStartDelay == 0) && isUiThread) {
if (mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3f74904..2ff88da 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -61,6 +61,7 @@ import android.util.Config;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.LogPrinter;
import android.util.Slog;
import android.view.Display;
import android.view.HardwareRenderer;
@@ -121,6 +122,7 @@ public final class ActivityThread {
private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
private static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean DEBUG_MESSAGES = false;
static final boolean DEBUG_BROADCAST = false;
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = false;
@@ -913,7 +915,7 @@ public final class ActivityThread {
public static final int DUMP_HEAP = 135;
public static final int DUMP_ACTIVITY = 136;
String codeToString(int code) {
- if (localLOGV) {
+ if (DEBUG_MESSAGES) {
switch (code) {
case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
@@ -957,6 +959,7 @@ public final class ActivityThread {
return "(unknown)";
}
public void handleMessage(Message msg) {
+ if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
switch (msg.what) {
case LAUNCH_ACTIVITY: {
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
@@ -1084,6 +1087,7 @@ public final class ActivityThread {
handleDumpActivity((DumpComponentInfo)msg.obj);
break;
}
+ if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
}
void maybeSnapshot() {
@@ -1550,7 +1554,7 @@ public final class ActivityThread {
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
- if (localLOGV) Slog.v(
+ if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
@@ -3699,6 +3703,11 @@ public final class ActivityThread {
ActivityThread thread = new ActivityThread();
thread.attach(false);
+ if (false) {
+ Looper.myLooper().setMessageLogging(new
+ LogPrinter(Log.DEBUG, "ActivityThread"));
+ }
+
Looper.loop();
if (Process.supportsProcesses()) {
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
index c76a517..aca8305 100644
--- a/core/java/android/app/IActivityController.aidl
+++ b/core/java/android/app/IActivityController.aidl
@@ -48,6 +48,11 @@ interface IActivityController
long timeMillis, String stackTrace);
/**
+ * Early call as soon as an ANR is detected.
+ */
+ int appEarlyNotResponding(String processName, int pid, String annotation);
+
+ /**
* An application process is not responding. Return 0 to show the "app
* not responding" dialog, 1 to continue waiting, or -1 to kill it
* immediately.
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 @@ package android.net;
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 @@ public class DownloadManager {
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 @@ public class DownloadManager {
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 class DownloadManager {
*/
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 @@ public class DownloadManager {
}
/**
- * 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 @@ public class DownloadManager {
}
/**
- * 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 @@ public class DownloadManager {
* 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 @@ public class DownloadManager {
* 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 @@ public class DownloadManager {
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 @@ public class DownloadManager {
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 @@ public class DownloadManager {
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/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ba8014f..d49c8be 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -301,7 +301,11 @@ public abstract class BatteryStats implements Parcelable {
*/
public static abstract class Proc {
- public static class ExcessiveWake {
+ public static class ExcessivePower {
+ public static final int TYPE_WAKE = 1;
+ public static final int TYPE_CPU = 2;
+
+ public int type;
public long overTime;
public long usedTime;
}
@@ -343,9 +347,9 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
- public abstract int countExcessiveWakes();
+ public abstract int countExcessivePowers();
- public abstract ExcessiveWake getExcessiveWake(int i);
+ public abstract ExcessivePower getExcessivePower(int i);
}
/**
@@ -1593,7 +1597,7 @@ public abstract class BatteryStats implements Parcelable {
systemTime = ps.getSystemTime(which);
starts = ps.getStarts(which);
numExcessive = which == STATS_SINCE_CHARGED
- ? ps.countExcessiveWakes() : 0;
+ ? ps.countExcessivePowers() : 0;
if (userTime != 0 || systemTime != 0 || starts != 0
|| numExcessive != 0) {
@@ -1609,9 +1613,17 @@ public abstract class BatteryStats implements Parcelable {
}
pw.println(sb.toString());
for (int e=0; e<numExcessive; e++) {
- Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);
+ Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
if (ew != null) {
- pw.print(prefix); pw.print(" * Killed for wake lock use: ");
+ pw.print(prefix); pw.print(" * Killed for ");
+ if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
+ pw.print("wake lock");
+ } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
+ pw.print("cpu");
+ } else {
+ pw.print("unknown");
+ }
+ pw.print(" use: ");
TimeUtils.formatDuration(ew.usedTime, pw);
pw.print(" over ");
TimeUtils.formatDuration(ew.overTime, pw);
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 479497a..7629c31 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -144,6 +144,7 @@ public abstract class PreferenceFragment extends Fragment implements
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPreferenceManager = new PreferenceManager(getActivity(), FIRST_REQUEST_CODE);
+ mPreferenceManager.setFragment(this);
mPreferenceManager.setOnPreferenceTreeClickListener(this);
}
diff --git a/core/java/android/preference/PreferenceManager.java b/core/java/android/preference/PreferenceManager.java
index fa83897..42150ed 100644
--- a/core/java/android/preference/PreferenceManager.java
+++ b/core/java/android/preference/PreferenceManager.java
@@ -16,12 +16,7 @@
package android.preference;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
import android.app.Activity;
-import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -34,6 +29,10 @@ import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.util.Log;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
/**
* Used to help create {@link Preference} hierarchies
* from activities or XML.
@@ -61,6 +60,11 @@ public class PreferenceManager {
private Activity mActivity;
/**
+ * Fragment that owns this instance.
+ */
+ private PreferenceFragment mFragment;
+
+ /**
* The context to use. This should always be set.
*
* @see #mActivity
@@ -158,7 +162,21 @@ public class PreferenceManager {
setSharedPreferencesName(getDefaultSharedPreferencesName(context));
}
-
+
+ /**
+ * Sets the owning preference fragment
+ */
+ void setFragment(PreferenceFragment fragment) {
+ mFragment = fragment;
+ }
+
+ /**
+ * Returns the owning preference fragment, if any.
+ */
+ PreferenceFragment getFragment() {
+ return mFragment;
+ }
+
/**
* Returns a list of {@link Activity} (indirectly) that match a given
* {@link Intent}.
diff --git a/core/java/android/preference/RingtonePreference.java b/core/java/android/preference/RingtonePreference.java
index b46f180..cf14097 100644
--- a/core/java/android/preference/RingtonePreference.java
+++ b/core/java/android/preference/RingtonePreference.java
@@ -24,7 +24,6 @@ import android.net.Uri;
import android.provider.Settings.System;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
/**
* A {@link Preference} that allows the user to choose a ringtone from those on the device.
@@ -137,7 +136,12 @@ public class RingtonePreference extends Preference implements
// Launch the ringtone picker
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
onPrepareRingtonePickerIntent(intent);
- getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
+ PreferenceFragment owningFragment = getPreferenceManager().getFragment();
+ if (owningFragment != null) {
+ owningFragment.startActivityForResult(intent, mRequestCode);
+ } else {
+ getPreferenceManager().getActivity().startActivityForResult(intent, mRequestCode);
+ }
}
/**
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 3796994..fbb13af 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -19,6 +19,7 @@ package android.view;
import android.graphics.Canvas;
import android.os.SystemClock;
+import android.util.EventLog;
import android.util.Log;
import javax.microedition.khronos.egl.EGL10;
@@ -406,6 +407,11 @@ public abstract class HardwareRenderer {
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
attachInfo.mIgnoreDirtyState = true;
view.mPrivateFlags |= View.DRAWN;
+
+ long startTime;
+ if (ViewDebug.DEBUG_PROFILE_DRAWING) {
+ startTime = SystemClock.elapsedRealtime();
+ }
checkCurrent();
@@ -423,6 +429,10 @@ public abstract class HardwareRenderer {
onPostDraw();
+ if (ViewDebug.DEBUG_PROFILE_DRAWING) {
+ EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
+ }
+
attachInfo.mIgnoreDirtyState = false;
sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2b92e87..12c49c4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1973,8 +1973,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (hasNoCache) {
final int multipliedAlpha = (int) (255 * alpha);
if (!child.onSetAlpha(multipliedAlpha)) {
+ int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
+ if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
+ layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
+ }
canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha,
- Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
+ layerFlags);
} else {
child.mPrivateFlags |= ALPHA_SET;
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 0321be0..6917bca 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1711,6 +1711,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
deliverPointerEvent(event);
} finally {
event.recycle();
+ if (msg.arg1 != 0) {
+ finishInputEvent();
+ }
if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
}
} break;
@@ -1720,6 +1723,9 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
deliverTrackballEvent(event);
} finally {
event.recycle();
+ if (msg.arg1 != 0) {
+ finishInputEvent();
+ }
}
} break;
case DISPATCH_APP_VISIBILITY:
@@ -1843,15 +1849,24 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
}
}
- private void finishKeyEvent(KeyEvent event) {
- if (LOCAL_LOGV) Log.v(TAG, "Telling window manager key is finished");
+ private void startInputEvent(Runnable finishedCallback) {
+ if (mFinishedCallback != null) {
+ Slog.w(TAG, "Received a new input event from the input queue but there is "
+ + "already an unfinished input event in progress.");
+ }
+
+ mFinishedCallback = finishedCallback;
+ }
+
+ private void finishInputEvent() {
+ if (LOCAL_LOGV) Log.v(TAG, "Telling window manager input event is finished");
if (mFinishedCallback != null) {
mFinishedCallback.run();
mFinishedCallback = null;
} else {
- Slog.w(TAG, "Attempted to tell the input queue that the current key event "
- + "is finished but there is no key event actually in progress.");
+ Slog.w(TAG, "Attempted to tell the input queue that the current input event "
+ + "is finished but there is no input event actually in progress.");
}
}
@@ -2310,7 +2325,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
boolean handled = mView == null || mView.dispatchKeyEventPreIme(event);
if (handled) {
if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
}
return;
}
@@ -2340,7 +2355,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
if (!handled) {
deliverKeyEventToViewHierarchy(event, sendDone);
} else if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
} else {
Log.w(TAG, "handleFinishedEvent(seq=" + seq
+ " handled=" + handled + " ev=" + event
@@ -2413,7 +2428,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
} finally {
if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
}
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
@@ -2606,20 +2621,13 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
private final InputHandler mInputHandler = new InputHandler() {
public void handleKey(KeyEvent event, Runnable finishedCallback) {
- if (mFinishedCallback != null) {
- Slog.w(TAG, "Received a new key event from the input queue but there is "
- + "already an unfinished key event in progress.");
- }
-
- mFinishedCallback = finishedCallback;
-
+ startInputEvent(finishedCallback);
dispatchKey(event, true);
}
public void handleMotion(MotionEvent event, Runnable finishedCallback) {
- finishedCallback.run();
-
- dispatchMotion(event);
+ startInputEvent(finishedCallback);
+ dispatchMotion(event, true);
}
};
@@ -2651,26 +2659,43 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
}
public void dispatchMotion(MotionEvent event) {
+ dispatchMotion(event, false);
+ }
+
+ private void dispatchMotion(MotionEvent event, boolean sendDone) {
int source = event.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- dispatchPointer(event);
+ dispatchPointer(event, sendDone);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
- dispatchTrackball(event);
+ dispatchTrackball(event, sendDone);
} else {
// TODO
Log.v(TAG, "Dropping unsupported motion event (unimplemented): " + event);
+ if (sendDone) {
+ finishInputEvent();
+ }
}
}
public void dispatchPointer(MotionEvent event) {
+ dispatchPointer(event, false);
+ }
+
+ private void dispatchPointer(MotionEvent event, boolean sendDone) {
Message msg = obtainMessage(DISPATCH_POINTER);
msg.obj = event;
+ msg.arg1 = sendDone ? 1 : 0;
sendMessageAtTime(msg, event.getEventTime());
}
public void dispatchTrackball(MotionEvent event) {
+ dispatchTrackball(event, false);
+ }
+
+ private void dispatchTrackball(MotionEvent event, boolean sendDone) {
Message msg = obtainMessage(DISPATCH_TRACKBALL);
msg.obj = event;
+ msg.arg1 = sendDone ? 1 : 0;
sendMessageAtTime(msg, event.getEventTime());
}
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 @@ public class BaseInputConnection implements InputConnection {
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/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 @@ import android.widget.RemoteViews.RemoteView;
/**
- * <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 @@ import android.widget.RemoteViews.RemoteView;
* }
* });
* }
- * }
- * </pre>
+ * }</pre>
+ *
+ * <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>
+ * &lt;Button
+ * android:layout_height="wrap_content"
+ * android:layout_width="wrap_content"
+ * android:text="@string/self_destruct"
+ * android:onClick="selfDestruct" /&gt;</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>
*
- * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff
- * tutorial</a>.</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/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4e61ddf..66149ac 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -67,7 +67,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 51;
+ private static final int VERSION = 52;
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -85,7 +85,7 @@ public final class BatteryStatsImpl extends BatteryStats {
static final int MSG_UPDATE_WAKELOCKS = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
- static final long DELAY_UPDATE_WAKELOCKS = 15*1000;
+ static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
public interface BatteryCallback {
public void batteryNeedsCpuUpdate();
@@ -1476,6 +1476,13 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
+ Uid u = mUidStats.get(uid);
+ if (u != null) {
+ u.reportExcessiveCpuLocked(proc, overTime, usedTime);
+ }
+ }
+
int mSensorNesting;
public void noteStartSensorLocked(int uid, int sensor) {
@@ -2977,7 +2984,7 @@ public final class BatteryStatsImpl extends BatteryStats {
SamplingCounter[] mSpeedBins;
- ArrayList<ExcessiveWake> mExcessiveWake;
+ ArrayList<ExcessivePower> mExcessivePower;
Proc() {
mUnpluggables.add(this);
@@ -3005,55 +3012,69 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- public int countExcessiveWakes() {
- return mExcessiveWake != null ? mExcessiveWake.size() : 0;
+ public int countExcessivePowers() {
+ return mExcessivePower != null ? mExcessivePower.size() : 0;
}
- public ExcessiveWake getExcessiveWake(int i) {
- if (mExcessiveWake != null) {
- return mExcessiveWake.get(i);
+ public ExcessivePower getExcessivePower(int i) {
+ if (mExcessivePower != null) {
+ return mExcessivePower.get(i);
}
return null;
}
public void addExcessiveWake(long overTime, long usedTime) {
- if (mExcessiveWake == null) {
- mExcessiveWake = new ArrayList<ExcessiveWake>();
+ if (mExcessivePower == null) {
+ mExcessivePower = new ArrayList<ExcessivePower>();
}
- ExcessiveWake ew = new ExcessiveWake();
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = ExcessivePower.TYPE_WAKE;
ew.overTime = overTime;
ew.usedTime = usedTime;
- mExcessiveWake.add(ew);
+ mExcessivePower.add(ew);
}
- void writeExcessiveWakeToParcelLocked(Parcel out) {
- if (mExcessiveWake == null) {
+ public void addExcessiveCpu(long overTime, long usedTime) {
+ if (mExcessivePower == null) {
+ mExcessivePower = new ArrayList<ExcessivePower>();
+ }
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = ExcessivePower.TYPE_CPU;
+ ew.overTime = overTime;
+ ew.usedTime = usedTime;
+ mExcessivePower.add(ew);
+ }
+
+ void writeExcessivePowerToParcelLocked(Parcel out) {
+ if (mExcessivePower == null) {
out.writeInt(0);
return;
}
- final int N = mExcessiveWake.size();
+ final int N = mExcessivePower.size();
out.writeInt(N);
for (int i=0; i<N; i++) {
- ExcessiveWake ew = mExcessiveWake.get(i);
+ ExcessivePower ew = mExcessivePower.get(i);
+ out.writeInt(ew.type);
out.writeLong(ew.overTime);
out.writeLong(ew.usedTime);
}
}
- void readExcessiveWakeFromParcelLocked(Parcel in) {
+ void readExcessivePowerFromParcelLocked(Parcel in) {
final int N = in.readInt();
if (N == 0) {
- mExcessiveWake = null;
+ mExcessivePower = null;
return;
}
- mExcessiveWake = new ArrayList<ExcessiveWake>();
+ mExcessivePower = new ArrayList<ExcessivePower>();
for (int i=0; i<N; i++) {
- ExcessiveWake ew = new ExcessiveWake();
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = in.readInt();
ew.overTime = in.readLong();
ew.usedTime = in.readLong();
- mExcessiveWake.add(ew);
+ mExcessivePower.add(ew);
}
}
@@ -3082,7 +3103,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- writeExcessiveWakeToParcelLocked(out);
+ writeExcessivePowerToParcelLocked(out);
}
void readFromParcelLocked(Parcel in) {
@@ -3112,7 +3133,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- readExcessiveWakeFromParcelLocked(in);
+ readExcessivePowerFromParcelLocked(in);
}
public BatteryStatsImpl getBatteryStats() {
@@ -3746,6 +3767,13 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
+ Proc p = getProcessStatsLocked(proc);
+ if (p != null) {
+ p.addExcessiveCpu(overTime, usedTime);
+ }
+ }
+
public void noteStartSensor(int sensor) {
StopwatchTimer t = getSensorTimerLocked(sensor, true);
if (t != null) {
@@ -4688,7 +4716,7 @@ public final class BatteryStatsImpl extends BatteryStats {
p.mSpeedBins[i].readSummaryFromParcelLocked(in);
}
}
- p.readExcessiveWakeFromParcelLocked(in);
+ p.readExcessivePowerFromParcelLocked(in);
}
NP = in.readInt();
@@ -4887,7 +4915,7 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(0);
}
}
- ps.writeExcessiveWakeToParcelLocked(out);
+ ps.writeExcessivePowerToParcelLocked(out);
}
}
diff --git a/core/java/com/android/internal/widget/DrawableHolder.java b/core/java/com/android/internal/widget/DrawableHolder.java
new file mode 100644
index 0000000..d53860c
--- /dev/null
+++ b/core/java/com/android/internal/widget/DrawableHolder.java
@@ -0,0 +1,232 @@
+/*
+ * 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 com.android.internal.widget;
+
+import java.util.ArrayList;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.animation.Animator.AnimatorListener;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.util.Log;
+import android.view.animation.DecelerateInterpolator;
+
+/**
+ * This class is a container for a Drawable with multiple animated properties.
+ *
+ */
+public class DrawableHolder implements AnimatorListener {
+ public static final DecelerateInterpolator EASE_OUT_INTERPOLATOR = new DecelerateInterpolator();
+ private static final String TAG = "DrawableHolder";
+ private static final boolean DBG = false;
+ private float mX = 0.0f;
+ private float mY = 0.0f;
+ private float mScaleX = 1.0f;
+ private float mScaleY = 1.0f;
+ private BitmapDrawable mDrawable;
+ private float mAlpha = 1f;
+ private ArrayList<ObjectAnimator<Float>> mAnimators = new ArrayList<ObjectAnimator<Float>>();
+ private ArrayList<ObjectAnimator<Float>> mNeedToStart = new ArrayList<ObjectAnimator<Float>>();
+
+ public DrawableHolder(BitmapDrawable drawable) {
+ this(drawable, 0.0f, 0.0f);
+ }
+
+ public DrawableHolder(BitmapDrawable drawable, float x, float y) {
+ mDrawable = drawable;
+ mX = x;
+ mY = y;
+ mDrawable.getPaint().setAntiAlias(true); // Force AA
+ mDrawable.setBounds(0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight());
+ }
+
+ /**
+ *
+ * Adds an animation that interpolates given property from its current value
+ * to the given value.
+ *
+ * @param duration the duration, in ms.
+ * @param delay the delay to start the animation, in ms.
+ * @param property the property to animate
+ * @param toValue the target value
+ * @param replace if true, replace the current animation with this one.
+ */
+ public ObjectAnimator<Float> addAnimTo(long duration, long delay,
+ String property, float toValue, boolean replace) {
+
+ if (replace) removeAnimationFor(property);
+
+ ObjectAnimator<Float> anim = new ObjectAnimator<Float>(duration, this, property, toValue);
+ anim.setStartDelay(delay);
+ anim.setInterpolator(EASE_OUT_INTERPOLATOR);
+ this.addAnimation(anim, replace);
+ if (DBG) Log.v(TAG, "animationCount = " + mAnimators.size());
+ return anim;
+ }
+
+ /**
+ * Stops all animations for the given property and removes it from the list.
+ *
+ * @param property
+ */
+ public void removeAnimationFor(String property) {
+ ArrayList<ObjectAnimator<Float>> removalList = new ArrayList<ObjectAnimator<Float>>();
+ for (ObjectAnimator<Float> currentAnim : mAnimators) {
+ if (property.equals(currentAnim.getPropertyName())) {
+ currentAnim.cancel();
+ removalList.add(currentAnim);
+ }
+ }
+ if (DBG) Log.v(TAG, "Remove list size: " + removalList.size());
+ mAnimators.removeAll(removalList);
+ }
+
+ /**
+ * Stops all animations and removes them from the list.
+ */
+ public void clearAnimations() {
+ for (ObjectAnimator<Float> currentAnim : mAnimators) {
+ currentAnim.cancel();
+ }
+ mAnimators.clear();
+ }
+
+ /**
+ * Adds the given animation to the list of animations for this object.
+ *
+ * @param anim
+ * @param overwrite
+ * @return
+ */
+ private DrawableHolder addAnimation(ObjectAnimator<Float> anim, boolean overwrite) {
+ if (anim != null)
+ mAnimators.add(anim);
+ mNeedToStart.add(anim);
+ return this;
+ }
+
+ /**
+ * Draw this object to the canvas using the properties defined in this class.
+ *
+ * @param canvas canvas to draw into
+ */
+ public void draw(Canvas canvas) {
+ final float threshold = 1.0f / 256.0f; // contribution less than 1 LSB of RGB byte
+ if (mAlpha <= threshold) // don't bother if it won't show up
+ return;
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.translate(mX, mY);
+ canvas.scale(mScaleX, mScaleY);
+ canvas.translate(-0.5f*getWidth(), -0.5f*getHeight());
+ mDrawable.setAlpha((int) Math.round(mAlpha * 255f));
+ mDrawable.draw(canvas);
+ canvas.restore();
+ }
+
+ /**
+ * Starts all animations added since the last call to this function. Used to synchronize
+ * animations.
+ *
+ * @param listener an optional listener to add to the animations. Typically used to know when
+ * to invalidate the surface these are being drawn to.
+ */
+ public void startAnimations(ValueAnimator.AnimatorUpdateListener listener) {
+ for (int i = 0; i < mNeedToStart.size(); i++) {
+ ObjectAnimator<Float> anim = mNeedToStart.get(i);
+ anim.addUpdateListener(listener);
+ anim.addListener(this);
+ anim.start();
+ }
+ mNeedToStart.clear();
+ }
+
+
+ public DrawableHolder setX(float value) {
+ mX = value;
+ return this;
+ }
+
+ public DrawableHolder setY(float value) {
+ mY = value;
+ return this;
+ }
+
+ public DrawableHolder setScaleX(float value) {
+ mScaleX = value;
+ return this;
+ }
+
+ public DrawableHolder setScaleY(float value) {
+ mScaleY = value;
+ return this;
+ }
+
+ public DrawableHolder setAlpha(float alpha) {
+ mAlpha = alpha;
+ return this;
+ }
+
+ public float getX() {
+ return mX;
+ }
+
+ public float getY() {
+ return mY;
+ }
+
+ public float getScaleX() {
+ return mScaleX;
+ }
+
+ public float getScaleY() {
+ return mScaleY;
+ }
+
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ public BitmapDrawable getDrawable() {
+ return mDrawable;
+ }
+
+ public int getWidth() {
+ return mDrawable.getIntrinsicWidth();
+ }
+
+ public int getHeight() {
+ return mDrawable.getIntrinsicHeight();
+ }
+
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ public void onAnimationEnd(Animator animation) {
+ mAnimators.remove(animation);
+ }
+
+ public void onAnimationRepeat(Animator animation) {
+
+ }
+
+ public void onAnimationStart(Animator animation) {
+
+ }
+}
diff --git a/core/java/com/android/internal/widget/WaveView.java b/core/java/com/android/internal/widget/WaveView.java
new file mode 100644
index 0000000..f4ee7ee
--- /dev/null
+++ b/core/java/com/android/internal/widget/WaveView.java
@@ -0,0 +1,573 @@
+/*
+ * 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 com.android.internal.widget;
+
+import java.util.ArrayList;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Vibrator;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * A special widget containing a center and outer ring. Moving the center ring to the outer ring
+ * causes an event that can be caught by implementing OnTriggerListener.
+ */
+public class WaveView extends View implements ValueAnimator.AnimatorUpdateListener {
+ private static final String TAG = "WaveView";
+ private static final boolean DBG = false;
+ private static final int WAVE_COUNT = 5; // default wave count
+ private static final long VIBRATE_SHORT = 20; // msec
+ private static final long VIBRATE_LONG = 20; // msec
+
+ // Lock state machine states
+ private static final int STATE_RESET_LOCK = 0;
+ private static final int STATE_READY = 1;
+ private static final int STATE_START_ATTEMPT = 2;
+ private static final int STATE_ATTEMPTING = 3;
+ private static final int STATE_UNLOCK_ATTEMPT = 4;
+ private static final int STATE_UNLOCK_SUCCESS = 5;
+
+ // Animation properties.
+ private static final long DURATION = 500; // duration of transitional animations
+ private static final long FINAL_DELAY = 1300; // delay for final animations
+ private static final long SHORT_DELAY = 100; // for starting one animation after another.
+ private static final long WAVE_DURATION = 2000; // amount of time for way to expand/decay
+ private static final long RESET_TIMEOUT = 3000; // elapsed time of inactivity before we reset
+ private static final long DELAY_INCREMENT = 15; // increment per wave while tracking motion
+ private static final long DELAY_INCREMENT2 = 12; // increment per wave while not tracking
+
+ private Vibrator mVibrator;
+ private OnTriggerListener mOnTriggerListener;
+ private ArrayList<DrawableHolder> mDrawables = new ArrayList<DrawableHolder>(3);
+ private ArrayList<DrawableHolder> mLightWaves = new ArrayList<DrawableHolder>(WAVE_COUNT);
+ private boolean mFingerDown = false;
+ private float mRingRadius = 182.0f; // Radius of bitmap ring. Used to snap halo to it
+ private int mSnapRadius = 136; // minimum threshold for drag unlock
+ private int mWaveDelay = 240; // time to delay
+ private int mWaveCount = WAVE_COUNT; // number of waves
+ private long mWaveTimerDelay = mWaveDelay;
+ private int mCurrentWave = 0;
+ private float mLockCenterX; // center of widget as dictated by widget size
+ private float mLockCenterY;
+ private float mMouseX; // current mouse position as of last touch event
+ private float mMouseY;
+ private DrawableHolder mUnlockRing;
+ private DrawableHolder mUnlockDefault;
+ private DrawableHolder mUnlockHalo;
+ private int mLockState = STATE_RESET_LOCK;
+ private int mGrabbedState = OnTriggerListener.NO_HANDLE;
+
+ public WaveView(Context context) {
+ this(context, null);
+ }
+
+ public WaveView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ // TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
+ // mOrientation = a.getInt(R.styleable.WaveView_orientation, HORIZONTAL);
+ // a.recycle();
+
+ initDrawables();
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mLockCenterX = 0.5f * w;
+ mLockCenterY = 0.5f * h;
+ super.onSizeChanged(w, h, oldw, oldh);
+ }
+
+ @Override
+ protected int getSuggestedMinimumWidth() {
+ // View should be large enough to contain the unlock ring + halo
+ return mUnlockRing.getWidth() + mUnlockHalo.getWidth();
+ }
+
+ @Override
+ protected int getSuggestedMinimumHeight() {
+ // View should be large enough to contain the unlock ring + halo
+ return mUnlockRing.getHeight() + mUnlockHalo.getHeight();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+ int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+ int width;
+ int height;
+
+ if (widthSpecMode == MeasureSpec.AT_MOST) {
+ width = Math.min(widthSpecSize, getSuggestedMinimumWidth());
+ } else if (widthSpecMode == MeasureSpec.EXACTLY) {
+ width = widthSpecSize;
+ } else {
+ width = getSuggestedMinimumWidth();
+ }
+
+ if (heightSpecMode == MeasureSpec.AT_MOST) {
+ height = Math.min(heightSpecSize, getSuggestedMinimumWidth());
+ } else if (heightSpecMode == MeasureSpec.EXACTLY) {
+ height = heightSpecSize;
+ } else {
+ height = getSuggestedMinimumHeight();
+ }
+
+ setMeasuredDimension(width, height);
+ }
+
+ private void initDrawables() {
+ mUnlockRing = new DrawableHolder(createDrawable(R.drawable.unlock_ring))
+ .setX(mLockCenterX).setY(mLockCenterY).setScaleX(0.1f).setScaleY(0.1f).setAlpha(0.0f);
+ mDrawables.add(mUnlockRing);
+
+ mUnlockDefault = new DrawableHolder(createDrawable(R.drawable.unlock_default))
+ .setX(mLockCenterX).setY(mLockCenterY).setScaleX(0.1f).setScaleY(0.1f).setAlpha(0.0f);
+ mDrawables.add(mUnlockDefault);
+
+ mUnlockHalo = new DrawableHolder(createDrawable(R.drawable.unlock_halo))
+ .setX(mLockCenterX).setY(mLockCenterY).setScaleX(0.1f).setScaleY(0.1f).setAlpha(0.0f);
+ mDrawables.add(mUnlockHalo);
+
+ BitmapDrawable wave = createDrawable(R.drawable.unlock_wave);
+ for (int i = 0; i < mWaveCount; i++) {
+ DrawableHolder holder = new DrawableHolder(wave);
+ mLightWaves.add(holder);
+ holder.setAlpha(0.0f);
+ }
+ }
+
+ private void waveUpdateFrame(float mouseX, float mouseY, boolean fingerDown) {
+ double distX = mouseX - mLockCenterX;
+ double distY = mouseY - mLockCenterY;
+ int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
+ double touchA = Math.atan2(distX, distY);
+ float ringX = (float) (mLockCenterX + mRingRadius * Math.sin(touchA));
+ float ringY = (float) (mLockCenterY + mRingRadius * Math.cos(touchA));
+
+ switch (mLockState) {
+ case STATE_RESET_LOCK:
+ if (DBG) Log.v(TAG, "State RESET_LOCK");
+ mWaveTimerDelay = mWaveDelay;
+ for (int i = 0; i < mLightWaves.size(); i++) {
+ //TweenMax.to(mLightWave.get(i), .3, {alpha:0, ease:Quint.easeOut});
+ DrawableHolder holder = mLightWaves.get(i);
+ holder.addAnimTo(300, 0, "alpha", 0.0f, false);
+ }
+ for (int i = 0; i < mLightWaves.size(); i++) {
+ mLightWaves.get(i).startAnimations(this);
+ }
+
+ //TweenMax.to(unlockRing, .5, { x: lockX, y: lockY, scaleX: .1, scaleY: .1,
+ // alpha: 0, overwrite: true, ease:Quint.easeOut });
+ mUnlockRing.addAnimTo(DURATION, 0, "x", mLockCenterX, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "y", mLockCenterY, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, true);
+
+ //TweenMax.to(unlockDefault, 0, { x: lockX, y: lockY, scaleX: .1, scaleY: .1,
+ // alpha: 0 , overwrite: true });
+ mUnlockDefault.removeAnimationFor("x");
+ mUnlockDefault.removeAnimationFor("y");
+ mUnlockDefault.removeAnimationFor("scaleX");
+ mUnlockDefault.removeAnimationFor("scaleY");
+ mUnlockDefault.removeAnimationFor("alpha");
+ mUnlockDefault.setX(mLockCenterX).setY(mLockCenterY).setScaleX(0.1f).setScaleY(0.1f)
+ .setAlpha(0.0f);
+
+ //TweenMax.to(unlockDefault, .5, { delay: .1, scaleX: 1, scaleY: 1,
+ // alpha: 1, overwrite: true, ease:Quint.easeOut });
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
+
+ //TweenMax.to(unlockHalo, 0, { x: lockX, y: lockY, scaleX:.1, scaleY: .1,
+ // alpha: 0 , overwrite: true });
+ mUnlockHalo.removeAnimationFor("x");
+ mUnlockHalo.removeAnimationFor("y");
+ mUnlockHalo.removeAnimationFor("scaleX");
+ mUnlockHalo.removeAnimationFor("scaleY");
+ mUnlockHalo.removeAnimationFor("alpha");
+ mUnlockHalo.setX(mLockCenterX).setY(mLockCenterY).setScaleX(0.1f).setScaleY(0.1f)
+ .setAlpha(0.0f);
+
+ //TweenMax.to(unlockHalo, .5, { x: lockX, y: lockY, scaleX: 1, scaleY: 1,
+ // alpha: 1 , overwrite: true, ease:Quint.easeOut });
+ mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "x", mLockCenterX, true);
+ mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "y", mLockCenterY, true);
+ mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, true);
+ mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, true);
+ mUnlockHalo.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, true);
+
+ //lockTimer.stop();
+ removeCallbacks(mLockTimerActions);
+
+ mLockState = STATE_READY;
+ break;
+
+ case STATE_READY:
+ if (DBG) Log.v(TAG, "State READY");
+ break;
+
+ case STATE_START_ATTEMPT:
+ if (DBG) Log.v(TAG, "State START_ATTEMPT");
+ //TweenMax.to(unlockDefault, 0, {scaleX: .1, scaleY:.1, alpha: 0,
+ // x:lockX +182, y: lockY , overwrite: true });
+ mUnlockDefault.removeAnimationFor("x");
+ mUnlockDefault.removeAnimationFor("y");
+ mUnlockDefault.removeAnimationFor("scaleX");
+ mUnlockDefault.removeAnimationFor("scaleY");
+ mUnlockDefault.removeAnimationFor("alpha");
+ mUnlockDefault.setX(mLockCenterX + 182).setY(mLockCenterY).setScaleX(0.1f)
+ .setScaleY(0.1f).setAlpha(0.0f);
+
+ //TweenMax.to(unlockDefault, 0.5, { delay: .1 , scaleX: 1, scaleY: 1,
+ // alpha: 1, ease:Quint.easeOut });
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleX", 1.0f, false);
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "scaleY", 1.0f, false);
+ mUnlockDefault.addAnimTo(DURATION, SHORT_DELAY, "alpha", 1.0f, false);
+
+ //TweenMax.to(unlockRing, 0.5, {scaleX: 1, scaleY: 1,
+ // alpha: 1, ease:Quint.easeOut, overwrite: true });
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
+ mUnlockRing.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
+
+ postDelayed(mAddWaveAction, mWaveTimerDelay);
+
+ mLockState = STATE_ATTEMPTING;
+ break;
+
+ case STATE_ATTEMPTING:
+ if (DBG) Log.v(TAG, "State ATTEMPTING");
+ //TweenMax.to(unlockHalo, 0.4, { x:mouseX, y:mouseY, scaleX:1, scaleY:1,
+ // alpha: 1, ease:Quint.easeOut });
+ if (dragDistance > mSnapRadius) {
+ if (fingerDown) {
+ //TweenMax.to(unlockHalo, 0.4, {x:ringX, y:ringY, scaleX:1, scaleY:1,
+ // alpha: 1 , ease:Quint.easeOut , overwrite: true });
+ mUnlockHalo.addAnimTo(0, 0, "x", ringX, true);
+ mUnlockHalo.addAnimTo(0, 0, "y", ringY, true);
+ mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
+ mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
+ mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
+ } else {
+ mLockState = STATE_UNLOCK_ATTEMPT;
+ }
+ } else {
+ mUnlockHalo.addAnimTo(0, 0, "x", mouseX, true);
+ mUnlockHalo.addAnimTo(0, 0, "y", mouseY, true);
+ mUnlockHalo.addAnimTo(0, 0, "scaleX", 1.0f, true);
+ mUnlockHalo.addAnimTo(0, 0, "scaleY", 1.0f, true);
+ mUnlockHalo.addAnimTo(0, 0, "alpha", 1.0f, true);
+ }
+ break;
+
+ case STATE_UNLOCK_ATTEMPT:
+ if (DBG) Log.v(TAG, "State UNLOCK_ATTEMPT");
+ if (dragDistance > mSnapRadius) {
+ for (int n = 0; n < mLightWaves.size(); n++) {
+ //TweenMax.to(this["lightWave"+n], .5,{alpha:0, delay: (6+n-currentWave)*.1,
+ // x:ringX, y:ringY, scaleX: .1, scaleY: .1, ease:Quint.easeOut});
+ DrawableHolder wave = mLightWaves.get(n);
+ long delay = 1000L*(6 + n - mCurrentWave)/10L;
+ wave.addAnimTo(DURATION, delay, "x", ringX, true);
+ wave.addAnimTo(DURATION, delay, "y", ringY, true);
+ wave.addAnimTo(DURATION, delay, "scaleX", 0.1f, true);
+ wave.addAnimTo(DURATION, delay, "scaleY", 0.1f, true);
+ wave.addAnimTo(DURATION, delay, "alpha", 0.0f, true);
+ }
+ for (int i = 0; i < mLightWaves.size(); i++) {
+ mLightWaves.get(i).startAnimations(this);
+ }
+
+ //TweenMax.to(unlockRing, .5, {x:ringX, y: ringY, scaleX: .1, scaleY: .1,
+ // alpha: 0, ease: Quint.easeOut });
+ mUnlockRing.addAnimTo(DURATION, 0, "x", ringX, false);
+ mUnlockRing.addAnimTo(DURATION, 0, "y", ringY, false);
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleX", 0.1f, false);
+ mUnlockRing.addAnimTo(DURATION, 0, "scaleY", 0.1f, false);
+ mUnlockRing.addAnimTo(DURATION, 0, "alpha", 0.0f, false);
+
+ //TweenMax.to(unlockRing, .5, { delay: 1.3, alpha: 0 , ease: Quint.easeOut });
+ mUnlockRing.addAnimTo(DURATION, FINAL_DELAY, "alpha", 0.0f, false);
+
+ //TweenMax.to(unlockDefault, 0, { x:ringX, y: ringY, scaleX: .1, scaleY: .1,
+ // alpha: 0 , overwrite: true });
+ mUnlockDefault.removeAnimationFor("x");
+ mUnlockDefault.removeAnimationFor("y");
+ mUnlockDefault.removeAnimationFor("scaleX");
+ mUnlockDefault.removeAnimationFor("scaleY");
+ mUnlockDefault.removeAnimationFor("alpha");
+ mUnlockDefault.setX(ringX).setY(ringY).setScaleX(0.1f).setScaleY(0.1f)
+ .setAlpha(0.0f);
+
+ //TweenMax.to(unlockDefault, .5, { x:ringX, y: ringY, scaleX: 1, scaleY: 1,
+ // alpha: 1 , ease: Quint.easeOut , overwrite: true });
+ mUnlockDefault.addAnimTo(DURATION, 0, "x", ringX, true);
+ mUnlockDefault.addAnimTo(DURATION, 0, "y", ringY, true);
+ mUnlockDefault.addAnimTo(DURATION, 0, "scaleX", 1.0f, true);
+ mUnlockDefault.addAnimTo(DURATION, 0, "scaleY", 1.0f, true);
+ mUnlockDefault.addAnimTo(DURATION, 0, "alpha", 1.0f, true);
+
+ //TweenMax.to(unlockDefault, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
+ // alpha: 1, ease: Quint.easeOut });
+ mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+ mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+ mUnlockDefault.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+
+ //TweenMax.to(unlockHalo, .5, { x:ringX, y: ringY , ease: Back.easeOut });
+ mUnlockHalo.addAnimTo(DURATION, 0, "x", ringX, false);
+ mUnlockHalo.addAnimTo(DURATION, 0, "y", ringY, false);
+
+ //TweenMax.to(unlockHalo, .5, { delay: 1.3, scaleX: 3, scaleY: 3,
+ // alpha: 1, ease: Quint.easeOut });
+ mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleX", 3.0f, false);
+ mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "scaleY", 3.0f, false);
+ mUnlockHalo.addAnimTo(DURATION, FINAL_DELAY, "alpha", 1.0f, false);
+
+ removeCallbacks(mLockTimerActions);
+
+ postDelayed(mLockTimerActions, RESET_TIMEOUT);
+
+ dispatchTriggerEvent(OnTriggerListener.CENTER_HANDLE);
+ mLockState = STATE_UNLOCK_SUCCESS;
+ } else {
+ mLockState = STATE_RESET_LOCK;
+ }
+ break;
+
+ case STATE_UNLOCK_SUCCESS:
+ if (DBG) Log.v(TAG, "State UNLOCK_SUCCESS");
+ removeCallbacks(mAddWaveAction);
+ break;
+
+ default:
+ if (DBG) Log.v(TAG, "Unknown state " + mLockState);
+ break;
+ }
+ mUnlockDefault.startAnimations(this);
+ mUnlockHalo.startAnimations(this);
+ mUnlockRing.startAnimations(this);
+ }
+
+ BitmapDrawable createDrawable(int resId) {
+ Resources res = getResources();
+ Bitmap bitmap = BitmapFactory.decodeResource(res, resId);
+ return new BitmapDrawable(res, bitmap);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ waveUpdateFrame(mMouseX, mMouseY, mFingerDown);
+ for (int i = 0; i < mDrawables.size(); ++i) {
+ mDrawables.get(i).draw(canvas);
+ }
+ for (int i = 0; i < mLightWaves.size(); ++i) {
+ mLightWaves.get(i).draw(canvas);
+ }
+ }
+
+ private final Runnable mLockTimerActions = new Runnable() {
+ public void run() {
+ if (DBG) Log.v(TAG, "LockTimerActions");
+ // reset lock after inactivity
+ if (mLockState == STATE_ATTEMPTING) {
+ mLockState = STATE_RESET_LOCK;
+ }
+ // for prototype, reset after successful unlock
+ if (mLockState == STATE_UNLOCK_SUCCESS) {
+ mLockState = STATE_RESET_LOCK;
+ }
+ invalidate();
+ }
+ };
+
+ private final Runnable mAddWaveAction = new Runnable() {
+ public void run() {
+ double distX = mMouseX - mLockCenterX;
+ double distY = mMouseY - mLockCenterY;
+ int dragDistance = (int) Math.ceil(Math.hypot(distX, distY));
+ if (mLockState == STATE_ATTEMPTING && dragDistance < mSnapRadius
+ && mWaveTimerDelay >= mWaveDelay) {
+ mWaveTimerDelay = Math.min(WAVE_DURATION, mWaveTimerDelay + DELAY_INCREMENT);
+
+ DrawableHolder wave = mLightWaves.get(mCurrentWave);
+ wave.setAlpha(0.0f);
+ wave.setScaleX(0.2f);
+ wave.setScaleY(0.2f);
+ wave.setX(mMouseX);
+ wave.setY(mMouseY);
+
+ //TweenMax.to(this["lightWave"+currentWave], 2, { x:lockX , y:lockY, alpha: 1.5,
+ // scaleX: 1, scaleY:1, ease:Cubic.easeOut});
+ wave.addAnimTo(WAVE_DURATION, 0, "x", mLockCenterX, true);
+ wave.addAnimTo(WAVE_DURATION, 0, "y", mLockCenterY, true);
+ wave.addAnimTo(WAVE_DURATION*2/3, 0, "alpha", 1.0f, true);
+ wave.addAnimTo(WAVE_DURATION, 0, "scaleX", 1.0f, true);
+ wave.addAnimTo(WAVE_DURATION, 0, "scaleY", 1.0f, true);
+
+ //TweenMax.to(this["lightWave"+currentWave], 1, { delay: 1.3
+ // , alpha: 0 , ease:Quint.easeOut});
+ wave.addAnimTo(1000, FINAL_DELAY, "alpha", 0.0f, false);
+ wave.startAnimations(WaveView.this);
+
+ mCurrentWave = (mCurrentWave+1) % mWaveCount;
+ if (DBG) Log.v(TAG, "WaveTimerDelay: start new wave in " + mWaveTimerDelay);
+ postDelayed(mAddWaveAction, mWaveTimerDelay);
+ } else {
+ mWaveTimerDelay += DELAY_INCREMENT2;
+ }
+ }
+ };
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int action = event.getAction();
+ mMouseX = event.getX();
+ mMouseY = event.getY();
+ boolean handled = false;
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ removeCallbacks(mLockTimerActions);
+ mFingerDown = true;
+ setGrabbedState(OnTriggerListener.CENTER_HANDLE);
+ {
+ float x = mMouseX - mUnlockHalo.getX();
+ float y = mMouseY - mUnlockHalo.getY();
+ float dist = (float) Math.hypot(x, y);
+ if (dist < mUnlockHalo.getWidth()*0.5f) {
+ if (mLockState == STATE_READY) {
+ mLockState = STATE_START_ATTEMPT;
+ }
+ }
+ }
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_UP:
+ mFingerDown = false;
+ postDelayed(mLockTimerActions, RESET_TIMEOUT);
+ setGrabbedState(OnTriggerListener.NO_HANDLE);
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ mFingerDown = false;
+ handled = true;
+ break;
+ }
+ invalidate();
+ return handled ? true : super.onTouchEvent(event);
+ }
+
+ /**
+ * Triggers haptic feedback.
+ */
+ private synchronized void vibrate(long duration) {
+ if (mVibrator == null) {
+ mVibrator = (android.os.Vibrator)
+ getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ }
+ mVibrator.vibrate(duration);
+ }
+
+ /**
+ * Registers a callback to be invoked when the user triggers an event.
+ *
+ * @param listener the OnDialTriggerListener to attach to this view
+ */
+ public void setOnTriggerListener(OnTriggerListener listener) {
+ mOnTriggerListener = listener;
+ }
+
+ /**
+ * Dispatches a trigger event to listener. Ignored if a listener is not set.
+ * @param whichHandle the handle that triggered the event.
+ */
+ private void dispatchTriggerEvent(int whichHandle) {
+ vibrate(VIBRATE_LONG);
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onTrigger(this, whichHandle);
+ }
+ }
+
+ /**
+ * Sets the current grabbed state, and dispatches a grabbed state change
+ * event to our listener.
+ */
+ private void setGrabbedState(int newState) {
+ if (newState != mGrabbedState) {
+ mGrabbedState = newState;
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
+ }
+ }
+ }
+
+ public interface OnTriggerListener {
+ /**
+ * Sent when the user releases the handle.
+ */
+ public static final int NO_HANDLE = 0;
+
+ /**
+ * Sent when the user grabs the center handle
+ */
+ public static final int CENTER_HANDLE = 10;
+
+ /**
+ * Called when the user drags the center ring beyond a threshold.
+ */
+ void onTrigger(View v, int whichHandle);
+
+ /**
+ * Called when the "grabbed state" changes (i.e. when the user either grabs or releases
+ * one of the handles.)
+ *
+ * @param v the view that was triggered
+ * @param grabbedState the new state: {@link #NO_HANDLE}, {@link #CENTER_HANDLE},
+ */
+ void onGrabbedStateChange(View v, int grabbedState);
+ }
+
+ public void onAnimationUpdate(ValueAnimator animation) {
+ invalidate();
+ }
+
+ public void reset() {
+ mLockState = STATE_RESET_LOCK;
+ }
+}
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 @@ namespace android {
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 @@ static jint android_net_wifi_addNetworkCommand(JNIEnv* env, jobject clazz)
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 @@ static JNINativeMethod gWifiMethods[] = {
{ "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/drawable-xlarge/unlock_default.png b/core/res/res/drawable-xlarge/unlock_default.png
new file mode 100644
index 0000000..0a441c0
--- /dev/null
+++ b/core/res/res/drawable-xlarge/unlock_default.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge/unlock_halo.png b/core/res/res/drawable-xlarge/unlock_halo.png
new file mode 100644
index 0000000..09b0526
--- /dev/null
+++ b/core/res/res/drawable-xlarge/unlock_halo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge/unlock_ring.png b/core/res/res/drawable-xlarge/unlock_ring.png
new file mode 100644
index 0000000..1ac6d54
--- /dev/null
+++ b/core/res/res/drawable-xlarge/unlock_ring.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge/unlock_wave.png b/core/res/res/drawable-xlarge/unlock_wave.png
new file mode 100644
index 0000000..21bfa24
--- /dev/null
+++ b/core/res/res/drawable-xlarge/unlock_wave.png
Binary files differ
diff --git a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
index 4761800..b3645aa 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock.xml
@@ -57,13 +57,10 @@
android:drawablePadding="4dip"
/>
- <com.android.internal.widget.SlidingTab
- android:id="@+id/tab_selector"
- android:orientation="horizontal"
- android:layout_width="match_parent"
+ <com.android.internal.widget.WaveView
+ android:id="@+id/wave_view"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="80dip"
/>
<!-- "emergency calls only" shown when sim is missing or PUKd -->
diff --git a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
index bb398f6..6c99cca 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_tab_unlock_land.xml
@@ -58,15 +58,14 @@
android:drawablePadding="4dip"
/>
- <com.android.internal.widget.SlidingTab
- android:id="@+id/tab_selector"
- android:orientation="vertical"
+ <com.android.internal.widget.WaveView
+ android:id="@+id/wave_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="0dip"
android:layout_weight="1.0"
/>
-
+
<!-- "emergency calls only" shown when sim is missing or PUKd -->
<TextView
android:id="@+id/emergencyCallText"
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/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 975a4c2..1289a9e 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -167,8 +167,7 @@ public class PackageManagerTests extends AndroidTestCase {
return ipm;
}
- public boolean invokeInstallPackage(Uri packageURI, int flags,
- GenericReceiver receiver) throws Exception {
+ public boolean invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver) {
PackageInstallObserver observer = new PackageInstallObserver();
final boolean received = false;
mContext.registerReceiver(receiver, receiver.filter);
@@ -180,11 +179,15 @@ public class PackageManagerTests extends AndroidTestCase {
getPm().installPackage(packageURI, observer, flags, null);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- observer.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ observer.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!observer.isDone()) {
- throw new Exception("Timed out waiting for packageInstalled callback");
+ fail("Timed out waiting for packageInstalled callback");
}
if (observer.returnCode != PackageManager.INSTALL_SUCCEEDED) {
Log.i(TAG, "Failed to install with error code = " + observer.returnCode);
@@ -193,11 +196,15 @@ public class PackageManagerTests extends AndroidTestCase {
// Verify we received the broadcast
waitTime = 0;
while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- receiver.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ receiver.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!receiver.isDone()) {
- throw new Exception("Timed out waiting for PACKAGE_ADDED notification");
+ fail("Timed out waiting for PACKAGE_ADDED notification");
}
return receiver.received;
}
@@ -207,7 +214,7 @@ public class PackageManagerTests extends AndroidTestCase {
}
}
- public void invokeInstallPackageFail(Uri packageURI, int flags, int result) throws Exception {
+ public void invokeInstallPackageFail(Uri packageURI, int flags, int result) {
PackageInstallObserver observer = new PackageInstallObserver();
try {
// Wait on observer
@@ -215,11 +222,15 @@ public class PackageManagerTests extends AndroidTestCase {
getPm().installPackage(packageURI, observer, flags, null);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- observer.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ observer.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!observer.isDone()) {
- throw new Exception("Timed out waiting for packageInstalled callback");
+ fail("Timed out waiting for packageInstalled callback");
}
assertEquals(observer.returnCode, result);
}
@@ -265,7 +276,7 @@ public class PackageManagerTests extends AndroidTestCase {
Environment.getExternalStorageDirectory().getPath());
sdSize = (long)sdStats.getAvailableBlocks() *
(long)sdStats.getBlockSize();
- // TODO check for thesholds here
+ // TODO check for thresholds here
return pkgLen <= sdSize;
}
@@ -368,12 +379,21 @@ public class PackageManagerTests extends AndroidTestCase {
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
} else if (rLoc == INSTALL_LOC_SD){
- assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
- assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("Application flags (" + info.flags
+ + ") should contain FLAG_EXTERNAL_STORAGE",
+ (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+ assertTrue("The APK path (" + srcPath + ") should start with "
+ + SECURE_CONTAINERS_PREFIX, srcPath
+ .startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("The public APK path (" + publicSrcPath + ") should start with "
+ + SECURE_CONTAINERS_PREFIX, publicSrcPath
+ .startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("The native library path (" + info.nativeLibraryDir
+ + ") should start with " + SECURE_CONTAINERS_PREFIX,
+ info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
} else {
// TODO handle error. Install should have failed.
+ fail("Install should have failed");
}
}
} catch (NameNotFoundException e) {
@@ -544,8 +564,6 @@ public class PackageManagerTests extends AndroidTestCase {
// Verify installed information
assertInstall(pkg, flags, expInstallLocation);
}
- } catch (Exception e) {
- failStr("Failed with exception : " + e);
} finally {
if (cleanUp) {
cleanUpInstall(ip);
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 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
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/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 6bcaaaf..1fd7bba 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -44,5 +44,5 @@
<name>monaco</name>
</font>
<fallback ttf="DroidSansFallback" />
- <fallback ttf="DroidSansJapanese" />
-</fonts> \ No newline at end of file
+ <fallback ttf="MTLmr3m" />
+</fonts>
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 @@ screen).</dd>
<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&mdash;the last drawable in the list is drawn on top.</p>
<p>Each drawable is represented by an {@code &lt;item&gt;} element inside a single {@code
@@ -641,7 +641,7 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
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"] />
&lt;/selector>
</pre>
</dd>
@@ -729,12 +729,12 @@ default value should always be last (as demonstrated in the following example).<
&lt;/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>
-&lt;ImageView
+&lt;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 @@ android:dashGap} is set.</dd>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- &lt;gradient
- android:startColor="#FFFF0000"
+ &lt;gradient
+ android:startColor="#FFFF0000"
android:endColor="#80FF00FF"
android:angle="45"/>
- &lt;padding android:left="7dp"
+ &lt;padding android:left="7dp"
android:top="7dp"
- android:right="7dp"
+ android:right="7dp"
android:bottom="7dp" />
&lt;corners android:radius="8dp" />
&lt;/shape>
diff --git a/docs/html/guide/tutorials/notepad/notepad-ex2.jd b/docs/html/guide/tutorials/notepad/notepad-ex2.jd
index a945a62..854731f 100644
--- a/docs/html/guide/tutorials/notepad/notepad-ex2.jd
+++ b/docs/html/guide/tutorials/notepad/notepad-ex2.jd
@@ -87,8 +87,8 @@ Open the Notepadv2 class.</p>
menu callback used for the options menu. Here, we add just one line, which will add a menu item
to delete a note. Call <code>menu.add()</code> like so:
<pre>
-public boolean onCreateContextMenu(Menu menu, View v
- ContextMenuInfo menuInfo) {
+public void onCreateContextMenu(Menu menu, View v,
+ ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}</pre>
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex2.jd b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
index 289b5fe..499b796 100644
--- a/docs/html/resources/tutorials/notepad/notepad-ex2.jd
+++ b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
@@ -87,8 +87,8 @@ Open the Notepadv2 class.</p>
menu callback used for the options menu. Here, we add just one line, which will add a menu item
to delete a note. Call <code>menu.add()</code> like so:
<pre>
-public boolean onCreateContextMenu(Menu menu, View v
- ContextMenuInfo menuInfo) {
+public void onCreateContextMenu(Menu menu, View v,
+ ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}</pre>
diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd
index 5e642d7..3da576a 100644
--- a/docs/html/sdk/adt_download.jd
+++ b/docs/html/sdk/adt_download.jd
@@ -22,10 +22,17 @@ ADT Installation</a>.</p>
<th>Notes</th>
</tr>
<tr>
+ <td>0.9.9</td>
+ <td><a href="http://dl-ssl.google.com/android/ADT-0.9.9.zip">ADT-0.9.9.zip</a></td>
+ <td><nobr>8301681 bytes</nobr></td>
+ <td>7deff0c9b25940a74cea7a0815a3bc36</td>
+ <td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
+ </tr>
+ <tr>
<td>0.9.8</td>
<td><a href="http://dl-ssl.google.com/android/ADT-0.9.8.zip">ADT-0.9.8.zip</a></td>
- <td><nobr>8703591 bytes</nobr></td>
- <td>22070f8e52924605a3b3abf87c1ba39f</td>
+ <td><nobr>8301417 bytes</nobr></td>
+ <td>27e0de800512f13feae46fb554e6ee2f</td>
<td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
</tr>
<tr>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index a984d56..9f3c8b0 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,9 +1,9 @@
page.title=ADT Plugin for Eclipse
sdk.preview=0
-adt.zip.version=0.9.8
-adt.zip.download=ADT-0.9.8.zip
-adt.zip.bytes=8703591
-adt.zip.checksum=22070f8e52924605a3b3abf87c1ba39f
+adt.zip.version=0.9.9
+adt.zip.download=ADT-0.9.9.zip
+adt.zip.bytes=8301681
+adt.zip.checksum=7deff0c9b25940a74cea7a0815a3bc36
@jd:body
@@ -100,11 +100,40 @@ padding: .25em 1em;
</style>
-
-
<div class="toggleable opened">
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+ADT 0.9.9</a> <em>(September 2010)</em>
+ <div class="toggleme">
+
+
+</ul>
+</dd>
+
+<dl>
+
+<dt>Dependencies:</dt>
+
+<dd><p>ADT 0.9.9 replaces ADT 0.9.8 and is designed for use with SDK Tools r7
+and later. ADT 0.9.9 includes the ADT 0.9.8 features as well as an important
+bugfix, so we recommend that you upgrade as soon as possible. If you haven't
+already installed SDK Tools r7 into your SDK, use the Android SDK Manager to do
+so.</p></dd>
+
+<dt>General notes:</dt>
+<dd>
+<ul>
+<li>Fixes a problem in project import, in which source files were deleted in some cases.</li>
+<li>Includes all other ADT 0.9.8 features (see below).</li>
+</ul>
+</dd>
+</dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
ADT 0.9.8</a> <em>(September 2010)</em>
<div class="toggleme">
@@ -116,9 +145,7 @@ ADT 0.9.8</a> <em>(September 2010)</em>
<dt>Dependencies:</dt>
-<dd><p>ADT 0.9.8 is designed for use with SDK Tools r7 and later. Before
-updating to ADT 0.9.8, we highly recommend that you use the Android SDK and
-AVD Manager to install SDK Tools r7 into your SDK.</p></dd>
+<dd><p>ADT 0.9.8 is now deprecated. Please use ADT 0.9.9 instead.</p></dd>
<dt>General notes:</dt>
<dd>
diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd
index d710b8e..7b11654 100644
--- a/docs/html/sdk/requirements.jd
+++ b/docs/html/sdk/requirements.jd
@@ -6,7 +6,7 @@ Android applications using the Android SDK. </p>
<h3>Supported Operating Systems</h3>
<ul>
- <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
+ <li>Windows XP (32-bit), Vista (32- or 64-bit), or Windows 7 (32- or 64-bit)</li>
<li>Mac OS X 10.5.8 or later (x86 only)</li>
<li>Linux (tested on Linux Ubuntu Hardy Heron)
<ul>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index a665e95..fdf4438 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -94,7 +94,7 @@
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.8
+ <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.9
<span style="display:none" class="de"></span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
diff --git a/libs/rs/java/Samples/src/com/android/samples/RsList.java b/libs/rs/java/Samples/src/com/android/samples/RsList.java
index d8c733d..0f6b1ac 100644
--- a/libs/rs/java/Samples/src/com/android/samples/RsList.java
+++ b/libs/rs/java/Samples/src/com/android/samples/RsList.java
@@ -54,7 +54,7 @@ public class RsList extends Activity {
@Override
protected void onResume() {
// Ideally a game should implement onResume() and onPause()
- // to take appropriate action when the activity looses focus
+ // to take appropriate action when the activity loses focus
super.onResume();
mView.onResume();
}
@@ -62,7 +62,7 @@ public class RsList extends Activity {
@Override
protected void onPause() {
// Ideally a game should implement onResume() and onPause()
- // to take appropriate action when the activity looses focus
+ // to take appropriate action when the activity loses focus
super.onPause();
mView.onPause();
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index cf9c6be..da64e02 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -19,10 +19,13 @@ package com.android.rs.test;
import android.content.res.Resources;
import android.renderscript.*;
import android.util.Log;
+import java.util.ArrayList;
+import java.util.ListIterator;
public class RSTestCore {
- public static final int PART_COUNT = 50000;
+ int mWidth;
+ int mHeight;
public RSTestCore() {
}
@@ -30,31 +33,85 @@ public class RSTestCore {
private Resources mRes;
private RenderScriptGL mRS;
- private ScriptC_test_root mRootScript;
+ private Font mFont;
+ ScriptField_ListAllocs_s mListAllocs;
+ int mLastX;
+ int mLastY;
+ private ScriptC_rslist mScript;
- private boolean fp_mad() {
- ScriptC_fp_mad s = new ScriptC_fp_mad(mRS, mRes, R.raw.fp_mad, true);
- s.invoke_doTest(0, 0);
- return true;
- }
-
- private boolean rs_primitives_test() {
- ScriptC_primitives s = new ScriptC_primitives(mRS, mRes, R.raw.primitives, true);
- s.invoke_rs_primitives_test(0, 0);
- return true;
- }
+ private ArrayList<UnitTest> unitTests;
public void init(RenderScriptGL rs, Resources res, int width, int height) {
mRS = rs;
mRes = res;
+ mWidth = width;
+ mHeight = height;
+
+ mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist, true);
+
+ unitTests = new ArrayList<UnitTest>();
+
+ unitTests.add(new UT_primitives(mRes));
+ unitTests.add(new UT_fp_mad(mRes));
+ /*
+ unitTests.add(new UnitTest("<Pass>", 1));
+ unitTests.add(new UnitTest());
+ unitTests.add(new UnitTest("<Fail>", -1));
+ */
+
+ UnitTest [] uta = new UnitTest[unitTests.size()];
+ uta = unitTests.toArray(uta);
+
+ /* Run the actual unit tests */
+ ListIterator<UnitTest> test_iter = unitTests.listIterator();
+ while (test_iter.hasNext()) {
+ UnitTest t = test_iter.next();
+ t.start();
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+ for (int i = 0; i < uta.length; i++) {
+ ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+ listElem.text = Allocation.createFromString(mRS, uta[i].name);
+ listElem.result = uta[i].result;
+ mListAllocs.set(listElem, i, false);
+ }
- mRootScript = new ScriptC_test_root(mRS, mRes, R.raw.test_root, true);
+ mListAllocs.copyAll();
- rs_primitives_test();
- fp_mad();
+ mScript.bind_gList(mListAllocs);
+ mFont = Font.createFromFamily(mRS, mRes, "serif", Font.Style.BOLD, 8);
+ mScript.set_gFont(mFont);
+
+ mRS.contextBindRootScript(mScript);
+ mRS.finish();
}
public void newTouchPosition(float x, float y, float pressure, int id) {
}
+
+ public void onActionDown(int x, int y) {
+ mScript.set_gDY(0.0f);
+ mLastX = x;
+ mLastY = y;
+ }
+
+ public void onActionMove(int x, int y) {
+ int dx = mLastX - x;
+ int dy = mLastY - y;
+
+ if (Math.abs(dy) <= 2) {
+ dy = 0;
+ }
+
+ mScript.set_gDY(dy);
+
+ mLastX = x;
+ mLastY = y;
+ }
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java
index 7ae0c08..ce99c6d 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestView.java
@@ -67,40 +67,28 @@ public class RSTestView extends RSSurfaceView {
}
}
-/*
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event)
+ {
+ return super.onKeyDown(keyCode, event);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev)
{
- int act = ev.getActionMasked();
- if (act == ev.ACTION_UP) {
- mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
- return false;
- } else if (act == MotionEvent.ACTION_POINTER_UP) {
- // only one pointer going up, we can get the index like this
- int pointerIndex = ev.getActionIndex();
- int pointerId = ev.getPointerId(pointerIndex);
- mRender.newTouchPosition(0, 0, 0, pointerId);
+ boolean ret = false;
+ int act = ev.getAction();
+ if (act == ev.ACTION_DOWN) {
+ mRender.onActionDown((int)ev.getX(), (int)ev.getY());
+ ret = true;
}
- int count = ev.getHistorySize();
- int pcount = ev.getPointerCount();
-
- for (int p=0; p < pcount; p++) {
- int id = ev.getPointerId(p);
- mRender.newTouchPosition(ev.getX(p),
- ev.getY(p),
- ev.getPressure(p),
- id);
-
- for (int i=0; i < count; i++) {
- mRender.newTouchPosition(ev.getHistoricalX(p, i),
- ev.getHistoricalY(p, i),
- ev.getHistoricalPressure(p, i),
- id);
- }
+ else if (act == ev.ACTION_MOVE) {
+ mRender.onActionMove((int)ev.getX(), (int)ev.getY());
+ ret = true;
}
- return true;
+
+ return ret;
}
- */
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java b/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java
new file mode 100644
index 0000000..c4e57e8
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_fp_mad.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_fp_mad extends UnitTest {
+ private Resources mRes;
+
+ protected UT_fp_mad(Resources res) {
+ super("Fp_Mad");
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create();
+ ScriptC_fp_mad s = new ScriptC_fp_mad(pRS, mRes, R.raw.fp_mad, true);
+ pRS.mMessageCallback = mRsMessage;
+ s.invoke_fp_mad_test(0, 0);
+ pRS.finish();
+ pRS.destroy();
+ }
+}
+
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java b/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java
new file mode 100644
index 0000000..629f0b2
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UT_primitives.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.rs.test;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_primitives extends UnitTest {
+ private Resources mRes;
+
+ protected UT_primitives(Resources res) {
+ super("Primitives");
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create();
+ ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives, true);
+ pRS.mMessageCallback = mRsMessage;
+ s.invoke_primitives_test(0, 0);
+ pRS.finish();
+ //android.util.Log.v("UT", "After pRS.finish");
+
+ pRS.destroy();
+ }
+}
+
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
new file mode 100644
index 0000000..5b55779
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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 com.android.rs.test;
+import android.renderscript.RenderScript.RSMessage;
+
+public class UnitTest extends Thread {
+ public String name;
+ public int result;
+
+ /* These constants must match those in shared.rsh */
+ public static final int RS_MSG_TEST_PASSED = 100;
+ public static final int RS_MSG_TEST_FAILED = 101;
+
+ protected UnitTest(String n, int initResult) {
+ super();
+ name = n;
+ result = initResult;
+ }
+
+ protected UnitTest(String n) {
+ this(n, 0);
+ }
+
+ protected UnitTest() {
+ this ("<Unknown>");
+ }
+
+ protected RSMessage mRsMessage = new RSMessage() {
+ public void run() {
+ switch (mID) {
+ case RS_MSG_TEST_PASSED:
+ result = 1;
+ break;
+ case RS_MSG_TEST_FAILED:
+ result = -1;
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ public void run() {
+ /* This method needs to be implemented for each subclass */
+ }
+}
+
diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
index 494ff35..eb82e56 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
@@ -3,8 +3,7 @@
const int TEST_COUNT = 1;
#pragma rs export_var(g_results)
-#pragma rs export_func(doTest)
-
+#pragma rs export_func(fp_mad_test)
static float data_f1[1025];
static float4 data_f4[1025];
@@ -143,7 +142,7 @@ static void test_clamp4(uint32_t index) {
rsDebug("fp_clamp4 M ops", 100.f / time);
}
-void doTest(uint32_t index, int test_num) {
+void fp_mad_test(uint32_t index, int test_num) {
for (int x=0; x < 1025; x++) {
data_f1[x] = (x & 0xf) * 0.1f;
data_f4[x].x = (x & 0xf) * 0.1f;
@@ -168,6 +167,10 @@ void doTest(uint32_t index, int test_num) {
test_sincos(index);
test_clamp4(index);
test_clamp(index);
+
+ // TODO Actually verify test result accuracy
+ rsDebug("fp_mad_test PASSED", 0);
+ rsSendToClient(RS_MSG_TEST_PASSED);
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
index 39bd2c4..2ba5d52 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -1,10 +1,8 @@
#include "shared.rsh"
-#pragma rs export_func(rs_primitives_test)
+#pragma rs export_func(primitives_test)
// Testing primitive types
-#pragma rs export_var(floatTest)
-#pragma rs export_var(doubleTest)
static float floatTest = 1.99f;
static double doubleTest = 2.05;
static char charTest = -8;
@@ -14,7 +12,7 @@ static uchar ucharTest = 8;
static ushort ushortTest = 16;
static uint uintTest = 32;
-static void test_primitive_types(uint32_t index) {
+static bool test_primitive_types(uint32_t index) {
bool failed = false;
start();
@@ -28,17 +26,26 @@ static void test_primitive_types(uint32_t index) {
_RS_ASSERT(uintTest == 32);
float time = end(index);
+
if (failed) {
- rsDebug("test_primitives FAILED ", time);
+ rsDebug("test_primitives FAILED", time);
}
else {
- rsDebug("test_primitives PASSED ", time);
+ rsDebug("test_primitives PASSED", time);
}
+
+ return failed;
}
+void primitives_test(uint32_t index, int test_num) {
+ bool failed = false;
+ failed |= test_primitive_types(index);
-void rs_primitives_test(uint32_t index, int test_num) {
- test_primitive_types(index);
+ if (failed) {
+ rsSendToClient(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClient(RS_MSG_TEST_PASSED);
+ }
}
-
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
new file mode 100644
index 0000000..fcea3ab
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
@@ -0,0 +1,86 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.test)
+
+#include "rs_graphics.rsh"
+
+float gDY;
+
+rs_font gFont;
+
+typedef struct ListAllocs_s {
+ rs_allocation text;
+ int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
+#pragma rs export_var(gDY, gFont, gList)
+
+void init() {
+ gDY = 0.0f;
+}
+
+int textPos = 0;
+
+int root(int launchID) {
+
+ rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ rsgClearDepth(1.0f);
+
+ textPos -= (int)gDY*2;
+ gDY *= 0.95;
+
+ rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+ rsgBindFont(gFont);
+ color(0.2, 0.2, 0.2, 0);
+
+ rs_allocation listAlloc = rsGetAllocation(gList);
+ int allocSize = rsAllocationGetDimX(listAlloc);
+
+ int width = rsgGetWidth();
+ int height = rsgGetHeight();
+
+ int itemHeight = 80;
+ int currentYPos = itemHeight + textPos;
+
+ for(int i = 0; i < allocSize; i ++) {
+ if(currentYPos - itemHeight > height) {
+ break;
+ }
+
+ if(currentYPos > 0) {
+ switch(gList[i].result) {
+ case 1: /* Passed */
+ rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f);
+ break;
+ case -1: /* Failed */
+ rsgFontColor(0.9f, 0.5f, 0.5f, 1.0f);
+ break;
+ case 0: /* Unknown */
+ default:
+ rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+ break;
+ }
+ rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0);
+ rsgDrawText(gList[i].text, 30, currentYPos - 32);
+ }
+ currentYPos += itemHeight;
+ }
+
+ return 10;
+}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
index 8c3e5f4..820fffd 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
+++ b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
@@ -25,7 +25,6 @@ static float end(uint32_t idx) {
#define _RS_ASSERT(b) \
do { \
- rsDebug("Checking " #b, ((int) (b))); \
if (!(b)) { \
failed = true; \
rsDebug(#b " FAILED", 0); \
@@ -33,3 +32,7 @@ do { \
\
} while (0)
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
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 @@ public class AudioTrack
//--------------------
/**
- * 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 @@ public class MediaPlayer
* 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/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index b64299a..403ed58 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -246,8 +246,30 @@ public class MtpDatabase {
return new int[] {
// allow transfering arbitrary files
MtpConstants.FORMAT_UNDEFINED,
+
MtpConstants.FORMAT_ASSOCIATION,
+ MtpConstants.FORMAT_TEXT,
+ MtpConstants.FORMAT_HTML,
+ MtpConstants.FORMAT_WAV,
+ MtpConstants.FORMAT_MP3,
+ MtpConstants.FORMAT_MPEG,
+ MtpConstants.FORMAT_EXIF_JPEG,
+ MtpConstants.FORMAT_TIFF_EP,
+ MtpConstants.FORMAT_GIF,
+ MtpConstants.FORMAT_JFIF,
+ MtpConstants.FORMAT_PNG,
+ MtpConstants.FORMAT_TIFF,
+ MtpConstants.FORMAT_WMA,
+ MtpConstants.FORMAT_OGG,
+ MtpConstants.FORMAT_AAC,
+ MtpConstants.FORMAT_MP4_CONTAINER,
+ MtpConstants.FORMAT_MP2,
+ MtpConstants.FORMAT_3GP_CONTAINER,
MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
+ MtpConstants.FORMAT_WPL_PLAYLIST,
+ MtpConstants.FORMAT_M3U_PLAYLIST,
+ MtpConstants.FORMAT_PLS_PLAYLIST,
+ MtpConstants.FORMAT_XML_DOCUMENT,
};
}
@@ -260,9 +282,13 @@ public class MtpDatabase {
return new int[] {
MtpConstants.PROPERTY_STORAGE_ID,
MtpConstants.PROPERTY_OBJECT_FORMAT,
+ MtpConstants.PROPERTY_PROTECTION_STATUS,
MtpConstants.PROPERTY_OBJECT_SIZE,
MtpConstants.PROPERTY_OBJECT_FILE_NAME,
+ MtpConstants.PROPERTY_DATE_MODIFIED,
MtpConstants.PROPERTY_PARENT_OBJECT,
+ MtpConstants.PROPERTY_PERSISTENT_UID,
+ MtpConstants.PROPERTY_NAME,
};
}
@@ -279,6 +305,11 @@ public class MtpDatabase {
String column = null;
boolean isString = false;
+ // temporary hack
+ if (property == MtpConstants.PROPERTY_NAME) {
+ property = MtpConstants.PROPERTY_OBJECT_FILE_NAME;
+ }
+
switch (property) {
case MtpConstants.PROPERTY_STORAGE_ID:
outIntValue[0] = mStorageID;
diff --git a/media/java/android/media/AudioEffect.java b/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.nio.ByteBuffer;
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 @@ public class AudioEffect {
/**
* 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 @@ public class AudioEffect {
/**
* 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 @@ public class AudioEffect {
// 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 class AudioEffect {
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 class AudioEffect {
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 @@ public class AudioEffect {
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 @@ public class AudioEffect {
* @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 @@ public class AudioEffect {
/**
* 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 @@ public class AudioEffect {
/**
* 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 @@ public class AudioEffect {
// --------------------
/**
- * 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 @@ public class AudioEffect {
* {@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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* short integer.
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int param, short value)
throws IllegalStateException {
@@ -428,6 +485,7 @@ public class AudioEffect {
* array of bytes.
*
* @see #setParameter(byte[], byte[])
+ * @hide
*/
public int setParameter(int param, byte[] value)
throws IllegalStateException {
@@ -440,6 +498,7 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* array of bytes.
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int param, byte[] value)
throws IllegalStateException {
@@ -552,6 +615,7 @@ public class AudioEffect {
* array of 1 or 2 integers
*
* @see #getParameter(byte[], byte[])
+ * @hide
*/
public int getParameter(int param, int[] value)
throws IllegalStateException {
@@ -576,6 +640,7 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
* 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 @@ public class AudioEffect {
}
/**
- * Returns effect engine enable state
+ * Returns effect enabled state
*
* @return true if the effect is enabled, false otherwise.
* @throws IllegalStateException
@@ -768,6 +837,7 @@ public class AudioEffect {
* Sets the listener AudioEffect notifies when a parameter is changed.
*
* @param listener
+ * @hide
*/
public void setParameterListener(OnParameterChangeListener listener) {
synchronized (mListenerLock) {
@@ -828,6 +898,7 @@ public class AudioEffect {
/**
* 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 @@ public class AudioEffect {
* {@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 @@ public class AudioEffect {
// Utility methods
// ------------------
+ /**
+ * @hide
+ */
public void checkState(String methodName) throws IllegalStateException {
synchronized (mStateLock) {
if (mState != STATE_INITIALIZED) {
@@ -1095,6 +1168,9 @@ public class AudioEffect {
}
}
+ /**
+ * @hide
+ */
public void checkStatus(int status) {
switch (status) {
case AudioEffect.SUCCESS:
@@ -1110,11 +1186,17 @@ public class AudioEffect {
}
}
+ /**
+ * @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 @@ public class AudioEffect {
}
+ /**
+ * @hide
+ */
public byte[] intToByteArray(int value) {
ByteBuffer converter = ByteBuffer.allocate(4);
converter.order(ByteOrder.nativeOrder());
@@ -1129,10 +1214,16 @@ public class AudioEffect {
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 @@ public class AudioEffect {
}
+ /**
+ * @hide
+ */
public byte[] shortToByteArray(short value) {
ByteBuffer converter = ByteBuffer.allocate(2);
converter.order(ByteOrder.nativeOrder());
@@ -1148,6 +1242,9 @@ public class AudioEffect {
return converter.array();
}
+ /**
+ * @hide
+ */
public byte[] concatArrays(byte[]... arrays) {
int len = 0;
for (byte[] a : arrays) {
@@ -1162,5 +1259,4 @@ public class AudioEffect {
}
return b;
}
-
}
diff --git a/media/java/android/media/BassBoost.java b/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 @@ import java.util.StringTokenizer;
/**
* 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 class BassBoost extends AudioEffect {
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 @@ public class BassBoost extends AudioEffect {
* 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
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.nio.ByteBuffer;
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 @@ import java.util.StringTokenizer;
* 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 class EnvironmentalReverb extends AudioEffect {
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 @@ public class EnvironmentalReverb extends AudioEffect {
* 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
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 @@ import java.util.StringTokenizer;
* <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 class Equalizer extends AudioEffect {
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 @@ public class Equalizer extends AudioEffect {
* 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
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 @@ import java.util.StringTokenizer;
* 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 @@ import java.util.StringTokenizer;
* 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 @@ public class PresetReverb extends AudioEffect {
/**
* 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 @@ public class PresetReverb extends AudioEffect {
* 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
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 @@ import java.util.StringTokenizer;
* <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 class Virtualizer extends AudioEffect {
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 @@ public class Virtualizer extends AudioEffect {
* 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
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 @@ import android.os.Message;
* 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 @@ import android.os.Message;
* 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/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
index 177b863..8c39577 100755
--- a/media/java/android/media/videoeditor/Effect.java
+++ b/media/java/android/media/videoeditor/Effect.java
@@ -84,7 +84,7 @@ public abstract class Effect {
* Set start time of the effect. If a preview or export is in progress, then
* this change is effective for next preview or export session.
*
- * @param startTimeMs The start time of the effect relative to the begining
+ * @param startTimeMs The start time of the effect relative to the beginning
* of the media item in milliseconds
*/
public void setStartTime(long startTimeMs) {
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index 9e32744..e7be35d 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -64,8 +64,8 @@ public abstract class MediaItem {
private int mRenderingMode;
// Beginning and end transitions
- private Transition mBeginTransition;
- private Transition mEndTransition;
+ protected Transition mBeginTransition;
+ protected Transition mEndTransition;
/**
* Constructor
@@ -113,6 +113,13 @@ public abstract class MediaItem {
*/
public void setRenderingMode(int renderingMode) {
mRenderingMode = renderingMode;
+ if (mBeginTransition != null) {
+ mBeginTransition.invalidate();
+ }
+
+ if (mEndTransition != null) {
+ mEndTransition.invalidate();
+ }
}
/**
@@ -271,7 +278,9 @@ public abstract class MediaItem {
*
* @param overlay The overlay to add
* @throws IllegalStateException if a preview or an export is in progress or
- * if the overlay id is not unique across all the overlays added.
+ * if the overlay id is not unique across all the overlays
+ * added or if the bitmap is not specified or if the dimensions of
+ * the bitmap do not match the dimensions of the media item
*/
public void addOverlay(Overlay overlay) {
if (mOverlays.contains(overlay)) {
@@ -283,6 +292,23 @@ public abstract class MediaItem {
"Overlay start time + overlay duration > media clip duration");
}
+ if (overlay instanceof OverlayFrame) {
+ final OverlayFrame frame = (OverlayFrame)overlay;
+ final Bitmap bitmap = frame.getBitmap();
+ if (bitmap == null) {
+ throw new IllegalArgumentException("Overlay bitmap not specified");
+ }
+
+ // The dimensions of the overlay bitmap must be the same as the
+ // media item dimensions
+ if (bitmap.getWidth() != getWidth() || bitmap.getHeight() != getHeight()) {
+ throw new IllegalArgumentException(
+ "Bitmap dimensions must match media item dimensions");
+ }
+ } else {
+ throw new IllegalArgumentException("Overlay not supported");
+ }
+
mOverlays.add(overlay);
invalidateTransitions(overlay);
}
@@ -302,6 +328,9 @@ public abstract class MediaItem {
for (Overlay overlay : mOverlays) {
if (overlay.getId().equals(overlayId)) {
mOverlays.remove(overlay);
+ if (overlay instanceof OverlayFrame) {
+ ((OverlayFrame)overlay).invalidate();
+ }
invalidateTransitions(overlay);
return overlay;
}
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 87e9a22..af50b83 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -264,8 +264,19 @@ public class MediaVideoItem extends MediaItem {
throw new IllegalArgumentException("Invalid end time");
}
- mBeginBoundaryTimeMs = beginMs;
- mEndBoundaryTimeMs = endMs;
+ if (beginMs != mBeginBoundaryTimeMs) {
+ mBeginBoundaryTimeMs = beginMs;
+ if (mBeginTransition != null) {
+ mBeginTransition.invalidate();
+ }
+ }
+
+ if (endMs == mEndBoundaryTimeMs) {
+ mEndBoundaryTimeMs = endMs;
+ if (mEndTransition != null) {
+ mEndTransition.invalidate();
+ }
+ }
// TODO: Validate/modify the start and the end time of effects and overlays
}
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
index e5d9b81..3abac6c 100755
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ b/media/java/android/media/videoeditor/OverlayFrame.java
@@ -16,16 +16,24 @@
package android.media.videoeditor;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap.CompressFormat;
+
/**
- * This class is used to overlay an image on top of a media item. This class
- * does not manage deletion of the overlay file so application may use
- * {@link #getFilename()} for this purpose.
+ * This class is used to overlay an image on top of a media item.
* {@hide}
*/
public class OverlayFrame extends Overlay {
// Instance variables
- private final String mFilename;
+ private final Bitmap mBitmap;
+ private String mFilename;
/**
* An object of this type cannot be instantiated by using the default
@@ -33,30 +41,90 @@ public class OverlayFrame extends Overlay {
*/
@SuppressWarnings("unused")
private OverlayFrame() {
- this(null, null, 0, 0);
+ this(null, (String)null, 0, 0);
}
/**
* Constructor for an OverlayFrame
*
* @param overlayId The overlay id
- * @param filename The file name that contains the overlay. Only PNG
- * supported.
+ * @param bitmap The bitmap to be used as an overlay. The size of the
+ * bitmap must equal to the size of the media item to which it is
+ * added. The bitmap is typically a decoded PNG file.
* @param startTimeMs The overlay start time in milliseconds
* @param durationMs The overlay duration in milliseconds
*
* @throws IllegalArgumentException if the file type is not PNG or the
* startTimeMs and durationMs are incorrect.
*/
- public OverlayFrame(String overlayId, String filename, long startTimeMs, long durationMs) {
+ public OverlayFrame(String overlayId, Bitmap bitmap, long startTimeMs,
+ long durationMs) {
+ super(overlayId, startTimeMs, durationMs);
+ mBitmap = bitmap;
+ mFilename = null;
+ }
+
+ /**
+ * Constructor for an OverlayFrame. This constructor can be used to
+ * restore the overlay after it was saved internally by the video editor.
+ *
+ * @param overlayId The overlay id
+ * @param filename The file name that contains the overlay.
+ * @param startTimeMs The overlay start time in milliseconds
+ * @param durationMs The overlay duration in milliseconds
+ *
+ * @throws IllegalArgumentException if the file type is not PNG or the
+ * startTimeMs and durationMs are incorrect.
+ */
+ OverlayFrame(String overlayId, String filename, long startTimeMs, long durationMs) {
super(overlayId, startTimeMs, durationMs);
mFilename = filename;
+ mBitmap = BitmapFactory.decodeFile(mFilename);
+ }
+
+ /**
+ * @return Get the overlay bitmap
+ */
+ public Bitmap getBitmap() {
+ return mBitmap;
}
/**
* Get the file name of this overlay
*/
- public String getFilename() {
+ String getFilename() {
return mFilename;
}
+
+ /**
+ * Save the overlay to the project folder
+ *
+ * @param editor The video editor
+ *
+ * @return
+ * @throws FileNotFoundException if the bitmap cannot be saved
+ * @throws IOException if the bitmap file cannot be saved
+ */
+ String save(VideoEditor editor) throws FileNotFoundException, IOException {
+ if (mFilename != null) {
+ return mFilename;
+ }
+
+ mFilename = editor.getPath() + "/" + getId() + ".png";
+ // Save the image to a local file
+ final FileOutputStream out = new FileOutputStream(mFilename);
+ mBitmap.compress(CompressFormat.PNG, 100, out);
+ out.flush();
+ out.close();
+ return mFilename;
+ }
+
+ /**
+ * Delete the overlay file
+ */
+ void invalidate() {
+ if (mFilename != null) {
+ new File(mFilename).delete();
+ }
+ }
}
diff --git a/media/java/android/media/videoeditor/TransitionAlpha.java b/media/java/android/media/videoeditor/TransitionAlpha.java
index 0a4a12f..30e66fc 100755
--- a/media/java/android/media/videoeditor/TransitionAlpha.java
+++ b/media/java/android/media/videoeditor/TransitionAlpha.java
@@ -58,17 +58,19 @@ public class TransitionAlpha extends Transition {
* Constructor
*
* @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this
- * media item
- * @param beforeMediaItem The transition is applied to the beginning of
- * this media item
+ * @param afterMediaItem The transition is applied to the end of this media
+ * item
+ * @param beforeMediaItem The transition is applied to the beginning of this
+ * media item
* @param durationMs duration of the transition in milliseconds
* @param behavior behavior is one of the behavior defined in Transition
* class
- * @param maskFilename JPEG file name
+ * @param maskFilename JPEG file name. The dimension of the image
+ * corresponds to 720p (16:9 aspect ratio). Mask files are
+ * shared between video editors and can be created in the
+ * projects folder (the parent folder for all projects).
* @param blendingPercent The blending percent applied
* @param invert true to invert the direction of the alpha blending
- *
* @throws IllegalArgumentException if behavior is not supported, or if
* direction are not supported.
*/
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index 14e2658..7226d5d 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -48,8 +48,8 @@ public class VideoEditorTestImpl implements VideoEditor {
private static final String TAG_PROJECT = "project";
private static final String TAG_MEDIA_ITEMS = "media_items";
private static final String TAG_MEDIA_ITEM = "media_item";
- private static final String TAG_BEGIN_TRANSITION = "begin_transition";
- private static final String TAG_END_TRANSITION = "end_transition";
+ private static final String TAG_TRANSITIONS = "transitions";
+ private static final String TAG_TRANSITION = "transition";
private static final String ATTR_ID = "id";
private static final String ATTR_FILENAME = "filename";
private static final String ATTR_AUDIO_WAVEFORM_FILENAME = "wavefoem";
@@ -65,6 +65,8 @@ public class VideoEditorTestImpl implements VideoEditor {
private static final String ATTR_BLENDING = "blending";
private static final String ATTR_INVERT = "invert";
private static final String ATTR_MASK = "mask";
+ private static final String ATTR_BEFORE_MEDIA_ITEM_ID = "before_media_item";
+ private static final String ATTR_AFTER_MEDIA_ITEM_ID = "after_media_item";
// Instance variables
private long mDurationMs;
@@ -400,6 +402,7 @@ public class VideoEditorTestImpl implements VideoEditor {
}
beforeMediaItem.setBeginTransition(transition);
}
+
computeTimelineDuration();
}
@@ -412,22 +415,25 @@ public class VideoEditorTestImpl implements VideoEditor {
}
final Transition transition = getTransition(transitionId);
- if (transition != null) {
- mTransitions.remove(transition);
- transition.invalidate();
- computeTimelineDuration();
+ if (transition == null) {
+ throw new IllegalStateException("Transition not found: " + transitionId);
}
- // Cross reference the transitions
+ // Remove the transition references
final MediaItem afterMediaItem = transition.getAfterMediaItem();
if (afterMediaItem != null) {
afterMediaItem.setEndTransition(null);
}
+
final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
if (beforeMediaItem != null) {
beforeMediaItem.setBeginTransition(null);
}
+ mTransitions.remove(transition);
+ transition.invalidate();
+ computeTimelineDuration();
+
return transition;
}
@@ -543,15 +549,14 @@ public class VideoEditorTestImpl implements VideoEditor {
serializer.startTag("", TAG_PROJECT);
serializer.attribute("", ATTR_ASPECT_RATIO, Integer.toString(mAspectRatio));
- boolean firstMediaItem = true;
serializer.startTag("", TAG_MEDIA_ITEMS);
for (MediaItem mediaItem : mMediaItems) {
serializer.startTag("", TAG_MEDIA_ITEM);
serializer.attribute("", ATTR_ID, mediaItem.getId());
serializer.attribute("", ATTR_TYPE, mediaItem.getClass().getSimpleName());
serializer.attribute("", ATTR_FILENAME, mediaItem.getFilename());
- serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(mediaItem
- .getRenderingMode()));
+ serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(
+ mediaItem.getRenderingMode()));
if (mediaItem instanceof MediaVideoItem) {
final MediaVideoItem mvi = (MediaVideoItem)mediaItem;
serializer
@@ -559,54 +564,49 @@ public class VideoEditorTestImpl implements VideoEditor {
serializer.attribute("", ATTR_END_TIME, Long.toString(mvi.getBoundaryEndTime()));
serializer.attribute("", ATTR_VOLUME, Integer.toString(mvi.getVolume()));
if (mvi.getAudioWaveformFilename() != null) {
- serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME, mvi
- .getAudioWaveformFilename());
+ serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
+ mvi.getAudioWaveformFilename());
}
} else if (mediaItem instanceof MediaImageItem) {
serializer.attribute("", ATTR_DURATION, Long.toString(mediaItem.getDuration()));
}
- if (firstMediaItem) {
- firstMediaItem = false;
- final Transition beginTransition = mediaItem.getBeginTransition();
- if (beginTransition != null) {
- serializer.startTag("", TAG_BEGIN_TRANSITION);
- serializer.attribute("", ATTR_ID, beginTransition.getId());
- serializer.attribute("", ATTR_TYPE, beginTransition.getClass()
- .getSimpleName());
- serializer.attribute("", ATTR_DURATION, Long.toString(beginTransition
- .getDuration()));
- serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(beginTransition
- .getBehavior()));
- serializer.endTag("", TAG_BEGIN_TRANSITION);
- }
+ serializer.endTag("", TAG_MEDIA_ITEM);
+ }
+ serializer.endTag("", TAG_MEDIA_ITEMS);
+
+ serializer.startTag("", TAG_TRANSITIONS);
+
+ for (Transition transition : mTransitions) {
+ serializer.startTag("", TAG_TRANSITION);
+ serializer.attribute("", ATTR_ID, transition.getId());
+ serializer.attribute("", ATTR_TYPE, transition.getClass().getSimpleName());
+ serializer.attribute("", ATTR_DURATION, Long.toString(transition.getDuration()));
+ serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(transition.getBehavior()));
+ final MediaItem afterMediaItem = transition.getAfterMediaItem();
+ if (afterMediaItem != null) {
+ serializer.attribute("", ATTR_AFTER_MEDIA_ITEM_ID, afterMediaItem.getId());
+ }
+
+ final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
+ if (beforeMediaItem != null) {
+ serializer.attribute("", ATTR_BEFORE_MEDIA_ITEM_ID, beforeMediaItem.getId());
}
- final Transition endTransition = mediaItem.getEndTransition();
- if (endTransition != null) {
- serializer.startTag("", TAG_END_TRANSITION);
- serializer.attribute("", ATTR_ID, endTransition.getId());
- serializer.attribute("", ATTR_TYPE, endTransition.getClass().getSimpleName());
- serializer.attribute("", ATTR_DURATION, Long.toString(endTransition
- .getDuration()));
- serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(endTransition
- .getBehavior()));
- if (endTransition instanceof TransitionSliding) {
- serializer.attribute("", ATTR_DIRECTION, Integer
- .toString(((TransitionSliding)endTransition).getDirection()));
- } else if (endTransition instanceof TransitionAlpha) {
- TransitionAlpha ta = (TransitionAlpha)endTransition;
- serializer.attribute("", ATTR_BLENDING, Integer.toString(ta
- .getBlendingPercent()));
- serializer.attribute("", ATTR_INVERT, Boolean.toString(ta.isInvert()));
+ if (transition instanceof TransitionSliding) {
+ serializer.attribute("", ATTR_DIRECTION,
+ Integer.toString(((TransitionSliding)transition).getDirection()));
+ } else if (transition instanceof TransitionAlpha) {
+ TransitionAlpha ta = (TransitionAlpha)transition;
+ serializer.attribute("", ATTR_BLENDING, Integer.toString(ta.getBlendingPercent()));
+ serializer.attribute("", ATTR_INVERT, Boolean.toString(ta.isInvert()));
+ if (ta.getMaskFilename() != null) {
serializer.attribute("", ATTR_MASK, ta.getMaskFilename());
}
- serializer.endTag("", TAG_END_TRANSITION);
}
-
- serializer.endTag("", TAG_MEDIA_ITEM);
+ serializer.endTag("", TAG_TRANSITION);
}
- serializer.endTag("", TAG_MEDIA_ITEMS);
+ serializer.endTag("", TAG_TRANSITIONS);
serializer.endTag("", TAG_PROJECT);
serializer.endDocument();
@@ -628,8 +628,6 @@ public class VideoEditorTestImpl implements VideoEditor {
parser.setInput(new FileInputStream(file), "UTF-8");
int eventType = parser.getEventType();
String name;
- MediaItem currentMediaItem = null;
- MediaItem previousMediaItem = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
@@ -644,6 +642,7 @@ public class VideoEditorTestImpl implements VideoEditor {
final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
ATTR_RENDERING_MODE));
+ MediaItem currentMediaItem;
if (MediaImageItem.class.getSimpleName().equals(type)) {
final long durationMs = Long.parseLong(parser.getAttributeValue("",
ATTR_DURATION));
@@ -671,29 +670,13 @@ public class VideoEditorTestImpl implements VideoEditor {
}
if (currentMediaItem != null) {
- if (previousMediaItem != null) {
- currentMediaItem.setBeginTransition(previousMediaItem
- .getEndTransition());
- }
mMediaItems.add(currentMediaItem);
}
- } else if (name.equals(TAG_BEGIN_TRANSITION)) {
- final Transition transition = parseTransition(parser, currentMediaItem,
- null);
- currentMediaItem.setBeginTransition(transition);
- } else if (name.equals(TAG_END_TRANSITION)) {
- final Transition transition = parseTransition(parser, previousMediaItem,
- currentMediaItem);
- currentMediaItem.setEndTransition(transition);
- }
- break;
- }
-
- case XmlPullParser.END_TAG: {
- name = parser.getName();
- if (name.equals(TAG_MEDIA_ITEM)) {
- previousMediaItem = currentMediaItem;
- currentMediaItem = null;
+ } else if (name.equals(TAG_TRANSITION)) {
+ final Transition transition = parseTransition(parser);
+ if (transition != null) {
+ mTransitions.add(transition);
+ }
}
break;
}
@@ -712,47 +695,72 @@ public class VideoEditorTestImpl implements VideoEditor {
* Parse the transition
*
* @param parser The parser
- * @param afterMediaItem The transition is at the end of this media item
- * @param beforeMediaItem The transition is at the beginning of this media
- * item
* @return The transition
*/
- private Transition parseTransition(XmlPullParser parser, MediaItem beforeMediaItem,
- MediaItem afterMediaItem) {
+ private Transition parseTransition(XmlPullParser parser) {
final String transitionId = parser.getAttributeValue("", ATTR_ID);
final String type = parser.getAttributeValue("", ATTR_TYPE);
final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
final int behavior = Integer.parseInt(parser.getAttributeValue("", ATTR_BEHAVIOR));
+
+ final String beforeMediaItemId = parser.getAttributeValue("", ATTR_BEFORE_MEDIA_ITEM_ID);
+ final MediaItem beforeMediaItem;
+ if (beforeMediaItemId != null) {
+ beforeMediaItem = getMediaItem(beforeMediaItemId);
+ } else {
+ beforeMediaItem = null;
+ }
+
+ final String afterMediaItemId = parser.getAttributeValue("", ATTR_AFTER_MEDIA_ITEM_ID);
+ final MediaItem afterMediaItem;
+ if (afterMediaItemId != null) {
+ afterMediaItem = getMediaItem(afterMediaItemId);
+ } else {
+ afterMediaItem = null;
+ }
+
+ final Transition transition;
if (TransitionStartCurtainOpening.class.getSimpleName().equals(type)) {
- return new TransitionStartCurtainOpening(transitionId, beforeMediaItem, durationMs,
- behavior);
+ transition = new TransitionStartCurtainOpening(transitionId, beforeMediaItem,
+ durationMs, behavior);
} else if (TransitionStartFadeFromBlack.class.getSimpleName().equals(type)) {
- return new TransitionStartFadeFromBlack(transitionId, beforeMediaItem, durationMs,
- behavior);
+ transition = new TransitionStartFadeFromBlack(transitionId, beforeMediaItem,
+ durationMs, behavior);
} else if (TransitionAlpha.class.getSimpleName().equals(type)) {
final int blending = Integer.parseInt(parser.getAttributeValue("", ATTR_BLENDING));
final String maskFilename = parser.getAttributeValue("", ATTR_MASK);
final boolean invert = Boolean.getBoolean(parser.getAttributeValue("", ATTR_INVERT));
- return new TransitionAlpha(transitionId, afterMediaItem, beforeMediaItem, durationMs,
- behavior, maskFilename, blending, invert);
- } else if (TransitionAlpha.class.getSimpleName().equals(type)) {
- return new TransitionCrossfade(transitionId, afterMediaItem, beforeMediaItem,
+ transition = new TransitionAlpha(transitionId, afterMediaItem, beforeMediaItem,
+ durationMs, behavior, maskFilename, blending, invert);
+ } else if (TransitionCrossfade.class.getSimpleName().equals(type)) {
+ transition = new TransitionCrossfade(transitionId, afterMediaItem, beforeMediaItem,
durationMs, behavior);
} else if (TransitionSliding.class.getSimpleName().equals(type)) {
final int direction = Integer.parseInt(parser.getAttributeValue("", ATTR_DIRECTION));
- return new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem, durationMs,
- behavior, direction);
+ transition = new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem,
+ durationMs, behavior, direction);
} else if (TransitionFadeToBlack.class.getSimpleName().equals(type)) {
- return new TransitionFadeToBlack(transitionId, afterMediaItem, beforeMediaItem,
+ transition = new TransitionFadeToBlack(transitionId, afterMediaItem, beforeMediaItem,
durationMs, behavior);
} else if (TransitionEndCurtainClosing.class.getSimpleName().equals(type)) {
- return new TransitionEndCurtainClosing(transitionId, beforeMediaItem, durationMs,
+ transition = new TransitionEndCurtainClosing(transitionId, afterMediaItem, durationMs,
behavior);
} else if (TransitionEndFadeToBlack.class.getSimpleName().equals(type)) {
- return new TransitionEndFadeToBlack(transitionId, beforeMediaItem, durationMs, behavior);
+ transition = new TransitionEndFadeToBlack(transitionId, afterMediaItem, durationMs,
+ behavior);
+ } else {
+ transition = null;
}
- return null;
+ if (beforeMediaItem != null) {
+ beforeMediaItem.setBeginTransition(transition);
+ }
+
+ if (afterMediaItem != null) {
+ afterMediaItem.setEndTransition(transition);
+ }
+
+ return transition;
}
public void cancelExport(String filename) {
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 1842cb2..227ee92 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -672,12 +672,15 @@ struct PropertyTableEntry {
};
static const PropertyTableEntry kObjectPropertyTable[] = {
- { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
- { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
- { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
- { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
- { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
- { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
+ { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
+ { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
+ { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
+ { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
+ { MTP_PROPERTY_NAME, MTP_TYPE_STR },
};
static const PropertyTableEntry kDevicePropertyTable[] = {
@@ -764,6 +767,7 @@ MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
case MTP_PROPERTY_PERSISTENT_UID:
result = new MtpProperty(property, MTP_TYPE_UINT128);
break;
+ case MTP_PROPERTY_NAME:
case MTP_PROPERTY_OBJECT_FILE_NAME:
case MTP_PROPERTY_DATE_MODIFIED:
result = new MtpProperty(property, MTP_TYPE_STR);
@@ -780,6 +784,7 @@ MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
// writeable string properties
result = new MtpProperty(property, MTP_TYPE_STR, true);
+ // FIXME - set current value here!
break;
}
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 @@ using namespace android;
#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 @@ android_media_AudioEffect_native_init(JNIEnv *env)
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 @@ android_media_AudioEffect_native_init(JNIEnv *env)
"<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 @@ using namespace android;
#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/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f0d8943..ba1e218 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2111,7 +2111,15 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->endBox(); // d263
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
CHECK(mCodecSpecificData);
- CHECK(mCodecSpecificDataSize > 0);
+ CHECK(mCodecSpecificDataSize >= 5);
+
+ // Patch avcc's lengthSize field to match the number
+ // of bytes we use to indicate the size of a nal unit.
+ uint8_t *ptr = (uint8_t *)mCodecSpecificData;
+ ptr[4] =
+ (ptr[4] & 0xfc)
+ | (mOwner->useNalLengthFour() ? 3 : 1);
+
mOwner->beginBox("avcC");
mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
mOwner->endBox(); // avcC
diff --git a/media/mtp/MtpCursor.cpp b/media/mtp/MtpCursor.cpp
index 8c964b4..865a294 100644
--- a/media/mtp/MtpCursor.cpp
+++ b/media/mtp/MtpCursor.cpp
@@ -66,7 +66,8 @@ namespace android {
#define OBJECT_THUMB 221
MtpCursor::MtpCursor(MtpClient* client, int queryType, int deviceID,
- int storageID, int objectID, int columnCount, int* columns)
+ MtpStorageID storageID, MtpObjectHandle objectID,
+ int columnCount, int* columns)
: mClient(client),
mQueryType(queryType),
mDeviceID(deviceID),
@@ -427,7 +428,8 @@ bool MtpCursor::putString(CursorWindow* window, const char* text, int row, int c
return true;
}
-bool MtpCursor::putThumbnail(CursorWindow* window, int objectID, int format, int row, int column) {
+bool MtpCursor::putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
+ MtpObjectFormat format, int row, int column) {
MtpDevice* device = mClient->getDevice(mDeviceID);
void* thumbnail;
int size, offset;
diff --git a/media/mtp/MtpCursor.h b/media/mtp/MtpCursor.h
index 3f84753..9e9833f 100644
--- a/media/mtp/MtpCursor.h
+++ b/media/mtp/MtpCursor.h
@@ -36,17 +36,18 @@ private:
OBJECT_CHILDREN = 8,
};
- MtpClient* mClient;
- int mQueryType;
- int mDeviceID;
- int mStorageID;
- int mQbjectID;
- int mColumnCount;
- int* mColumns;
+ MtpClient* mClient;
+ int mQueryType;
+ int mDeviceID;
+ MtpStorageID mStorageID;
+ MtpObjectHandle mQbjectID;
+ int mColumnCount;
+ int* mColumns;
public:
MtpCursor(MtpClient* client, int queryType, int deviceID,
- int storageID, int objectID, int columnCount, int* columns);
+ MtpStorageID storageID, MtpObjectHandle objectID,
+ int columnCount, int* columns);
virtual ~MtpCursor();
int fillWindow(CursorWindow* window, int startPos);
@@ -68,7 +69,8 @@ private:
bool prepareRow(CursorWindow* window);
bool putLong(CursorWindow* window, int value, int row, int column);
bool putString(CursorWindow* window, const char* text, int row, int column);
- bool putThumbnail(CursorWindow* window, int objectID, int format, int row, int column);
+ bool putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
+ MtpObjectFormat format, int row, int column);
};
}; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 6332b4e..84a3e2c 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -26,6 +26,8 @@
#include <cutils/properties.h>
+#define LOG_TAG "MtpServer"
+
#include "MtpDebug.h"
#include "MtpDatabase.h"
#include "MtpProperty.h"
@@ -68,8 +70,8 @@ static const MtpOperationCode kSupportedOperationCodes[] = {
// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
MTP_OPERATION_GET_OBJECT_PROP_DESC,
-// MTP_OPERATION_GET_OBJECT_PROP_VALUE,
-// MTP_OPERATION_SET_OBJECT_PROP_VALUE,
+ MTP_OPERATION_GET_OBJECT_PROP_VALUE,
+ MTP_OPERATION_SET_OBJECT_PROP_VALUE,
MTP_OPERATION_GET_OBJECT_REFERENCES,
MTP_OPERATION_SET_OBJECT_REFERENCES,
// MTP_OPERATION_SKIP,
@@ -294,6 +296,7 @@ bool MtpServer::handleRequest() {
response = doGetDevicePropDesc();
break;
default:
+ LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation));
response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
break;
}
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..34025f6 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 @@ package com.android.mediaframeworktest.functional;
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 @@ public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<Media
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 @@ public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<Media
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 @@ public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<Media
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 @@ public class MediaAudioEffectTest extends ActivityInstrumentationTestCase2<Media
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 b5b1c3e..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.MediaFrameworkTest;
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;
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 d5538f1..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.MediaFrameworkTest;
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;
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 a78668c..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.MediaFrameworkTest;
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;
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 fbd8a78..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.MediaFrameworkTest;
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;
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 7123db4..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.MediaFrameworkTest;
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;
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.MediaFrameworkTest;
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 a8200be..bc944a0 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -444,13 +444,14 @@ static void(*findProcAddress(const char* name,
// ----------------------------------------------------------------------------
-static void gl_no_context() {
+static int gl_no_context() {
tls_t* tls = getTLS();
if (tls->logCallWithNoContext == EGL_TRUE) {
tls->logCallWithNoContext = EGL_FALSE;
LOGE("call to OpenGL ES API with no current context "
"(logged once per thread)");
}
+ return 0;
}
static void early_egl_init(void)
@@ -463,6 +464,7 @@ static void early_egl_init(void)
(uint32_t*)(void*)&gHooksNoContext,
addr,
sizeof(gHooksNoContext));
+
setGlThreadSpecific(&gHooksNoContext);
}
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index a12edf2..fee4609 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -60,6 +60,7 @@ using namespace android;
"ldr r12, [r12, %[tls]] \n" \
"cmp r12, #0 \n" \
"ldrne pc, [r12, %[api]] \n" \
+ "mov r0, #0 \n" \
"bx lr \n" \
: \
: [tls] "J"(TLS_SLOT_OPENGL_API*4), \
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index d71ff76..ee29f12 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -114,6 +114,7 @@ GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
"ldr r12, [r12, %[tls]] \n" \
"cmp r12, #0 \n" \
"ldrne pc, [r12, %[api]] \n" \
+ "mov r0, #0 \n" \
"bx lr \n" \
: \
: [tls] "J"(TLS_SLOT_OPENGL_API*4), \
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d98bd7d..0ca0572 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -22,6 +22,7 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.Canvas;
import android.util.Slog;
+import android.util.Log;
import android.view.ViewDebug;
import android.widget.FrameLayout;
@@ -124,4 +125,10 @@ public class StatusBarIconView extends AnimatedImageView {
public StatusBarIcon getStatusBarIcon() {
return mIcon;
}
+
+ protected void debug(int depth) {
+ super.debug(depth);
+ Log.d("View", debugIndent(depth) + "slot=" + mSlot);
+ Log.d("View", debugIndent(depth) + "icon=" + mIcon);
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index f8c0aba..3583ab9 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -20,6 +20,8 @@ import com.android.internal.R;
import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.SlidingTab;
+import com.android.internal.widget.WaveView;
+import com.android.internal.widget.WaveView.OnTriggerListener;
import android.content.Context;
import android.content.res.Configuration;
@@ -46,8 +48,9 @@ import java.io.File;
* information about the device depending on its state, and how to get
* past it, as applicable.
*/
-class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateMonitor.InfoCallback,
- KeyguardUpdateMonitor.SimStateCallback, SlidingTab.OnTriggerListener {
+class LockScreen extends LinearLayout implements KeyguardScreen,
+ KeyguardUpdateMonitor.InfoCallback,
+ KeyguardUpdateMonitor.SimStateCallback {
private static final boolean DBG = false;
private static final String TAG = "LockScreen";
@@ -59,7 +62,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
private final KeyguardUpdateMonitor mUpdateMonitor;
private final KeyguardScreenCallback mCallback;
- private SlidingTab mSelector;
+ private SlidingTab mSlidingTab;
private TextView mScreenLocked;
private TextView mEmergencyCallText;
private Button mEmergencyCallButton;
@@ -89,6 +92,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
private boolean mEnableMenuKeyInLockScreen;
private StatusView mStatusView;
+ private WaveView mEnergyWave;
+ private SlidingTabMethods mSlidingTabMethods;
+ private WaveViewMethods mWaveViewMethods;
/**
* The status of this lock screen.
@@ -141,6 +147,91 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
}
}
+ class SlidingTabMethods implements SlidingTab.OnTriggerListener {
+
+ private void updateRightTabResources() {
+ boolean vibe = mSilentMode
+ && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
+
+ mSlidingTab.setRightTabResources(
+ mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on
+ : R.drawable.ic_jog_dial_sound_off )
+ : R.drawable.ic_jog_dial_sound_on,
+ mSilentMode ? R.drawable.jog_tab_target_yellow
+ : R.drawable.jog_tab_target_gray,
+ mSilentMode ? R.drawable.jog_tab_bar_right_sound_on
+ : R.drawable.jog_tab_bar_right_sound_off,
+ mSilentMode ? R.drawable.jog_tab_right_sound_on
+ : R.drawable.jog_tab_right_sound_off);
+ }
+
+ /** {@inheritDoc} */
+ public void onTrigger(View v, int whichHandle) {
+ if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
+ mCallback.goToUnlockScreen();
+ } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
+ // toggle silent mode
+ mSilentMode = !mSilentMode;
+ if (mSilentMode) {
+ final boolean vibe = (Settings.System.getInt(
+ getContext().getContentResolver(),
+ Settings.System.VIBRATE_IN_SILENT, 1) == 1);
+
+ mAudioManager.setRingerMode(vibe
+ ? AudioManager.RINGER_MODE_VIBRATE
+ : AudioManager.RINGER_MODE_SILENT);
+ } else {
+ mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ }
+
+ updateRightTabResources();
+
+ String message = mSilentMode ?
+ getContext().getString(R.string.global_action_silent_mode_on_status) :
+ getContext().getString(R.string.global_action_silent_mode_off_status);
+
+ final int toastIcon = mSilentMode
+ ? R.drawable.ic_lock_ringer_off
+ : R.drawable.ic_lock_ringer_on;
+
+ final int toastColor = mSilentMode
+ ? getContext().getResources().getColor(R.color.keyguard_text_color_soundoff)
+ : getContext().getResources().getColor(R.color.keyguard_text_color_soundon);
+ toastMessage(mScreenLocked, message, toastColor, toastIcon);
+ mCallback.pokeWakelock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void onGrabbedStateChange(View v, int grabbedState) {
+ if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
+ mSilentMode = isSilentMode();
+ mSlidingTab.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
+ : R.string.lockscreen_sound_off_label);
+ }
+ mCallback.pokeWakelock();
+ }
+ }
+
+ class WaveViewMethods implements WaveView.OnTriggerListener {
+ /** {@inheritDoc} */
+ public void onTrigger(View v, int whichHandle) {
+ if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
+ // Delay hiding lock screen long enough for animation to finish
+ postDelayed(new Runnable() {
+ public void run() {
+ mCallback.goToUnlockScreen();
+ }
+ }, 500);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void onGrabbedStateChange(View v, int grabbedState) {
+ mCallback.pokeWakelock();
+ }
+ }
+
/**
* In general, we enable unlocking the insecure key guard with the menu key. However, there are
* some cases where we wish to disable it, notably when the menu button placement or technology
@@ -195,9 +286,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
mScreenLocked = (TextView) findViewById(R.id.screenLocked);
- mSelector = (SlidingTab) findViewById(R.id.tab_selector);
- mSelector.setHoldAfterTrigger(true, false);
- mSelector.setLeftHintText(R.string.lockscreen_unlock_label);
mEmergencyCallText = (TextView) findViewById(R.id.emergencyCallText);
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
@@ -220,15 +308,25 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mSilentMode = isSilentMode();
- mSelector.setLeftTabResources(
- R.drawable.ic_jog_dial_unlock,
- R.drawable.jog_tab_target_green,
- R.drawable.jog_tab_bar_left_unlock,
- R.drawable.jog_tab_left_unlock);
-
- updateRightTabResources();
-
- mSelector.setOnTriggerListener(this);
+ mSlidingTab = (SlidingTab) findViewById(R.id.tab_selector);
+ mEnergyWave = (WaveView) findViewById(R.id.wave_view);
+ if (mSlidingTab != null) {
+ mSlidingTab.setHoldAfterTrigger(true, false);
+ mSlidingTab.setLeftHintText(R.string.lockscreen_unlock_label);
+ mSlidingTab.setLeftTabResources(
+ R.drawable.ic_jog_dial_unlock,
+ R.drawable.jog_tab_target_green,
+ R.drawable.jog_tab_bar_left_unlock,
+ R.drawable.jog_tab_left_unlock);
+ mSlidingTabMethods = new SlidingTabMethods();
+ mSlidingTab.setOnTriggerListener(mSlidingTabMethods);
+ mSlidingTabMethods.updateRightTabResources();
+ } else if (mEnergyWave != null) {
+ mWaveViewMethods = new WaveViewMethods();
+ mEnergyWave.setOnTriggerListener(mWaveViewMethods);
+ } else {
+ throw new IllegalStateException("Must have either SlidingTab or WaveView defined");
+ }
resetStatusInfo(updateMonitor);
}
@@ -237,22 +335,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
return mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
}
- private void updateRightTabResources() {
- boolean vibe = mSilentMode
- && (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
-
- mSelector.setRightTabResources(
- mSilentMode ? ( vibe ? R.drawable.ic_jog_dial_vibrate_on
- : R.drawable.ic_jog_dial_sound_off )
- : R.drawable.ic_jog_dial_sound_on,
- mSilentMode ? R.drawable.jog_tab_target_yellow
- : R.drawable.jog_tab_target_gray,
- mSilentMode ? R.drawable.jog_tab_bar_right_sound_on
- : R.drawable.jog_tab_bar_right_sound_off,
- mSilentMode ? R.drawable.jog_tab_right_sound_on
- : R.drawable.jog_tab_right_sound_off);
- }
-
private void resetStatusInfo(KeyguardUpdateMonitor updateMonitor) {
mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
mPluggedIn = updateMonitor.isDevicePluggedIn();
@@ -278,53 +360,6 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
return false;
}
- /** {@inheritDoc} */
- public void onTrigger(View v, int whichHandle) {
- if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
- mCallback.goToUnlockScreen();
- } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
- // toggle silent mode
- mSilentMode = !mSilentMode;
- if (mSilentMode) {
- final boolean vibe = (Settings.System.getInt(
- getContext().getContentResolver(),
- Settings.System.VIBRATE_IN_SILENT, 1) == 1);
-
- mAudioManager.setRingerMode(vibe
- ? AudioManager.RINGER_MODE_VIBRATE
- : AudioManager.RINGER_MODE_SILENT);
- } else {
- mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- }
-
- updateRightTabResources();
-
- String message = mSilentMode ?
- getContext().getString(R.string.global_action_silent_mode_on_status) :
- getContext().getString(R.string.global_action_silent_mode_off_status);
-
- final int toastIcon = mSilentMode
- ? R.drawable.ic_lock_ringer_off
- : R.drawable.ic_lock_ringer_on;
-
- final int toastColor = mSilentMode
- ? getContext().getResources().getColor(R.color.keyguard_text_color_soundoff)
- : getContext().getResources().getColor(R.color.keyguard_text_color_soundon);
- toastMessage(mScreenLocked, message, toastColor, toastIcon);
- mCallback.pokeWakelock();
- }
- }
-
- /** {@inheritDoc} */
- public void onGrabbedStateChange(View v, int grabbedState) {
- if (grabbedState == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
- mSilentMode = isSilentMode();
- mSelector.setRightHintText(mSilentMode ? R.string.lockscreen_sound_on_label
- : R.string.lockscreen_sound_off_label);
- }
- mCallback.pokeWakelock();
- }
-
/**
* Displays a message in a text view and then restores the previous text.
* @param textView The text view.
@@ -460,6 +495,22 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
}
/**
+ * Enables unlocking of this screen. Typically just shows the unlock widget.
+ */
+ private void enableUnlock() {
+ if (mEnergyWave != null) mEnergyWave.setVisibility(View.VISIBLE);
+ if (mSlidingTab != null) mSlidingTab.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Disable unlocking of this screen. Typically just hides the unlock widget.
+ */
+ private void disableUnlock() {
+ if (mEnergyWave != null) mEnergyWave.setVisibility(View.GONE);
+ if (mSlidingTab != null) mSlidingTab.setVisibility(View.GONE);
+ }
+
+ /**
* Update the layout to match the current status.
*/
private void updateLayout(Status status) {
@@ -481,9 +532,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.INVISIBLE);
- mSelector.setVisibility(View.VISIBLE);
mEmergencyCallText.setVisibility(View.GONE);
+ enableUnlock();
break;
+
case NetworkLocked:
// The carrier string shows both sim card status (i.e. No Sim Card) and
// carrier's name and/or "Emergency Calls Only" status
@@ -495,9 +547,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mSelector.setVisibility(View.VISIBLE);
mEmergencyCallText.setVisibility(View.GONE);
+ enableUnlock();
break;
+
case SimMissing:
// text
mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
@@ -505,10 +558,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mSelector.setVisibility(View.VISIBLE);
mEmergencyCallText.setVisibility(View.VISIBLE);
- // do not need to show the e-call button; user may unlock
+ enableUnlock(); // do not need to show the e-call button; user may unlock
break;
+
case SimMissingLocked:
// text
mStatusView.setCarrierText(
@@ -519,10 +572,11 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mSelector.setVisibility(View.GONE); // cannot unlock
mEmergencyCallText.setVisibility(View.VISIBLE);
mEmergencyCallButton.setVisibility(View.VISIBLE);
+ disableUnlock();
break;
+
case SimLocked:
// text
mStatusView.setCarrierText(
@@ -532,9 +586,10 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.INVISIBLE);
- mSelector.setVisibility(View.VISIBLE);
mEmergencyCallText.setVisibility(View.GONE);
+ enableUnlock();
break;
+
case SimPukLocked:
// text
mStatusView.setCarrierText(
@@ -545,9 +600,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
// layout
mScreenLocked.setVisibility(View.VISIBLE);
- mSelector.setVisibility(View.GONE); // cannot unlock
mEmergencyCallText.setVisibility(View.VISIBLE);
mEmergencyCallButton.setVisibility(View.VISIBLE);
+ disableUnlock();
break;
}
}
@@ -614,7 +669,9 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
/** {@inheritDoc} */
public void onPause() {
-
+ if (mEnergyWave != null) {
+ mEnergyWave.reset();
+ }
}
/** {@inheritDoc} */
@@ -632,7 +689,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
boolean silent = AudioManager.RINGER_MODE_NORMAL != state;
if (silent != mSilentMode) {
mSilentMode = silent;
- updateRightTabResources();
+ if (mSlidingTabMethods != null) mSlidingTabMethods.updateRightTabResources();
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7009c65..c047522 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -235,8 +235,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void handleMotion(MotionEvent event, Runnable finishedCallback) {
finishedCallback.run();
+
synchronized (mLock) {
- mPointerLocationView.addTouchEvent(event);
+ if (mPointerLocationView != null) {
+ mPointerLocationView.addTouchEvent(event);
+ }
}
}
};
@@ -287,7 +290,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
int mIncallPowerBehavior;
- int mLandscapeRotation = -1;
+ int mLandscapeRotation = -1; // default landscape rotation
+ int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation
int mPortraitRotation = -1;
// Nothing to see here, move along...
@@ -360,9 +364,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
// The user preference says we can rotate, and the app is willing to rotate.
+ // Note we include SCREEN_ORIENTATION_LANDSCAPE since we can use the sensor to choose
+ // between the two possible landscape rotations.
if (mAccelerometerDefault != 0 &&
(appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
return true;
}
// We're in a dock that has a rotation affinity, an the app is willing to rotate.
@@ -371,7 +378,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Note we override the nosensor flag here.
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
return true;
}
}
@@ -2117,20 +2125,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (d.getWidth() > d.getHeight()) {
mPortraitRotation = Surface.ROTATION_90;
mLandscapeRotation = Surface.ROTATION_0;
+ mSeascapeRotation = Surface.ROTATION_180;
} else {
mPortraitRotation = Surface.ROTATION_0;
mLandscapeRotation = Surface.ROTATION_90;
+ mSeascapeRotation = Surface.ROTATION_270;
}
}
synchronized (mLock) {
- switch (orientation) {
- case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
- //always return landscape if orientation set to landscape
- return mLandscapeRotation;
- case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
- //always return portrait if orientation set to portrait
- return mPortraitRotation;
+ if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ //always return portrait if orientation set to portrait
+ return mPortraitRotation;
+ } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ return getCurrentLandscapeRotation(lastRotation);
}
// case for nosensor meaning ignore sensor and consider only lid
// or orientation sensor disabled
@@ -2150,6 +2158,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private int getCurrentLandscapeRotation(int lastRotation) {
+ // landscape-only apps can take either landscape rotation
+ if (useSensorForOrientationLp(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
+ int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
+ if (isLandscapeOrSeascape(sensorRotation)) {
+ return sensorRotation;
+ }
+ }
+ // try to preserve the old rotation if it was landscape
+ if (isLandscapeOrSeascape(lastRotation)) {
+ return lastRotation;
+ }
+ // default to one of the two landscape rotations
+ return mLandscapeRotation;
+ }
+
+ private boolean isLandscapeOrSeascape(int sensorRotation) {
+ return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
+ }
+
public boolean detectSafeMode() {
try {
int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 5bdadcc..43dbcc0 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -80,16 +80,24 @@ public class ProcessStats {
PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
PROC_SPACE_TERM,
PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
- PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 14: stime
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 21: vsize
};
static final int PROCESS_FULL_STAT_MINOR_FAULTS = 1;
static final int PROCESS_FULL_STAT_MAJOR_FAULTS = 2;
static final int PROCESS_FULL_STAT_UTIME = 3;
static final int PROCESS_FULL_STAT_STIME = 4;
+ static final int PROCESS_FULL_STAT_VSIZE = 5;
- private final String[] mProcessFullStatsStringData = new String[5];
- private final long[] mProcessFullStatsData = new long[5];
+ private final String[] mProcessFullStatsStringData = new String[6];
+ private final long[] mProcessFullStatsData = new long[6];
private static final int[] SYSTEM_CPU_FORMAT = new int[] {
PROC_SPACE_TERM|PROC_COMBINE,
@@ -171,6 +179,8 @@ public class ProcessStats {
final ArrayList<Stats> threadStats;
final ArrayList<Stats> workingThreads;
+ public boolean interesting;
+
public String baseName;
public String name;
int nameWidth;
@@ -349,59 +359,62 @@ public class ProcessStats {
+ (parentPid < 0 ? "process" : "thread")
+ " pid " + pid + ": " + st);
- final long uptime = SystemClock.uptimeMillis();
+ if (st.interesting) {
+ final long uptime = SystemClock.uptimeMillis();
- final long[] procStats = mProcessStatsData;
- if (!Process.readProcFile(st.statFile.toString(),
- PROCESS_STATS_FORMAT, null, procStats, null)) {
- continue;
- }
-
- final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
- final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
- final long utime = procStats[PROCESS_STAT_UTIME];
- final long stime = procStats[PROCESS_STAT_STIME];
-
- if (utime == st.base_utime && stime == st.base_stime) {
- st.rel_utime = 0;
- st.rel_stime = 0;
- st.rel_minfaults = 0;
- st.rel_majfaults = 0;
- if (st.active) {
- st.active = false;
+ final long[] procStats = mProcessStatsData;
+ if (!Process.readProcFile(st.statFile.toString(),
+ PROCESS_STATS_FORMAT, null, procStats, null)) {
+ continue;
}
- continue;
- }
- if (!st.active) {
- st.active = true;
- }
+ final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
+ final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
+ final long utime = procStats[PROCESS_STAT_UTIME];
+ final long stime = procStats[PROCESS_STAT_STIME];
+
+ if (utime == st.base_utime && stime == st.base_stime) {
+ st.rel_utime = 0;
+ st.rel_stime = 0;
+ st.rel_minfaults = 0;
+ st.rel_majfaults = 0;
+ if (st.active) {
+ st.active = false;
+ }
+ continue;
+ }
- if (parentPid < 0) {
- getName(st, st.cmdlineFile);
- if (st.threadStats != null) {
- mCurThreadPids = collectStats(st.threadsDir, pid, false,
- mCurThreadPids, st.threadStats);
+ if (!st.active) {
+ st.active = true;
}
+
+ if (parentPid < 0) {
+ getName(st, st.cmdlineFile);
+ if (st.threadStats != null) {
+ mCurThreadPids = collectStats(st.threadsDir, pid, false,
+ mCurThreadPids, st.threadStats);
+ }
+ }
+
+ if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid
+ + " utime=" + utime + "-" + st.base_utime
+ + " stime=" + stime + "-" + st.base_stime
+ + " minfaults=" + minfaults + "-" + st.base_minfaults
+ + " majfaults=" + majfaults + "-" + st.base_majfaults);
+
+ st.rel_uptime = uptime - st.base_uptime;
+ st.base_uptime = uptime;
+ st.rel_utime = (int)(utime - st.base_utime);
+ st.rel_stime = (int)(stime - st.base_stime);
+ st.base_utime = utime;
+ st.base_stime = stime;
+ st.rel_minfaults = (int)(minfaults - st.base_minfaults);
+ st.rel_majfaults = (int)(majfaults - st.base_majfaults);
+ st.base_minfaults = minfaults;
+ st.base_majfaults = majfaults;
+ st.working = true;
}
- if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid
- + " utime=" + utime + "-" + st.base_utime
- + " stime=" + stime + "-" + st.base_stime
- + " minfaults=" + minfaults + "-" + st.base_minfaults
- + " majfaults=" + majfaults + "-" + st.base_majfaults);
-
- st.rel_uptime = uptime - st.base_uptime;
- st.base_uptime = uptime;
- st.rel_utime = (int)(utime - st.base_utime);
- st.rel_stime = (int)(stime - st.base_stime);
- st.base_utime = utime;
- st.base_stime = stime;
- st.rel_minfaults = (int)(minfaults - st.base_minfaults);
- st.rel_majfaults = (int)(majfaults - st.base_majfaults);
- st.base_minfaults = minfaults;
- st.base_majfaults = majfaults;
- st.working = true;
continue;
}
@@ -421,12 +434,24 @@ public class ProcessStats {
if (Process.readProcFile(st.statFile.toString(),
PROCESS_FULL_STATS_FORMAT, procStatsString,
procStats, null)) {
- st.baseName = procStatsString[0];
- st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS];
- st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS];
- st.base_utime = procStats[PROCESS_FULL_STAT_UTIME];
- st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
+ // This is a possible way to filter out processes that
+ // are actually kernel threads... do we want to? Some
+ // of them do use CPU, but there can be a *lot* that are
+ // not doing anything.
+ if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) {
+ st.interesting = true;
+ st.baseName = procStatsString[0];
+ st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS];
+ st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS];
+ st.base_utime = procStats[PROCESS_FULL_STAT_UTIME];
+ st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
+ } else {
+ Slog.i(TAG, "Skipping kernel process pid " + pid
+ + " name " + procStatsString[0]);
+ st.baseName = procStatsString[0];
+ }
} else {
+ Slog.w(TAG, "Skipping unknown process pid " + pid);
st.baseName = "<unknown>";
st.base_utime = st.base_stime = 0;
st.base_minfaults = st.base_majfaults = 0;
@@ -438,7 +463,7 @@ public class ProcessStats {
mCurThreadPids = collectStats(st.threadsDir, pid, true,
mCurThreadPids, st.threadStats);
}
- } else {
+ } else if (st.interesting) {
st.name = st.baseName;
st.nameWidth = onMeasureProcessName(st.name);
}
@@ -452,7 +477,7 @@ public class ProcessStats {
st.rel_minfaults = 0;
st.rel_majfaults = 0;
st.added = true;
- if (!first) {
+ if (!first && st.interesting) {
st.working = true;
}
continue;
@@ -624,6 +649,14 @@ public class ProcessStats {
}
}
+ final public int countStats() {
+ return mProcStats.size();
+ }
+
+ final public Stats getStats(int index) {
+ return mProcStats.get(index);
+ }
+
final public int countWorkingStats() {
buildWorkingProcs();
return mWorkingProcs.size();
@@ -788,7 +821,8 @@ public class ProcessStats {
private void getName(Stats st, String cmdlineFile) {
String newName = st.name;
- if (st.name == null || st.name.equals("app_process")) {
+ if (st.name == null || st.name.equals("app_process")
+ || st.name.equals("<pre-initialized>")) {
String cmdName = readFile(cmdlineFile, '\0');
if (cmdName != null && cmdName.length() > 1) {
newName = cmdName;
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 @@ public class WifiService extends IWifiManager.Stub {
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/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c896c94..8e22652 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -122,6 +122,8 @@ import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -145,6 +147,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_BROADCAST = localLOGV || false;
static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
static final boolean DEBUG_SERVICE = localLOGV || false;
+ static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
static final boolean DEBUG_VISBILITY = localLOGV || false;
static final boolean DEBUG_PROCESSES = localLOGV || false;
static final boolean DEBUG_PROVIDER = localLOGV || false;
@@ -153,6 +156,8 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_RESULTS = localLOGV || false;
static final boolean DEBUG_BACKUP = localLOGV || false;
static final boolean DEBUG_CONFIGURATION = localLOGV || false;
+ static final boolean DEBUG_POWER = localLOGV || false;
+ static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
static final boolean VALIDATE_TOKENS = false;
static final boolean SHOW_ACTIVITY_START_TIME = true;
@@ -198,8 +203,16 @@ public final class ActivityManagerService extends ActivityManagerNative
// The minimum amount of time between successive GC requests for a process.
static final int GC_MIN_INTERVAL = 60*1000;
- // The rate at which we check for apps using excessive wake locks -- 15 mins.
- static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
+ // The rate at which we check for apps using excessive power -- 15 mins.
+ static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
+
+ // The minimum sample duration we will allow before deciding we have
+ // enough data on wake locks to start killing things.
+ static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
+
+ // The minimum sample duration we will allow before deciding we have
+ // enough data on CPU usage to start killing things.
+ static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_TIMEOUT = 10*1000;
@@ -780,9 +793,14 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean mDidAppSwitch;
/**
- * Last time (in realtime) at which we checked for wake lock usage.
+ * Last time (in realtime) at which we checked for power usage.
+ */
+ long mLastPowerCheckRealtime;
+
+ /**
+ * Last time (in uptime) at which we checked for power usage.
*/
- long mLastWakeLockCheckTime;
+ long mLastPowerCheckUptime;
/**
* Set while we are wanting to sleep, to prevent any
@@ -1195,12 +1213,10 @@ public final class ActivityManagerService extends ActivityManagerNative
} break;
case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
synchronized (ActivityManagerService.this) {
- checkExcessiveWakeLocksLocked(true);
+ checkExcessivePowerUsageLocked(true);
removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- if (mSleeping) {
- Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
- }
+ Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
+ sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
} break;
}
@@ -1395,7 +1411,8 @@ public final class ActivityManagerService extends ActivityManagerNative
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
- mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
+ mOnBattery = DEBUG_POWER ? true
+ : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
mUsageStatsService = new UsageStatsService(new File(
@@ -1515,10 +1532,12 @@ public final class ActivityManagerService extends ActivityManagerNative
int perc = bstats.startAddingCpuLocked();
int totalUTime = 0;
int totalSTime = 0;
- final int N = mProcessStats.countWorkingStats();
+ final int N = mProcessStats.countStats();
for (int i=0; i<N; i++) {
- ProcessStats.Stats st
- = mProcessStats.getWorkingStats(i);
+ ProcessStats.Stats st = mProcessStats.getStats(i);
+ if (!st.working) {
+ continue;
+ }
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
@@ -1529,6 +1548,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ps.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
+ pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps =
bstats.getProcessStatsLocked(st.name, st.pid);
@@ -1565,7 +1585,7 @@ public final class ActivityManagerService extends ActivityManagerNative
updateCpuStatsNow();
synchronized (this) {
synchronized(mPidsSelfLocked) {
- mOnBattery = onBattery;
+ mOnBattery = DEBUG_POWER ? true : onBattery;
}
}
}
@@ -2795,6 +2815,16 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
+ if (mController != null) {
+ try {
+ // 0 == continue, -1 = kill process immediately
+ int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
+ if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
+ } catch (RemoteException e) {
+ mController = null;
+ }
+ }
+
long anrTime = SystemClock.uptimeMillis();
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
@@ -2845,10 +2875,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final ProcessStats processStats = new ProcessStats(true);
-
- File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
-
// Log the ANR to the main log.
StringBuilder info = mStringBuilder;
info.setLength(0);
@@ -2864,6 +2890,10 @@ public final class ActivityManagerService extends ActivityManagerNative
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
+ final ProcessStats processStats = new ProcessStats(true);
+
+ File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
+
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
@@ -3742,7 +3772,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
// Start looking for apps that are abusing wake locks.
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
+ mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
broadcastIntentLocked(null, null,
@@ -5655,10 +5685,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// Initialize the wake times of all processes.
- checkExcessiveWakeLocksLocked(false);
+ checkExcessivePowerUsageLocked(false);
mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
+ mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
}
@@ -5708,7 +5738,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.setEventDispatching(true);
mSleeping = false;
mMainStack.resumeTopActivityLocked(null);
- mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
}
}
@@ -7055,12 +7084,13 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println("Activity manager dump options:");
pw.println(" [-a] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
- pw.println(" activities: activity stack state");
- pw.println(" broadcasts: broadcast state");
- pw.println(" intents: pending intent state");
- pw.println(" processes: process state");
- pw.println(" providers: content provider state");
- pw.println(" services: service state");
+ pw.println(" a[ctivities]: activity stack state");
+ pw.println(" b[roadcasts]: broadcast state");
+ pw.println(" i[ntents]: pending intent state");
+ pw.println(" p[rocesses]: process state");
+ pw.println(" o[om]: out of memory management");
+ pw.println(" prov[iders]: content provider state");
+ pw.println(" s[ervices]: service state");
pw.println(" service [name]: service client-side state");
return;
} else {
@@ -7092,6 +7122,11 @@ public final class ActivityManagerService extends ActivityManagerNative
dumpProcessesLocked(fd, pw, args, opti, true);
}
return;
+ } else if ("oom".equals(cmd) || "o".equals(cmd)) {
+ synchronized (this) {
+ dumpOomLocked(fd, pw, args, opti, true);
+ }
+ return;
} else if ("providers".equals(cmd) || "prov".equals(cmd)) {
synchronized (this) {
dumpProvidersLocked(fd, pw, args, opti, true);
@@ -7213,7 +7248,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
-
+
boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll) {
boolean needSep = false;
@@ -7243,8 +7278,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (needSep) pw.println(" ");
needSep = true;
pw.println(" Running processes (most recent first):");
- dumpProcessList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", true);
+ dumpProcessOomList(pw, this, mLruProcesses, " ",
+ "Proc", "PERS", false);
needSep = true;
}
@@ -7275,7 +7310,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Persisent processes that are starting:");
dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
- "Starting Norm", "Restarting PERS", false);
+ "Starting Norm", "Restarting PERS");
}
if (mStartingProcesses.size() > 0) {
@@ -7283,7 +7318,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are starting:");
dumpProcessList(pw, this, mStartingProcesses, " ",
- "Starting Norm", "Starting PERS", false);
+ "Starting Norm", "Starting PERS");
}
if (mRemovedProcesses.size() > 0) {
@@ -7291,7 +7326,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are being removed:");
dumpProcessList(pw, this, mRemovedProcesses, " ",
- "Removed Norm", "Removed PERS", false);
+ "Removed Norm", "Removed PERS");
}
if (mProcessesOnHold.size() > 0) {
@@ -7299,26 +7334,10 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are on old until the system is ready:");
dumpProcessList(pw, this, mProcessesOnHold, " ",
- "OnHold Norm", "OnHold PERS", false);
+ "OnHold Norm", "OnHold PERS");
}
- if (mProcessesToGc.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Processes that are waiting to GC:");
- long now = SystemClock.uptimeMillis();
- for (int i=0; i<mProcessesToGc.size(); i++) {
- ProcessRecord proc = mProcessesToGc.get(i);
- pw.print(" Process "); pw.println(proc);
- pw.print(" lowMem="); pw.print(proc.reportLowMemory);
- pw.print(", last gced=");
- pw.print(now-proc.lastRequestedGc);
- pw.print(" ms ago, last lowMem=");
- pw.print(now-proc.lastLowMemory);
- pw.println(" ms ago");
-
- }
- }
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
if (mProcessCrashTimes.getMap().size() > 0) {
if (needSep) pw.println(" ");
@@ -7382,6 +7401,12 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println(" mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
+ pw.print(" mLastPowerCheckRealtime=");
+ TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
+ pw.println("");
+ pw.print(" mLastPowerCheckUptime=");
+ TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
+ pw.println("");
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
@@ -7390,6 +7415,75 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
+ boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean needSep, boolean dumpAll) {
+ if (mProcessesToGc.size() > 0) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Processes that are waiting to GC:");
+ long now = SystemClock.uptimeMillis();
+ for (int i=0; i<mProcessesToGc.size(); i++) {
+ ProcessRecord proc = mProcessesToGc.get(i);
+ pw.print(" Process "); pw.println(proc);
+ pw.print(" lowMem="); pw.print(proc.reportLowMemory);
+ pw.print(", last gced=");
+ pw.print(now-proc.lastRequestedGc);
+ pw.print(" ms ago, last lowMem=");
+ pw.print(now-proc.lastLowMemory);
+ pw.println(" ms ago");
+
+ }
+ }
+ return needSep;
+ }
+
+ boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean dumpAll) {
+ boolean needSep = false;
+
+ if (mLruProcesses.size() > 0) {
+ ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
+
+ Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
+ @Override
+ public int compare(ProcessRecord object1, ProcessRecord object2) {
+ if (object1.setAdj != object2.setAdj) {
+ return object1.setAdj > object2.setAdj ? -1 : 1;
+ }
+ if (object1.setSchedGroup != object2.setSchedGroup) {
+ return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
+ }
+ if (object1.keeping != object2.keeping) {
+ return object1.keeping ? -1 : 1;
+ }
+ if (object1.pid != object2.pid) {
+ return object1.pid > object2.pid ? -1 : 1;
+ }
+ return 0;
+ }
+ };
+
+ Collections.sort(procs, comparator);
+
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Process OOM control:");
+ dumpProcessOomList(pw, this, procs, " ",
+ "Proc", "PERS", true);
+ needSep = true;
+ }
+
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
+
+ pw.println(" ");
+ pw.println(" mHomeProcess: " + mHomeProcess);
+ if (mHeavyWeightProcess != null) {
+ pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
+ }
+
+ return true;
+ }
+
/**
* There are three ways to call this:
* - no service specified: dump all the services
@@ -7833,89 +7927,145 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final int dumpProcessList(PrintWriter pw,
ActivityManagerService service, List list,
- String prefix, String normalLabel, String persistentLabel,
- boolean inclOomAdj) {
+ String prefix, String normalLabel, String persistentLabel) {
int numPers = 0;
final int N = list.size()-1;
for (int i=N; i>=0; i--) {
ProcessRecord r = (ProcessRecord)list.get(i);
- if (false) {
- pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
- + " #" + i + ":");
- r.dump(pw, prefix + " ");
- } else if (inclOomAdj) {
- String oomAdj;
- if (r.setAdj >= EMPTY_APP_ADJ) {
- oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
- } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
- oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
- } else if (r.setAdj >= HOME_APP_ADJ) {
- oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
- } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
- oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
- } else if (r.setAdj >= BACKUP_APP_ADJ) {
- oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
- } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
- oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
- } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
- oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
- } else if (r.setAdj >= VISIBLE_APP_ADJ) {
- oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
- } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
- oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
- } else if (r.setAdj >= CORE_SERVER_ADJ) {
- oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
- } else if (r.setAdj >= SYSTEM_ADJ) {
- oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
+ pw.println(String.format("%s%s #%2d: %s",
+ prefix, (r.persistent ? persistentLabel : normalLabel),
+ i, r.toString()));
+ if (r.persistent) {
+ numPers++;
+ }
+ }
+ return numPers;
+ }
+
+ private static final void dumpProcessOomList(PrintWriter pw,
+ ActivityManagerService service, List<ProcessRecord> list,
+ String prefix, String normalLabel, String persistentLabel,
+ boolean inclDetails) {
+
+ final long curRealtime = SystemClock.elapsedRealtime();
+ final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
+ final long curUptime = SystemClock.uptimeMillis();
+ final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+
+ final int N = list.size()-1;
+ for (int i=N; i>=0; i--) {
+ ProcessRecord r = list.get(i);
+ String oomAdj;
+ if (r.setAdj >= EMPTY_APP_ADJ) {
+ oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
+ } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
+ oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
+ } else if (r.setAdj >= HOME_APP_ADJ) {
+ oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
+ } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
+ oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
+ } else if (r.setAdj >= BACKUP_APP_ADJ) {
+ oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
+ } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
+ oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
+ } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
+ oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
+ } else if (r.setAdj >= VISIBLE_APP_ADJ) {
+ oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
+ } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
+ oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
+ } else if (r.setAdj >= CORE_SERVER_ADJ) {
+ oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
+ } else if (r.setAdj >= SYSTEM_ADJ) {
+ oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
+ } else {
+ oomAdj = Integer.toString(r.setAdj);
+ }
+ String schedGroup;
+ switch (r.setSchedGroup) {
+ case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+ schedGroup = "B";
+ break;
+ case Process.THREAD_GROUP_DEFAULT:
+ schedGroup = "F";
+ break;
+ default:
+ schedGroup = Integer.toString(r.setSchedGroup);
+ break;
+ }
+ pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
+ prefix, (r.persistent ? persistentLabel : normalLabel),
+ N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
+ if (r.adjSource != null || r.adjTarget != null) {
+ pw.print(prefix);
+ pw.print(" ");
+ if (r.adjTarget instanceof ComponentName) {
+ pw.print(((ComponentName)r.adjTarget).flattenToShortString());
+ } else if (r.adjTarget != null) {
+ pw.print(r.adjTarget.toString());
} else {
- oomAdj = Integer.toString(r.setAdj);
- }
- String schedGroup;
- switch (r.setSchedGroup) {
- case Process.THREAD_GROUP_BG_NONINTERACTIVE:
- schedGroup = "B";
- break;
- case Process.THREAD_GROUP_DEFAULT:
- schedGroup = "F";
- break;
- default:
- schedGroup = Integer.toString(r.setSchedGroup);
- break;
+ pw.print("{null}");
+ }
+ pw.print("<=");
+ if (r.adjSource instanceof ProcessRecord) {
+ pw.print("Proc{");
+ pw.print(((ProcessRecord)r.adjSource).toShortString());
+ pw.println("}");
+ } else if (r.adjSource != null) {
+ pw.println(r.adjSource.toString());
+ } else {
+ pw.println("{null}");
}
- pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
- prefix, (r.persistent ? persistentLabel : normalLabel),
- N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
- if (r.adjSource != null || r.adjTarget != null) {
- pw.print(prefix);
- pw.print(" ");
- if (r.adjTarget instanceof ComponentName) {
- pw.print(((ComponentName)r.adjTarget).flattenToShortString());
- } else if (r.adjTarget != null) {
- pw.print(r.adjTarget.toString());
- } else {
- pw.print("{null}");
- }
- pw.print("<=");
- if (r.adjSource instanceof ProcessRecord) {
- pw.print("Proc{");
- pw.print(((ProcessRecord)r.adjSource).toShortString());
- pw.println("}");
- } else if (r.adjSource != null) {
- pw.println(r.adjSource.toString());
- } else {
- pw.println("{null}");
+ }
+ if (inclDetails) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("oom: max="); pw.print(r.maxAdj);
+ pw.print(" hidden="); pw.print(r.hiddenAdj);
+ pw.print(" curRaw="); pw.print(r.curRawAdj);
+ pw.print(" setRaw="); pw.print(r.setRawAdj);
+ pw.print(" cur="); pw.print(r.curAdj);
+ pw.print(" set="); pw.println(r.setAdj);
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("keeping="); pw.print(r.keeping);
+ pw.print(" hidden="); pw.print(r.hidden);
+ pw.print(" empty="); pw.println(r.empty);
+
+ if (!r.keeping) {
+ if (r.lastWakeTime != 0) {
+ long wtime;
+ BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
+ synchronized (stats) {
+ wtime = stats.getProcessWakeTime(r.info.uid,
+ r.pid, curRealtime);
+ }
+ long timeUsed = wtime - r.lastWakeTime;
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("keep awake over ");
+ TimeUtils.formatDuration(realtimeSince, pw);
+ pw.print(" used ");
+ TimeUtils.formatDuration(timeUsed, pw);
+ pw.print(" (");
+ pw.print((timeUsed*100)/realtimeSince);
+ pw.println("%)");
+ }
+ if (r.lastCpuTime != 0) {
+ long timeUsed = r.curCpuTime - r.lastCpuTime;
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("run cpu over ");
+ TimeUtils.formatDuration(uptimeSince, pw);
+ pw.print(" used ");
+ TimeUtils.formatDuration(timeUsed, pw);
+ pw.print(" (");
+ pw.print((timeUsed*100)/uptimeSince);
+ pw.println("%)");
}
}
- } else {
- pw.println(String.format("%s%s #%2d: %s",
- prefix, (r.persistent ? persistentLabel : normalLabel),
- i, r.toString()));
- }
- if (r.persistent) {
- numPers++;
}
}
- return numPers;
}
static final void dumpApplicationMemoryUsage(FileDescriptor fd,
@@ -8544,7 +8694,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
- private final void bumpServiceExecutingLocked(ServiceRecord r) {
+ private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
+ if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
+ + why + " of " + r + " in app " + r.app);
+ else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
+ + why + " of " + r.shortName);
long now = SystemClock.uptimeMillis();
if (r.executeNesting == 0 && r.app != null) {
if (r.app.executingServices.size() == 0) {
@@ -8582,8 +8736,7 @@ public final class ActivityManagerService extends ActivityManagerNative
grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
r.packageName, si.intent, si.getUriPermissionsLocked());
}
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "start");
if (!oomAdjusted) {
oomAdjusted = true;
updateOomAdjLocked(r.app);
@@ -8616,9 +8769,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
- + " in " + i + ": shouldUnbind=" + i.hasBound);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "bind");
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
if (!rebind) {
i.requested = true;
@@ -8653,8 +8804,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r);
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "create");
updateLruProcessLocked(app, true, true);
boolean created = false;
@@ -8906,9 +9056,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ ": hasBound=" + ibr.hasBound);
if (r.app != null && r.app.thread != null && ibr.hasBound) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
- + " for " + ibr);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "bring down unbind");
updateOomAdjLocked(r.app);
ibr.hasBound = false;
r.app.thread.scheduleUnbindService(r,
@@ -8959,12 +9107,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.app.services.remove(r);
if (r.app.thread != null) {
try {
- if (DEBUG_SERVICE) {
- RuntimeException here = new RuntimeException();
- here.fillInStackTrace();
- Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
- }
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "stop");
mStoppingServices.add(r);
updateOomAdjLocked(r.app);
r.app.thread.scheduleStopService(r);
@@ -9420,9 +9563,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
- + " from " + b);
- bumpServiceExecutingLocked(s);
+ bumpServiceExecutingLocked(s, "unbind");
updateOomAdjLocked(s.app);
b.intent.hasBound = false;
// Assume the client doesn't want to know about a rebind;
@@ -9643,14 +9784,20 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ ": nesting=" + r.executeNesting
+ ", inStopping=" + inStopping + ", app=" + r.app);
+ else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
r.executeNesting--;
if (r.executeNesting <= 0 && r.app != null) {
+ if (DEBUG_SERVICE) Slog.v(TAG,
+ "Nesting at 0 of " + r.shortName);
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
+ if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
+ "No more executingServices of " + r.shortName);
mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
}
if (inStopping) {
- if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG,
+ "doneExecuting remove stopping " + r);
mStoppingServices.remove(r);
}
updateOomAdjLocked(r.app);
@@ -9760,20 +9907,20 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
return;
}
+ }
- long oldIdent = Binder.clearCallingIdentity();
- try {
- IBackupManager bm = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- bm.agentConnected(agentPackageName, agent);
- } catch (RemoteException e) {
- // can't happen; the backup manager service is local
- } catch (Exception e) {
- Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
- e.printStackTrace();
- } finally {
- Binder.restoreCallingIdentity(oldIdent);
- }
+ long oldIdent = Binder.clearCallingIdentity();
+ try {
+ IBackupManager bm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ bm.agentConnected(agentPackageName, agent);
+ } catch (RemoteException e) {
+ // can't happen; the backup manager service is local
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
+ e.printStackTrace();
+ } finally {
+ Binder.restoreCallingIdentity(oldIdent);
}
}
@@ -11326,6 +11473,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
+ app.keeping = true;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
return (app.curAdj=app.maxAdj);
}
@@ -11333,6 +11481,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
+ app.keeping = false;
app.empty = false;
app.hidden = false;
@@ -11462,6 +11611,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (adj > SECONDARY_SERVER_ADJ) {
app.adjType = "started-bg-services";
}
+ // Don't kill this process because it is doing work; it
+ // has said it is doing work.
+ app.keeping = true;
}
if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
@@ -11495,6 +11647,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!client.hidden) {
app.hidden = false;
}
+ if (client.keeping) {
+ app.keeping = true;
+ }
app.adjType = "service";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
@@ -11528,7 +11683,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- // Finally, f this process has active services running in it, we
+ // Finally, if this process has active services running in it, we
// would like to avoid killing it unless it would prevent the current
// application from running. By default we put the process in
// with the rest of the background processes; as we scan through
@@ -11570,6 +11725,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!client.hidden) {
app.hidden = false;
}
+ if (client.keeping) {
+ app.keeping = true;
+ }
app.adjType = "provider";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
@@ -11589,6 +11747,7 @@ public final class ActivityManagerService extends ActivityManagerNative
adj = FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.hidden = false;
+ app.keeping = true;
app.adjType = "provider";
app.adjTarget = cpr.name;
}
@@ -11606,6 +11765,9 @@ public final class ActivityManagerService extends ActivityManagerNative
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
+ if (adj < HIDDEN_APP_MIN_ADJ) {
+ app.keeping = true;
+ }
app.curAdj = adj;
app.curSchedGroup = schedGroup;
@@ -11743,57 +11905,99 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final void checkExcessiveWakeLocksLocked(boolean doKills) {
+ final void checkExcessivePowerUsageLocked(boolean doKills) {
+ updateCpuStatsNow();
+
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- if (mLastWakeLockCheckTime == 0) {
- doKills = false;
+ boolean doWakeKills = doKills;
+ boolean doCpuKills = doKills;
+ if (mLastPowerCheckRealtime == 0) {
+ doWakeKills = false;
+ }
+ if (mLastPowerCheckUptime == 0) {
+ doCpuKills = false;
}
if (stats.isScreenOn()) {
- doKills = false;
+ doWakeKills = false;
}
final long curRealtime = SystemClock.elapsedRealtime();
- final long timeSince = curRealtime - mLastWakeLockCheckTime;
- mLastWakeLockCheckTime = curRealtime;
- if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
- doKills = false;
+ final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
+ final long curUptime = SystemClock.uptimeMillis();
+ final long uptimeSince = curUptime - mLastPowerCheckUptime;
+ mLastPowerCheckRealtime = curRealtime;
+ mLastPowerCheckUptime = curUptime;
+ if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
+ doWakeKills = false;
+ }
+ if (uptimeSince < CPU_MIN_CHECK_DURATION) {
+ doCpuKills = false;
}
int i = mLruProcesses.size();
while (i > 0) {
i--;
ProcessRecord app = mLruProcesses.get(i);
- if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
+ if (!app.keeping) {
long wtime;
synchronized (stats) {
wtime = stats.getProcessWakeTime(app.info.uid,
app.pid, curRealtime);
}
- long timeUsed = wtime - app.lastWakeTime;
- if (false) {
+ long wtimeUsed = wtime - app.lastWakeTime;
+ long cputimeUsed = app.curCpuTime - app.lastCpuTime;
+ if (DEBUG_POWER) {
StringBuilder sb = new StringBuilder(128);
sb.append("Wake for ");
app.toShortString(sb);
sb.append(": over ");
- TimeUtils.formatDuration(timeSince, sb);
+ TimeUtils.formatDuration(realtimeSince, sb);
+ sb.append(" used ");
+ TimeUtils.formatDuration(wtimeUsed, sb);
+ sb.append(" (");
+ sb.append((wtimeUsed*100)/realtimeSince);
+ sb.append("%)");
+ Slog.i(TAG, sb.toString());
+ sb.setLength(0);
+ sb.append("CPU for ");
+ app.toShortString(sb);
+ sb.append(": over ");
+ TimeUtils.formatDuration(uptimeSince, sb);
sb.append(" used ");
- TimeUtils.formatDuration(timeUsed, sb);
+ TimeUtils.formatDuration(cputimeUsed, sb);
sb.append(" (");
- sb.append((timeUsed*100)/timeSince);
+ sb.append((cputimeUsed*100)/uptimeSince);
sb.append("%)");
Slog.i(TAG, sb.toString());
}
// If a process has held a wake lock for more
// than 50% of the time during this period,
// that sounds pad. Kill!
- if (doKills && timeSince > 0
- && ((timeUsed*100)/timeSince) >= 50) {
- Slog.i(TAG, "Excessive wake lock in " + app.processName
- + " (pid " + app.pid + "): held " + timeUsed
- + " during " + timeSince);
+ if (doWakeKills && realtimeSince > 0
+ && ((wtimeUsed*100)/realtimeSince) >= 50) {
+ synchronized (stats) {
+ stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
+ realtimeSince, wtimeUsed);
+ }
+ Slog.w(TAG, "Excessive wake lock in " + app.processName
+ + " (pid " + app.pid + "): held " + wtimeUsed
+ + " during " + realtimeSince);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
app.processName, app.setAdj, "excessive wake lock");
Process.killProcessQuiet(app.pid);
+ } else if (doCpuKills && uptimeSince > 0
+ && ((cputimeUsed*100)/uptimeSince) >= 50) {
+ synchronized (stats) {
+ stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
+ uptimeSince, cputimeUsed);
+ }
+ Slog.w(TAG, "Excessive CPU in " + app.processName
+ + " (pid " + app.pid + "): used " + cputimeUsed
+ + " during " + uptimeSince);
+ EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+ app.processName, app.setAdj, "excessive cpu");
+ Process.killProcessQuiet(app.pid);
} else {
app.lastWakeTime = wtime;
+ app.lastCpuTime = app.curCpuTime;
}
}
}
@@ -11807,6 +12011,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
+ final boolean wasKeeping = app.keeping;
+
int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
@@ -11821,13 +12027,20 @@ public final class ActivityManagerService extends ActivityManagerNative
// Likewise do a gc when an app is moving in to the
// background (such as a service stopping).
scheduleAppGcLocked(app);
- // And note its current wake lock time.
+ }
+
+ if (wasKeeping && !app.keeping) {
+ // This app is no longer something we want to keep. Note
+ // its current wake lock time to later know to kill it if
+ // it is not behaving well.
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
app.pid, SystemClock.elapsedRealtime());
}
+ app.lastCpuTime = app.curCpuTime;
}
+
app.setRawAdj = app.curRawAdj;
}
if (adj != app.setAdj) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 67df707..404c6be 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -60,6 +60,7 @@ class ProcessRecord {
int setAdj; // Last set OOM adjustment for this process
int curSchedGroup; // Currently desired scheduling class
int setSchedGroup; // Last set to background scheduling class
+ boolean keeping; // Actively running code so don't kill due to that?
boolean setIsForeground; // Running foreground UI when last set?
boolean foregroundServices; // Running any services that are foreground?
boolean bad; // True if disabled in the bad process list
@@ -75,6 +76,8 @@ class ProcessRecord {
ComponentName instrumentationResultClass;// copy of instrumentationClass
BroadcastRecord curReceiver;// receiver currently running in the app
long lastWakeTime; // How long proc held wake lock at last check
+ long lastCpuTime; // How long proc has run CPU at last check
+ long curCpuTime; // How long proc has run CPU most recently
long lastRequestedGc; // When we last asked the app to do a gc
long lastLowMemory; // When we last told the app that memory is low
boolean reportLowMemory; // Set to true when waiting to report low mem
@@ -131,13 +134,6 @@ class ProcessRecord {
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
- long wtime;
- synchronized (batteryStats.getBatteryStats()) {
- wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
- pid, SystemClock.elapsedRealtime());
- }
- long timeUsed = wtime - lastWakeTime;
-
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
}
@@ -170,6 +166,7 @@ class ProcessRecord {
pw.print(prefix); pw.print("lastActivityTime=");
TimeUtils.formatDuration(lastActivityTime, now, pw);
pw.print(" lruWeight="); pw.print(lruWeight);
+ pw.print(" keeping="); pw.print(keeping);
pw.print(" hidden="); pw.print(hidden);
pw.print(" empty="); pw.println(empty);
pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
@@ -188,9 +185,20 @@ class ProcessRecord {
pw.print(" persistentActivities="); pw.println(persistentActivities);
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.println(lruSeq);
- pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
- pw.print(" time used=");
- TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ if (!keeping) {
+ long wtime;
+ synchronized (batteryStats.getBatteryStats()) {
+ wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
+ pid, SystemClock.elapsedRealtime());
+ }
+ long timeUsed = wtime - lastWakeTime;
+ pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
+ pw.print(" time used=");
+ TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
+ pw.print(" time used=");
+ TimeUtils.formatDuration(curCpuTime-lastCpuTime, pw); pw.println("");
+ }
pw.print(prefix); pw.print("lastRequestedGc=");
TimeUtils.formatDuration(lastRequestedGc, now, pw);
pw.print(" lastLowMemory=");
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index f35a68e..e5aceb4 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -347,7 +347,9 @@ class ServiceRecord extends Binder {
// If it gave us a garbage notification, it doesn't
// get to be foreground.
ams.setServiceForeground(name, ServiceRecord.this,
- localForegroundId, null, true);
+ 0, null, true);
+ ams.crashApplication(appUid, appPid, localPackageName,
+ "Bad notification for startForeground: " + e);
}
}
});
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index f1dcd5a..3f43e1c 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -30,8 +30,8 @@ import android.net.sip.ISipSessionListener;
import android.net.sip.SipErrorCode;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
+import android.net.sip.SipSession;
import android.net.sip.SipSessionAdapter;
-import android.net.sip.SipSessionState;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
@@ -143,7 +143,7 @@ public final class SipService extends ISipService.Stub {
}
private void openToReceiveCalls(SipProfile localProfile) {
- open3(localProfile, SipManager.SIP_INCOMING_CALL_ACTION, null);
+ open3(localProfile, SipManager.ACTION_SIP_INCOMING_CALL, null);
}
public synchronized void open3(SipProfile localProfile,
@@ -255,15 +255,15 @@ public final class SipService extends ISipService.Stub {
private void notifyProfileAdded(SipProfile localProfile) {
if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile);
- Intent intent = new Intent(SipManager.SIP_ADD_PHONE_ACTION);
- intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE);
+ intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
}
private void notifyProfileRemoved(SipProfile localProfile) {
if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile);
- Intent intent = new Intent(SipManager.SIP_REMOVE_PHONE_ACTION);
- intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
+ intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
}
@@ -474,8 +474,8 @@ public final class SipService extends ISipService.Stub {
// send out incoming call broadcast
addPendingSession(session);
Intent intent = SipManager.createIncomingCallBroadcast(
- mIncomingCallBroadcastAction, session.getCallId(),
- sessionDescription);
+ session.getCallId(), sessionDescription)
+ .setAction(mIncomingCallBroadcastAction);
if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": "
+ caller.getUri() + ": " + session.getCallId()
+ " " + mIncomingCallBroadcastAction);
@@ -613,10 +613,10 @@ public final class SipService extends ISipService.Stub {
try {
int state = (mSession == null)
- ? SipSessionState.READY_TO_CALL
+ ? SipSession.State.READY_TO_CALL
: mSession.getState();
- if ((state == SipSessionState.REGISTERING)
- || (state == SipSessionState.DEREGISTERING)) {
+ if ((state == SipSession.State.REGISTERING)
+ || (state == SipSession.State.DEREGISTERING)) {
mProxy.onRegistering(mSession);
} else if (mRegistered) {
int duration = (int)
@@ -1138,7 +1138,8 @@ public final class SipService extends ISipService.Stub {
event.mTriggerTime += event.mPeriod;
// run the callback in a new thread to prevent deadlock
- new Thread(event.mCallback).start();
+ new Thread(event.mCallback, "SipServiceTimerCallbackThread")
+ .start();
}
if (DEBUG_TIMER) {
Log.d(TAG, "after timeout execution");
diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java
index b4c2241..66a2c05 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/services/java/com/android/server/sip/SipSessionGroup.java
@@ -25,11 +25,10 @@ import gov.nist.javax.sip.message.SIPMessage;
import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
-import android.net.sip.SessionDescription;
import android.net.sip.SipErrorCode;
import android.net.sip.SipProfile;
+import android.net.sip.SipSession;
import android.net.sip.SipSessionAdapter;
-import android.net.sip.SipSessionState;
import android.text.TextUtils;
import android.util.Log;
@@ -121,7 +120,7 @@ class SipSessionGroup implements SipListener {
reset(localIp);
}
- void reset(String localIp) throws SipException, IOException {
+ synchronized void reset(String localIp) throws SipException, IOException {
mLocalIp = localIp;
if (localIp == null) return;
@@ -301,7 +300,7 @@ class SipSessionGroup implements SipListener {
boolean processed = (session != null) && session.process(event);
if (isLoggable && processed) {
Log.d(TAG, "new state after: "
- + SipSessionState.toString(session.mState));
+ + SipSession.State.toString(session.mState));
}
} catch (Throwable e) {
Log.w(TAG, "event process error: " + event, e);
@@ -332,7 +331,7 @@ class SipSessionGroup implements SipListener {
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
- + SipSessionState.toString(mState) + ": processing "
+ + SipSession.State.toString(mState) + ": processing "
+ log(evt));
if (isRequestEvent(Request.INVITE, evt)) {
RequestEvent event = (RequestEvent) evt;
@@ -342,13 +341,16 @@ class SipSessionGroup implements SipListener {
newSession.mDialog = newSession.mServerTransaction.getDialog();
newSession.mInviteReceived = event;
newSession.mPeerProfile = createPeerProfile(event.getRequest());
- newSession.mState = SipSessionState.INCOMING_CALL;
+ newSession.mState = SipSession.State.INCOMING_CALL;
newSession.mPeerSessionDescription =
extractContent(event.getRequest());
addSipSession(newSession);
mProxy.onRinging(newSession, newSession.mPeerProfile,
newSession.mPeerSessionDescription);
return true;
+ } else if (isRequestEvent(Request.OPTIONS, evt)) {
+ mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
+ return true;
} else {
return false;
}
@@ -358,7 +360,7 @@ class SipSessionGroup implements SipListener {
class SipSessionImpl extends ISipSession.Stub {
SipProfile mPeerProfile;
SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
- int mState = SipSessionState.READY_TO_CALL;
+ int mState = SipSession.State.READY_TO_CALL;
RequestEvent mInviteReceived;
Dialog mDialog;
ServerTransaction mServerTransaction;
@@ -378,7 +380,7 @@ class SipSessionGroup implements SipListener {
sleep(timeout);
if (mRunning) timeout();
}
- }).start();
+ }, "SipSessionTimerThread").start();
}
synchronized void cancel() {
@@ -413,7 +415,7 @@ class SipSessionGroup implements SipListener {
mInCall = false;
removeSipSession(this);
mPeerProfile = null;
- mState = SipSessionState.READY_TO_CALL;
+ mState = SipSession.State.READY_TO_CALL;
mInviteReceived = null;
mDialog = null;
mServerTransaction = null;
@@ -470,7 +472,7 @@ class SipSessionGroup implements SipListener {
onError(e);
}
}
- }).start();
+ }, "SipSessionAsyncCmdThread").start();
}
public void makeCall(SipProfile peerProfile, String sessionDescription,
@@ -520,10 +522,10 @@ class SipSessionGroup implements SipListener {
}
public void sendKeepAlive() {
- mState = SipSessionState.PINGING;
+ mState = SipSession.State.PINGING;
try {
processCommand(new OptionsCommand());
- while (SipSessionState.PINGING == mState) {
+ while (SipSession.State.PINGING == mState) {
Thread.sleep(1000);
}
} catch (SipException e) {
@@ -550,7 +552,7 @@ class SipSessionGroup implements SipListener {
try {
String s = super.toString();
return s.substring(s.indexOf("@")) + ":"
- + SipSessionState.toString(mState);
+ + SipSession.State.toString(mState);
} catch (Throwable e) {
return super.toString();
}
@@ -558,7 +560,7 @@ class SipSessionGroup implements SipListener {
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
- + SipSessionState.toString(mState) + ": processing "
+ + SipSession.State.toString(mState) + ": processing "
+ log(evt));
synchronized (SipSessionGroup.this) {
if (isClosed()) return false;
@@ -574,30 +576,30 @@ class SipSessionGroup implements SipListener {
boolean processed;
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
processed = registeringToReady(evt);
break;
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
processed = keepAliveProcess(evt);
break;
- case SipSessionState.READY_TO_CALL:
+ case SipSession.State.READY_TO_CALL:
processed = readyForCall(evt);
break;
- case SipSessionState.INCOMING_CALL:
+ case SipSession.State.INCOMING_CALL:
processed = incomingCall(evt);
break;
- case SipSessionState.INCOMING_CALL_ANSWERING:
+ case SipSession.State.INCOMING_CALL_ANSWERING:
processed = incomingCallToInCall(evt);
break;
- case SipSessionState.OUTGOING_CALL:
- case SipSessionState.OUTGOING_CALL_RING_BACK:
+ case SipSession.State.OUTGOING_CALL:
+ case SipSession.State.OUTGOING_CALL_RING_BACK:
processed = outgoingCall(evt);
break;
- case SipSessionState.OUTGOING_CALL_CANCELING:
+ case SipSession.State.OUTGOING_CALL_CANCELING:
processed = outgoingCallToReady(evt);
break;
- case SipSessionState.IN_CALL:
+ case SipSession.State.IN_CALL:
processed = inCall(evt);
break;
default:
@@ -625,6 +627,9 @@ class SipSessionGroup implements SipListener {
(TransactionTerminatedEvent) evt);
}
return true;
+ } else if (isRequestEvent(Request.OPTIONS, evt)) {
+ mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
+ return true;
} else if (evt instanceof DialogTerminatedEvent) {
processDialogTerminated((DialogTerminatedEvent) evt);
return true;
@@ -644,8 +649,8 @@ class SipSessionGroup implements SipListener {
private void processTransactionTerminated(
TransactionTerminatedEvent event) {
switch (mState) {
- case SipSessionState.IN_CALL:
- case SipSessionState.READY_TO_CALL:
+ case SipSession.State.IN_CALL:
+ case SipSession.State.READY_TO_CALL:
Log.d(TAG, "Transaction terminated; do nothing");
break;
default:
@@ -664,27 +669,27 @@ class SipSessionGroup implements SipListener {
? event.getServerTransaction()
: event.getClientTransaction();
- if ((current != target) && (mState != SipSessionState.PINGING)) {
+ if ((current != target) && (mState != SipSession.State.PINGING)) {
Log.d(TAG, "not the current transaction; current=" + current
+ ", timed out=" + target);
return;
}
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
reset();
mProxy.onRegistrationTimeout(this);
break;
- case SipSessionState.INCOMING_CALL:
- case SipSessionState.INCOMING_CALL_ANSWERING:
- case SipSessionState.OUTGOING_CALL:
- case SipSessionState.OUTGOING_CALL_CANCELING:
+ case SipSession.State.INCOMING_CALL:
+ case SipSession.State.INCOMING_CALL_ANSWERING:
+ case SipSession.State.OUTGOING_CALL:
+ case SipSession.State.OUTGOING_CALL_CANCELING:
onError(SipErrorCode.TIME_OUT, event.toString());
break;
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
reset();
mReRegisterFlag = true;
- mState = SipSessionState.READY_TO_CALL;
+ mState = SipSession.State.READY_TO_CALL;
break;
default:
@@ -758,7 +763,7 @@ class SipSessionGroup implements SipListener {
switch (statusCode) {
case Response.OK:
int state = mState;
- onRegistrationDone((state == SipSessionState.REGISTERING)
+ onRegistrationDone((state == SipSession.State.REGISTERING)
? getExpiryTime(((ResponseEvent) evt).getResponse())
: -1);
mLastNonce = null;
@@ -845,7 +850,7 @@ class SipSessionGroup implements SipListener {
generateTag());
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.OUTGOING_CALL;
+ mState = SipSession.State.OUTGOING_CALL;
mProxy.onCalling(this);
startSessionTimer(cmd.getTimeout());
return true;
@@ -855,7 +860,7 @@ class SipSessionGroup implements SipListener {
generateTag(), duration);
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.REGISTERING;
+ mState = SipSession.State.REGISTERING;
mProxy.onRegistering(this);
return true;
} else if (DEREGISTER == evt) {
@@ -863,7 +868,7 @@ class SipSessionGroup implements SipListener {
generateTag(), 0);
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.DEREGISTERING;
+ mState = SipSession.State.DEREGISTERING;
mProxy.onRegistering(this);
return true;
}
@@ -878,7 +883,7 @@ class SipSessionGroup implements SipListener {
mLocalProfile,
((MakeCallCommand) evt).getSessionDescription(),
mServerTransaction);
- mState = SipSessionState.INCOMING_CALL_ANSWERING;
+ mState = SipSession.State.INCOMING_CALL_ANSWERING;
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
} else if (END_CALL == evt) {
@@ -919,8 +924,8 @@ class SipSessionGroup implements SipListener {
int statusCode = response.getStatusCode();
switch (statusCode) {
case Response.RINGING:
- if (mState == SipSessionState.OUTGOING_CALL) {
- mState = SipSessionState.OUTGOING_CALL_RING_BACK;
+ if (mState == SipSession.State.OUTGOING_CALL) {
+ mState = SipSession.State.OUTGOING_CALL_RING_BACK;
mProxy.onRingingBack(this);
cancelSessionTimer();
}
@@ -963,7 +968,7 @@ class SipSessionGroup implements SipListener {
// response comes back yet. We are cheating for not checking
// response.
mSipHelper.sendCancel(mClientTransaction);
- mState = SipSessionState.OUTGOING_CALL_CANCELING;
+ mState = SipSession.State.OUTGOING_CALL_CANCELING;
startSessionTimer(CANCEL_CALL_TIMER);
return true;
}
@@ -1019,7 +1024,7 @@ class SipSessionGroup implements SipListener {
} else if (isRequestEvent(Request.INVITE, evt)) {
// got Re-INVITE
RequestEvent event = mInviteReceived = (RequestEvent) evt;
- mState = SipSessionState.INCOMING_CALL;
+ mState = SipSession.State.INCOMING_CALL;
mPeerSessionDescription = extractContent(event.getRequest());
mServerTransaction = null;
mProxy.onRinging(this, mPeerProfile, mPeerSessionDescription);
@@ -1032,7 +1037,7 @@ class SipSessionGroup implements SipListener {
// to change call
mClientTransaction = mSipHelper.sendReinvite(mDialog,
((MakeCallCommand) evt).getSessionDescription());
- mState = SipSessionState.OUTGOING_CALL;
+ mState = SipSession.State.OUTGOING_CALL;
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
}
@@ -1060,14 +1065,14 @@ class SipSessionGroup implements SipListener {
}
private void establishCall() {
- mState = SipSessionState.IN_CALL;
+ mState = SipSession.State.IN_CALL;
mInCall = true;
cancelSessionTimer();
mProxy.onCallEstablished(this, mPeerSessionDescription);
}
private void fallbackToPreviousInCall(int errorCode, String message) {
- mState = SipSessionState.IN_CALL;
+ mState = SipSession.State.IN_CALL;
mProxy.onCallChangeFailed(this, errorCode, message);
}
@@ -1089,8 +1094,8 @@ class SipSessionGroup implements SipListener {
private void onError(int errorCode, String message) {
cancelSessionTimer();
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
onRegistrationFailed(errorCode, message);
break;
default:
@@ -1264,7 +1269,7 @@ class SipSessionGroup implements SipListener {
private static boolean isLoggable(SipSessionImpl s) {
if (s != null) {
switch (s.mState) {
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
return DEBUG_PING;
}
}
diff --git a/services/java/com/android/server/sip/SipSessionListenerProxy.java b/services/java/com/android/server/sip/SipSessionListenerProxy.java
index a4cd102..f8be0a8 100644
--- a/services/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/services/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -40,7 +40,7 @@ class SipSessionListenerProxy extends ISipSessionListener.Stub {
// One thread for each calling back.
// Note: Guarantee ordering if the issue becomes important. Currently,
// the chance of handling two callback events at a time is none.
- new Thread(runnable).start();
+ new Thread(runnable, "SipSessionCallbackThread").start();
}
public void onCalling(final ISipSession session) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 129be4e..ff887e4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <utils/String8.h>
#include <hardware/hardware.h>
@@ -100,5 +101,25 @@ hwc_layer_t* HWComposer::getLayers() const {
return mList ? mList->hwLayers : 0;
}
+void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
+ if (mHwc && mList) {
+ result.append("Hardware Composer state:\n");
+
+ snprintf(buffer, SIZE, " numHwLayers=%u, flags=%08x\n",
+ mList->numHwLayers, mList->flags);
+ result.append(buffer);
+
+ for (size_t i=0 ; i<mList->numHwLayers ; i++) {
+ const hwc_layer_t& l(mList->hwLayers[i]);
+ snprintf(buffer, SIZE, " %8s | %08x | %08x | %02x | %04x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d]\n",
+ l.compositionType ? "OVERLAY" : "FB",
+ l.hints, l.flags, l.transform, l.blending,
+ l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
+ l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom);
+ result.append(buffer);
+ }
+ }
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 22ff10c..5a9e9eb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -27,6 +27,8 @@
namespace android {
// ---------------------------------------------------------------------------
+class String8;
+
class HWComposer
{
public:
@@ -54,6 +56,9 @@ public:
size_t getNumLayers() const;
hwc_layer_t* getLayers() const;
+ // for debugging
+ void dump(String8& out, char* scratch, size_t SIZE) const;
+
private:
hw_module_t const* mModule;
hwc_composer_device_t* mHwc;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b45f6fe..b353bff 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -85,6 +85,7 @@ SurfaceFlinger::SurfaceFlinger()
mFreezeDisplayTime(0),
mDebugRegion(0),
mDebugBackground(0),
+ mDebugDisableHWC(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
@@ -768,6 +769,10 @@ void SurfaceFlinger::handleWorkList()
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 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty)
continue;
}
}
+
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
@@ -1522,6 +1528,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
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);
+ hwc.dump(result, buffer, SIZE);
+
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
alloc.dump(result);
@@ -1580,6 +1593,11 @@ status_t SurfaceFlinger::onTransact(
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 @@ private:
// 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/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 9fcf12d..4791fbd 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -27,7 +27,7 @@ import android.net.sip.SipErrorCode;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
-import android.net.sip.SipSessionState;
+import android.net.sip.SipSession;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
@@ -91,7 +91,7 @@ public class SipPhone extends SipPhoneBase {
foregroundCall = new SipCall();
backgroundCall = new SipCall();
mProfile = profile;
- mSipManager = SipManager.getInstance(context);
+ mSipManager = SipManager.newInstance(context);
// FIXME: what's this for SIP?
//Change the system property
@@ -710,8 +710,8 @@ public class SipPhone extends SipPhoneBase {
void dial() throws SipException {
setState(Call.State.DIALING);
- mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile,
- mPeer, null, SESSION_TIMEOUT);
+ mSipAudioCall = mSipManager.makeAudioCall(mProfile, mPeer, null,
+ SESSION_TIMEOUT);
mSipAudioCall.setRingbackToneEnabled(false);
mSipAudioCall.setListener(mAdapter);
}
@@ -807,20 +807,20 @@ public class SipPhone extends SipPhoneBase {
if (sipAudioCall.isOnHold()) return Call.State.HOLDING;
int sessionState = sipAudioCall.getState();
switch (sessionState) {
- case SipSessionState.READY_TO_CALL: return Call.State.IDLE;
- case SipSessionState.INCOMING_CALL:
- case SipSessionState.INCOMING_CALL_ANSWERING: return Call.State.INCOMING;
- case SipSessionState.OUTGOING_CALL: return Call.State.DIALING;
- case SipSessionState.OUTGOING_CALL_RING_BACK: return Call.State.ALERTING;
- case SipSessionState.OUTGOING_CALL_CANCELING: return Call.State.DISCONNECTING;
- case SipSessionState.IN_CALL: return Call.State.ACTIVE;
+ case SipSession.State.READY_TO_CALL: return Call.State.IDLE;
+ case SipSession.State.INCOMING_CALL:
+ case SipSession.State.INCOMING_CALL_ANSWERING: return Call.State.INCOMING;
+ case SipSession.State.OUTGOING_CALL: return Call.State.DIALING;
+ case SipSession.State.OUTGOING_CALL_RING_BACK: return Call.State.ALERTING;
+ case SipSession.State.OUTGOING_CALL_CANCELING: return Call.State.DISCONNECTING;
+ case SipSession.State.IN_CALL: return Call.State.ACTIVE;
default:
Log.w(LOG_TAG, "illegal connection state: " + sessionState);
return Call.State.DISCONNECTED;
}
}
- private abstract class SipAudioCallAdapter extends SipAudioCall.Adapter {
+ private abstract class SipAudioCallAdapter extends SipAudioCall.Listener {
protected abstract void onCallEnded(Connection.DisconnectCause cause);
protected abstract void onError(Connection.DisconnectCause cause);
diff --git a/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java b/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
index 48c4520..5fb09a7 100644
--- a/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
+++ b/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
@@ -25,6 +25,7 @@ import android.os.BatteryManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.View;
+import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -38,7 +39,6 @@ public class BatteryWaster extends Activity {
TextView mLog;
DateFormat mDateFormat;
IntentFilter mFilter;
- PowerManager.WakeLock mWakeLock;
PowerManager.WakeLock mPartialWakeLock;
SpinThread mThread;
@@ -65,24 +65,26 @@ public class BatteryWaster extends Activity {
mFilter.addAction(Intent.ACTION_POWER_CONNECTED);
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "BatteryWaster");
- mWakeLock.setReferenceCounted(false);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BatteryWaster");
mPartialWakeLock.setReferenceCounted(false);
}
@Override
- public void onPause() {
- super.onPause();
- stopRunning();
+ public void onResume() {
+ super.onResume();
+ if (((CheckBox)findViewById(R.id.checkbox)).isChecked()) {
+ startRunning();
+ }
+ if (((CheckBox)findViewById(R.id.checkbox_wake)).isChecked()) {
+ mWaking = true;
+ updateWakeLock();
+ }
}
@Override
public void onDestroy() {
super.onDestroy();
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
+ stopRunning();
if (mPartialWakeLock.isHeld()) {
mPartialWakeLock.release();
}
@@ -140,13 +142,9 @@ public class BatteryWaster extends Activity {
void updateWakeLock() {
if (mWasting) {
- if (!mWakeLock.isHeld()) {
- mWakeLock.acquire();
- }
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
if (mWaking) {
if (!mPartialWakeLock.isHeld()) {
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index a1bc241..c5aa573 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -45,7 +45,7 @@ public:
mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL),
- mMaxResVersion(NULL), mDebugMode(false),
+ mMaxResVersion(NULL), mDebugMode(false), mProduct(NULL),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
@@ -139,6 +139,8 @@ public:
void setMaxResVersion(const char * val) { mMaxResVersion = val; }
bool getDebugMode() { return mDebugMode; }
void setDebugMode(bool val) { mDebugMode = val; }
+ const char* getProduct() const { return mProduct; }
+ void setProduct(const char * val) { mProduct = val; }
/*
* Set and get the file specification.
@@ -237,6 +239,7 @@ private:
const char* mCustomPackage;
const char* mMaxResVersion;
bool mDebugMode;
+ const char* mProduct;
/* file specification */
int mArgc;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 71c023d..739b01f 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -67,6 +67,7 @@ void usage(void)
" [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n"
" [-S resource-sources [-S resource-sources ...]] "
" [-F apk-file] [-J R-file-dir] \\\n"
+ " [--product product1,product2,...] \\\n"
" [raw-files-dir [raw-files-dir] ...]\n"
"\n"
" Package the android resources. It will read assets and resources that are\n"
@@ -154,6 +155,9 @@ void usage(void)
" components target the given package. Useful when used in\n"
" conjunction with --rename-manifest-package to fix tests against\n"
" a package that has been renamed.\n"
+ " --product\n"
+ " Specifies which variant to choose for strings that have\n"
+ " product variants\n"
" --utf16\n"
" changes default encoding for resources to UTF-16. Only useful when API\n"
" level is set to 7 or higher where the default encoding is UTF-8.\n");
@@ -484,6 +488,15 @@ int main(int argc, char* const argv[])
bundle.setInstrumentationPackageNameOverride(argv[0]);
} else if (strcmp(cp, "-auto-add-overlay") == 0) {
bundle.setAutoAddOverlay(true);
+ } else if (strcmp(cp, "-product") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--product' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setProduct(argv[0]);
} else {
fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
wantUsage = true;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index f40a877..90a6256 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -574,6 +574,7 @@ status_t parseAndAddBag(Bundle* bundle,
const String16& itemIdent,
int32_t curFormat,
bool isFormatted,
+ const String16& product,
bool pseudolocalize,
const bool overwrite,
ResourceTable* outTable)
@@ -606,6 +607,32 @@ status_t parseAndAddBag(Bundle* bundle,
return err;
}
+/*
+ * Returns true if needle is one of the elements in the comma-separated list
+ * haystack, false otherwise.
+ */
+bool isInProductList(const String16& needle, const String16& haystack) {
+ const char16_t *needle2 = needle.string();
+ const char16_t *haystack2 = haystack.string();
+ size_t needlesize = needle.size();
+
+ while (*haystack2 != '\0') {
+ if (strncmp16(haystack2, needle2, needlesize) == 0) {
+ if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
+ return true;
+ }
+ }
+
+ while (*haystack2 != '\0' && *haystack2 != ',') {
+ haystack2++;
+ }
+ if (*haystack2 == ',') {
+ haystack2++;
+ }
+ }
+
+ return false;
+}
status_t parseAndAddEntry(Bundle* bundle,
const sp<AaptFile>& in,
@@ -618,6 +645,7 @@ status_t parseAndAddEntry(Bundle* bundle,
bool curIsStyled,
int32_t curFormat,
bool isFormatted,
+ const String16& product,
bool pseudolocalize,
const bool overwrite,
ResourceTable* outTable)
@@ -634,6 +662,47 @@ status_t parseAndAddEntry(Bundle* bundle,
return err;
}
+ /*
+ * If a product type was specified on the command line
+ * and also in the string, and the two are not the same,
+ * return without adding the string.
+ */
+
+ const char *bundleProduct = bundle->getProduct();
+ if (bundleProduct == NULL) {
+ bundleProduct = "";
+ }
+
+ if (product.size() != 0) {
+ /*
+ * If the command-line-specified product is empty, only "default"
+ * matches. Other variants are skipped. This is so generation
+ * of the R.java file when the product is not known is predictable.
+ */
+
+ if (bundleProduct[0] == '\0') {
+ if (strcmp16(String16("default").string(), product.string()) != 0) {
+ return NO_ERROR;
+ }
+ } else {
+ /*
+ * The command-line product is not empty.
+ * If the product for this string is on the command-line list,
+ * it matches. "default" also matches, but only if nothing
+ * else has matched already.
+ */
+
+ if (isInProductList(product, String16(bundleProduct))) {
+ ;
+ } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
+ !outTable->hasBagOrEntry(myPackage, curType, ident)) {
+ ;
+ } else {
+ return NO_ERROR;
+ }
+ }
+ }
+
NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
config.language[0], config.language[1],
config.country[0], config.country[1],
@@ -713,6 +782,7 @@ status_t compileResourceFile(Bundle* bundle,
const String16 translatable16("translatable");
const String16 formatted16("formatted");
const String16 false16("false");
+ const String16 product16("product");
const String16 myPackage(assets->getPackage());
@@ -760,6 +830,7 @@ status_t compileResourceFile(Bundle* bundle,
bool curIsStyled = false;
bool curIsPseudolocalizable = false;
bool curIsFormatted = fileIsTranslatable;
+ String16 curProduct;
bool localHasErrors = false;
if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
@@ -1157,6 +1228,8 @@ status_t compileResourceFile(Bundle* bundle,
translatable.setTo(block.getAttributeStringValue(i, &length));
} else if (strcmp16(attr, formatted16.string()) == 0) {
formatted.setTo(block.getAttributeStringValue(i, &length));
+ } else if (strcmp16(attr, product16.string()) == 0) {
+ curProduct.setTo(block.getAttributeStringValue(i, &length));
}
}
@@ -1374,7 +1447,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
ident, parentIdent, itemIdent, curFormat, curIsFormatted,
- false, overwrite, outTable);
+ curProduct, false, overwrite, outTable);
if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
&& bundle->getPseudolocalize()) {
@@ -1383,7 +1456,7 @@ status_t compileResourceFile(Bundle* bundle,
block.setPosition(parserPosition);
err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
curType, ident, parentIdent, itemIdent, curFormat,
- curIsFormatted, true, overwrite, outTable);
+ curIsFormatted, curProduct, true, overwrite, outTable);
#endif
}
}
@@ -1407,7 +1480,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
- false, overwrite, outTable);
+ curProduct, false, overwrite, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1419,7 +1492,8 @@ status_t compileResourceFile(Bundle* bundle,
block.setPosition(parserPosition);
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
ident, *curTag, curIsStyled, curFormat,
- curIsFormatted, true, overwrite, outTable);
+ curIsFormatted, curProduct,
+ true, overwrite, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
diff --git a/voip/java/android/net/sip/SdpSessionDescription.java b/voip/java/android/net/sip/SdpSessionDescription.java
deleted file mode 100644
index f6ae837..0000000
--- a/voip/java/android/net/sip/SdpSessionDescription.java
+++ /dev/null
@@ -1,428 +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.net.sip;
-
-import gov.nist.javax.sdp.SessionDescriptionImpl;
-import gov.nist.javax.sdp.fields.AttributeField;
-import gov.nist.javax.sdp.fields.ConnectionField;
-import gov.nist.javax.sdp.fields.MediaField;
-import gov.nist.javax.sdp.fields.OriginField;
-import gov.nist.javax.sdp.fields.ProtoVersionField;
-import gov.nist.javax.sdp.fields.SessionNameField;
-import gov.nist.javax.sdp.fields.TimeField;
-import gov.nist.javax.sdp.parser.SDPAnnounceParser;
-
-import android.util.Log;
-
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Vector;
-import javax.sdp.Connection;
-import javax.sdp.MediaDescription;
-import javax.sdp.SdpException;
-
-/**
- * A session description that follows SDP (Session Description Protocol).
- * Refer to <a href="http://tools.ietf.org/html/rfc4566">RFC 4566</a>.
- * @hide
- */
-public class SdpSessionDescription extends SessionDescription {
- private static final String TAG = "SDP";
- private static final String AUDIO = "audio";
- private static final String RTPMAP = "rtpmap";
- private static final String PTIME = "ptime";
- private static final String SENDONLY = "sendonly";
- private static final String RECVONLY = "recvonly";
- private static final String INACTIVE = "inactive";
-
- private SessionDescriptionImpl mSessionDescription;
-
- /**
- * The audio codec information parsed from "rtpmap".
- */
- public static class AudioCodec {
- public final int payloadType;
- public final String name;
- public final int sampleRate;
- public final int sampleCount;
-
- public AudioCodec(int payloadType, String name, int sampleRate,
- int sampleCount) {
- this.payloadType = payloadType;
- this.name = name;
- this.sampleRate = sampleRate;
- this.sampleCount = sampleCount;
- }
- }
-
- /**
- * The builder class used to create an {@link SdpSessionDescription} object.
- */
- public static class Builder {
- private SdpSessionDescription mSdp = new SdpSessionDescription();
- private SessionDescriptionImpl mSessionDescription;
-
- public Builder(String sessionName) throws SdpException {
- mSessionDescription = new SessionDescriptionImpl();
- mSdp.mSessionDescription = mSessionDescription;
- try {
- ProtoVersionField proto = new ProtoVersionField();
- proto.setVersion(0);
- mSessionDescription.addField(proto);
-
- TimeField time = new TimeField();
- time.setZero();
- mSessionDescription.addField(time);
-
- SessionNameField session = new SessionNameField();
- session.setValue(sessionName);
- mSessionDescription.addField(session);
- } catch (Exception e) {
- throwSdpException(e);
- }
- }
-
- public Builder setConnectionInfo(String networkType, String addressType,
- String addr) throws SdpException {
- try {
- ConnectionField connection = new ConnectionField();
- connection.setNetworkType(networkType);
- connection.setAddressType(addressType);
- connection.setAddress(addr);
- mSessionDescription.addField(connection);
- } catch (Exception e) {
- throwSdpException(e);
- }
- return this;
- }
-
- public Builder setOrigin(SipProfile user, long sessionId,
- long sessionVersion, String networkType, String addressType,
- String address) throws SdpException {
- try {
- OriginField origin = new OriginField();
- origin.setUsername(user.getUserName());
- origin.setSessionId(sessionId);
- origin.setSessionVersion(sessionVersion);
- origin.setAddressType(addressType);
- origin.setNetworkType(networkType);
- origin.setAddress(address);
- mSessionDescription.addField(origin);
- } catch (Exception e) {
- throwSdpException(e);
- }
- return this;
- }
-
- public Builder addMedia(String media, int port, int numPorts,
- String transport, Integer... types) throws SdpException {
- MediaField field = new MediaField();
- Vector<Integer> typeVector = new Vector<Integer>();
- Collections.addAll(typeVector, types);
- try {
- field.setMediaType(media);
- field.setMediaPort(port);
- field.setPortCount(numPorts);
- field.setProtocol(transport);
- field.setMediaFormats(typeVector);
- mSessionDescription.addField(field);
- } catch (Exception e) {
- throwSdpException(e);
- }
- return this;
- }
-
- public Builder addMediaAttribute(String type, String name, String value)
- throws SdpException {
- try {
- MediaDescription md = mSdp.getMediaDescription(type);
- if (md == null) {
- throw new SdpException("Should add media first!");
- }
- AttributeField attribute = new AttributeField();
- attribute.setName(name);
- attribute.setValueAllowNull(value);
- mSessionDescription.addField(attribute);
- } catch (Exception e) {
- throwSdpException(e);
- }
- return this;
- }
-
- public Builder addSessionAttribute(String name, String value)
- throws SdpException {
- try {
- AttributeField attribute = new AttributeField();
- attribute.setName(name);
- attribute.setValueAllowNull(value);
- mSessionDescription.addField(attribute);
- } catch (Exception e) {
- throwSdpException(e);
- }
- return this;
- }
-
- private void throwSdpException(Exception e) throws SdpException {
- if (e instanceof SdpException) {
- throw (SdpException) e;
- } else {
- throw new SdpException(e.toString(), e);
- }
- }
-
- public String build() {
- return mSdp.toString();
- }
- }
-
- private SdpSessionDescription() {
- }
-
- /**
- * Constructor.
- *
- * @param sdpString an SDP session description to parse
- */
- public SdpSessionDescription(String sdpString) throws SdpException {
- try {
- mSessionDescription = new SDPAnnounceParser(sdpString).parse();
- } catch (ParseException e) {
- throw new SdpException(e.toString(), e);
- }
- verify();
- }
-
- /**
- * Constructor.
- *
- * @param content a raw SDP session description to parse
- */
- public SdpSessionDescription(byte[] content) throws SdpException {
- this(new String(content));
- }
-
- private void verify() throws SdpException {
- // make sure the syntax is correct over the fields we're interested in
- Vector<MediaDescription> descriptions = (Vector<MediaDescription>)
- mSessionDescription.getMediaDescriptions(false);
- for (MediaDescription md : descriptions) {
- md.getMedia().getMediaPort();
- Connection connection = md.getConnection();
- if (connection != null) connection.getAddress();
- md.getMedia().getFormats();
- }
- Connection connection = mSessionDescription.getConnection();
- if (connection != null) connection.getAddress();
- }
-
- /**
- * Gets the connection address of the media.
- *
- * @param type the media type; e.g., "AUDIO"
- * @return the media connection address of the peer
- */
- public String getPeerMediaAddress(String type) {
- try {
- MediaDescription md = getMediaDescription(type);
- Connection connection = md.getConnection();
- if (connection == null) {
- connection = mSessionDescription.getConnection();
- }
- return ((connection == null) ? null : connection.getAddress());
- } catch (SdpException e) {
- // should not occur
- return null;
- }
- }
-
- /**
- * Gets the connection port number of the media.
- *
- * @param type the media type; e.g., "AUDIO"
- * @return the media connection port number of the peer
- */
- public int getPeerMediaPort(String type) {
- try {
- MediaDescription md = getMediaDescription(type);
- return md.getMedia().getMediaPort();
- } catch (SdpException e) {
- // should not occur
- return -1;
- }
- }
-
- private boolean containsAttribute(String type, String name) {
- if (name == null) return false;
- MediaDescription md = getMediaDescription(type);
- Vector<AttributeField> v = (Vector<AttributeField>)
- md.getAttributeFields();
- for (AttributeField field : v) {
- if (name.equals(field.getAttribute().getName())) return true;
- }
- return false;
- }
-
- /**
- * Checks if the media is "sendonly".
- *
- * @param type the media type; e.g., "AUDIO"
- * @return true if the media is "sendonly"
- */
- public boolean isSendOnly(String type) {
- boolean answer = containsAttribute(type, SENDONLY);
- Log.d(TAG, " sendonly? " + answer);
- return answer;
- }
-
- /**
- * Checks if the media is "recvonly".
- *
- * @param type the media type; e.g., "AUDIO"
- * @return true if the media is "recvonly"
- */
- public boolean isReceiveOnly(String type) {
- boolean answer = containsAttribute(type, RECVONLY);
- Log.d(TAG, " recvonly? " + answer);
- return answer;
- }
-
- /**
- * Checks if the media is in sending; i.e., not "recvonly" and not
- * "inactive".
- *
- * @param type the media type; e.g., "AUDIO"
- * @return true if the media is sending
- */
- public boolean isSending(String type) {
- boolean answer = !containsAttribute(type, RECVONLY)
- && !containsAttribute(type, INACTIVE);
-
- Log.d(TAG, " sending? " + answer);
- return answer;
- }
-
- /**
- * Checks if the media is in receiving; i.e., not "sendonly" and not
- * "inactive".
- *
- * @param type the media type; e.g., "AUDIO"
- * @return true if the media is receiving
- */
- public boolean isReceiving(String type) {
- boolean answer = !containsAttribute(type, SENDONLY)
- && !containsAttribute(type, INACTIVE);
- Log.d(TAG, " receiving? " + answer);
- return answer;
- }
-
- private AudioCodec parseAudioCodec(String rtpmap, int ptime) {
- String[] ss = rtpmap.split(" ");
- int payloadType = Integer.parseInt(ss[0]);
-
- ss = ss[1].split("/");
- String name = ss[0];
- int sampleRate = Integer.parseInt(ss[1]);
- int channelCount = 1;
- if (ss.length > 2) channelCount = Integer.parseInt(ss[2]);
- int sampleCount = sampleRate / (1000 / ptime) * channelCount;
- return new AudioCodec(payloadType, name, sampleRate, sampleCount);
- }
-
- /**
- * Gets the list of audio codecs in this session description.
- *
- * @return the list of audio codecs in this session description
- */
- public List<AudioCodec> getAudioCodecs() {
- MediaDescription md = getMediaDescription(AUDIO);
- if (md == null) return new ArrayList<AudioCodec>();
-
- // FIXME: what happens if ptime is missing
- int ptime = 20;
- try {
- String value = md.getAttribute(PTIME);
- if (value != null) ptime = Integer.parseInt(value);
- } catch (Throwable t) {
- Log.w(TAG, "getCodecs(): ignored: " + t);
- }
-
- List<AudioCodec> codecs = new ArrayList<AudioCodec>();
- Vector<AttributeField> v = (Vector<AttributeField>)
- md.getAttributeFields();
- for (AttributeField field : v) {
- try {
- if (RTPMAP.equals(field.getName())) {
- AudioCodec codec = parseAudioCodec(field.getValue(), ptime);
- if (codec != null) codecs.add(codec);
- }
- } catch (Throwable t) {
- Log.w(TAG, "getCodecs(): ignored: " + t);
- }
- }
- return codecs;
- }
-
- /**
- * Gets the media description of the specified type.
- *
- * @param type the media type; e.g., "AUDIO"
- * @return the media description of the specified type
- */
- public MediaDescription getMediaDescription(String type) {
- MediaDescription[] all = getMediaDescriptions();
- if ((all == null) || (all.length == 0)) return null;
- for (MediaDescription md : all) {
- String t = md.getMedia().getMedia();
- if (t.equalsIgnoreCase(type)) return md;
- }
- return null;
- }
-
- /**
- * Gets all the media descriptions in this session description.
- *
- * @return all the media descriptions in this session description
- */
- public MediaDescription[] getMediaDescriptions() {
- try {
- Vector<MediaDescription> descriptions = (Vector<MediaDescription>)
- mSessionDescription.getMediaDescriptions(false);
- MediaDescription[] all = new MediaDescription[descriptions.size()];
- return descriptions.toArray(all);
- } catch (SdpException e) {
- Log.e(TAG, "getMediaDescriptions", e);
- }
- return null;
- }
-
- @Override
- public String getType() {
- return "sdp";
- }
-
- @Override
- public byte[] getContent() {
- return mSessionDescription.toString().getBytes();
- }
-
- @Override
- public String toString() {
- return mSessionDescription.toString();
- }
-}
diff --git a/voip/java/android/net/sip/SessionDescription.aidl b/voip/java/android/net/sip/SessionDescription.aidl
deleted file mode 100644
index a120d16..0000000
--- a/voip/java/android/net/sip/SessionDescription.aidl
+++ /dev/null
@@ -1,19 +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.net.sip;
-
-parcelable SessionDescription;
diff --git a/voip/java/android/net/sip/SessionDescription.java b/voip/java/android/net/sip/SessionDescription.java
deleted file mode 100644
index d476f0b..0000000
--- a/voip/java/android/net/sip/SessionDescription.java
+++ /dev/null
@@ -1,83 +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.net.sip;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Abstract class of a session description.
- * @hide
- */
-public abstract class SessionDescription implements Parcelable {
- /** @hide */
- public static final Parcelable.Creator<SessionDescription> CREATOR =
- new Parcelable.Creator<SessionDescription>() {
- public SessionDescription createFromParcel(Parcel in) {
- return new SessionDescriptionImpl(in);
- }
-
- public SessionDescription[] newArray(int size) {
- return new SessionDescriptionImpl[size];
- }
- };
-
- /**
- * Gets the type of the session description; e.g., "SDP".
- *
- * @return the session description type
- */
- public abstract String getType();
-
- /**
- * Gets the raw content of the session description.
- *
- * @return the content of the session description
- */
- public abstract byte[] getContent();
-
- /** @hide */
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(getType());
- out.writeByteArray(getContent());
- }
-
- /** @hide */
- public int describeContents() {
- return 0;
- }
-
- private static class SessionDescriptionImpl extends SessionDescription {
- private String mType;
- private byte[] mContent;
-
- SessionDescriptionImpl(Parcel in) {
- mType = in.readString();
- mContent = in.createByteArray();
- }
-
- @Override
- public String getType() {
- return mType;
- }
-
- @Override
- public byte[] getContent() {
- return mContent;
- }
- }
-}
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 0069fe0..2135fcb 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -16,120 +16,184 @@
package android.net.sip;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.media.ToneGenerator;
+import android.net.Uri;
+import android.net.rtp.AudioCodec;
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;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
- * Interface for making audio calls over SIP.
- * @hide
+ * Class that handles an audio call over SIP.
*/
-public interface SipAudioCall {
+/** @hide */
+public class SipAudioCall extends SipSessionAdapter {
+ private static final String TAG = SipAudioCall.class.getSimpleName();
+ private static final boolean RELEASE_SOCKET = true;
+ private static final boolean DONT_RELEASE_SOCKET = false;
+ private static final int SESSION_TIMEOUT = 5; // in seconds
+
/** Listener class for all event callbacks. */
- public interface Listener {
+ public static class Listener {
/**
* Called when the call object is ready to make another call.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that is ready to make another call
*/
- void onReadyToCall(SipAudioCall call);
+ public void onReadyToCall(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when a request is sent out to initiate a new call.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onCalling(SipAudioCall call);
+ public void onCalling(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when a new call comes in.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
* @param caller the SIP profile of the caller
*/
- void onRinging(SipAudioCall call, SipProfile caller);
+ public void onRinging(SipAudioCall call, SipProfile caller) {
+ onChanged(call);
+ }
/**
- * Called when a RINGING response is received for the INVITE request sent
+ * Called when a RINGING response is received for the INVITE request
+ * sent. The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onRingingBack(SipAudioCall call);
+ public void onRingingBack(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when the session is established.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onCallEstablished(SipAudioCall call);
+ public void onCallEstablished(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when the session is terminated.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onCallEnded(SipAudioCall call);
+ public void onCallEnded(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when the peer is busy during session initialization.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onCallBusy(SipAudioCall call);
+ public void onCallBusy(SipAudioCall call) {
+ onChanged(call);
+ }
/**
* Called when the call is on hold.
+ * The default implementation calls {@link #onChange}.
*
* @param call the call object that carries out the audio call
*/
- void onCallHeld(SipAudioCall call);
+ public void onCallHeld(SipAudioCall call) {
+ onChanged(call);
+ }
/**
- * Called when an error occurs.
+ * Called when an error occurs. The default implementation is no op.
*
* @param call the call object that carries out the audio call
* @param errorCode error code of this error
* @param errorMessage error message
* @see SipErrorCode
*/
- void onError(SipAudioCall call, int errorCode, String errorMessage);
+ public void onError(SipAudioCall call, int errorCode,
+ String errorMessage) {
+ // no-op
+ }
+
+ /**
+ * Called when an event occurs and the corresponding callback is not
+ * overridden. The default implementation is no op. Error events are
+ * not re-directed to this callback and are handled in {@link #onError}.
+ */
+ public void onChanged(SipAudioCall call) {
+ // no-op
+ }
}
+ private Context mContext;
+ private SipProfile mLocalProfile;
+ private SipAudioCall.Listener mListener;
+ private SipSession mSipSession;
+
+ private long mSessionId = System.currentTimeMillis();
+ private String mPeerSd;
+
+ private AudioStream mAudioStream;
+ private AudioGroup mAudioGroup;
+
+ private boolean mInCall = false;
+ private boolean mMuted = false;
+ private boolean mHold = false;
+
+ private boolean mRingbackToneEnabled = true;
+ private boolean mRingtoneEnabled = true;
+ private Ringtone mRingtone;
+ private ToneGenerator mRingbackTone;
+
+ private SipProfile mPendingCallRequest;
+ private WifiManager mWm;
+ private WifiManager.WifiLock mWifiHighPerfLock;
+
+ private int mErrorCode = SipErrorCode.NO_ERROR;
+ private String mErrorMessage;
+
/**
- * The adapter class for {@link Listener}. The default implementation of
- * all callback methods is no-op.
+ * Creates a call object with the local SIP profile.
+ * @param context the context for accessing system services such as
+ * ringtone, audio, WIFI etc
*/
- public class Adapter implements Listener {
- protected void onChanged(SipAudioCall call) {
- }
- public void onReadyToCall(SipAudioCall call) {
- onChanged(call);
- }
- public void onCalling(SipAudioCall call) {
- onChanged(call);
- }
- public void onRinging(SipAudioCall call, SipProfile caller) {
- onChanged(call);
- }
- public void onRingingBack(SipAudioCall call) {
- onChanged(call);
- }
- public void onCallEstablished(SipAudioCall call) {
- onChanged(call);
- }
- public void onCallEnded(SipAudioCall call) {
- onChanged(call);
- }
- public void onCallBusy(SipAudioCall call) {
- onChanged(call);
- }
- public void onCallHeld(SipAudioCall call) {
- onChanged(call);
- }
- public void onError(SipAudioCall call, int errorCode,
- String errorMessage) {
- onChanged(call);
- }
+ public SipAudioCall(Context context, SipProfile localProfile) {
+ mContext = context;
+ mLocalProfile = localProfile;
+ mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
}
/**
@@ -139,7 +203,9 @@ public interface SipAudioCall {
* @param listener to listen to the audio call events of this object
* @see #setListener(Listener, boolean)
*/
- void setListener(Listener listener);
+ public void setListener(SipAudioCall.Listener listener) {
+ setListener(listener, false);
+ }
/**
* Sets the listener to listen to the audio call events. A
@@ -150,44 +216,355 @@ public interface SipAudioCall {
* @param callbackImmediately set to true if the caller wants to be called
* back immediately on the current state
*/
- void setListener(Listener listener, boolean callbackImmediately);
+ public void setListener(SipAudioCall.Listener listener,
+ boolean callbackImmediately) {
+ mListener = listener;
+ try {
+ if ((listener == null) || !callbackImmediately) {
+ // do nothing
+ } else if (mErrorCode != SipErrorCode.NO_ERROR) {
+ listener.onError(this, mErrorCode, mErrorMessage);
+ } else if (mInCall) {
+ if (mHold) {
+ listener.onCallHeld(this);
+ } else {
+ listener.onCallEstablished(this);
+ }
+ } else {
+ int state = getState();
+ switch (state) {
+ case SipSession.State.READY_TO_CALL:
+ listener.onReadyToCall(this);
+ break;
+ case SipSession.State.INCOMING_CALL:
+ listener.onRinging(this, getPeerProfile());
+ break;
+ case SipSession.State.OUTGOING_CALL:
+ listener.onCalling(this);
+ break;
+ case SipSession.State.OUTGOING_CALL_RING_BACK:
+ listener.onRingingBack(this);
+ break;
+ }
+ }
+ } catch (Throwable t) {
+ Log.e(TAG, "setListener()", t);
+ }
+ }
+
+ /**
+ * Checks if the call is established.
+ *
+ * @return true if the call is established
+ */
+ public synchronized boolean isInCall() {
+ return mInCall;
+ }
+
+ /**
+ * Checks if the call is on hold.
+ *
+ * @return true if the call is on hold
+ */
+ public synchronized boolean isOnHold() {
+ return mHold;
+ }
/**
* Closes this object. This object is not usable after being closed.
*/
- void close();
+ public void close() {
+ close(true);
+ }
+
+ private synchronized void close(boolean closeRtp) {
+ if (closeRtp) stopCall(RELEASE_SOCKET);
+ stopRingbackTone();
+ stopRinging();
+
+ mInCall = false;
+ mHold = false;
+ mSessionId = System.currentTimeMillis();
+ mErrorCode = SipErrorCode.NO_ERROR;
+ mErrorMessage = null;
+
+ if (mSipSession != null) {
+ mSipSession.setListener(null);
+ mSipSession = null;
+ }
+ }
/**
- * Initiates an audio call to the specified profile. The attempt will be
- * timed out if the call is not established within {@code timeout} seconds
- * and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
- * will be called.
+ * Gets the local SIP profile.
*
- * @param callee the SIP profile to make the call to
- * @param sipManager the {@link SipManager} object to help make call with
- * @param timeout the timeout value in seconds
- * @see Listener.onError
+ * @return the local SIP profile
*/
- void makeCall(SipProfile callee, SipManager sipManager, int timeout)
- throws SipException;
+ public synchronized SipProfile getLocalProfile() {
+ return mLocalProfile;
+ }
/**
- * Starts the audio for the established call. This method should be called
- * after {@link Listener#onCallEstablished} is called.
+ * Gets the peer's SIP profile.
+ *
+ * @return the peer's SIP profile
*/
- void startAudio();
+ public synchronized SipProfile getPeerProfile() {
+ return (mSipSession == null) ? null : mSipSession.getPeerProfile();
+ }
+
+ /**
+ * Gets the state of the {@link SipSession} that carries this call.
+ * The value returned must be one of the states in {@link SipSession.State}.
+ *
+ * @return the session state
+ */
+ public synchronized int getState() {
+ if (mSipSession == null) return SipSession.State.READY_TO_CALL;
+ return mSipSession.getState();
+ }
+
+
+ /**
+ * Gets the {@link SipSession} that carries this call.
+ *
+ * @return the session object that carries this call
+ * @hide
+ */
+ public synchronized SipSession getSipSession() {
+ return mSipSession;
+ }
+
+ private SipSession.Listener createListener() {
+ return new SipSession.Listener() {
+ @Override
+ public void onCalling(SipSession session) {
+ Log.d(TAG, "calling... " + session);
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onCalling(SipAudioCall.this);
+ } catch (Throwable t) {
+ Log.i(TAG, "onCalling(): " + t);
+ }
+ }
+ }
+
+ @Override
+ public void onRingingBack(SipSession session) {
+ Log.d(TAG, "sip call ringing back: " + session);
+ if (!mInCall) startRingbackTone();
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onRingingBack(SipAudioCall.this);
+ } catch (Throwable t) {
+ Log.i(TAG, "onRingingBack(): " + t);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void onRinging(SipSession session,
+ SipProfile peerProfile, String sessionDescription) {
+ if ((mSipSession == null) || !mInCall
+ || !session.getCallId().equals(mSipSession.getCallId())) {
+ // should not happen
+ session.endCall();
+ return;
+ }
+
+ // session changing request
+ try {
+ String answer = createAnswer(sessionDescription).encode();
+ mSipSession.answerCall(answer, SESSION_TIMEOUT);
+ } catch (Throwable e) {
+ Log.e(TAG, "onRinging()", e);
+ session.endCall();
+ }
+ }
+
+ @Override
+ public void onCallEstablished(SipSession session,
+ String sessionDescription) {
+ stopRingbackTone();
+ stopRinging();
+ mPeerSd = sessionDescription;
+ Log.v(TAG, "onCallEstablished()" + mPeerSd);
+
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ if (mHold) {
+ listener.onCallHeld(SipAudioCall.this);
+ } else {
+ listener.onCallEstablished(SipAudioCall.this);
+ }
+ } catch (Throwable t) {
+ Log.i(TAG, "onCallEstablished(): " + t);
+ }
+ }
+ }
+
+ @Override
+ public void onCallEnded(SipSession session) {
+ Log.d(TAG, "sip call ended: " + session);
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onCallEnded(SipAudioCall.this);
+ } catch (Throwable t) {
+ Log.i(TAG, "onCallEnded(): " + t);
+ }
+ }
+ close();
+ }
+
+ @Override
+ public void onCallBusy(SipSession session) {
+ Log.d(TAG, "sip call busy: " + session);
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onCallBusy(SipAudioCall.this);
+ } catch (Throwable t) {
+ Log.i(TAG, "onCallBusy(): " + t);
+ }
+ }
+ close(false);
+ }
+
+ @Override
+ public void onCallChangeFailed(SipSession session, int errorCode,
+ String message) {
+ Log.d(TAG, "sip call change failed: " + message);
+ mErrorCode = errorCode;
+ mErrorMessage = message;
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onError(SipAudioCall.this, mErrorCode,
+ message);
+ } catch (Throwable t) {
+ Log.i(TAG, "onCallBusy(): " + t);
+ }
+ }
+ }
+
+ @Override
+ public void onError(SipSession session, int errorCode,
+ String message) {
+ SipAudioCall.this.onError(errorCode, message);
+ }
+
+ @Override
+ public void onRegistering(SipSession session) {
+ // irrelevant
+ }
+
+ @Override
+ public void onRegistrationTimeout(SipSession session) {
+ // irrelevant
+ }
+
+ @Override
+ public void onRegistrationFailed(SipSession session, int errorCode,
+ String message) {
+ // irrelevant
+ }
+
+ @Override
+ public void onRegistrationDone(SipSession session, int duration) {
+ // irrelevant
+ }
+ };
+ }
+
+ private void onError(int errorCode, String message) {
+ Log.d(TAG, "sip session error: "
+ + SipErrorCode.toString(errorCode) + ": " + message);
+ mErrorCode = errorCode;
+ mErrorMessage = message;
+ Listener listener = mListener;
+ if (listener != null) {
+ try {
+ listener.onError(this, errorCode, message);
+ } catch (Throwable t) {
+ Log.i(TAG, "onError(): " + t);
+ }
+ }
+ synchronized (this) {
+ if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
+ || !isInCall()) {
+ close(true);
+ }
+ }
+ }
/**
* Attaches an incoming call to this call object.
*
* @param session the session that receives the incoming call
* @param sessionDescription the session description of the incoming call
+ * @throws SipException if the SIP service fails to attach this object to
+ * the session
+ */
+ public synchronized void attachCall(SipSession session,
+ String sessionDescription) throws SipException {
+ mSipSession = session;
+ mPeerSd = sessionDescription;
+ Log.v(TAG, "attachCall()" + mPeerSd);
+ try {
+ session.setListener(createListener());
+
+ if (getState() == SipSession.State.INCOMING_CALL) startRinging();
+ } catch (Throwable e) {
+ Log.e(TAG, "attachCall()", e);
+ throwSipException(e);
+ }
+ }
+
+ /**
+ * Initiates an audio call to the specified profile. The attempt will be
+ * timed out if the call is not established within {@code timeout} seconds
+ * and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
+ * will be called.
+ *
+ * @param callee the SIP profile to make the call to
+ * @param sipManager the {@link SipManager} object to help make call with
+ * @param timeout the timeout value in seconds. Default value (defined by
+ * SIP protocol) is used if {@code timeout} is zero or negative.
+ * @see Listener.onError
+ * @throws SipException if the SIP service fails to create a session for the
+ * call
*/
- void attachCall(ISipSession session, String sessionDescription)
- throws SipException;
+ public synchronized void makeCall(SipProfile peerProfile,
+ SipManager sipManager, int timeout) throws SipException {
+ SipSession s = mSipSession = sipManager.createSipSession(
+ mLocalProfile, createListener());
+ if (s == null) {
+ throw new SipException(
+ "Failed to create SipSession; network available?");
+ }
+ try {
+ mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
+ s.makeCall(peerProfile, createOffer().encode(), timeout);
+ } catch (IOException e) {
+ throw new SipException("makeCall()", e);
+ }
+ }
- /** Ends a call. */
- void endCall() throws SipException;
+ /**
+ * Ends a call.
+ * @throws SipException if the SIP service fails to end the call
+ */
+ public synchronized void endCall() throws SipException {
+ stopRinging();
+ stopCall(RELEASE_SOCKET);
+ mInCall = false;
+
+ // perform the above local ops first and then network op
+ if (mSipSession != null) mSipSession.endCall();
+ }
/**
* Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is
@@ -196,10 +573,19 @@ public interface SipAudioCall {
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
* will be called.
*
- * @param timeout the timeout value in seconds
+ * @param timeout the timeout value in seconds. Default value (defined by
+ * SIP protocol) is used if {@code timeout} is zero or negative.
* @see Listener.onError
+ * @throws SipException if the SIP service fails to hold the call
*/
- void holdCall(int timeout) throws SipException;
+ public synchronized void holdCall(int timeout) throws SipException {
+ if (mHold) return;
+ mSipSession.changeCall(createHoldOffer().encode(), timeout);
+ mHold = true;
+
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ }
/**
* Answers a call. The attempt will be timed out if the call is not
@@ -207,10 +593,20 @@ public interface SipAudioCall {
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
* will be called.
*
- * @param timeout the timeout value in seconds
+ * @param timeout the timeout value in seconds. Default value (defined by
+ * SIP protocol) is used if {@code timeout} is zero or negative.
* @see Listener.onError
+ * @throws SipException if the SIP service fails to answer the call
*/
- void answerCall(int timeout) throws SipException;
+ public synchronized void answerCall(int timeout) throws SipException {
+ stopRinging();
+ try {
+ mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
+ mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout);
+ } catch (IOException e) {
+ throw new SipException("answerCall()", e);
+ }
+ }
/**
* Continues a call that's on hold. When succeeds,
@@ -219,45 +615,191 @@ public interface SipAudioCall {
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
* will be called.
*
- * @param timeout the timeout value in seconds
+ * @param timeout the timeout value in seconds. Default value (defined by
+ * SIP protocol) is used if {@code timeout} is zero or negative.
* @see Listener.onError
+ * @throws SipException if the SIP service fails to unhold the call
*/
- void continueCall(int timeout) throws SipException;
+ public synchronized void continueCall(int timeout) throws SipException {
+ if (!mHold) return;
+ mSipSession.changeCall(createContinueOffer().encode(), timeout);
+ mHold = false;
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_NORMAL);
+ }
- /** Puts the device to speaker mode. */
- void setSpeakerMode(boolean speakerMode);
+ 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;
+ }
- /** Toggles mute. */
- void toggleMute();
+ 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);
- /**
- * Checks if the call is on hold.
- *
- * @return true if the call is on hold
- */
- boolean isOnHold();
+ // 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));
+ }
+ }
+
+ // 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;
+ }
+ }
+ // Reject the media.
+ Media reply = answer.newMedia(
+ media.getType(), 0, 1, media.getProtocol());
+ for (String format : media.getFormats()) {
+ reply.setFormat(format, null);
+ }
+ }
+ 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;
+ }
+
+ private void grabWifiHighPerfLock() {
+ /* not available in master yet
+ if (mWifiHighPerfLock == null) {
+ Log.v(TAG, "acquire wifi high perf lock");
+ mWifiHighPerfLock = ((WifiManager)
+ mContext.getSystemService(Context.WIFI_SERVICE))
+ .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
+ mWifiHighPerfLock.acquire();
+ }
+ */
+ }
+
+ private void releaseWifiHighPerfLock() {
+ if (mWifiHighPerfLock != null) {
+ Log.v(TAG, "release wifi high perf lock");
+ mWifiHighPerfLock.release();
+ mWifiHighPerfLock = null;
+ }
+ }
+
+ private boolean isWifiOn() {
+ return (mWm.getConnectionInfo().getBSSID() == null) ? false : true;
+ }
+
+ /** Toggles mute. */
+ public synchronized void toggleMute() {
+ AudioGroup audioGroup = getAudioGroup();
+ if (audioGroup != null) {
+ audioGroup.setMode(
+ mMuted ? AudioGroup.MODE_NORMAL : AudioGroup.MODE_MUTED);
+ mMuted = !mMuted;
+ }
+ }
/**
* Checks if the call is muted.
*
* @return true if the call is muted
*/
- boolean isMuted();
+ public synchronized boolean isMuted() {
+ return mMuted;
+ }
+
+ /** Puts the device to speaker mode. */
+ public synchronized void setSpeakerMode(boolean speakerMode) {
+ ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
+ .setSpeakerphoneOn(speakerMode);
+ }
/**
- * Sends a DTMF code.
+ * Sends a DTMF code. According to RFC2833, event 0--9 maps to decimal
+ * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event
+ * flash to 16. Currently, event flash is not supported.
*
- * @param code the DTMF code to send
+ * @param code the DTMF code to send. Value 0 to 15 (inclusive) are valid
+ * inputs.
+ * @see http://tools.ietf.org/html/rfc2833
*/
- void sendDtmf(int code);
+ public void sendDtmf(int code) {
+ sendDtmf(code, null);
+ }
/**
- * Sends a DTMF code.
+ * Sends a DTMF code. According to RFC2833, event 0--9 maps to decimal
+ * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event
+ * flash to 16. Currently, event flash is not supported.
*
- * @param code the DTMF code to send
+ * @param code the DTMF code to send. Value 0 to 15 (inclusive) are valid
+ * inputs.
* @param result the result message to send when done
*/
- void sendDtmf(int code, Message result);
+ public synchronized void sendDtmf(int code, Message result) {
+ AudioGroup audioGroup = getAudioGroup();
+ if ((audioGroup != null) && (mSipSession != null)
+ && (SipSession.State.IN_CALL == getState())) {
+ Log.v(TAG, "send DTMF: " + code);
+ audioGroup.sendDtmf(code);
+ }
+ if (result != null) result.sendToTarget();
+ }
/**
* Gets the {@link AudioStream} object used in this call. The object
@@ -268,8 +810,11 @@ public interface SipAudioCall {
*
* @return the {@link AudioStream} object or null if the RTP stream has not
* yet been set up
+ * @hide
*/
- AudioStream getAudioStream();
+ public synchronized AudioStream getAudioStream() {
+ return mAudioStream;
+ }
/**
* Gets the {@link AudioGroup} object which the {@link AudioStream} object
@@ -283,8 +828,12 @@ public interface SipAudioCall {
* @return the {@link AudioGroup} object or null if the RTP stream has not
* yet been set up
* @see #getAudioStream
+ * @hide
*/
- AudioGroup getAudioGroup();
+ public synchronized AudioGroup getAudioGroup() {
+ if (mAudioGroup != null) return mAudioGroup;
+ return ((mAudioStream == null) ? null : mAudioStream.getGroup());
+ }
/**
* Sets the {@link AudioGroup} object which the {@link AudioStream} object
@@ -292,56 +841,214 @@ public interface SipAudioCall {
* will be dynamically created when needed.
*
* @see #getAudioStream
+ * @hide
*/
- void setAudioGroup(AudioGroup audioGroup);
+ public synchronized void setAudioGroup(AudioGroup group) {
+ if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
+ mAudioStream.join(group);
+ }
+ mAudioGroup = group;
+ }
/**
- * Checks if the call is established.
- *
- * @return true if the call is established
+ * Starts the audio for the established call. This method should be called
+ * after {@link Listener#onCallEstablished} is called.
*/
- boolean isInCall();
+ public void startAudio() {
+ try {
+ startAudioInternal();
+ } catch (UnknownHostException e) {
+ onError(SipErrorCode.PEER_NOT_REACHABLE, e.getMessage());
+ } catch (Throwable e) {
+ onError(SipErrorCode.CLIENT_ERROR, e.getMessage());
+ }
+ }
- /**
- * Gets the local SIP profile.
- *
- * @return the local SIP profile
- */
- SipProfile getLocalProfile();
+ private synchronized void startAudioInternal() throws UnknownHostException {
+ if (mPeerSd == null) {
+ Log.v(TAG, "startAudioInternal() mPeerSd = null");
+ throw new IllegalStateException("mPeerSd = null");
+ }
- /**
- * Gets the peer's SIP profile.
- *
- * @return the peer's SIP profile
- */
- SipProfile getPeerProfile();
+ stopCall(DONT_RELEASE_SOCKET);
+ mInCall = true;
- /**
- * Gets the state of the {@link ISipSession} that carries this call.
- * The value returned must be one of the states in {@link SipSessionState}.
- *
- * @return the session state
- */
- int getState();
+ // 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;
+ }
+ }
+
+ 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());
+
+ 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);
+ }
+ }
+
+ // 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 (isWifiOn()) grabWifiHighPerfLock();
+
+ if (!mHold) {
+ /* 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.
+ */
+ ((AudioManager) mContext.getSystemService
+ (Context.AUDIO_SERVICE))
+ .setMode(AudioManager.MODE_NORMAL);
+ }
+
+ // AudioGroup logic:
+ AudioGroup audioGroup = getAudioGroup();
+ if (mHold) {
+ if (audioGroup != null) {
+ audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
+ }
+ // don't create an AudioGroup here; doing so will fail if
+ // there's another AudioGroup out there that's active
+ } else {
+ if (audioGroup == null) audioGroup = new AudioGroup();
+ stream.join(audioGroup);
+ if (mMuted) {
+ audioGroup.setMode(AudioGroup.MODE_MUTED);
+ } else {
+ audioGroup.setMode(AudioGroup.MODE_NORMAL);
+ }
+ }
+ }
+
+ private void stopCall(boolean releaseSocket) {
+ Log.d(TAG, "stop audiocall");
+ releaseWifiHighPerfLock();
+ if (mAudioStream != null) {
+ mAudioStream.join(null);
+
+ if (releaseSocket) {
+ mAudioStream.release();
+ mAudioStream = null;
+ }
+ }
+ }
+
+ private String getLocalIp() {
+ return mSipSession.getLocalIp();
+ }
- /**
- * Gets the {@link ISipSession} that carries this call.
- *
- * @return the session object that carries this call
- */
- ISipSession getSipSession();
/**
* Enables/disables the ring-back tone.
*
* @param enabled true to enable; false to disable
*/
- void setRingbackToneEnabled(boolean enabled);
+ public synchronized void setRingbackToneEnabled(boolean enabled) {
+ mRingbackToneEnabled = enabled;
+ }
/**
* Enables/disables the ring tone.
*
* @param enabled true to enable; false to disable
*/
- void setRingtoneEnabled(boolean enabled);
+ public synchronized void setRingtoneEnabled(boolean enabled) {
+ mRingtoneEnabled = enabled;
+ }
+
+ private void startRingbackTone() {
+ if (!mRingbackToneEnabled) return;
+ if (mRingbackTone == null) {
+ // The volume relative to other sounds in the stream
+ int toneVolume = 80;
+ mRingbackTone = new ToneGenerator(
+ AudioManager.STREAM_VOICE_CALL, toneVolume);
+ }
+ mRingbackTone.startTone(ToneGenerator.TONE_CDMA_LOW_PBX_L);
+ }
+
+ private void stopRingbackTone() {
+ if (mRingbackTone != null) {
+ mRingbackTone.stopTone();
+ mRingbackTone.release();
+ mRingbackTone = null;
+ }
+ }
+
+ private void startRinging() {
+ if (!mRingtoneEnabled) return;
+ ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
+ .vibrate(new long[] {0, 1000, 1000}, 1);
+ AudioManager am = (AudioManager)
+ mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (am.getStreamVolume(AudioManager.STREAM_RING) > 0) {
+ String ringtoneUri =
+ Settings.System.DEFAULT_RINGTONE_URI.toString();
+ mRingtone = RingtoneManager.getRingtone(mContext,
+ Uri.parse(ringtoneUri));
+ mRingtone.play();
+ }
+ }
+
+ private void stopRinging() {
+ ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
+ .cancel();
+ if (mRingtone != null) mRingtone.stop();
+ }
+
+ private void throwSipException(Throwable throwable) throws SipException {
+ if (throwable instanceof SipException) {
+ throw (SipException) throwable;
+ } else {
+ throw new SipException("", throwable);
+ }
+ }
+
+ private SipProfile getPeerProfile(SipSession session) {
+ return session.getPeerProfile();
+ }
}
diff --git a/voip/java/android/net/sip/SipAudioCallImpl.java b/voip/java/android/net/sip/SipAudioCallImpl.java
deleted file mode 100644
index 5eecc05..0000000
--- a/voip/java/android/net/sip/SipAudioCallImpl.java
+++ /dev/null
@@ -1,738 +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.net.sip;
-
-import android.content.Context;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.media.ToneGenerator;
-import android.net.Uri;
-import android.net.rtp.AudioCodec;
-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;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Class that handles an audio call over SIP.
- */
-/** @hide */
-public class SipAudioCallImpl extends SipSessionAdapter
- implements SipAudioCall {
- 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 int SESSION_TIMEOUT = 5; // in seconds
-
- private Context mContext;
- private SipProfile mLocalProfile;
- private SipAudioCall.Listener mListener;
- private ISipSession mSipSession;
-
- private long mSessionId = System.currentTimeMillis();
- private String mPeerSd;
-
- private AudioStream mAudioStream;
- private AudioGroup mAudioGroup;
-
- private boolean mInCall = false;
- private boolean mMuted = false;
- private boolean mHold = false;
-
- private boolean mRingbackToneEnabled = true;
- private boolean mRingtoneEnabled = true;
- private Ringtone mRingtone;
- private ToneGenerator mRingbackTone;
-
- private SipProfile mPendingCallRequest;
-
- private int mErrorCode = SipErrorCode.NO_ERROR;
- private String mErrorMessage;
-
- public SipAudioCallImpl(Context context, SipProfile localProfile) {
- mContext = context;
- mLocalProfile = localProfile;
- }
-
- public void setListener(SipAudioCall.Listener listener) {
- setListener(listener, false);
- }
-
- public void setListener(SipAudioCall.Listener listener,
- boolean callbackImmediately) {
- mListener = listener;
- try {
- if ((listener == null) || !callbackImmediately) {
- // do nothing
- } else if (mErrorCode != SipErrorCode.NO_ERROR) {
- listener.onError(this, mErrorCode, mErrorMessage);
- } else if (mInCall) {
- if (mHold) {
- listener.onCallHeld(this);
- } else {
- listener.onCallEstablished(this);
- }
- } else {
- int state = getState();
- switch (state) {
- case SipSessionState.READY_TO_CALL:
- listener.onReadyToCall(this);
- break;
- case SipSessionState.INCOMING_CALL:
- listener.onRinging(this, getPeerProfile(mSipSession));
- break;
- case SipSessionState.OUTGOING_CALL:
- listener.onCalling(this);
- break;
- case SipSessionState.OUTGOING_CALL_RING_BACK:
- listener.onRingingBack(this);
- break;
- }
- }
- } catch (Throwable t) {
- Log.e(TAG, "setListener()", t);
- }
- }
-
- public synchronized boolean isInCall() {
- return mInCall;
- }
-
- public synchronized boolean isOnHold() {
- return mHold;
- }
-
- public void close() {
- close(true);
- }
-
- private synchronized void close(boolean closeRtp) {
- if (closeRtp) stopCall(RELEASE_SOCKET);
- stopRingbackTone();
- stopRinging();
-
- mInCall = false;
- mHold = false;
- mSessionId = System.currentTimeMillis();
- mErrorCode = SipErrorCode.NO_ERROR;
- mErrorMessage = null;
-
- if (mSipSession != null) {
- try {
- mSipSession.setListener(null);
- } catch (RemoteException e) {
- // don't care
- }
- mSipSession = null;
- }
- }
-
- public synchronized SipProfile getLocalProfile() {
- return mLocalProfile;
- }
-
- public synchronized SipProfile getPeerProfile() {
- try {
- return (mSipSession == null) ? null : mSipSession.getPeerProfile();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- public synchronized int getState() {
- if (mSipSession == null) return SipSessionState.READY_TO_CALL;
- try {
- return mSipSession.getState();
- } catch (RemoteException e) {
- return SipSessionState.REMOTE_ERROR;
- }
- }
-
-
- public synchronized ISipSession getSipSession() {
- return mSipSession;
- }
-
- @Override
- public void onCalling(ISipSession session) {
- Log.d(TAG, "calling... " + session);
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onCalling(this);
- } catch (Throwable t) {
- Log.e(TAG, "onCalling()", t);
- }
- }
- }
-
- @Override
- public void onRingingBack(ISipSession session) {
- Log.d(TAG, "sip call ringing back: " + session);
- if (!mInCall) startRingbackTone();
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onRingingBack(this);
- } catch (Throwable t) {
- Log.e(TAG, "onRingingBack()", t);
- }
- }
- }
-
- @Override
- public synchronized void onRinging(ISipSession session,
- SipProfile peerProfile, String sessionDescription) {
- try {
- if ((mSipSession == null) || !mInCall
- || !session.getCallId().equals(mSipSession.getCallId())) {
- // should not happen
- session.endCall();
- return;
- }
-
- // session changing request
- try {
- String answer = createAnswer(sessionDescription).encode();
- mSipSession.answerCall(answer, SESSION_TIMEOUT);
- } catch (Throwable e) {
- Log.e(TAG, "onRinging()", e);
- session.endCall();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "onRinging()", e);
- }
- }
-
- @Override
- public void onCallEstablished(ISipSession session,
- String sessionDescription) {
- stopRingbackTone();
- stopRinging();
- mPeerSd = sessionDescription;
- Log.v(TAG, "onCallEstablished()" + mPeerSd);
-
- Listener listener = mListener;
- if (listener != null) {
- try {
- if (mHold) {
- listener.onCallHeld(this);
- } else {
- listener.onCallEstablished(this);
- }
- } catch (Throwable t) {
- Log.e(TAG, "onCallEstablished()", t);
- }
- }
- }
-
- @Override
- public void onCallEnded(ISipSession session) {
- Log.d(TAG, "sip call ended: " + session);
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onCallEnded(this);
- } catch (Throwable t) {
- Log.e(TAG, "onCallEnded()", t);
- }
- }
- close();
- }
-
- @Override
- public void onCallBusy(ISipSession session) {
- Log.d(TAG, "sip call busy: " + session);
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onCallBusy(this);
- } catch (Throwable t) {
- Log.e(TAG, "onCallBusy()", t);
- }
- }
- close(false);
- }
-
- @Override
- public void onCallChangeFailed(ISipSession session, int errorCode,
- String message) {
- Log.d(TAG, "sip call change failed: " + message);
- mErrorCode = errorCode;
- mErrorMessage = message;
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onError(this, mErrorCode, message);
- } catch (Throwable t) {
- Log.e(TAG, "onCallBusy()", t);
- }
- }
- }
-
- @Override
- public void onError(ISipSession session, int errorCode, String message) {
- Log.d(TAG, "sip session error: " + SipErrorCode.toString(errorCode)
- + ": " + message);
- mErrorCode = errorCode;
- mErrorMessage = message;
- Listener listener = mListener;
- if (listener != null) {
- try {
- listener.onError(this, errorCode, message);
- } catch (Throwable t) {
- Log.e(TAG, "onError()", t);
- }
- }
- synchronized (this) {
- if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
- || !isInCall()) {
- close(true);
- }
- }
- }
-
- public synchronized void attachCall(ISipSession session,
- String sessionDescription) throws SipException {
- mSipSession = session;
- mPeerSd = sessionDescription;
- Log.v(TAG, "attachCall()" + mPeerSd);
- try {
- session.setListener(this);
- if (getState() == SipSessionState.INCOMING_CALL) startRinging();
- } catch (Throwable e) {
- Log.e(TAG, "attachCall()", e);
- throwSipException(e);
- }
- }
-
- public synchronized void makeCall(SipProfile peerProfile,
- SipManager sipManager, int timeout) throws SipException {
- try {
- mSipSession = sipManager.createSipSession(mLocalProfile, this);
- if (mSipSession == null) {
- throw new SipException(
- "Failed to create SipSession; network available?");
- }
- mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp()));
- mSipSession.makeCall(peerProfile, createOffer().encode(), timeout);
- } catch (Throwable e) {
- if (e instanceof SipException) {
- throw (SipException) e;
- } else {
- throwSipException(e);
- }
- }
- }
-
- public synchronized void endCall() throws SipException {
- try {
- stopRinging();
- stopCall(RELEASE_SOCKET);
- mInCall = false;
-
- // perform the above local ops first and then network op
- if (mSipSession != null) mSipSession.endCall();
- } catch (Throwable e) {
- throwSipException(e);
- }
- }
-
- public synchronized void answerCall(int timeout) throws SipException {
- try {
- stopRinging();
- 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 holdCall(int timeout) throws SipException {
- if (mHold) return;
- try {
- 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 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 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);
-
- // 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));
- }
- }
-
- // 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;
- }
- }
- // Reject the media.
- Media reply = answer.newMedia(
- media.getType(), 0, 1, media.getProtocol());
- for (String format : media.getFormats()) {
- reply.setFormat(format, null);
- }
- }
- 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() {
- AudioGroup audioGroup = getAudioGroup();
- if (audioGroup != null) {
- audioGroup.setMode(
- mMuted ? AudioGroup.MODE_NORMAL : AudioGroup.MODE_MUTED);
- mMuted = !mMuted;
- }
- }
-
- public synchronized boolean isMuted() {
- return mMuted;
- }
-
- public synchronized void setSpeakerMode(boolean speakerMode) {
- ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
- .setSpeakerphoneOn(speakerMode);
- }
-
- public void sendDtmf(int code) {
- sendDtmf(code, null);
- }
-
- public synchronized void sendDtmf(int code, Message result) {
- AudioGroup audioGroup = getAudioGroup();
- if ((audioGroup != null) && (mSipSession != null)
- && (SipSessionState.IN_CALL == getState())) {
- Log.v(TAG, "send DTMF: " + code);
- audioGroup.sendDtmf(code);
- }
- if (result != null) result.sendToTarget();
- }
-
- public synchronized AudioStream getAudioStream() {
- return mAudioStream;
- }
-
- public synchronized AudioGroup getAudioGroup() {
- if (mAudioGroup != null) return mAudioGroup;
- return ((mAudioStream == null) ? null : mAudioStream.getGroup());
- }
-
- public synchronized void setAudioGroup(AudioGroup group) {
- if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) {
- mAudioStream.join(group);
- }
- mAudioGroup = group;
- }
-
- public void startAudio() {
- try {
- startAudioInternal();
- } catch (UnknownHostException e) {
- onError(mSipSession, SipErrorCode.PEER_NOT_REACHABLE,
- e.getMessage());
- } catch (Throwable e) {
- onError(mSipSession, SipErrorCode.CLIENT_ERROR,
- e.getMessage());
- }
- }
-
- 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;
-
- // 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;
- }
- }
-
- 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());
-
- 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);
- }
- }
-
- // 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) {
- /* 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.
- */
- ((AudioManager) mContext.getSystemService
- (Context.AUDIO_SERVICE))
- .setMode(AudioManager.MODE_NORMAL);
- }
-
- // AudioGroup logic:
- AudioGroup audioGroup = getAudioGroup();
- if (mHold) {
- if (audioGroup != null) {
- audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
- }
- // don't create an AudioGroup here; doing so will fail if
- // there's another AudioGroup out there that's active
- } else {
- if (audioGroup == null) audioGroup = new AudioGroup();
- mAudioStream.join(audioGroup);
- if (mMuted) {
- audioGroup.setMode(AudioGroup.MODE_MUTED);
- } else {
- audioGroup.setMode(AudioGroup.MODE_NORMAL);
- }
- }
- }
-
- private void stopCall(boolean releaseSocket) {
- Log.d(TAG, "stop audiocall");
- if (mAudioStream != null) {
- mAudioStream.join(null);
-
- if (releaseSocket) {
- mAudioStream.release();
- mAudioStream = null;
- }
- }
- }
-
- private String getLocalIp() {
- try {
- return mSipSession.getLocalIp();
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
- }
-
- public synchronized void setRingbackToneEnabled(boolean enabled) {
- mRingbackToneEnabled = enabled;
- }
-
- public synchronized void setRingtoneEnabled(boolean enabled) {
- mRingtoneEnabled = enabled;
- }
-
- private void startRingbackTone() {
- if (!mRingbackToneEnabled) return;
- if (mRingbackTone == null) {
- // The volume relative to other sounds in the stream
- int toneVolume = 80;
- mRingbackTone = new ToneGenerator(
- AudioManager.STREAM_VOICE_CALL, toneVolume);
- }
- mRingbackTone.startTone(ToneGenerator.TONE_CDMA_LOW_PBX_L);
- }
-
- private void stopRingbackTone() {
- if (mRingbackTone != null) {
- mRingbackTone.stopTone();
- mRingbackTone.release();
- mRingbackTone = null;
- }
- }
-
- private void startRinging() {
- if (!mRingtoneEnabled) return;
- ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
- .vibrate(new long[] {0, 1000, 1000}, 1);
- AudioManager am = (AudioManager)
- mContext.getSystemService(Context.AUDIO_SERVICE);
- if (am.getStreamVolume(AudioManager.STREAM_RING) > 0) {
- String ringtoneUri =
- Settings.System.DEFAULT_RINGTONE_URI.toString();
- mRingtone = RingtoneManager.getRingtone(mContext,
- Uri.parse(ringtoneUri));
- mRingtone.play();
- }
- }
-
- private void stopRinging() {
- ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
- .cancel();
- if (mRingtone != null) mRingtone.stop();
- }
-
- private void throwSipException(Throwable throwable) throws SipException {
- if (throwable instanceof SipException) {
- throw (SipException) throwable;
- } else {
- throw new SipException("", throwable);
- }
- }
-
- private SipProfile getPeerProfile(ISipSession session) {
- try {
- return session.getPeerProfile();
- } catch (RemoteException e) {
- return null;
- }
- }
-}
diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java
index 31768d7..5976a04 100644
--- a/voip/java/android/net/sip/SipManager.java
+++ b/voip/java/android/net/sip/SipManager.java
@@ -30,8 +30,9 @@ import java.text.ParseException;
* The class provides API for various SIP related tasks. Specifically, the API
* allows an application to:
* <ul>
- * <li>register a {@link SipProfile} to have the background SIP service listen
- * to incoming calls and broadcast them with registered command string. See
+ * <li>open a {@link SipProfile} to get ready for making outbound calls or have
+ * the background SIP service listen to incoming calls and broadcast them
+ * with registered command string. See
* {@link #open(SipProfile, String, SipRegistrationListener)},
* {@link #open(SipProfile)}, {@link #close}, {@link #isOpened} and
* {@link #isRegistered}. It also facilitates handling of the incoming call
@@ -40,39 +41,59 @@ import java.text.ParseException;
* {@link #getOfferSessionDescription} and {@link #takeAudioCall}.</li>
* <li>make/take SIP-based audio calls. See
* {@link #makeAudioCall} and {@link #takeAudioCall}.</li>
- * <li>register/unregister with a SIP service provider. See
+ * <li>register/unregister with a SIP service provider manually. See
* {@link #register} and {@link #unregister}.</li>
- * <li>process SIP events directly with a {@link ISipSession} created by
+ * <li>process SIP events directly with a {@link SipSession} created by
* {@link #createSipSession}.</li>
* </ul>
* @hide
*/
public class SipManager {
- /** @hide */
- public static final String SIP_INCOMING_CALL_ACTION =
+ /**
+ * Action string for the incoming call intent for the Phone app.
+ * Internal use only.
+ * @hide
+ */
+ public static final String ACTION_SIP_INCOMING_CALL =
"com.android.phone.SIP_INCOMING_CALL";
- /** @hide */
- public static final String SIP_ADD_PHONE_ACTION =
+ /**
+ * Action string for the add-phone intent.
+ * Internal use only.
+ * @hide
+ */
+ public static final String ACTION_SIP_ADD_PHONE =
"com.android.phone.SIP_ADD_PHONE";
- /** @hide */
- public static final String SIP_REMOVE_PHONE_ACTION =
+ /**
+ * Action string for the remove-phone intent.
+ * Internal use only.
+ * @hide
+ */
+ public static final String ACTION_SIP_REMOVE_PHONE =
"com.android.phone.SIP_REMOVE_PHONE";
- /** @hide */
- public static final String LOCAL_URI_KEY = "LOCAL SIPURI";
+ /**
+ * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents.
+ * Internal use only.
+ * @hide
+ */
+ public static final String EXTRA_LOCAL_URI = "android:localSipUri";
- private static final String CALL_ID_KEY = "CallID";
- private static final String OFFER_SD_KEY = "OfferSD";
+ /** Part of the incoming call intent. */
+ public static final String EXTRA_CALL_ID = "android:sipCallID";
+
+ /** Part of the incoming call intent. */
+ public static final String EXTRA_OFFER_SD = "android:sipOfferSD";
private ISipService mSipService;
+ private Context mContext;
/**
- * Gets a manager instance. Returns null if SIP API is not supported.
+ * Creates a manager instance. Returns null if SIP API is not supported.
*
- * @param context application context for checking if SIP API is supported
+ * @param context application context for creating the manager object
* @return the manager instance or null if SIP API is not supported
*/
- public static SipManager getInstance(Context context) {
- return (isApiSupported(context) ? new SipManager() : null);
+ public static SipManager newInstance(Context context) {
+ return (isApiSupported(context) ? new SipManager(context) : null);
}
/**
@@ -80,7 +101,7 @@ public class SipManager {
*/
public static boolean isApiSupported(Context context) {
return true;
- /*
+ /* TODO: uncomment this before ship
return context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SIP);
*/
@@ -91,7 +112,7 @@ public class SipManager {
*/
public static boolean isVoipSupported(Context context) {
return true;
- /*
+ /* TODO: uncomment this before ship
return context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context);
*/
@@ -105,23 +126,21 @@ public class SipManager {
com.android.internal.R.bool.config_sip_wifi_only);
}
- private SipManager() {
+ private SipManager(Context context) {
+ mContext = context;
createSipService();
}
private void createSipService() {
- if (mSipService != null) return;
IBinder b = ServiceManager.getService(Context.SIP_SERVICE);
mSipService = ISipService.Stub.asInterface(b);
}
/**
- * Opens the profile for making calls and/or receiving calls. Subsequent
- * SIP calls can be made through the default phone UI. The caller may also
- * make subsequent calls through {@link #makeAudioCall}.
- * If the receiving-call option is enabled in the profile, the SIP service
- * will register the profile to the corresponding server periodically in
- * order to receive calls from the server.
+ * Opens the profile for making calls. The caller may make subsequent calls
+ * through {@link #makeAudioCall}. If one also wants to receive calls on the
+ * profile, use {@link #open(SipProfile, String, SipRegistrationListener)}
+ * instead.
*
* @param localProfile the SIP profile to make calls from
* @throws SipException if the profile contains incorrect settings or
@@ -136,12 +155,11 @@ public class SipManager {
}
/**
- * Opens the profile for making calls and/or receiving calls. Subsequent
- * SIP calls can be made through the default phone UI. The caller may also
- * make subsequent calls through {@link #makeAudioCall}.
- * If the receiving-call option is enabled in the profile, the SIP service
- * will register the profile to the corresponding server periodically in
- * order to receive calls from the server.
+ * Opens the profile for making calls and/or receiving calls. The caller may
+ * make subsequent calls through {@link #makeAudioCall}. If the
+ * auto-registration option is enabled in the profile, the SIP service
+ * will register the profile to the corresponding SIP provider periodically
+ * in order to receive calls from the provider.
*
* @param localProfile the SIP profile to receive incoming calls for
* @param incomingCallBroadcastAction the action to be broadcast when an
@@ -195,7 +213,8 @@ public class SipManager {
}
/**
- * Checks if the specified profile is enabled to receive calls.
+ * Checks if the specified profile is opened in the SIP service for
+ * making and/or receiving calls.
*
* @param localProfileUri the URI of the profile in question
* @return true if the profile is enabled to receive calls
@@ -210,11 +229,16 @@ public class SipManager {
}
/**
- * Checks if the specified profile is registered to the server for
- * receiving calls.
+ * Checks if the SIP service has successfully registered the profile to the
+ * SIP provider (specified in the profile) for receiving calls. Returning
+ * true from this method also implies the profile is opened
+ * ({@link #isOpened}).
*
* @param localProfileUri the URI of the profile in question
- * @return true if the profile is registered to the server
+ * @return true if the profile is registered to the SIP provider; false if
+ * the profile has not been opened in the SIP service or the SIP
+ * service has not yet successfully registered the profile to the SIP
+ * provider
* @throws SipException if calling the SIP service results in an error
*/
public boolean isRegistered(String localProfileUri) throws SipException {
@@ -231,7 +255,6 @@ public class SipManager {
* {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
* will be called.
*
- * @param context context to create a {@link SipAudioCall} object
* @param localProfile the SIP profile to make the call from
* @param peerProfile the SIP profile to make the call to
* @param listener to listen to the call events from {@link SipAudioCall};
@@ -241,10 +264,10 @@ public class SipManager {
* @throws SipException if calling the SIP service results in an error
* @see SipAudioCall.Listener.onError
*/
- public SipAudioCall makeAudioCall(Context context, SipProfile localProfile,
+ public SipAudioCall makeAudioCall(SipProfile localProfile,
SipProfile peerProfile, SipAudioCall.Listener listener, int timeout)
throws SipException {
- SipAudioCall call = new SipAudioCallImpl(context, localProfile);
+ SipAudioCall call = new SipAudioCall(mContext, localProfile);
call.setListener(listener);
call.makeCall(peerProfile, this, timeout);
return call;
@@ -257,7 +280,6 @@ public class SipManager {
* {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
* will be called.
*
- * @param context context to create a {@link SipAudioCall} object
* @param localProfileUri URI of the SIP profile to make the call from
* @param peerProfileUri URI of the SIP profile to make the call to
* @param listener to listen to the call events from {@link SipAudioCall};
@@ -267,11 +289,11 @@ public class SipManager {
* @throws SipException if calling the SIP service results in an error
* @see SipAudioCall.Listener.onError
*/
- public SipAudioCall makeAudioCall(Context context, String localProfileUri,
+ public SipAudioCall makeAudioCall(String localProfileUri,
String peerProfileUri, SipAudioCall.Listener listener, int timeout)
throws SipException {
try {
- return makeAudioCall(context,
+ return makeAudioCall(
new SipProfile.Builder(localProfileUri).build(),
new SipProfile.Builder(peerProfileUri).build(), listener,
timeout);
@@ -281,15 +303,14 @@ public class SipManager {
}
/**
- * The method calls {@code takeAudioCall(context, incomingCallIntent,
+ * The method calls {@code takeAudioCall(incomingCallIntent,
* listener, true}.
*
- * @see #takeAudioCall(Context, Intent, SipAudioCall.Listener, boolean)
+ * @see #takeAudioCall(Intent, SipAudioCall.Listener, boolean)
*/
- public SipAudioCall takeAudioCall(Context context,
- Intent incomingCallIntent, SipAudioCall.Listener listener)
- throws SipException {
- return takeAudioCall(context, incomingCallIntent, listener, true);
+ public SipAudioCall takeAudioCall(Intent incomingCallIntent,
+ SipAudioCall.Listener listener) throws SipException {
+ return takeAudioCall(incomingCallIntent, listener, true);
}
/**
@@ -298,16 +319,15 @@ public class SipManager {
* {@link SipAudioCall.Listener#onRinging}
* callback.
*
- * @param context context to create a {@link SipAudioCall} object
* @param incomingCallIntent the incoming call broadcast intent
* @param listener to listen to the call events from {@link SipAudioCall};
* can be null
* @return a {@link SipAudioCall} object
* @throws SipException if calling the SIP service results in an error
*/
- public SipAudioCall takeAudioCall(Context context,
- Intent incomingCallIntent, SipAudioCall.Listener listener,
- boolean ringtoneEnabled) throws SipException {
+ public SipAudioCall takeAudioCall(Intent incomingCallIntent,
+ SipAudioCall.Listener listener, boolean ringtoneEnabled)
+ throws SipException {
if (incomingCallIntent == null) return null;
String callId = getCallId(incomingCallIntent);
@@ -324,10 +344,10 @@ public class SipManager {
try {
ISipSession session = mSipService.getPendingSession(callId);
if (session == null) return null;
- SipAudioCall call = new SipAudioCallImpl(
- context, session.getLocalProfile());
+ SipAudioCall call = new SipAudioCall(
+ mContext, session.getLocalProfile());
call.setRingtoneEnabled(ringtoneEnabled);
- call.attachCall(session, offerSd);
+ call.attachCall(new SipSession(session), offerSd);
call.setListener(listener);
return call;
} catch (Throwable t) {
@@ -355,7 +375,7 @@ public class SipManager {
* @return the call ID or null if the intent does not contain it
*/
public static String getCallId(Intent incomingCallIntent) {
- return incomingCallIntent.getStringExtra(CALL_ID_KEY);
+ return incomingCallIntent.getStringExtra(EXTRA_CALL_ID);
}
/**
@@ -367,30 +387,30 @@ public class SipManager {
* have it
*/
public static String getOfferSessionDescription(Intent incomingCallIntent) {
- return incomingCallIntent.getStringExtra(OFFER_SD_KEY);
+ return incomingCallIntent.getStringExtra(EXTRA_OFFER_SD);
}
/**
* Creates an incoming call broadcast intent.
*
- * @param action the action string to broadcast
* @param callId the call ID of the incoming call
* @param sessionDescription the session description of the incoming call
* @return the incoming call intent
* @hide
*/
- public static Intent createIncomingCallBroadcast(String action,
- String callId, String sessionDescription) {
- Intent intent = new Intent(action);
- intent.putExtra(CALL_ID_KEY, callId);
- intent.putExtra(OFFER_SD_KEY, sessionDescription);
+ public static Intent createIncomingCallBroadcast(String callId,
+ String sessionDescription) {
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_CALL_ID, callId);
+ intent.putExtra(EXTRA_OFFER_SD, sessionDescription);
return intent;
}
/**
- * Registers the profile to the corresponding server for receiving calls.
- * {@link #open} is still needed to be called at least once in order for
- * the SIP service to broadcast an intent when an incoming call is received.
+ * Manually registers the profile to the corresponding SIP provider for
+ * receiving calls. {@link #open(SipProfile, String, SipRegistrationListener)}
+ * is still needed to be called at least once in order for the SIP service
+ * to broadcast an intent when an incoming call is received.
*
* @param localProfile the SIP profile to register with
* @param expiryTime registration expiration time (in seconds)
@@ -409,8 +429,10 @@ public class SipManager {
}
/**
- * Unregisters the profile from the corresponding server for not receiving
- * further calls.
+ * Manually unregisters the profile from the corresponding SIP provider for
+ * stop receiving further calls. This may interference with the auto
+ * registration process in the SIP service if the auto-registration option
+ * in the profile is enabled.
*
* @param localProfile the SIP profile to register with
* @param listener to listen to the registration events
@@ -460,10 +482,11 @@ public class SipManager {
* @param localProfile the SIP profile the session is associated with
* @param listener to listen to SIP session events
*/
- public ISipSession createSipSession(SipProfile localProfile,
- ISipSessionListener listener) throws SipException {
+ public SipSession createSipSession(SipProfile localProfile,
+ SipSession.Listener listener) throws SipException {
try {
- return mSipService.createSession(localProfile, listener);
+ ISipSession s = mSipService.createSession(localProfile, null);
+ return new SipSession(s, listener);
} catch (RemoteException e) {
throw new SipException("createSipSession()", e);
}
diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java
index 88bfba9..6d5cb3c 100644
--- a/voip/java/android/net/sip/SipProfile.java
+++ b/voip/java/android/net/sip/SipProfile.java
@@ -48,7 +48,6 @@ public class SipProfile implements Parcelable, Serializable, Cloneable {
private boolean mAutoRegistration = true;
private transient int mCallingUid = 0;
- /** @hide */
public static final Parcelable.Creator<SipProfile> CREATOR =
new Parcelable.Creator<SipProfile>() {
public SipProfile createFromParcel(Parcel in) {
@@ -287,7 +286,7 @@ public class SipProfile implements Parcelable, Serializable, Cloneable {
mCallingUid = in.readInt();
}
- /** @hide */
+ @Override
public void writeToParcel(Parcel out, int flags) {
out.writeSerializable(mAddress);
out.writeString(mProxyAddress);
@@ -300,7 +299,7 @@ public class SipProfile implements Parcelable, Serializable, Cloneable {
out.writeInt(mCallingUid);
}
- /** @hide */
+ @Override
public int describeContents() {
return 0;
}
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
new file mode 100644
index 0000000..0cc7206
--- /dev/null
+++ b/voip/java/android/net/sip/SipSession.java
@@ -0,0 +1,531 @@
+/*
+ * 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 android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A SIP session that is associated with a SIP dialog or a standalone
+ * transaction not within a dialog.
+ * @hide
+ */
+public final class SipSession {
+ private static final String TAG = "SipSession";
+
+ /**
+ * Defines {@link SipSession} states.
+ * @hide
+ */
+ public static class State {
+ /** When session is ready to initiate a call or transaction. */
+ public static final int READY_TO_CALL = 0;
+
+ /** When the registration request is sent out. */
+ public static final int REGISTERING = 1;
+
+ /** When the unregistration request is sent out. */
+ public static final int DEREGISTERING = 2;
+
+ /** When an INVITE request is received. */
+ public static final int INCOMING_CALL = 3;
+
+ /** When an OK response is sent for the INVITE request received. */
+ public static final int INCOMING_CALL_ANSWERING = 4;
+
+ /** When an INVITE request is sent. */
+ public static final int OUTGOING_CALL = 5;
+
+ /** When a RINGING response is received for the INVITE request sent. */
+ public static final int OUTGOING_CALL_RING_BACK = 6;
+
+ /** When a CANCEL request is sent for the INVITE request sent. */
+ public static final int OUTGOING_CALL_CANCELING = 7;
+
+ /** When a call is established. */
+ public static final int IN_CALL = 8;
+
+ /** When an OPTIONS request is sent. */
+ public static final int PINGING = 9;
+
+ /** Not defined. */
+ public static final int NOT_DEFINED = 101;
+
+ /**
+ * Converts the state to string.
+ */
+ public static String toString(int state) {
+ switch (state) {
+ case READY_TO_CALL:
+ return "READY_TO_CALL";
+ case REGISTERING:
+ return "REGISTERING";
+ case DEREGISTERING:
+ return "DEREGISTERING";
+ case INCOMING_CALL:
+ return "INCOMING_CALL";
+ case INCOMING_CALL_ANSWERING:
+ return "INCOMING_CALL_ANSWERING";
+ case OUTGOING_CALL:
+ return "OUTGOING_CALL";
+ case OUTGOING_CALL_RING_BACK:
+ return "OUTGOING_CALL_RING_BACK";
+ case OUTGOING_CALL_CANCELING:
+ return "OUTGOING_CALL_CANCELING";
+ case IN_CALL:
+ return "IN_CALL";
+ case PINGING:
+ return "PINGING";
+ default:
+ return "NOT_DEFINED";
+ }
+ }
+
+ private State() {
+ }
+ }
+
+ /**
+ * Listener class that listens to {@link SipSession} events.
+ * @hide
+ */
+ public static class Listener {
+ /**
+ * Called when an INVITE request is sent to initiate a new call.
+ *
+ * @param session the session object that carries out the transaction
+ */
+ public void onCalling(SipSession session) {
+ }
+
+ /**
+ * Called when an INVITE request is received.
+ *
+ * @param session the session object that carries out the transaction
+ * @param caller the SIP profile of the caller
+ * @param sessionDescription the caller's session description
+ */
+ public void onRinging(SipSession session, SipProfile caller,
+ String sessionDescription) {
+ }
+
+ /**
+ * Called when a RINGING response is received for the INVITE request sent
+ *
+ * @param session the session object that carries out the transaction
+ */
+ public void onRingingBack(SipSession session) {
+ }
+
+ /**
+ * Called when the session is established.
+ *
+ * @param session the session object that is associated with the dialog
+ * @param sessionDescription the peer's session description
+ */
+ public void onCallEstablished(SipSession session,
+ String sessionDescription) {
+ }
+
+ /**
+ * Called when the session is terminated.
+ *
+ * @param session the session object that is associated with the dialog
+ */
+ public void onCallEnded(SipSession session) {
+ }
+
+ /**
+ * Called when the peer is busy during session initialization.
+ *
+ * @param session the session object that carries out the transaction
+ */
+ public void onCallBusy(SipSession session) {
+ }
+
+ /**
+ * Called when an error occurs during session initialization and
+ * termination.
+ *
+ * @param session the session object that carries out the transaction
+ * @param errorCode error code defined in {@link SipErrorCode}
+ * @param errorMessage error message
+ */
+ public void onError(SipSession session, int errorCode,
+ String errorMessage) {
+ }
+
+ /**
+ * Called when an error occurs during session modification negotiation.
+ *
+ * @param session the session object that carries out the transaction
+ * @param errorCode error code defined in {@link SipErrorCode}
+ * @param errorMessage error message
+ */
+ public void onCallChangeFailed(SipSession session, int errorCode,
+ String errorMessage) {
+ }
+
+ /**
+ * Called when a registration request is sent.
+ *
+ * @param session the session object that carries out the transaction
+ */
+ public void onRegistering(SipSession session) {
+ }
+
+ /**
+ * Called when registration is successfully done.
+ *
+ * @param session the session object that carries out the transaction
+ * @param duration duration in second before the registration expires
+ */
+ public void onRegistrationDone(SipSession session, int duration) {
+ }
+
+ /**
+ * Called when the registration fails.
+ *
+ * @param session the session object that carries out the transaction
+ * @param errorCode error code defined in {@link SipErrorCode}
+ * @param errorMessage error message
+ */
+ public void onRegistrationFailed(SipSession session, int errorCode,
+ String errorMessage) {
+ }
+
+ /**
+ * Called when the registration gets timed out.
+ *
+ * @param session the session object that carries out the transaction
+ */
+ public void onRegistrationTimeout(SipSession session) {
+ }
+ }
+
+ private final ISipSession mSession;
+ private Listener mListener;
+
+ SipSession(ISipSession realSession) {
+ mSession = realSession;
+ if (realSession != null) {
+ try {
+ realSession.setListener(createListener());
+ } catch (RemoteException e) {
+ Log.e(TAG, "SipSession.setListener(): " + e);
+ }
+ }
+ }
+
+ SipSession(ISipSession realSession, Listener listener) {
+ this(realSession);
+ setListener(listener);
+ }
+
+ /**
+ * Gets the IP address of the local host on which this SIP session runs.
+ *
+ * @return the IP address of the local host
+ */
+ public String getLocalIp() {
+ try {
+ return mSession.getLocalIp();
+ } catch (RemoteException e) {
+ Log.e(TAG, "getLocalIp(): " + e);
+ return "127.0.0.1";
+ }
+ }
+
+ /**
+ * Gets the SIP profile that this session is associated with.
+ *
+ * @return the SIP profile that this session is associated with
+ */
+ public SipProfile getLocalProfile() {
+ try {
+ return mSession.getLocalProfile();
+ } catch (RemoteException e) {
+ Log.e(TAG, "getLocalProfile(): " + e);
+ return null;
+ }
+ }
+
+ /**
+ * Gets the SIP profile that this session is connected to. Only available
+ * when the session is associated with a SIP dialog.
+ *
+ * @return the SIP profile that this session is connected to
+ */
+ public SipProfile getPeerProfile() {
+ try {
+ return mSession.getPeerProfile();
+ } catch (RemoteException e) {
+ Log.e(TAG, "getPeerProfile(): " + e);
+ return null;
+ }
+ }
+
+ /**
+ * Gets the session state. The value returned must be one of the states in
+ * {@link SipSessionState}.
+ *
+ * @return the session state
+ */
+ public int getState() {
+ try {
+ return mSession.getState();
+ } catch (RemoteException e) {
+ Log.e(TAG, "getState(): " + e);
+ return State.NOT_DEFINED;
+ }
+ }
+
+ /**
+ * Checks if the session is in a call.
+ *
+ * @return true if the session is in a call
+ */
+ public boolean isInCall() {
+ try {
+ return mSession.isInCall();
+ } catch (RemoteException e) {
+ Log.e(TAG, "isInCall(): " + e);
+ return false;
+ }
+ }
+
+ /**
+ * Gets the call ID of the session.
+ *
+ * @return the call ID
+ */
+ public String getCallId() {
+ try {
+ return mSession.getCallId();
+ } catch (RemoteException e) {
+ Log.e(TAG, "getCallId(): " + e);
+ return null;
+ }
+ }
+
+
+ /**
+ * Sets the listener to listen to the session events. A {@code SipSession}
+ * can only hold one listener at a time. Subsequent calls to this method
+ * override the previous listener.
+ *
+ * @param listener to listen to the session events of this object
+ */
+ public void setListener(Listener listener) {
+ mListener = listener;
+ }
+
+
+ /**
+ * Performs registration to the server specified by the associated local
+ * profile. The session listener is called back upon success or failure of
+ * registration. The method is only valid to call when the session state is
+ * in {@link SipSessionState#READY_TO_CALL}.
+ *
+ * @param duration duration in second before the registration expires
+ * @see Listener
+ */
+ public void register(int duration) {
+ try {
+ mSession.register(duration);
+ } catch (RemoteException e) {
+ Log.e(TAG, "register(): " + e);
+ }
+ }
+
+ /**
+ * Performs unregistration to the server specified by the associated local
+ * profile. Unregistration is technically the same as registration with zero
+ * expiration duration. The session listener is called back upon success or
+ * failure of unregistration. The method is only valid to call when the
+ * session state is in {@link SipSessionState#READY_TO_CALL}.
+ *
+ * @see Listener
+ */
+ public void unregister() {
+ try {
+ mSession.unregister();
+ } catch (RemoteException e) {
+ Log.e(TAG, "unregister(): " + e);
+ }
+ }
+
+ /**
+ * Initiates a call to the specified profile. The session listener is called
+ * back upon defined session events. The method is only valid to call when
+ * the session state is in {@link SipSessionState#READY_TO_CALL}.
+ *
+ * @param callee the SIP profile to make the call to
+ * @param sessionDescription the session description of this call
+ * @param timeout the session will be timed out if the call is not
+ * established within {@code timeout} seconds. Default value (defined
+ * by SIP protocol) is used if {@code timeout} is zero or negative.
+ * @see Listener
+ */
+ public void makeCall(SipProfile callee, String sessionDescription,
+ int timeout) {
+ try {
+ mSession.makeCall(callee, sessionDescription, timeout);
+ } catch (RemoteException e) {
+ Log.e(TAG, "makeCall(): " + e);
+ }
+ }
+
+ /**
+ * Answers an incoming call with the specified session description. The
+ * method is only valid to call when the session state is in
+ * {@link SipSessionState#INCOMING_CALL}.
+ *
+ * @param sessionDescription the session description to answer this call
+ * @param timeout the session will be timed out if the call is not
+ * established within {@code timeout} seconds. Default value (defined
+ * by SIP protocol) is used if {@code timeout} is zero or negative.
+ */
+ public void answerCall(String sessionDescription, int timeout) {
+ try {
+ mSession.answerCall(sessionDescription, timeout);
+ } catch (RemoteException e) {
+ Log.e(TAG, "answerCall(): " + e);
+ }
+ }
+
+ /**
+ * Ends an established call, terminates an outgoing call or rejects an
+ * incoming call. The method is only valid to call when the session state is
+ * in {@link SipSessionState#IN_CALL},
+ * {@link SipSessionState#INCOMING_CALL},
+ * {@link SipSessionState#OUTGOING_CALL} or
+ * {@link SipSessionState#OUTGOING_CALL_RING_BACK}.
+ */
+ public void endCall() {
+ try {
+ mSession.endCall();
+ } catch (RemoteException e) {
+ Log.e(TAG, "endCall(): " + e);
+ }
+ }
+
+ /**
+ * Changes the session description during a call. The method is only valid
+ * to call when the session state is in {@link SipSessionState#IN_CALL}.
+ *
+ * @param sessionDescription the new session description
+ * @param timeout the session will be timed out if the call is not
+ * established within {@code timeout} seconds. Default value (defined
+ * by SIP protocol) is used if {@code timeout} is zero or negative.
+ */
+ public void changeCall(String sessionDescription, int timeout) {
+ try {
+ mSession.changeCall(sessionDescription, timeout);
+ } catch (RemoteException e) {
+ Log.e(TAG, "changeCall(): " + e);
+ }
+ }
+
+ ISipSession getRealSession() {
+ return mSession;
+ }
+
+ private ISipSessionListener createListener() {
+ return new ISipSessionListener.Stub() {
+ public void onCalling(ISipSession session) {
+ if (mListener != null) {
+ mListener.onCalling(SipSession.this);
+ }
+ }
+
+ public void onRinging(ISipSession session, SipProfile caller,
+ String sessionDescription) {
+ if (mListener != null) {
+ mListener.onRinging(SipSession.this, caller,
+ sessionDescription);
+ }
+ }
+
+ public void onRingingBack(ISipSession session) {
+ if (mListener != null) {
+ mListener.onRingingBack(SipSession.this);
+ }
+ }
+
+ public void onCallEstablished(ISipSession session,
+ String sessionDescription) {
+ if (mListener != null) {
+ mListener.onCallEstablished(SipSession.this,
+ sessionDescription);
+ }
+ }
+
+ public void onCallEnded(ISipSession session) {
+ if (mListener != null) {
+ mListener.onCallEnded(SipSession.this);
+ }
+ }
+
+ public void onCallBusy(ISipSession session) {
+ if (mListener != null) {
+ mListener.onCallBusy(SipSession.this);
+ }
+ }
+
+ public void onCallChangeFailed(ISipSession session, int errorCode,
+ String message) {
+ if (mListener != null) {
+ mListener.onCallChangeFailed(SipSession.this, errorCode,
+ message);
+ }
+ }
+
+ public void onError(ISipSession session, int errorCode, String message) {
+ if (mListener != null) {
+ mListener.onError(SipSession.this, errorCode, message);
+ }
+ }
+
+ public void onRegistering(ISipSession session) {
+ if (mListener != null) {
+ mListener.onRegistering(SipSession.this);
+ }
+ }
+
+ public void onRegistrationDone(ISipSession session, int duration) {
+ if (mListener != null) {
+ mListener.onRegistrationDone(SipSession.this, duration);
+ }
+ }
+
+ public void onRegistrationFailed(ISipSession session, int errorCode,
+ String message) {
+ if (mListener != null) {
+ mListener.onRegistrationFailed(SipSession.this, errorCode,
+ message);
+ }
+ }
+
+ public void onRegistrationTimeout(ISipSession session) {
+ if (mListener != null) {
+ mListener.onRegistrationTimeout(SipSession.this);
+ }
+ }
+ };
+ }
+}
diff --git a/voip/java/android/net/sip/SipSessionState.java b/voip/java/android/net/sip/SipSessionState.java
deleted file mode 100644
index 31e9d3f..0000000
--- a/voip/java/android/net/sip/SipSessionState.java
+++ /dev/null
@@ -1,94 +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.net.sip;
-
-/**
- * Defines {@link ISipSession} states.
- * @hide
- */
-public class SipSessionState {
- /** When session is ready to initiate a call or transaction. */
- public static final int READY_TO_CALL = 0;
-
- /** When the registration request is sent out. */
- public static final int REGISTERING = 1;
-
- /** When the unregistration request is sent out. */
- public static final int DEREGISTERING = 2;
-
- /** When an INVITE request is received. */
- public static final int INCOMING_CALL = 3;
-
- /** When an OK response is sent for the INVITE request received. */
- public static final int INCOMING_CALL_ANSWERING = 4;
-
- /** When an INVITE request is sent. */
- public static final int OUTGOING_CALL = 5;
-
- /** When a RINGING response is received for the INVITE request sent. */
- public static final int OUTGOING_CALL_RING_BACK = 6;
-
- /** When a CANCEL request is sent for the INVITE request sent. */
- public static final int OUTGOING_CALL_CANCELING = 7;
-
- /** When a call is established. */
- public static final int IN_CALL = 8;
-
- /** Some error occurs when making a remote call to {@link ISipSession}. */
- public static final int REMOTE_ERROR = 9;
-
- /** When an OPTIONS request is sent. */
- public static final int PINGING = 10;
-
- /** Not defined. */
- public static final int NOT_DEFINED = 101;
-
- /**
- * Converts the state to string.
- */
- public static String toString(int state) {
- switch (state) {
- case READY_TO_CALL:
- return "READY_TO_CALL";
- case REGISTERING:
- return "REGISTERING";
- case DEREGISTERING:
- return "DEREGISTERING";
- case INCOMING_CALL:
- return "INCOMING_CALL";
- case INCOMING_CALL_ANSWERING:
- return "INCOMING_CALL_ANSWERING";
- case OUTGOING_CALL:
- return "OUTGOING_CALL";
- case OUTGOING_CALL_RING_BACK:
- return "OUTGOING_CALL_RING_BACK";
- case OUTGOING_CALL_CANCELING:
- return "OUTGOING_CALL_CANCELING";
- case IN_CALL:
- return "IN_CALL";
- case REMOTE_ERROR:
- return "REMOTE_ERROR";
- case PINGING:
- return "PINGING";
- default:
- return "NOT_DEFINED";
- }
- }
-
- private SipSessionState() {
- }
-}
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 @@ interface IWifiManager
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.DhcpInfo;
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 @@ class WifiConfigStore {
* 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 @@ class WifiConfigStore {
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 @@ class WifiConfigStore {
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 @@ class WifiConfigStore {
* @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 @@ class WifiConfigStore {
}
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 @@ class WifiConfigStore {
}
/**
+ * 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 @@ class WifiConfigStore {
sContext.sendBroadcast(intent);
}
- private static void updateConfiguredNetworks() {
+ static void loadConfiguredNetworks() {
String listStr = WifiNative.listNetworksCommand();
sLastPriority = 0;
@@ -391,6 +412,22 @@ class WifiConfigStore {
}
}
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 @@ class WifiConfigStore {
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 @@ class WifiConfigStore {
"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 class WifiConfiguration implements Parcelable {
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 class WifiConfiguration implements Parcelable {
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 @@ public class WifiManager {
}
/**
+ * 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 class WifiNative {
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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
/* 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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
* 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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
* 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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
/* 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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
@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 @@ public class WifiStateMachine extends HierarchicalStateMachine {
@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;