summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/4.xml4
-rw-r--r--api/current.xml1238
-rw-r--r--cmds/bootanimation/BootAnimation.cpp5
-rw-r--r--cmds/bootanimation/bootanimation_main.cpp21
-rw-r--r--cmds/keystore/keymgmt.c38
-rw-r--r--cmds/keystore/tests/Android.mk28
-rw-r--r--cmds/keystore/tests/netkeystore_test.c249
-rw-r--r--cmds/stagefright/record.cpp3
-rw-r--r--cmds/stagefright/stagefright.cpp11
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java4
-rw-r--r--core/java/android/app/ActivityManagerNative.java40
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/ApplicationContext.java11
-rw-r--r--core/java/android/app/IActivityManager.java8
-rw-r--r--core/java/android/app/IActivityWatcher.aidl1
-rw-r--r--core/java/android/app/IWallpaperService.aidl2
-rw-r--r--core/java/android/app/PendingIntent.java7
-rw-r--r--core/java/android/app/SearchDialog.java110
-rw-r--r--core/java/android/backup/BackupDataInput.java7
-rw-r--r--core/java/android/bluetooth/BluetoothPbap.java32
-rw-r--r--core/java/android/content/ContentProviderOperation.java21
-rw-r--r--core/java/android/content/Context.java3
-rw-r--r--core/java/android/content/ContextWrapper.java1
-rw-r--r--core/java/android/content/Intent.java67
-rw-r--r--core/java/android/content/IntentSender.java9
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java5
-rw-r--r--core/java/android/content/res/AssetManager.java3
-rw-r--r--core/java/android/content/res/TypedArray.java1
-rw-r--r--core/java/android/gesture/GestureLibrary.java1
-rw-r--r--core/java/android/os/FileObserver.java39
-rw-r--r--core/java/android/os/IPowerManager.aidl1
-rw-r--r--core/java/android/os/PowerManager.java43
-rw-r--r--core/java/android/preference/VolumePreference.java38
-rw-r--r--core/java/android/provider/ContactsContract.java135
-rw-r--r--core/java/android/provider/Settings.java11
-rw-r--r--core/java/android/provider/SocialContract.java8
-rw-r--r--core/java/android/server/search/SearchDialogWrapper.java40
-rw-r--r--core/java/android/server/search/SearchManagerService.java5
-rw-r--r--core/java/android/server/search/SearchableInfo.java8
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java303
-rw-r--r--core/java/android/text/style/ImageSpan.java23
-rw-r--r--core/java/android/util/EventLog.java6
-rw-r--r--core/java/android/view/MotionEvent.java4
-rw-r--r--core/java/android/view/Surface.java8
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewDebug.java5
-rw-r--r--core/java/android/view/ViewRoot.java5
-rw-r--r--core/java/android/view/VolumePanel.java31
-rw-r--r--core/java/android/webkit/CallbackProxy.java172
-rwxr-xr-xcore/java/android/webkit/GeolocationPermissions.java202
-rw-r--r--core/java/android/webkit/LoadListener.java1
-rw-r--r--core/java/android/webkit/MimeTypeMap.java1
-rw-r--r--core/java/android/webkit/WebChromeClient.java36
-rw-r--r--core/java/android/webkit/WebStorage.java21
-rw-r--r--core/java/android/webkit/WebTextView.java60
-rw-r--r--core/java/android/webkit/WebView.java305
-rw-r--r--core/java/android/webkit/WebViewCore.java317
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java23
-rw-r--r--core/java/android/widget/ImageView.java1
-rw-r--r--core/java/android/widget/RelativeLayout.java14
-rw-r--r--core/java/android/widget/TabWidget.java6
-rw-r--r--core/java/android/widget/TextView.java11
-rw-r--r--core/java/com/android/internal/backup/SystemBackupAgent.java35
-rw-r--r--core/java/com/google/android/gdata/client/QueryParamsImpl.java4
-rw-r--r--core/jni/android/graphics/Canvas.cpp46
-rw-r--r--core/jni/android/graphics/MaskFilter.cpp22
-rw-r--r--core/jni/android/graphics/Shader.cpp20
-rw-r--r--core/jni/android_media_AudioTrack.cpp16
-rw-r--r--core/jni/android_util_AssetManager.cpp26
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/drawable/expander_ic_maximized.9.pngbin1149 -> 1150 bytes
-rw-r--r--core/res/res/drawable/expander_ic_minimized.9.pngbin1172 -> 1167 bytes
-rw-r--r--core/res/res/layout/preference_dialog.xml (renamed from packages/SettingsProvider/res/values-fr/defaults.xml)26
-rw-r--r--core/res/res/values/strings.xml8
-rw-r--r--core/res/res/values/styles.xml3
-rw-r--r--graphics/java/android/graphics/Canvas.java29
-rw-r--r--graphics/java/android/renderscript/RenderScript.java40
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp44
-rw-r--r--include/media/mediarecorder.h4
-rw-r--r--include/media/stagefright/OMXDecoder.h43
-rw-r--r--include/media/stagefright/TIHardwareRenderer.h58
-rw-r--r--include/ui/FramebufferNativeWindow.h1
-rw-r--r--include/ui/Overlay.h6
-rw-r--r--include/ui/Surface.h6
-rw-r--r--include/ui/egl/android_natives.h15
-rw-r--r--include/utils/ResourceTypes.h6
-rw-r--r--keystore/java/android/security/CertTool.java2
-rw-r--r--keystore/jni/cert.c2
-rw-r--r--keystore/jni/certtool.c12
-rw-r--r--libs/audioflinger/Android.mk1
-rw-r--r--libs/audioflinger/AudioFlinger.cpp2
-rw-r--r--libs/rs/RenderScript.h34
-rw-r--r--libs/rs/RenderScriptEnv.h8
-rw-r--r--libs/rs/java/Film/res/drawable/p01.pngbin0 -> 254040 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p02.pngbin0 -> 138822 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p03.pngbin0 -> 152567 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p04.pngbin0 -> 280950 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p05.pngbin0 -> 349923 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p06.pngbin0 -> 120523 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p07.pngbin0 -> 139555 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p08.pngbin0 -> 321251 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p09.pngbin0 -> 281133 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p10.pngbin0 -> 366289 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p11.pngbin0 -> 319259 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p12.pngbin0 -> 368751 bytes
-rw-r--r--libs/rs/java/Film/res/drawable/p13.pngbin0 -> 312561 bytes
-rw-r--r--libs/rs/java/Film/res/raw/filmstrip.c112
-rw-r--r--libs/rs/java/Film/src/com/android/film/FilmRS.java157
-rw-r--r--libs/rs/java/Film/src/com/android/film/FilmView.java2
-rw-r--r--libs/rs/java/Grass/Android.mk25
-rw-r--r--libs/rs/java/Grass/AndroidManifest.xml20
-rw-r--r--libs/rs/java/Grass/res/drawable-hdpi/night.jpgbin0 -> 65755 bytes
-rw-r--r--libs/rs/java/Grass/res/drawable-hdpi/sky.jpgbin0 -> 27766 bytes
-rw-r--r--libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpgbin0 -> 30351 bytes
-rw-r--r--libs/rs/java/Grass/res/drawable-hdpi/sunset.jpgbin0 -> 33914 bytes
-rw-r--r--libs/rs/java/Grass/res/raw/grass.c112
-rw-r--r--libs/rs/java/Grass/src/com/android/grass/rs/Grass.java46
-rw-r--r--libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java151
-rw-r--r--libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java36
-rw-r--r--libs/rs/java/Rollo/res/raw/calendar.pngbin0 -> 4551 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/g1155.pngbin0 -> 5094 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/g2140.pngbin0 -> 3982 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/maps.pngbin0 -> 5374 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path1920.pngbin0 -> 3812 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path1927.pngbin0 -> 4034 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path3099.pngbin0 -> 4981 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path3950.pngbin0 -> 4873 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path431.pngbin0 -> 3995 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path4481.pngbin0 -> 4113 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path5168.pngbin0 -> 5328 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path676.pngbin0 -> 4351 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path754.pngbin0 -> 3205 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/path815.pngbin0 -> 5536 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/polygon2408.pngbin0 -> 3873 bytes
-rw-r--r--libs/rs/java/Rollo/res/raw/rollo.c117
-rw-r--r--libs/rs/java/Rollo/res/raw/rollo2.c176
-rw-r--r--libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java220
-rw-r--r--libs/rs/java/Rollo/src/com/android/rollo/RolloView.java18
-rw-r--r--libs/rs/rs.spec15
-rw-r--r--libs/rs/rsAllocation.cpp74
-rw-r--r--libs/rs/rsContext.cpp3
-rw-r--r--libs/rs/rsContext.h1
-rw-r--r--libs/rs/rsProgramVertex.cpp21
-rw-r--r--libs/rs/rsProgramVertex.h4
-rw-r--r--libs/rs/rsScript.h3
-rw-r--r--libs/rs/rsScriptC.cpp6
-rw-r--r--libs/rs/rsScriptC_Lib.cpp161
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp3
-rw-r--r--libs/surfaceflinger/LayerBase.cpp3
-rw-r--r--libs/surfaceflinger/LayerBitmap.cpp25
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp15
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h1
-rw-r--r--libs/ui/BufferMapper.cpp2
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp18
-rw-r--r--libs/ui/Overlay.cpp12
-rw-r--r--libs/ui/Surface.cpp35
-rw-r--r--libs/utils/BackupData.cpp20
-rw-r--r--libs/utils/ResourceTypes.cpp11
-rwxr-xr-xlocation/java/com/android/internal/location/GpsLocationProvider.java25
-rw-r--r--media/java/android/media/AudioManager.java34
-rw-r--r--media/java/android/media/AudioService.java93
-rw-r--r--media/java/android/media/IAudioService.aidl8
-rw-r--r--media/java/android/media/JetPlayer.java1
-rw-r--r--media/java/android/media/RingtoneManager.java22
-rw-r--r--media/jni/android_media_MediaRecorder.cpp2
-rw-r--r--media/jni/soundpool/SoundPool.cpp19
-rw-r--r--media/jni/soundpool/SoundPool.h1
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp2
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/AudioPlayer.cpp9
-rw-r--r--media/libstagefright/MP3Extractor.cpp2
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp121
-rw-r--r--media/libstagefright/MediaPlayerImpl.cpp21
-rw-r--r--media/libstagefright/OMXDecoder.cpp590
-rw-r--r--media/libstagefright/TIHardwareRenderer.cpp99
-rw-r--r--opengl/libagl/egl.cpp50
-rw-r--r--opengl/libs/EGL/Loader.cpp2
-rw-r--r--packages/SettingsProvider/res/values-cs/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-cs/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-de/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-de/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-es/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-es/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-fr/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-it/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-it/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-nl/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-nl/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-pl/defaults.xml22
-rw-r--r--packages/SettingsProvider/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml7
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java20
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java68
-rwxr-xr-xpackages/TtsService/src/android/tts/TtsService.java62
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java32
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java6
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java6
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/L2tpService.java5
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java20
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/PptpService.java8
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnService.java217
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java61
-rw-r--r--preloaded-classes18
-rw-r--r--services/java/com/android/server/AccessibilityManagerService.java19
-rw-r--r--services/java/com/android/server/BackupManagerService.java400
-rw-r--r--services/java/com/android/server/BatteryService.java6
-rw-r--r--services/java/com/android/server/JournaledFile.java107
-rw-r--r--services/java/com/android/server/PackageManagerService.java147
-rw-r--r--services/java/com/android/server/PowerManagerService.java67
-rw-r--r--services/java/com/android/server/ShutdownActivity.java46
-rw-r--r--services/java/com/android/server/SystemBackupAgent.java67
-rw-r--r--services/java/com/android/server/WallpaperService.java319
-rw-r--r--services/java/com/android/server/WifiService.java18
-rw-r--r--services/java/com/android/server/WindowManagerService.java4
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java51
-rw-r--r--services/java/com/android/server/status/StatusBarPolicy.java17
-rw-r--r--telephony/java/android/telephony/SmsManager.java17
-rw-r--r--telephony/java/android/telephony/SmsMessage.java84
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java2
-rw-r--r--telephony/java/android/telephony/gsm/SmsManager.java1
-rw-r--r--telephony/java/com/android/internal/telephony/CommandsInterface.java10
-rw-r--r--telephony/java/com/android/internal/telephony/RIL.java30
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java19
-rw-r--r--telephony/java/com/android/internal/telephony/ServiceStateTracker.java1
-rw-r--r--telephony/java/com/android/internal/telephony/SmsMessageBase.java13
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CDMAPhone.java41
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java33
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java5
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java7
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java110
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/SmsMessage.java13
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java411
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java8
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/PdpConnection.java8
-rw-r--r--telephony/java/com/android/internal/telephony/test/SimulatedCommands.java2
-rw-r--r--test-runner/android/test/ProviderTestCase2.java11
-rw-r--r--test-runner/android/test/mock/MockContext.java1
-rw-r--r--tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java10
-rwxr-xr-xtests/AndroidTests/src/com/android/unit_tests/VpnTest.java116
-rw-r--r--tests/CoreTests/android/core/CryptoTest.java11
-rw-r--r--tests/DpiTest/res/drawable-hdpi/reslogo240dpi.pngbin0 -> 13388 bytes
-rw-r--r--tests/DpiTest/res/drawable-hdpi/stylogo240dpi.pngbin0 -> 13388 bytes
-rw-r--r--tests/DpiTest/res/drawable-ldpi/reslogo120dpi.pngbin0 -> 5178 bytes
-rw-r--r--tests/DpiTest/res/drawable-ldpi/stylogo120dpi.pngbin0 -> 5178 bytes
-rw-r--r--tests/DpiTest/res/drawable/reslogo160dpi.pngbin0 -> 8114 bytes
-rw-r--r--tests/DpiTest/res/drawable/stylogo160dpi.pngbin0 -> 8114 bytes
-rw-r--r--tests/DpiTest/res/layout/image_views.xml37
-rw-r--r--tests/DpiTest/res/layout/styled_image_views.xml (renamed from packages/SettingsProvider/res/values-zh-rTW/defaults.xml)20
-rw-r--r--tests/DpiTest/res/values/styles.xml35
-rw-r--r--tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java12
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java147
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java11
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java112
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java117
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java92
-rw-r--r--vpn/java/android/net/vpn/PptpProfile.java26
-rw-r--r--vpn/java/android/net/vpn/VpnManager.java4
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java78
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java1
261 files changed, 8178 insertions, 2506 deletions
diff --git a/api/4.xml b/api/4.xml
index c8a2e83..cac3ae8 100644
--- a/api/4.xml
+++ b/api/4.xml
@@ -256713,7 +256713,7 @@
extends="java.lang.Enum"
abstract="false"
static="false"
- final="true"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
@@ -258766,7 +258766,7 @@
<package name="java.util.concurrent.locks"
>
<class name="AbstractQueuedSynchronizer"
- extends="java.lang.Object"
+ extends="java.util.concurrent.locks.AbstractOwnableSynchronizer"
abstract="true"
static="false"
final="false"
diff --git a/api/current.xml b/api/current.xml
index c819972..b0b9ce6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1024,17 +1024,6 @@
visibility="public"
>
</field>
-<field name="SHUTDOWN"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.permission.SHUTDOWN&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="SIGNAL_PERSISTENT_PROCESSES"
type="java.lang.String"
transient="false"
@@ -1057,17 +1046,6 @@
visibility="public"
>
</field>
-<field name="STOP_APP_SWITCHES"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.permission.STOP_APP_SWITCHES&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="SUBSCRIBED_FEEDS_READ"
type="java.lang.String"
transient="false"
@@ -31763,17 +31741,6 @@
visibility="public"
>
</field>
-<field name="BACKUP_SERVICE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;backup&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="BIND_AUTO_CREATE"
type="int"
transient="false"
@@ -32619,19 +32586,6 @@
<parameter name="mode" type="int">
</parameter>
</method>
-<method name="getSharedPrefsFile"
- return="java.io.File"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
<method name="getSystemService"
return="java.lang.Object"
abstract="false"
@@ -33426,70 +33380,6 @@
</exception>
</method>
</interface>
-<interface name="IIntentReceiver"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.IInterface">
-</implements>
-<method name="performReceive"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-<parameter name="resultCode" type="int">
-</parameter>
-<parameter name="data" type="java.lang.String">
-</parameter>
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-<parameter name="ordered" type="boolean">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</interface>
-<interface name="IIntentSender"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.IInterface">
-</implements>
-<method name="send"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="code" type="int">
-</parameter>
-<parameter name="intent" type="android.content.Intent">
-</parameter>
-<parameter name="resolvedType" type="java.lang.String">
-</parameter>
-<parameter name="finishedReceiver" type="android.content.IIntentReceiver">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</interface>
<class name="Intent"
extends="java.lang.Object"
abstract="false"
@@ -35835,39 +35725,6 @@
visibility="public"
>
</field>
-<field name="ACTION_TTS_CHECK_TTS_DATA"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.intent.action.CHECK_TTS_DATA&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_TTS_INSTALL_TTS_DATA"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.intent.action.INSTALL_TTS_DATA&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_TTS_QUEUE_PROCESSING_COMPLETED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ACTION_UID_REMOVED"
type="java.lang.String"
transient="false"
@@ -37683,26 +37540,6 @@
>
<implements name="android.os.Parcelable">
</implements>
-<constructor name="IntentSender"
- type="android.content.IntentSender"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="target" type="android.content.IIntentSender">
-</parameter>
-</constructor>
-<constructor name="IntentSender"
- type="android.content.IntentSender"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="target" type="android.os.IBinder">
-</parameter>
-</constructor>
<method name="describeContents"
return="int"
abstract="false"
@@ -51230,17 +51067,6 @@
<parameter name="entryName" type="java.lang.String">
</parameter>
</method>
-<method name="getLearner"
- return="android.gesture.Learner"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="getOrientationStyle"
return="int"
abstract="false"
@@ -52509,15 +52335,6 @@
>
</field>
</class>
-<class name="Learner"
- extends="java.lang.Object"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility=""
->
-</class>
<class name="OrientedBoundingBox"
extends="java.lang.Object"
abstract="false"
@@ -84500,6 +84317,19 @@
visibility="public"
>
</method>
+<method name="setReferenceCounted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="refCounted" type="boolean">
+</parameter>
+</method>
</class>
<class name="WifiManager.WifiLock"
extends="java.lang.Object"
@@ -116439,7 +116269,18 @@
<parameter name="filename" type="java.lang.String">
</parameter>
</method>
-<field name="TTS_ERROR"
+<field name="ACTION_TTS_QUEUE_PROCESSING_COMPLETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR"
type="int"
transient="false"
volatile="false"
@@ -116450,7 +116291,7 @@
visibility="public"
>
</field>
-<field name="TTS_LANG_AVAILABLE"
+<field name="LANG_AVAILABLE"
type="int"
transient="false"
volatile="false"
@@ -116461,7 +116302,7 @@
visibility="public"
>
</field>
-<field name="TTS_LANG_COUNTRY_AVAILABLE"
+<field name="LANG_COUNTRY_AVAILABLE"
type="int"
transient="false"
volatile="false"
@@ -116472,7 +116313,7 @@
visibility="public"
>
</field>
-<field name="TTS_LANG_COUNTRY_VAR_AVAILABLE"
+<field name="LANG_COUNTRY_VAR_AVAILABLE"
type="int"
transient="false"
volatile="false"
@@ -116483,7 +116324,7 @@
visibility="public"
>
</field>
-<field name="TTS_LANG_MISSING_DATA"
+<field name="LANG_MISSING_DATA"
type="int"
transient="false"
volatile="false"
@@ -116494,7 +116335,7 @@
visibility="public"
>
</field>
-<field name="TTS_LANG_NOT_SUPPORTED"
+<field name="LANG_NOT_SUPPORTED"
type="int"
transient="false"
volatile="false"
@@ -116505,7 +116346,7 @@
visibility="public"
>
</field>
-<field name="TTS_QUEUE_ADD"
+<field name="QUEUE_ADD"
type="int"
transient="false"
volatile="false"
@@ -116516,7 +116357,7 @@
visibility="public"
>
</field>
-<field name="TTS_QUEUE_FLUSH"
+<field name="QUEUE_FLUSH"
type="int"
transient="false"
volatile="false"
@@ -116527,7 +116368,7 @@
visibility="public"
>
</field>
-<field name="TTS_SUCCESS"
+<field name="SUCCESS"
type="int"
transient="false"
volatile="false"
@@ -116555,6 +116396,28 @@
visibility="public"
>
</constructor>
+<field name="ACTION_CHECK_TTS_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.tts.engine.CHECK_TTS_DATA&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_INSTALL_TTS_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.tts.engine.INSTALL_TTS_DATA&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CHECK_VOICE_DATA_BAD_DATA"
type="int"
transient="false"
@@ -116610,7 +116473,7 @@
visibility="public"
>
</field>
-<field name="TTS_DEFAULT_STREAM"
+<field name="DEFAULT_STREAM"
type="int"
transient="false"
volatile="false"
@@ -116621,55 +116484,55 @@
visibility="public"
>
</field>
-<field name="TTS_KEY_PARAM_STREAM"
+<field name="EXTRA_VOICE_DATA_FILES"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;streamType&quot;"
+ value="&quot;dataFiles&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="TTS_KEY_PARAM_UTTERANCE_ID"
+<field name="EXTRA_VOICE_DATA_FILES_INFO"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;utteranceId&quot;"
+ value="&quot;dataFilesInfo&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="VOICE_DATA_FILES"
+<field name="EXTRA_VOICE_DATA_ROOT_DIRECTORY"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;dataFiles&quot;"
+ value="&quot;dataRoot&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="VOICE_DATA_FILES_INFO"
+<field name="KEY_PARAM_STREAM"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;dataFilesInfo&quot;"
+ value="&quot;streamType&quot;"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="VOICE_DATA_ROOT_DIRECTORY"
+<field name="KEY_PARAM_UTTERANCE_ID"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;dataRoot&quot;"
+ value="&quot;utteranceId&quot;"
static="true"
final="true"
deprecated="not deprecated"
@@ -117974,6 +117837,746 @@
>
</field>
</class>
+<class name="SmsManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="divideMessage"
+ return="java.util.ArrayList&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDefault"
+ return="android.telephony.SmsManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="sendDataMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationPort" type="short">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="sentIntent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="deliveryIntent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<method name="sendMultipartTextMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="parts" type="java.util.ArrayList&lt;java.lang.String&gt;">
+</parameter>
+<parameter name="sentIntents" type="java.util.ArrayList&lt;android.app.PendingIntent&gt;">
+</parameter>
+<parameter name="deliveryIntents" type="java.util.ArrayList&lt;android.app.PendingIntent&gt;">
+</parameter>
+</method>
+<method name="sendTextMessage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="text" type="java.lang.String">
+</parameter>
+<parameter name="sentIntent" type="android.app.PendingIntent">
+</parameter>
+<parameter name="deliveryIntent" type="android.app.PendingIntent">
+</parameter>
+</method>
+<field name="RESULT_ERROR_GENERIC_FAILURE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_NO_SERVICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_NULL_PDU"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RESULT_ERROR_RADIO_OFF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_FREE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_READ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_SENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_UNREAD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_ON_ICC_UNSENT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SmsMessage"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="calculateLength"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="msgBody" type="java.lang.CharSequence">
+</parameter>
+<parameter name="use7bitOnly" type="boolean">
+</parameter>
+</method>
+<method name="calculateLength"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="messageBody" type="java.lang.String">
+</parameter>
+<parameter name="use7bitOnly" type="boolean">
+</parameter>
+</method>
+<method name="createFromPdu"
+ return="android.telephony.SmsMessage"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pdu" type="byte[]">
+</parameter>
+</method>
+<method name="getDisplayMessageBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDisplayOriginatingAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEmailBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getEmailFrom"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIndexOnIcc"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getIndexOnSim"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageBody"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMessageClass"
+ return="android.telephony.SmsMessage.MessageClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOriginatingAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPdu"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getProtocolIdentifier"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPseudoSubject"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getServiceCenterAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatus"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatusOnIcc"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStatusOnSim"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSubmitPdu"
+ return="android.telephony.SmsMessage.SubmitPdu"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="message" type="java.lang.String">
+</parameter>
+<parameter name="statusReportRequested" type="boolean">
+</parameter>
+</method>
+<method name="getSubmitPdu"
+ return="android.telephony.SmsMessage.SubmitPdu"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationAddress" type="java.lang.String">
+</parameter>
+<parameter name="destinationPort" type="short">
+</parameter>
+<parameter name="data" type="byte[]">
+</parameter>
+<parameter name="statusReportRequested" type="boolean">
+</parameter>
+</method>
+<method name="getTPLayerLengthForPDU"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pdu" type="java.lang.String">
+</parameter>
+</method>
+<method name="getTimestampMillis"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUserData"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isCphsMwiMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEmail"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMWIClearMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMWISetMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isMwiDontStore"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReplace"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReplyPathPresent"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isStatusReportMessage"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="ENCODING_16BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_7BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_8BIT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCODING_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_BYTES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="140"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_BYTES_WITH_HEADER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_SEPTETS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MAX_USER_DATA_SEPTETS_WITH_HEADER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="153"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="SmsMessage.MessageClass"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.telephony.SmsMessage.MessageClass"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.telephony.SmsMessage.MessageClass[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="SmsMessage.SubmitPdu"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="encodedMessage"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="encodedScAddress"
+ type="byte[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="TelephonyManager"
extends="java.lang.Object"
abstract="false"
@@ -123165,19 +123768,6 @@
<parameter name="mode" type="int">
</parameter>
</method>
-<method name="getSharedPrefsFile"
- return="java.io.File"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
<method name="getSystemService"
return="java.lang.Object"
abstract="false"
@@ -135194,9 +135784,33 @@
type="android.text.style.ImageSpan"
static="false"
final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+</constructor>
+<constructor name="ImageSpan"
+ type="android.text.style.ImageSpan"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="b" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="verticalAlignment" type="int">
+</parameter>
+</constructor>
+<constructor name="ImageSpan"
+ type="android.text.style.ImageSpan"
+ static="false"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
+<parameter name="context" type="android.content.Context">
+</parameter>
<parameter name="b" type="android.graphics.Bitmap">
</parameter>
</constructor>
@@ -135207,6 +135821,8 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="context" type="android.content.Context">
+</parameter>
<parameter name="b" type="android.graphics.Bitmap">
</parameter>
<parameter name="verticalAlignment" type="int">
@@ -146942,7 +147558,7 @@
value="2"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -146968,6 +147584,17 @@
visibility="public"
>
</field>
+<field name="SURFACE_FROZEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SURFACE_HIDDEN"
type="int"
transient="false"
@@ -163493,6 +164120,8 @@
</parameter>
<parameter name="currentQuota" type="long">
</parameter>
+<parameter name="totalUsedQuota" type="long">
+</parameter>
<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
</parameter>
</method>
@@ -165153,6 +165782,8 @@
</parameter>
<parameter name="currentQuota" type="long">
</parameter>
+<parameter name="totalUsedQuota" type="long">
+</parameter>
<parameter name="quotaUpdater" type="android.webkit.WebStorage.QuotaUpdater">
</parameter>
</method>
@@ -193475,7 +194106,7 @@
<method name="valid"
return="boolean"
abstract="false"
- native="true"
+ native="false"
synchronized="false"
static="false"
final="false"
@@ -198598,7 +199229,7 @@
return="java.nio.channels.FileChannel"
abstract="false"
native="false"
- synchronized="false"
+ synchronized="true"
static="false"
final="true"
deprecated="not deprecated"
@@ -207468,7 +208099,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="i" type="int">
+<parameter name="value" type="int">
</parameter>
</method>
<method name="toString"
@@ -208268,10 +208899,10 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="y" type="double">
-</parameter>
<parameter name="x" type="double">
</parameter>
+<parameter name="y" type="double">
+</parameter>
</method>
<method name="cbrt"
return="double"
@@ -273628,7 +274259,7 @@
return="void"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -273641,7 +274272,7 @@
return="void"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -273652,7 +274283,7 @@
return="int"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -273687,7 +274318,7 @@
return="boolean"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -273722,7 +274353,7 @@
return="void"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -276067,7 +276698,7 @@
return="E"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -277433,7 +278064,7 @@
return="E"
abstract="false"
native="false"
- synchronized="true"
+ synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
@@ -277913,7 +278544,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="offer"
@@ -277926,7 +278557,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<parameter name="timeout" type="long">
</parameter>
@@ -277984,7 +278615,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<exception name="InterruptedException" type="java.lang.InterruptedException">
</exception>
@@ -278044,7 +278675,20 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
+</parameter>
+</method>
+<method name="contains"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
</parameter>
</method>
<method name="drainTo"
@@ -278085,7 +278729,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="offer"
@@ -278098,7 +278742,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<parameter name="timeout" type="long">
</parameter>
@@ -278134,7 +278778,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<exception name="InterruptedException" type="java.lang.InterruptedException">
</exception>
@@ -278150,6 +278794,19 @@
visibility="public"
>
</method>
+<method name="remove"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
<method name="take"
return="E"
abstract="true"
@@ -278367,7 +279024,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="java.util.Map&lt;? extends K, ? extends V&gt;">
+<parameter name="m" type="java.util.Map&lt;? extends K, ? extends V&gt;">
</parameter>
</constructor>
<method name="contains"
@@ -278530,7 +279187,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="peek"
@@ -278680,7 +279337,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="array" type="E[]">
+<parameter name="toCopyIn" type="E[]">
</parameter>
</constructor>
<method name="add"
@@ -278708,7 +279365,7 @@
>
<parameter name="index" type="int">
</parameter>
-<parameter name="e" type="E">
+<parameter name="element" type="E">
</parameter>
</method>
<method name="addAll"
@@ -278836,9 +279493,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="e" type="E">
-</parameter>
-<parameter name="index" type="int">
+<parameter name="o" type="java.lang.Object">
</parameter>
</method>
<method name="indexOf"
@@ -278851,7 +279506,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="java.lang.Object">
+<parameter name="e" type="E">
+</parameter>
+<parameter name="index" type="int">
</parameter>
</method>
<method name="isEmpty"
@@ -278886,9 +279543,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="e" type="E">
-</parameter>
-<parameter name="index" type="int">
+<parameter name="o" type="java.lang.Object">
</parameter>
</method>
<method name="lastIndexOf"
@@ -278901,7 +279556,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="java.lang.Object">
+<parameter name="e" type="E">
+</parameter>
+<parameter name="index" type="int">
</parameter>
</method>
<method name="listIterator"
@@ -278992,7 +279649,7 @@
>
<parameter name="index" type="int">
</parameter>
-<parameter name="e" type="E">
+<parameter name="element" type="E">
</parameter>
</method>
<method name="size"
@@ -279356,7 +280013,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="offer"
@@ -279369,7 +280026,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<parameter name="timeout" type="long">
</parameter>
@@ -279397,12 +280054,6 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="time" type="long">
-</parameter>
-<parameter name="unit" type="java.util.concurrent.TimeUnit">
-</parameter>
-<exception name="InterruptedException" type="java.lang.InterruptedException">
-</exception>
</method>
<method name="poll"
return="E"
@@ -279414,6 +280065,12 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="timeout" type="long">
+</parameter>
+<parameter name="unit" type="java.util.concurrent.TimeUnit">
+</parameter>
+<exception name="InterruptedException" type="java.lang.InterruptedException">
+</exception>
</method>
<method name="put"
return="void"
@@ -279425,7 +280082,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="remainingCapacity"
@@ -280496,7 +281153,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<parameter name="timeout" type="long">
</parameter>
@@ -280515,7 +281172,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="peek"
@@ -280567,7 +281224,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<exception name="InterruptedException" type="java.lang.InterruptedException">
</exception>
@@ -280720,7 +281377,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="offer"
@@ -280733,7 +281390,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
<parameter name="timeout" type="long">
</parameter>
@@ -280789,7 +281446,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="remainingCapacity"
@@ -281519,7 +282176,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="o" type="E">
+<parameter name="e" type="E">
</parameter>
</method>
<method name="peek"
@@ -282224,7 +282881,7 @@
extends="java.lang.Enum"
abstract="false"
static="false"
- final="true"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
@@ -282238,9 +282895,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="duration" type="long">
+<parameter name="sourceDuration" type="long">
</parameter>
-<parameter name="unit" type="java.util.concurrent.TimeUnit">
+<parameter name="sourceUnit" type="java.util.concurrent.TimeUnit">
</parameter>
</method>
<method name="sleep"
@@ -284276,12 +284933,55 @@
</package>
<package name="java.util.concurrent.locks"
>
-<class name="AbstractQueuedSynchronizer"
+<class name="AbstractOwnableSynchronizer"
extends="java.lang.Object"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
+ visibility=""
+>
+<implements name="java.io.Serializable">
+</implements>
+<constructor name="AbstractOwnableSynchronizer"
+ type="java.util.concurrent.locks.AbstractOwnableSynchronizer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</constructor>
+<method name="getExclusiveOwnerThread"
+ return="java.lang.Thread"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="setExclusiveOwnerThread"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="t" type="java.lang.Thread">
+</parameter>
+</method>
+</class>
+<class name="AbstractQueuedSynchronizer"
+ extends="java.util.concurrent.locks.AbstractOwnableSynchronizer"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
visibility="public"
>
<implements name="java.io.Serializable">
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index e2d01de..f101007 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -202,7 +202,6 @@ bool BootAnimation::android() {
// draw and update only what we need
mFlingerSurface->setSwapRectangle(updateRect);
- glEnable(GL_SCISSOR_TEST);
glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(),
updateRect.height());
@@ -218,6 +217,10 @@ bool BootAnimation::android() {
GLint offset = (1 - (t - floorf(t))) * mAndroid[1].w;
GLint x = xc - offset;
+ glDisable(GL_SCISSOR_TEST);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
glDrawTexiOES(x, yc, 0, mAndroid[1].w, mAndroid[1].h);
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 346f156..3c82fe5 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -16,9 +16,12 @@
#define LOG_TAG "BootAnimation"
+#include <cutils/properties.h>
+
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+
#include <utils/Log.h>
#include <utils/threads.h>
@@ -41,12 +44,20 @@ int main(int argc, char** argv)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif
- sp<ProcessState> proc(ProcessState::self());
- ProcessState::self()->startThreadPool();
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.nobootanimation", value, "0");
+ int noBootAnimation = atoi(value);
+ LOGI_IF(noBootAnimation, "boot animation disabled");
+ if (!noBootAnimation) {
+
+ sp<ProcessState> proc(ProcessState::self());
+ ProcessState::self()->startThreadPool();
+
+ // create the boot animation object
+ sp<BootAnimation> boot = new BootAnimation();
- // create the boot animation object
- sp<BootAnimation> boot = new BootAnimation();
+ IPCThreadState::self()->joinThreadPool();
- IPCThreadState::self()->joinThreadPool();
+ }
return 0;
}
diff --git a/cmds/keystore/keymgmt.c b/cmds/keystore/keymgmt.c
index c45b53c..9a1f845 100644
--- a/cmds/keystore/keymgmt.c
+++ b/cmds/keystore/keymgmt.c
@@ -228,6 +228,11 @@ int remove_key(const char *namespace, const char *keyname)
char keyfile[KEYFILE_LEN];
if (state != UNLOCKED) return -state;
+ if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+ (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
+ LOGE("keyname is too long.");
+ return -1;
+ }
sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
return unlink(keyfile);
}
@@ -243,12 +248,12 @@ int put_key(const char *namespace, const char *keyname,
LOGE("Can not store key with current state %d\n", state);
return -state;
}
- sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
- // flatten the args
- if (strlen(keyname) >= MAX_KEY_NAME_LENGTH) {
+ if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+ (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
LOGE("keyname is too long.");
return -1;
}
+ sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
strcpy(blob.keyname, keyname);
blob.value_size = size;
if (size > MAX_KEY_VALUE_LENGTH) {
@@ -271,6 +276,11 @@ int get_key(const char *namespace, const char *keyname,
LOGE("Can not retrieve key value with current state %d\n", state);
return -state;
}
+ if ((strlen(namespace) >= MAX_KEY_NAME_LENGTH) ||
+ (strlen(keyname) >= MAX_KEY_NAME_LENGTH)) {
+ LOGE("keyname is too long.");
+ return -1;
+ }
sprintf(keyfile, KEYFILE_NAME, namespace, keyname);
ret = load_n_decrypt(keyname, keyfile, &decryptKey, &blob);
if (!ret) {
@@ -299,6 +309,13 @@ int list_keys(const char *namespace, char reply[BUFFER_MAX])
LOGE("cannot open keystore dir or namespace is null\n");
return -1;
}
+
+ if (strlen(namespace) >= MAX_KEY_NAME_LENGTH) {
+ LOGE("namespace is too long.");
+ return -1;
+ }
+
+ reply[0] = 0;
while ((de = readdir(d))) {
char *prefix, *name, *keyfile = de->d_name;
char *context = NULL;
@@ -367,6 +384,7 @@ KEYSTORE_STATE get_state()
int reset_keystore()
{
+ int ret = 0;
DIR *d;
struct dirent *de;
@@ -374,18 +392,24 @@ int reset_keystore()
LOGE("cannot open keystore dir\n");
return -1;
}
- while ((de = readdir(d))) unlink(de->d_name);
+ while ((de = readdir(d))) {
+ if (unlink(de->d_name) != 0) ret = -1;
+ }
closedir(d);
state = UNINITIALIZED;
- LOGI("keystore is reset.");
- return 0;
+ if (ret == 0) {
+ LOGI("keystore is reset.");
+ } else {
+ LOGI("keystore can not be cleaned up entirely.");
+ }
+ return ret;
}
int init_keystore(const char *dir)
{
int fd;
- if (!dir) mkdir(dir, 0770);
+ if (dir) mkdir(dir, 0770);
if (!dir || chdir(dir)) {
LOGE("Can not open/create the keystore directory %s\n",
dir ? dir : "(null)");
diff --git a/cmds/keystore/tests/Android.mk b/cmds/keystore/tests/Android.mk
new file mode 100644
index 0000000..33541cc
--- /dev/null
+++ b/cmds/keystore/tests/Android.mk
@@ -0,0 +1,28 @@
+# 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.
+#
+# define the KEYSTORE_TESTS environment variable to build the test programs
+ifdef KEYSTORE_TESTS
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:= netkeystore_test.c ../keymgmt.c
+LOCAL_SHARED_LIBRARIES := libcutils libssl
+LOCAL_MODULE:= netkeystore_test
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES := external/openssl/include \
+ frameworks/base/cmds/keystore
+EXTRA_CFLAGS := -g -O0 -DGTEST_OS_LINUX -DGTEST_HAS_STD_STRING
+include $(BUILD_EXECUTABLE)
+
+endif #KEYSTORE_TESTS
diff --git a/cmds/keystore/tests/netkeystore_test.c b/cmds/keystore/tests/netkeystore_test.c
new file mode 100644
index 0000000..e7e686b
--- /dev/null
+++ b/cmds/keystore/tests/netkeystore_test.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "keymgmt.h"
+
+typedef int FUNC_PTR();
+typedef struct {
+ const char *name;
+ FUNC_PTR *func;
+} TESTFUNC;
+
+#define FUNC_NAME(x) { #x, test_##x }
+#define FUNC_BODY(x) int test_##x()
+
+#define TEST_PASSWD "12345678"
+#define TEST_NPASSWD "11111111"
+#define TEST_DIR "/data/local/tmp/keystore"
+#define READONLY_DIR "/proc/keystore"
+#define TEST_NAMESPACE "test"
+#define TEST_KEYNAME "key"
+#define TEST_KEYNAME2 "key2"
+#define TEST_KEYVALUE "ANDROID"
+
+void setup()
+{
+ if (init_keystore(TEST_DIR) != 0) {
+ fprintf(stderr, "Can not create the test directory %s\n", TEST_DIR);
+ exit(-1);
+ }
+}
+
+void teardown()
+{
+ reset_keystore();
+ rmdir(TEST_DIR);
+}
+
+FUNC_BODY(init_keystore)
+{
+ if (init_keystore(READONLY_DIR) == 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(reset_keystore)
+{
+ chdir("/procx");
+ if (reset_keystore() == 0) return -1;
+ chdir(TEST_DIR);
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(get_state)
+{
+ if (get_state() != UNINITIALIZED) return -1;
+ passwd(TEST_PASSWD);
+ if (get_state() != UNLOCKED) return -1;
+ lock();
+ if (get_state() != LOCKED) return -1;
+ reset_keystore();
+ if (get_state() != UNINITIALIZED) return -1;
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(passwd)
+{
+ char buf[512];
+
+ if (passwd(" 23432dsfsdf") == 0) return -1;
+ if (passwd("dsfsdf") == 0) return -1;
+ passwd(TEST_PASSWD);
+ lock();
+ if (unlock("55555555") == 0) return -1;
+ if (unlock(TEST_PASSWD) != 0) return -1;
+
+ // change the password
+ sprintf(buf, "%s %s", "klfdjdsklfjg", "abcdefghi");
+ if (passwd(buf) == 0) return -1;
+
+ sprintf(buf, "%s %s", TEST_PASSWD, TEST_NPASSWD);
+ if (passwd(buf) != 0) return -1;
+ lock();
+
+ if (unlock(TEST_PASSWD) == 0) return -1;
+ if (unlock(TEST_NPASSWD) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(lock)
+{
+ if (lock() == 0) return -1;
+ passwd(TEST_PASSWD);
+ if (lock() != 0) return -1;
+ if (lock() != 0) return -1;
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(unlock)
+{
+ int i = MAX_RETRY_COUNT;
+ passwd(TEST_PASSWD);
+ lock();
+ while (i > 1) {
+ if (unlock(TEST_NPASSWD) != --i) return -1;
+ }
+ if (unlock(TEST_NPASSWD) != -1) return -1;
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(put_key)
+{
+ int i = 0;
+ char keyname[512];
+
+ if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE)) == 0) return -1;
+ passwd(TEST_PASSWD);
+ if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE)) != 0) return -1;
+
+ for(i = 0; i < 500; i++) keyname[i] = 'K';
+ keyname[i] = 0;
+ if (put_key(TEST_NAMESPACE, keyname, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE)) == 0) return -1;
+ if (put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ MAX_KEY_VALUE_LENGTH + 1) == 0) return -1;
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(get_key)
+{
+ int size;
+ unsigned char data[MAX_KEY_VALUE_LENGTH];
+
+ if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) == 0) return -1;
+
+ passwd(TEST_PASSWD);
+ put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE));
+ if (get_key(TEST_NAMESPACE, TEST_KEYNAME, data, &size) != 0) return -1;
+ if (memcmp(data, TEST_KEYVALUE, size) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(remove_key)
+{
+ if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
+
+ passwd(TEST_PASSWD);
+ if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) == 0) return -1;
+
+ put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE));
+ if (remove_key(TEST_NAMESPACE, TEST_KEYNAME) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
+FUNC_BODY(list_keys)
+{
+ int i;
+ char buf[128];
+ char reply[BUFFER_MAX];
+
+ for(i = 0; i < 100; i++) buf[i] = 'K';
+ buf[i] = 0;
+
+ if (list_keys(TEST_NAMESPACE, reply) == 0) return -1;
+
+ passwd(TEST_PASSWD);
+ if (list_keys(buf, reply) == 0) return -1;
+
+ if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+ if (strcmp(reply, "") != 0) return -1;
+
+ put_key(TEST_NAMESPACE, TEST_KEYNAME, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE));
+ if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+ if (strcmp(reply, TEST_KEYNAME) != 0) return -1;
+
+ put_key(TEST_NAMESPACE, TEST_KEYNAME2, (unsigned char *)TEST_KEYVALUE,
+ strlen(TEST_KEYVALUE));
+
+ if (list_keys(TEST_NAMESPACE, reply) != 0) return -1;
+ sprintf(buf, "%s %s", TEST_KEYNAME2, TEST_KEYNAME);
+ if (strcmp(reply, buf) != 0) return -1;
+
+ return EXIT_SUCCESS;
+}
+
+TESTFUNC all_tests[] = {
+ FUNC_NAME(init_keystore),
+ FUNC_NAME(reset_keystore),
+ FUNC_NAME(get_state),
+ FUNC_NAME(passwd),
+ FUNC_NAME(lock),
+ FUNC_NAME(unlock),
+ FUNC_NAME(put_key),
+ FUNC_NAME(get_key),
+ FUNC_NAME(remove_key),
+ FUNC_NAME(list_keys),
+};
+
+int main(int argc, char **argv) {
+ int i, ret;
+ for (i = 0 ; i < (int)(sizeof(all_tests)/sizeof(TESTFUNC)) ; ++i) {
+ setup();
+ if ((ret = all_tests[i].func()) != EXIT_SUCCESS) {
+ fprintf(stderr, "ERROR in function %s\n", all_tests[i].name);
+ return ret;
+ } else {
+ fprintf(stderr, "function %s PASSED!\n", all_tests[i].name);
+ }
+ teardown();
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 12bdead..d8db8b3 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -119,7 +119,8 @@ int main(int argc, char **argv) {
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
- OMXDecoder *encoder = OMXDecoder::CreateEncoder(&client, enc_meta);
+ OMXDecoder *encoder =
+ OMXDecoder::Create(&client, enc_meta, true /* createEncoder */);
encoder->setSource(decoder);
// encoder->setSource(meta, new DummySource(width, height));
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 961942a..7e23574 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -102,6 +102,7 @@ static int64_t getNowUs() {
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
+ bool audioOnly = false;
if (argc > 1 && !strcmp(argv[1], "--list")) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.player"));
@@ -121,6 +122,10 @@ int main(int argc, char **argv) {
}
return 0;
+ } else if (argc > 1 && !strcmp(argv[1], "--audio")) {
+ audioOnly = true;
+ ++argv;
+ --argc;
}
#if 0
@@ -149,7 +154,11 @@ int main(int argc, char **argv) {
const char *mime;
meta->findCString(kKeyMIMEType, &mime);
- if (!strncasecmp(mime, "video/", 6)) {
+ if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
+ break;
+ }
+
+ if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
break;
}
}
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index a3456c7..79bd6e7 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -163,6 +163,10 @@ public abstract class AccessibilityService extends Service {
}
}
+ /**
+ * Implement to return the implementation of the internal accessibility
+ * service interface. Subclasses should not override.
+ */
@Override
public final IBinder onBind(Intent intent) {
return new IEventListenerWrapper(this);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index ba6cc32..447512a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1085,6 +1085,23 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(result);
return true;
}
+
+ case KILL_APPLICATION_WITH_UID_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ int uid = data.readInt();
+ killApplicationWithUid(pkg, uid);
+ reply.writeNoException();
+ return true;
+ }
+
+ case CLOSE_SYSTEM_DIALOGS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String reason = data.readString();
+ closeSystemDialogs(reason);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -2368,6 +2385,29 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
return result;
}
+
+ public void killApplicationWithUid(String pkg, int uid) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(pkg);
+ data.writeInt(uid);
+ mRemote.transact(KILL_APPLICATION_WITH_UID_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ public void closeSystemDialogs(String reason) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(reason);
+ mRemote.transact(CLOSE_SYSTEM_DIALOGS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e21b1d9..32a2891 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3634,7 +3634,7 @@ public final class ActivityThread {
Locale.setDefault(config.locale);
}
- Resources.updateSystemConfiguration(config, null);
+ Resources.updateSystemConfiguration(config, dm);
ApplicationContext.ApplicationPackageManager.configurationChanged();
//Log.i(TAG, "Configuration changed in " + currentPackageName());
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 1e4ab68..b095e30 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -578,7 +578,7 @@ class ApplicationContext extends Context {
@Override
public void setWallpaper(Bitmap bitmap) throws IOException {
try {
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+ ParcelFileDescriptor fd = getWallpaperService().setWallpaper(null);
if (fd == null) {
return;
}
@@ -598,7 +598,7 @@ class ApplicationContext extends Context {
@Override
public void setWallpaper(InputStream data) throws IOException {
try {
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+ ParcelFileDescriptor fd = getWallpaperService().setWallpaper(null);
if (fd == null) {
return;
}
@@ -627,13 +627,16 @@ class ApplicationContext extends Context {
@Override
public void clearWallpaper() throws IOException {
try {
+ Resources resources = getResources();
/* Set the wallpaper to the default values */
- ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
+ ParcelFileDescriptor fd = getWallpaperService().setWallpaper(
+ "res:" + resources.getResourceName(
+ com.android.internal.R.drawable.default_wallpaper));
if (fd != null) {
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- setWallpaper(getResources().openRawResource(
+ setWallpaper(resources.openRawResource(
com.android.internal.R.drawable.default_wallpaper),
fos);
} finally {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 95b376c..f6ef549 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -266,7 +266,11 @@ public interface IActivityManager extends IInterface {
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded)
throws RemoteException;
-
+
+ public void killApplicationWithUid(String pkg, int uid) throws RemoteException;
+
+ public void closeSystemDialogs(String reason) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -421,4 +425,6 @@ public interface IActivityManager extends IInterface {
int REGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
int UNREGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
+ int KILL_APPLICATION_WITH_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+ int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
}
diff --git a/core/java/android/app/IActivityWatcher.aidl b/core/java/android/app/IActivityWatcher.aidl
index 5d36e3f..6737545 100644
--- a/core/java/android/app/IActivityWatcher.aidl
+++ b/core/java/android/app/IActivityWatcher.aidl
@@ -23,4 +23,5 @@ package android.app;
*/
oneway interface IActivityWatcher {
void activityResuming(int activityId);
+ void closingSystemDialogs(String reason);
}
diff --git a/core/java/android/app/IWallpaperService.aidl b/core/java/android/app/IWallpaperService.aidl
index a332b1a..281a060 100644
--- a/core/java/android/app/IWallpaperService.aidl
+++ b/core/java/android/app/IWallpaperService.aidl
@@ -25,7 +25,7 @@ interface IWallpaperService {
/**
* Set the wallpaper.
*/
- ParcelFileDescriptor setWallpaper();
+ ParcelFileDescriptor setWallpaper(String name);
/**
* Get the wallpaper.
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index f9c38f9..f7479bc 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -273,11 +273,6 @@ public final class PendingIntent implements Parcelable {
return null;
}
- private class IntentSenderWrapper extends IntentSender {
- protected IntentSenderWrapper(IIntentSender target) {
- super(target);
- }
- }
/**
* Retrieve a IntentSender object that wraps the existing sender of the PendingIntent
*
@@ -285,7 +280,7 @@ public final class PendingIntent implements Parcelable {
*
*/
public IntentSender getIntentSender() {
- return new IntentSenderWrapper(mTarget);
+ return new IntentSender(mTarget);
}
/**
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index dd70130..18e4a52 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -51,6 +51,7 @@ import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
+import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -244,7 +245,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
return success;
}
-
+
+ private boolean isInRealAppSearch() {
+ return !mGlobalSearchMode
+ && (mPreviousComponents == null || mPreviousComponents.isEmpty());
+ }
+
/**
* Called in response to a press of the hard search button in
* {@link #onKeyDown(int, KeyEvent)}, this method toggles between in-app
@@ -264,6 +270,16 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (!mGlobalSearchMode) {
mStoredComponentName = mLaunchComponent;
mStoredAppSearchData = mAppSearchData;
+
+ // If this is the browser, we have a special case to not show the icon to the left
+ // of the text field, for extra space for url entry (this should be reconciled in
+ // Eclair). So special case a second tap of the search button to remove any
+ // already-entered text so that we can be sure to show the "Quick Search Box" hint
+ // text to still make it clear to the user that we've jumped out to global search.
+ //
+ // TODO: When the browser icon issue is reconciled in Eclair, remove this special case.
+ if (isBrowserSearch()) currentSearchText = "";
+
return doShow(currentSearchText, false, null, mAppSearchData, true);
} else {
if (mStoredComponentName != null) {
@@ -535,7 +551,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
// we dismiss the entire dialog instead
mSearchAutoComplete.setDropDownDismissedOnCompletion(false);
- if (mGlobalSearchMode) {
+ if (!isInRealAppSearch()) {
mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in
} else {
mSearchAutoComplete.setDropDownAlwaysVisible(false);
@@ -571,7 +587,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
private void updateSearchAppIcon() {
- if (mGlobalSearchMode) {
+ // In Donut, we special-case the case of the browser to hide the app icon as if it were
+ // global search, for extra space for url entry.
+ //
+ // TODO: Remove this special case once the issue has been reconciled in Eclair.
+ if (mGlobalSearchMode || isBrowserSearch()) {
mAppIcon.setImageResource(0);
mAppIcon.setVisibility(View.GONE);
mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_GLOBAL,
@@ -664,6 +684,49 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
/**
+ * Hack to determine whether this is the browser, so we can remove the browser icon
+ * to the left of the search field, as a special requirement for Donut.
+ *
+ * TODO: For Eclair, reconcile this with the rest of the global search UI.
+ */
+ private boolean isBrowserSearch() {
+ return mLaunchComponent.flattenToShortString().startsWith("com.android.browser/");
+ }
+
+ /*
+ * Menu.
+ */
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Show search settings menu item if anyone handles the intent for it
+ Intent settingsIntent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS);
+ settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ PackageManager pm = getContext().getPackageManager();
+ ActivityInfo activityInfo = settingsIntent.resolveActivityInfo(pm, 0);
+ if (activityInfo != null) {
+ settingsIntent.setClassName(activityInfo.applicationInfo.packageName,
+ activityInfo.name);
+ CharSequence label = activityInfo.loadLabel(getContext().getPackageManager());
+ menu.add(Menu.NONE, Menu.NONE, Menu.NONE, label)
+ .setIcon(android.R.drawable.ic_menu_preferences)
+ .setAlphabeticShortcut('P')
+ .setIntent(settingsIntent);
+ return true;
+ }
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onMenuOpened(int featureId, Menu menu) {
+ // The menu shows up above the IME, regardless of whether it is in front
+ // of the drop-down or not. This looks weird when there is no IME, so
+ // we make sure it is visible.
+ mSearchAutoComplete.ensureImeVisible();
+ return super.onMenuOpened(featureId, menu);
+ }
+
+ /**
* Listeners of various types
*/
@@ -840,6 +903,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
getContext().startActivity(mVoiceWebSearchIntent);
} else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent);
+
+ // Stop the existing search before starting voice search, or else we'll end
+ // up showing the search dialog again once we return to the app.
+ ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE)).
+ stopSearch();
+
getContext().startActivity(appSearchIntent);
}
} catch (ActivityNotFoundException e) {
@@ -1175,11 +1244,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
// ensure the icons will work for global search
cv.put(SearchManager.SUGGEST_COLUMN_ICON_1,
wrapIconForPackage(
- source,
+ mSearchable.getSuggestPackage(),
getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_1)));
cv.put(SearchManager.SUGGEST_COLUMN_ICON_2,
wrapIconForPackage(
- source,
+ mSearchable.getSuggestPackage(),
getColumnString(c, SearchManager.SUGGEST_COLUMN_ICON_2)));
// the rest can be passed through directly
@@ -1218,11 +1287,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
* Wraps an icon for a particular package. If the icon is a resource id, it is converted into
* an android.resource:// URI.
*
- * @param source The source of the icon
+ * @param packageName The source of the icon
* @param icon The icon retrieved from a suggestion column
* @return An icon string appropriate for the package.
*/
- private String wrapIconForPackage(ComponentName source, String icon) {
+ private String wrapIconForPackage(String packageName, String icon) {
if (icon == null || icon.length() == 0 || "0".equals(icon)) {
// SearchManager specifies that null or zero can be returned to indicate
// no icon. We also allow empty string.
@@ -1230,7 +1299,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
} else if (!Character.isDigit(icon.charAt(0))){
return icon;
} else {
- String packageName = source.getPackageName();
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
@@ -1258,11 +1326,17 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (mGlobalSearchMode) {
launchGlobalSearchIntent(intent);
} else {
+ // If the intent was created from a suggestion, it will always have an explicit
+ // component here.
+ Log.i(LOG_TAG, "Starting (as ourselves) " + intent.toURI());
getContext().startActivity(intent);
- // in global search mode, SearchDialogWrapper#performActivityResuming
+ // If the search switches to a different activity,
+ // SearchDialogWrapper#performActivityResuming
// will handle hiding the dialog when the next activity starts, but for
- // in-app search, we still need to dismiss the dialog.
- dismiss();
+ // real in-app search, we still need to dismiss the dialog.
+ if (isInRealAppSearch()) {
+ dismiss();
+ }
}
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "Failed launch activity: " + intent, ex);
@@ -1296,7 +1370,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
setBrowserApplicationId(intent);
- if (DBG) Log.d(LOG_TAG, "Launching intent " + intent.toURI() + " as " + packageName);
startActivityInPackage(intent, packageName);
}
@@ -1337,6 +1410,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
String resultWho = null;
int requestCode = -1;
boolean onlyIfNeeded = false;
+ Log.i(LOG_TAG, "Starting (uid " + uid + ", " + packageName + ") " + intent.toURI());
int result = ActivityManagerNative.getDefault().startActivityInPackage(
uid, intent, resolvedType, resultTo, resultWho, requestCode, onlyIfNeeded);
checkStartActivityResult(result, intent);
@@ -1401,13 +1475,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
return;
}
if (DBG) Log.d(LOG_TAG, "Switching to " + componentName);
-
- ComponentName previous = mLaunchComponent;
+
+ pushPreviousComponent(mLaunchComponent);
if (!show(componentName, mAppSearchData, false)) {
Log.w(LOG_TAG, "Failed to switch to source " + componentName);
+ popPreviousComponent();
return;
}
- pushPreviousComponent(previous);
String query = intent.getStringExtra(SearchManager.QUERY);
setUserQuery(query);
@@ -1701,6 +1775,12 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
if (mSearchDialog.backToPreviousComponent()) {
return true;
}
+ // If the drop-down obscures the keyboard, the user wouldn't see anything
+ // happening when pressing back, so we dismiss the entire dialog instead.
+ if (isInputMethodNotNeeded()) {
+ mSearchDialog.cancel();
+ return true;
+ }
return false; // will dismiss soft keyboard if necessary
}
return false;
diff --git a/core/java/android/backup/BackupDataInput.java b/core/java/android/backup/BackupDataInput.java
index 69c206c..e67b0be 100644
--- a/core/java/android/backup/BackupDataInput.java
+++ b/core/java/android/backup/BackupDataInput.java
@@ -97,12 +97,7 @@ public class BackupDataInput {
public void skipEntityData() throws IOException {
if (mHeaderReady) {
- int result = skipEntityData_native(mBackupReader);
- if (result >= 0) {
- return;
- } else {
- throw new IOException("result=0x" + Integer.toHexString(result));
- }
+ skipEntityData_native(mBackupReader);
} else {
throw new IllegalStateException("mHeaderReady=false");
}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index d604414..5782644 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -16,8 +16,6 @@
package android.bluetooth;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -75,11 +73,11 @@ public class BluetoothPbap {
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
- /** No headset currently connected */
+ /** No Pce currently connected */
public static final int STATE_DISCONNECTED = 0;
/** Connection attempt in progress */
public static final int STATE_CONNECTING = 1;
- /** A headset is currently connected */
+ /** A Pce is currently connected */
public static final int STATE_CONNECTED = 2;
public static final int RESULT_FAILURE = 0;
@@ -87,11 +85,9 @@ public class BluetoothPbap {
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
- public static final int PRIORITY_AUTO = 100;
- public static final int PRIORITY_OFF = 0;
/**
* An interface for notifying Bluetooth PCE IPC clients when they have
- * been connected to the BluetoothHeadset service.
+ * been connected to the BluetoothPbap service.
*/
public interface ServiceListener {
/**
@@ -113,7 +109,7 @@ public class BluetoothPbap {
}
/**
- * Create a BluetoothHeadset proxy object.
+ * Create a BluetoothPbap proxy object.
*/
public BluetoothPbap(Context context, ServiceListener l) {
mContext = context;
@@ -133,7 +129,7 @@ public class BluetoothPbap {
/**
* Close the connection to the backing service.
- * Other public functions of BluetoothHeadset will return default error
+ * Other public functions of BluetoothPbap will return default error
* results once close() has been called. Multiple invocations of close()
* are ok.
*/
@@ -145,9 +141,9 @@ public class BluetoothPbap {
}
/**
- * Get the current state of the Bluetooth Headset service.
+ * Get the current state of the BluetoothPbap service.
* @return One of the STATE_ return codes, or STATE_ERROR if this proxy
- * object is currently not connected to the Headset service.
+ * object is currently not connected to the Pbap service.
*/
public int getState() {
if (DBG) log("getState()");
@@ -159,13 +155,13 @@ public class BluetoothPbap {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
}
- return BluetoothHeadset.STATE_ERROR;
+ return BluetoothPbap.STATE_ERROR;
}
/**
- * Get the Bluetooth address of the current headset.
+ * Get the Bluetooth address of the current Pce.
* @return The Bluetooth address, or null if not in connected or connecting
- * state, or if this proxy object is not connected to the Headset
+ * state, or if this proxy object is not connected to the Pbap
* service.
*/
public String getPceAddress() {
@@ -182,9 +178,9 @@ public class BluetoothPbap {
}
/**
- * Returns true if the specified headset is connected (does not include
+ * Returns true if the specified Pcs is connected (does not include
* connecting). Returns false if not connected, or if this proxy object
- * if not currently connected to the headset service.
+ * if not currently connected to the Pbap service.
*/
public boolean isConnected(String address) {
if (DBG) log("isConnected(" + address + ")");
@@ -200,9 +196,9 @@ public class BluetoothPbap {
}
/**
- * Disconnects the current headset. Currently this call blocks, it may soon
+ * Disconnects the current Pce. Currently this call blocks, it may soon
* be made asynchornous. Returns false if this proxy object is
- * not currently connected to the Headset service.
+ * not currently connected to the Pbap service.
*/
public boolean disconnectPce() {
if (DBG) log("disconnectPce()");
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 8b0b6ab..c0db01a 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -26,10 +26,14 @@ import java.util.Map;
import java.util.HashMap;
public class ContentProviderOperation implements Parcelable {
- private final static int TYPE_INSERT = 1;
- private final static int TYPE_UPDATE = 2;
- private final static int TYPE_DELETE = 3;
- private final static int TYPE_COUNT = 4;
+ /** @hide exposed for unit tests */
+ public final static int TYPE_INSERT = 1;
+ /** @hide exposed for unit tests */
+ public final static int TYPE_UPDATE = 2;
+ /** @hide exposed for unit tests */
+ public final static int TYPE_DELETE = 3;
+ /** @hide exposed for unit tests */
+ public final static int TYPE_COUNT = 4;
private final int mType;
private final Uri mUri;
@@ -65,7 +69,7 @@ public class ContentProviderOperation implements Parcelable {
mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null;
mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
mValuesBackReferences = source.readInt() != 0
-
+
? ContentValues.CREATOR.createFromParcel(source)
: null;
mSelectionArgsBackReferences = source.readInt() != 0
@@ -167,6 +171,11 @@ public class ContentProviderOperation implements Parcelable {
return mUri;
}
+ /** @hide exposed for unit tests */
+ public int getType() {
+ return mType;
+ }
+
public boolean isWriteOperation() {
return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
}
@@ -492,7 +501,7 @@ public class ContentProviderOperation implements Parcelable {
}
return this;
}
-
+
/**
* The selection and arguments to use. An occurrence of '?' in the selection will be
* replaced with the corresponding occurence of the selection argument. Any of the
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c6c9835..84449ef 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1293,7 +1293,8 @@ public abstract class Context {
* Use with {@link #getSystemService} to retrieve an
* {@blink android.backup.IBackupManager IBackupManager} for communicating
* with the backup mechanism.
- *
+ * @hide
+ *
* @see #getSystemService
*/
public static final String BACKUP_SERVICE = "backup";
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 45a082a..15612ce 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -135,6 +135,7 @@ public class ContextWrapper extends Context {
return mBase.getPackageCodePath();
}
+ /** @hide */
@Override
public File getSharedPrefsFile(String name) {
return mBase.getSharedPrefsFile(name);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 66b507d..f9b082f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1409,6 +1409,17 @@ public class Intent implements Parcelable {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN";
/**
+ * Activity Action: Start this activity to request system shutdown.
+ * The optional boolean extra field {@link #EXTRA_KEY_CONFIRM} can be set to true
+ * to request confirmation from the user before shutting down.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system.
+ *
+ * {@hide}
+ */
+ public static final String ACTION_REQUEST_SHUTDOWN = "android.intent.action.ACTION_REQUEST_SHUTDOWN";
+ /**
* Broadcast Action: Indicates low memory condition on the device
*
* <p class="note">This is a protected intent that can only be sent
@@ -1684,53 +1695,7 @@ public class Intent implements Parcelable {
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_REBOOT =
"android.intent.action.REBOOT";
- /**
- * Broadcast Action: Triggers the platform Text-To-Speech engine to
- * start the activity that installs the resource files on the device
- * that are required for TTS to be operational. Since the installation
- * of the data can be interrupted or declined by the user, the application
- * shouldn't expect successful installation upon return from that intent,
- * and if need be, should check installation status with
- * {@link #ACTION_TTS_CHECK_TTS_DATA}.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TTS_INSTALL_TTS_DATA =
- "android.intent.action.INSTALL_TTS_DATA";
-
- /**
- * Broadcast Action: Starts the activity from the platform Text-To-Speech
- * engine to verify the proper installation and availability of the
- * resource files on the system. Upon completion, the activity will
- * return one of the following codes:
- * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_PASS},
- * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_FAIL},
- * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_BAD_DATA},
- * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_MISSING_DATA}, or
- * {@link android.speech.tts.TextToSpeech.Engine#CHECK_VOICE_DATA_MISSING_VOLUME}.
- * <p> Moreover, the data received in the activity result will contain the following
- * fields:
- * <ul>
- * <li>{@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_ROOT_DIRECTORY} which
- * indicates the path to the location of the resource files</li>,
- * <li>{@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_FILES} which contains
- * the list of all the resource files</li>,
- * <li>and {@link android.speech.tts.TextToSpeech.Engine#VOICE_DATA_FILES_INFO} which
- * contains, for each resource file, the description of the language covered by
- * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code,
- * and YYY is the 3-letter ISO country code.</li>
- * </ul>
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TTS_CHECK_TTS_DATA =
- "android.intent.action.CHECK_TTS_DATA";
- /**
- * Broadcast Action: The TextToSpeech synthesizer has completed processing
- * all of the text in the speech queue.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
- "android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED";
/**
* Broadcast Action: a remote intent is to be broadcasted.
@@ -1939,6 +1904,14 @@ public class Intent implements Parcelable {
public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
/**
+ * Set to true in {@link #ACTION_REQUEST_SHUTDOWN} to request confirmation from the user
+ * before shutting down.
+ *
+ * {@hide}
+ */
+ public static final String EXTRA_KEY_CONFIRM = "android.intent.extra.KEY_CONFIRM";
+
+ /**
* Used as an boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} or
* {@link android.content.Intent#ACTION_PACKAGE_CHANGED} intents to override the default action
* of restarting the application.
@@ -2412,7 +2385,7 @@ public class Intent implements Parcelable {
/**
* Create an intent from a URI. This URI may encode the action,
* category, and other intent fields, if it was returned by
- * {@link #toUri}.. If the Intent was not generate by toUri(), its data
+ * {@link #toUri}. If the Intent was not generate by toUri(), its data
* will be the entire URI and its action will be ACTION_VIEW.
*
* <p>The URI given here must not be relative -- that is, it must include
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 4da49d9..0e4d984 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -52,6 +52,9 @@ import android.util.AndroidException;
* categories, and components, and same flags), it will receive a IntentSender
* representing the same token if that is still valid.
*
+ * <p>Instances of this class can not be made directly, but rather must be
+ * created from an existing {@link android.app.PendingIntent} with
+ * {@link android.app.PendingIntent#getIntentSender() PendingIntent.getIntentSender()}.
*/
public class IntentSender implements Parcelable {
private final IIntentSender mTarget;
@@ -245,11 +248,13 @@ public class IntentSender implements Parcelable {
return b != null ? new IntentSender(b) : null;
}
- protected IntentSender(IIntentSender target) {
+ /** @hide */
+ public IntentSender(IIntentSender target) {
mTarget = target;
}
- protected IntentSender(IBinder target) {
+ /** @hide */
+ public IntentSender(IBinder target) {
mTarget = IIntentSender.Stub.asInterface(target);
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9ca11cd..0a42a6f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -131,8 +131,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7;
/**
- * Value for {@link #flags}: this is set of the application has set
- * its android:targetSdkVersion to something >= the current SDK version.
+ * Value for {@link #flags}: this is set of the application has specified
+ * {@link android.R.styleable#AndroidManifestApplication_testOnly
+ * android:testOnly} to be true.
*/
public static final int FLAG_TEST_ONLY = 1<<8;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 5c7b01f..8ebe093 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -637,12 +637,13 @@ public final class AssetManager {
* mRetData. */
private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
boolean resolve);
- /*package*/ static final int STYLE_NUM_ENTRIES = 5;
+ /*package*/ static final int STYLE_NUM_ENTRIES = 6;
/*package*/ static final int STYLE_TYPE = 0;
/*package*/ static final int STYLE_DATA = 1;
/*package*/ static final int STYLE_ASSET_COOKIE = 2;
/*package*/ static final int STYLE_RESOURCE_ID = 3;
/*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+ /*package*/ static final int STYLE_DENSITY = 5;
/*package*/ native static final boolean applyStyle(int theme,
int defStyleAttr, int defStyleRes, int xmlParser,
int[] inAttrs, int[] outValues, int[] outIndices);
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 3a32c03..016ee7f 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -654,6 +654,7 @@ public class TypedArray {
outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS];
+ outValue.density = data[index+AssetManager.STYLE_DENSITY];
if (type == TypedValue.TYPE_STRING) {
outValue.string = loadStringValueAt(index);
}
diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java
index a29c2c8..ec2e78c 100644
--- a/core/java/android/gesture/GestureLibrary.java
+++ b/core/java/android/gesture/GestureLibrary.java
@@ -35,6 +35,7 @@ public abstract class GestureLibrary {
return false;
}
+ /** @hide */
public Learner getLearner() {
return mStore.getLearner();
}
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index d9804ea..38d252e 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -25,22 +25,35 @@ import java.util.ArrayList;
import java.util.HashMap;
public abstract class FileObserver {
- public static final int ACCESS = 0x00000001; /* File was accessed */
- public static final int MODIFY = 0x00000002; /* File was modified */
- public static final int ATTRIB = 0x00000004; /* Metadata changed */
- public static final int CLOSE_WRITE = 0x00000008; /* Writtable file was closed */
- public static final int CLOSE_NOWRITE = 0x00000010; /* Unwrittable file closed */
- public static final int OPEN = 0x00000020; /* File was opened */
- public static final int MOVED_FROM = 0x00000040; /* File was moved from X */
- public static final int MOVED_TO = 0x00000080; /* File was moved to Y */
- public static final int CREATE = 0x00000100; /* Subfile was created */
- public static final int DELETE = 0x00000200; /* Subfile was deleted */
- public static final int DELETE_SELF = 0x00000400; /* Self was deleted */
- public static final int MOVE_SELF = 0x00000800; /* Self was moved */
+ /** File was accessed */
+ public static final int ACCESS = 0x00000001;
+ /** File was modified */
+ public static final int MODIFY = 0x00000002;
+ /** Metadata changed */
+ public static final int ATTRIB = 0x00000004;
+ /** Writable file was closed */
+ public static final int CLOSE_WRITE = 0x00000008;
+ /** Unwrittable file closed */
+ public static final int CLOSE_NOWRITE = 0x00000010;
+ /** File was opened */
+ public static final int OPEN = 0x00000020;
+ /** File was moved from X */
+ public static final int MOVED_FROM = 0x00000040;
+ /** File was moved to Y */
+ public static final int MOVED_TO = 0x00000080;
+ /** Subfile was created */
+ public static final int CREATE = 0x00000100;
+ /** Subfile was deleted */
+ public static final int DELETE = 0x00000200;
+ /** Self was deleted */
+ public static final int DELETE_SELF = 0x00000400;
+ /** Self was moved */
+ public static final int MOVE_SELF = 0x00000800;
+
public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
| CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
| DELETE_SELF | MOVE_SELF;
-
+
private static final String LOG_TAG = "FileObserver";
private static class ObserverThread extends Thread {
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 5486920..188e7ff 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -26,6 +26,7 @@ interface IPowerManager
void userActivity(long when, boolean noChangeLights);
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
void setPokeLock(int pokey, IBinder lock, String tag);
+ int getSupportedWakeLockFlags();
void setStayOnSetting(int val);
long getScreenOnTime();
void preventScreenOn(boolean prevent);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index bfcf2fc..d5934102 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -114,12 +114,14 @@ public class PowerManager
private static final int WAKE_BIT_SCREEN_DIM = 4;
private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
+ private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
| WAKE_BIT_CPU_WEAK
| WAKE_BIT_SCREEN_DIM
| WAKE_BIT_SCREEN_BRIGHT
- | WAKE_BIT_KEYBOARD_BRIGHT;
+ | WAKE_BIT_KEYBOARD_BRIGHT
+ | WAKE_BIT_PROXIMITY_SCREEN_OFF;
/**
* Wake lock that ensures that the CPU is running. The screen might
@@ -147,6 +149,16 @@ public class PowerManager
public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
/**
+ * Wake lock that turns the screen off when the proximity sensor activates.
+ * Since not all devices have proximity sensors, use
+ * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
+ * this wake lock mode is supported.
+ *
+ * {@hide}
+ */
+ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF;
+
+ /**
* Normally wake locks don't actually wake the device, they just cause
* it to remain on once it's already on. Think of the video player
* app as the normal behavior. Notifications that pop up and want
@@ -196,6 +208,7 @@ public class PowerManager
case SCREEN_DIM_WAKE_LOCK:
case SCREEN_BRIGHT_WAKE_LOCK:
case FULL_WAKE_LOCK:
+ case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
break;
default:
throw new IllegalArgumentException();
@@ -365,7 +378,33 @@ public class PowerManager
} catch (RemoteException e) {
}
}
-
+
+ /**
+ * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
+ * that are supported on the device.
+ * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
+ * is supported:
+ *
+ * {@samplecode
+ * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ * int supportedFlags = pm.getSupportedWakeLockFlags();
+ * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
+ * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
+ * }
+ *
+ * @return the set of supported WakeLock flags.
+ *
+ * {@hide}
+ */
+ public int getSupportedWakeLockFlags()
+ {
+ try {
+ return mService.getSupportedWakeLockFlags();
+ } catch (RemoteException e) {
+ return 0;
+ }
+ }
+
private PowerManager()
{
}
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index abdcd93..db25cfa 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -28,6 +28,7 @@ import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.System;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.View;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -36,7 +37,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
* @hide
*/
public class VolumePreference extends SeekBarPreference implements
- PreferenceManager.OnActivityStopListener {
+ PreferenceManager.OnActivityStopListener, View.OnKeyListener {
private static final String TAG = "VolumePreference";
@@ -66,6 +67,30 @@ public class VolumePreference extends SeekBarPreference implements
mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType);
getPreferenceManager().registerOnActivityStopListener(this);
+
+ // grab focus and key events so that pressing the volume buttons in the
+ // dialog doesn't also show the normal volume adjust toast.
+ view.setOnKeyListener(this);
+ view.setFocusableInTouchMode(true);
+ view.requestFocus();
+ }
+
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN);
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ if (isdown) {
+ mSeekBarVolumizer.changeVolumeBy(-1);
+ }
+ return true;
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ if (isdown) {
+ mSeekBarVolumizer.changeVolumeBy(1);
+ }
+ return true;
+ default:
+ return false;
+ }
}
@Override
@@ -158,7 +183,9 @@ public class VolumePreference extends SeekBarPreference implements
}
mRingtone = RingtoneManager.getRingtone(mContext, defaultUri);
- mRingtone.setStreamType(mStreamType);
+ if (mRingtone != null) {
+ mRingtone.setStreamType(mStreamType);
+ }
}
public void stop() {
@@ -215,5 +242,12 @@ public class VolumePreference extends SeekBarPreference implements
return mSeekBar;
}
+ public void changeVolumeBy(int amount) {
+ mSeekBar.incrementProgressBy(amount);
+ if (mRingtone != null && !mRingtone.isPlaying()) {
+ sample();
+ }
+ postSetVolume(mSeekBar.getProgress());
+ }
}
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index fce8630..01189fe 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -113,7 +113,7 @@ public final class ContactsContract {
public static final String SEND_TO_VOICEMAIL = "send_to_voicemail";
}
- private interface AggregatesColumns {
+ private interface ContactsColumns {
/**
* The display name for the contact.
* <P>Type: TEXT</P>
@@ -140,7 +140,7 @@ public final class ContactsContract {
/**
* Lookup value that reflects the {@link Groups#GROUP_VISIBLE} state of
- * any {@link GroupMembership} for this aggregate.
+ * any {@link GroupMembership} for this contact.
*/
public static final String IN_VISIBLE_GROUP = "in_visible_group";
@@ -171,32 +171,33 @@ public final class ContactsContract {
/**
- * Constants for the aggregates table, which contains a record per group
- * of contact representing the same person.
+ * Constants for the contacts table, which contains a record per group
+ * of raw contact representing the same person.
*/
- public static final class Aggregates implements BaseColumns, AggregatesColumns,
+ // TODO make final once renaming is complete
+ public static /*final*/ class Contacts implements BaseColumns, ContactsColumns,
ContactOptionsColumns {
/**
* This utility class cannot be instantiated
*/
- private Aggregates() {}
+ private Contacts() {}
/**
* The content:// style URI for this table
*/
- public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "aggregates");
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
/**
* The content:// style URI for this table joined with useful data from
* {@link Data}.
*/
public static final Uri CONTENT_SUMMARY_URI = Uri.withAppendedPath(AUTHORITY_URI,
- "aggregates_summary");
+ "contacts_summary");
/**
* The content:// style URI used for "type-to-filter" functionality on the
* {@link #CONTENT_SUMMARY_URI} URI. The filter string will be used to match
- * various parts of the aggregate name. The filter argument should be passed
+ * various parts of the contact name. The filter argument should be passed
* as an additional path segment after this URI.
*/
public static final Uri CONTENT_SUMMARY_FILTER_URI = Uri.withAppendedPath(
@@ -204,8 +205,8 @@ public final class ContactsContract {
/**
* The content:// style URI for this table joined with useful data from
- * {@link Data}, filtered to include only starred aggregates
- * and the most frequently contacted aggregates.
+ * {@link Data}, filtered to include only starred contacts
+ * and the most frequently contacted contacts.
*/
public static final Uri CONTENT_SUMMARY_STREQUENT_URI = Uri.withAppendedPath(
CONTENT_SUMMARY_URI, "strequent");
@@ -213,7 +214,7 @@ public final class ContactsContract {
/**
* The content:// style URI used for "type-to-filter" functionality on the
* {@link #CONTENT_SUMMARY_STREQUENT_URI} URI. The filter string will be used to match
- * various parts of the aggregate name. The filter argument should be passed
+ * various parts of the contact name. The filter argument should be passed
* as an additional path segment after this URI.
*/
public static final Uri CONTENT_SUMMARY_STREQUENT_FILTER_URI = Uri.withAppendedPath(
@@ -225,16 +226,16 @@ public final class ContactsContract {
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person_aggregate";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person_aggregate";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact";
/**
- * A sub-directory of a single contact aggregate that contains all of their
+ * A sub-directory of a single contact that contains all of the constituent raw contact
* {@link Data} rows.
*/
public static final class Data implements BaseColumns, DataColumns {
@@ -251,10 +252,10 @@ public final class ContactsContract {
/**
* A sub-directory of a single contact aggregate that contains all aggregation suggestions
- * (other aggregates). The aggregation suggestions are computed based on approximate
- * data matches with this aggregate.
+ * (other contacts). The aggregation suggestions are computed based on approximate
+ * data matches with this contact.
*/
- public static final class AggregationSuggestions implements BaseColumns, AggregatesColumns {
+ public static final class AggregationSuggestions implements BaseColumns, ContactsColumns {
/**
* No public constructor since this is a utility class
*/
@@ -275,6 +276,9 @@ public final class ContactsContract {
}
}
+ @Deprecated
+ public static final class Aggregates extends Contacts {}
+
/**
* Columns that appear when each row of a table belongs to a specific
* account, including sync information that an account may need.
@@ -317,10 +321,11 @@ public final class ContactsContract {
private interface RawContactsColumns {
/**
- * A reference to the {@link Aggregates#_ID} that this data belongs to.
+ * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} that this
+ * data belongs to.
* <P>Type: INTEGER</P>
*/
- public static final String AGGREGATE_ID = "aggregate_id";
+ public static final String CONTACT_ID = "contact_id";
/**
* Flag indicating that this {@link RawContacts} entry and its children has
@@ -340,11 +345,10 @@ public final class ContactsContract {
/**
* The "deleted" flag: "0" by default, "1" if the row has been marked
* for deletion. When {@link android.content.ContentResolver#delete} is
- * called on a contact, it is marked for deletion and removed from its
- * aggregate. The sync adaptor deletes the contact on the server and
+ * called on a raw contact, it is marked for deletion and removed from its
+ * aggregate contact. The sync adaptor deletes the raw contact on the server and
* then calls ContactResolver.delete once more, this time passing the
- * {@link android.provider.ContactsContract.Contacts#DELETE_PERMANENTLY}
- * query parameter to finalize the data removal.
+ * {@link RawContacts#DELETE_PERMANENTLY} query parameter to finalize the data removal.
* <P>Type: INTEGER</P>
*/
public static final String DELETED = "deleted";
@@ -355,8 +359,7 @@ public final class ContactsContract {
* information per sync source. Sync adapters and contact management apps
* are the primary consumers of this API.
*/
- // TODO make final as soon as renaming is complete
- public static /*final*/ class RawContacts implements BaseColumns, RawContactsColumns,
+ public static final class RawContacts implements BaseColumns, RawContactsColumns,
SyncColumns, ContactOptionsColumns {
/**
* This utility class cannot be instantiated
@@ -367,7 +370,7 @@ public final class ContactsContract {
/**
* The content:// style URI for this table
*/
- public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "contacts");
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "raw_contacts");
/**
* The content:// style URL for filtering people by email address. The
@@ -383,13 +386,13 @@ public final class ContactsContract {
* The MIME type of {@link #CONTENT_URI} providing a directory of
* people.
*/
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/raw_contact";
/**
* The MIME type of a {@link #CONTENT_URI} subdirectory of a single
* person.
*/
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/raw_contact";
/**
* Query parameter that can be passed with the {@link #CONTENT_URI} URI
@@ -405,19 +408,19 @@ public final class ContactsContract {
public static final int AGGREGATION_MODE_DEFAULT = 0;
/**
- * Aggregation mode: aggregate at the time the contact is inserted/updated.
+ * Aggregation mode: aggregate at the time the raw contact is inserted/updated.
*/
public static final int AGGREGATION_MODE_IMMEDITATE = 1;
/**
- * Aggregation mode: never aggregate this contact (note that the contact will not
+ * Aggregation mode: never aggregate this raw contact (note that the raw contact will not
* have a corresponding Aggregate and therefore will not be included in Aggregates
* query results.)
*/
public static final int AGGREGATION_MODE_DISABLED = 2;
/**
- * A sub-directory of a single contact that contains all of their {@link Data} rows.
+ * A sub-directory of a single raw contact that contains all of their {@link Data} rows.
* To access this directory append
*/
public static final class Data implements BaseColumns, DataColumns {
@@ -434,13 +437,6 @@ public final class ContactsContract {
}
}
- /**
- * TODO remove as soon as full renaming is complete.
- */
- @Deprecated
- public static final class Contacts extends RawContacts {
- }
-
private interface DataColumns {
/**
* The package name to use when creating {@link Resources} objects for
@@ -455,20 +451,21 @@ public final class ContactsContract {
public static final String MIMETYPE = "mimetype";
/**
- * A reference to the {@link android.provider.ContactsContract.Contacts#_ID}
+ * A reference to the {@link RawContacts#_ID}
* that this data belongs to.
*/
- public static final String CONTACT_ID = "contact_id";
+ public static final String RAW_CONTACT_ID = "raw_contact_id";
/**
- * Whether this is the primary entry of its kind for the contact it belongs to
+ * Whether this is the primary entry of its kind for the raw contact it belongs to
* <P>Type: INTEGER (if set, non-0 means true)</P>
*/
public static final String IS_PRIMARY = "is_primary";
/**
- * Whether this is the primary entry of its kind for the aggregate it belongs to. Any data
- * record that is "super primary" must also be "primary".
+ * Whether this is the primary entry of its kind for the aggregate
+ * contact it belongs to. Any data record that is "super primary" must
+ * also be "primary".
* <P>Type: INTEGER (if set, non-0 means true)</P>
*/
public static final String IS_SUPER_PRIMARY = "is_super_primary";
@@ -514,7 +511,7 @@ public final class ContactsContract {
}
/**
- * Constants for the data table, which contains data points tied to a contact.
+ * Constants for the data table, which contains data points tied to a raw contact.
* For example, a phone number or email address. Each row in this table contains a type
* definition and some generic columns. Each data type can define the meaning for each of
* the generic columns.
@@ -539,10 +536,10 @@ public final class ContactsContract {
/**
* A table that represents the result of looking up a phone number, for
* example for caller ID. The table joins that data row for the phone number
- * with the contact that owns the number. To perform a lookup you must
+ * with the raw contact that owns the number. To perform a lookup you must
* append the number you want to find to {@link #CONTENT_FILTER_URI}.
*/
- public static final class PhoneLookup implements BaseColumns, DataColumns, AggregatesColumns {
+ public static final class PhoneLookup implements BaseColumns, DataColumns, ContactsColumns {
/**
* This utility class cannot be instantiated
*/
@@ -562,7 +559,7 @@ public final class ContactsContract {
/**
* Additional data mixed in with {@link Im.CommonPresenceColumns} to link
- * back to specific {@link ContactsContract.Aggregates#_ID} entries.
+ * back to specific {@link ContactsContract.Contacts#_ID} entries.
*/
private interface PresenceColumns {
@@ -573,11 +570,10 @@ public final class ContactsContract {
public static final String _ID = "presence_id";
/**
- * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} this presence
- * references.
+ * Reference to the {@link RawContacts#_ID} this presence references.
* <P>Type: INTEGER</P>
*/
- public static final String CONTACT_ID = "contact_id";
+ public static final String RAW_CONTACT_ID = "raw_contact_id";
/**
* Reference to the {@link Data#_ID} entry that owns this presence.
@@ -694,9 +690,12 @@ public final class ContactsContract {
public static final String MIMETYPE = "mimetype";
/**
- * The {@link Contacts#_ID} that this data belongs to.
+ * The {@link RawContacts#_ID} that this data belongs to.
*/
- public static final String CONTACT_ID = "contact_id";
+ public static final String RAW_CONTACT_ID = "raw_contact_id";
+
+ @Deprecated
+ public static final String CONTACT_ID = RAW_CONTACT_ID;
}
/**
@@ -835,7 +834,7 @@ public final class ContactsContract {
/**
* The content:// style URI for all data records of the
* {@link Phone#CONTENT_ITEM_TYPE} MIME type, combined with the
- * associated contact and aggregate data.
+ * associated raw contact and aggregate contact data.
*/
public static final Uri CONTENT_URI = Uri.withAppendedPath(Data.CONTENT_URI,
"phones");
@@ -843,7 +842,7 @@ public final class ContactsContract {
/**
* The content:// style URI for filtering data records of the
* {@link Phone#CONTENT_ITEM_TYPE} MIME type, combined with the
- * associated contact and aggregate data. The filter argument should
+ * associated raw contact and aggregate contact data. The filter argument should
* be passed as an additional path segment after this URI.
*/
public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(CONTENT_URI,
@@ -1090,7 +1089,7 @@ public final class ContactsContract {
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
/**
- * Thumbnail photo of the contact. This is the raw bytes of an image
+ * Thumbnail photo of the raw contact. This is the raw bytes of an image
* that could be inflated using {@link BitmapFactory}.
* <p>
* Type: BLOB
@@ -1193,7 +1192,7 @@ public final class ContactsContract {
public static final String SYSTEM_ID = "system_id";
/**
- * The total number of {@link Aggregates} that have
+ * The total number of {@link Contacts} that have
* {@link GroupMembership} in this group. Read-only value that is only
* present when querying {@link Groups#CONTENT_SUMMARY_URI}.
* <p>
@@ -1202,7 +1201,7 @@ public final class ContactsContract {
public static final String SUMMARY_COUNT = "summ_count";
/**
- * The total number of {@link Aggregates} that have both
+ * The total number of {@link Contacts} that have both
* {@link GroupMembership} in this group, and also have phone numbers.
* Read-only value that is only present when querying
* {@link Groups#CONTENT_SUMMARY_URI}.
@@ -1290,31 +1289,33 @@ public final class ContactsContract {
public static final String TYPE = "type";
/**
- * Allows the provider to automatically decide whether the aggregate should include
- * a particular contact or not.
+ * Allows the provider to automatically decide whether the aggregate
+ * contact should include a particular raw contact or not.
*/
public static final int TYPE_AUTOMATIC = 0;
/**
- * Makes sure that the specified contact is included in the specified aggregate.
+ * Makes sure that the specified raw contact is included in the
+ * specified aggregate contact.
*/
public static final int TYPE_KEEP_IN = 1;
/**
- * Makes sure that the specified contact is NOT included in the specified aggregate.
+ * Makes sure that the specified raw contact is NOT included in the
+ * specified aggregate contact.
*/
public static final int TYPE_KEEP_OUT = 2;
/**
- * A reference to the {@link Aggregates#_ID} of the aggregate that the rule applies to.
+ * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} of the
+ * aggregate contact that the rule applies to.
*/
- public static final String AGGREGATE_ID = "aggregate_id";
+ public static final String CONTACT_ID = "contact_id";
/**
- * A reference to the {@link android.provider.ContactsContract.Contacts#_ID} of the
- * contact that the rule applies to.
+ * A reference to the {@link RawContacts#_ID} of the raw contact that the rule applies to.
*/
- public static final String CONTACT_ID = "contact_id";
+ public static final String RAW_CONTACT_ID = "raw_contact_id";
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0c2b65e..1db17c8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -879,6 +879,17 @@ public final class Settings {
public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
/**
+ * A comma separated list of radios that should to be disabled when airplane mode
+ * is on, but can be manually reenabled by the user. For example, if RADIO_WIFI is
+ * added to both AIRPLANE_MODE_RADIOS and AIRPLANE_MODE_TOGGLEABLE_RADIOS, then Wifi
+ * will be turned off when entering airplane mode, but the user will be able to reenable
+ * Wifi in the Settings app.
+ *
+ * {@hide}
+ */
+ public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios";
+
+ /**
* The policy for deciding when Wi-Fi should go to sleep (which will in
* turn switch to using the mobile data as an Internet connection).
* <p>
diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java
index a3b1d6e..ee271ba 100644
--- a/core/java/android/provider/SocialContract.java
+++ b/core/java/android/provider/SocialContract.java
@@ -19,7 +19,7 @@ package android.provider;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.provider.ContactsContract.Aggregates;
+import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
/**
@@ -165,11 +165,11 @@ public class SocialContract {
/**
* The {@link Uri} for the latest social activity performed by any
- * contact aggregated under the specified {@link Aggregates#_ID}. Will
+ * raw contact aggregated under the specified {@link Contacts#_ID}. Will
* also join with most-present {@link Presence} for this aggregate.
*/
- public static final Uri CONTENT_AGGREGATE_STATUS_URI =
- Uri.withAppendedPath(AUTHORITY_URI, "aggregate_status");
+ public static final Uri CONTENT_CONTACT_STATUS_URI =
+ Uri.withAppendedPath(AUTHORITY_URI, "contact_status");
/**
* The MIME type of {@link #CONTENT_URI} providing a directory of social
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index b8a9875..49718cb 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -63,6 +63,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
private static final int MSG_STOP_SEARCH = 2;
// arg1 is activity id
private static final int MSG_ACTIVITY_RESUMING = 3;
+ // obj is the reason
+ private static final int MSG_CLOSING_SYSTEM_DIALOGS = 4;
private static final String KEY_INITIAL_QUERY = "q";
private static final String KEY_LAUNCH_ACTIVITY = "a";
@@ -127,8 +129,7 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
private void registerBroadcastReceiver() {
if (!mReceiverRegistered) {
IntentFilter filter = new IntentFilter(
- Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ Intent.ACTION_CONFIGURATION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, filter, null,
mSearchUiThread);
mReceiverRegistered = true;
@@ -149,12 +150,7 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- if (!"search".equals(intent.getStringExtra("reason"))) {
- if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- performStopSearch();
- }
- } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+ if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
if (DBG) debug(Intent.ACTION_CONFIGURATION_CHANGED);
performOnConfigurationChanged();
}
@@ -219,6 +215,18 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
mSearchUiThread.sendMessage(msg);
}
+ /**
+ * Handles closing of system windows/dialogs
+ * Can be called from any thread.
+ */
+ public void closingSystemDialogs(String reason) {
+ if (DBG) debug("closingSystemDialogs(reason=" + reason + ")");
+ Message msg = Message.obtain();
+ msg.what = MSG_CLOSING_SYSTEM_DIALOGS;
+ msg.obj = reason;
+ mSearchUiThread.sendMessage(msg);
+ }
+
//
// Implementation methods that run on the search UI thread
//
@@ -244,6 +252,9 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
case MSG_ACTIVITY_RESUMING:
performActivityResuming(msg.arg1);
break;
+ case MSG_CLOSING_SYSTEM_DIALOGS:
+ performClosingSystemDialogs((String)msg.obj);
+ break;
}
}
@@ -330,6 +341,19 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
}
/**
+ * Updates due to system dialogs being closed
+ * This must be called on the search UI thread.
+ */
+ void performClosingSystemDialogs(String reason) {
+ if (DBG) debug("performClosingSystemDialogs(): mStartedIdent="
+ + mStartedIdent + ", reason: " + reason);
+ if (!"search".equals(reason)) {
+ if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ performStopSearch();
+ }
+ }
+
+ /**
* Must be called from the search UI thread.
*/
void performOnConfigurationChanged() {
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index fdeb8f9..afed4a4 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -138,6 +138,11 @@ public class SearchManagerService extends ISearchManager.Stub {
if (mSearchDialog == null) return;
mSearchDialog.activityResuming(activityId);
}
+ public void closingSystemDialogs(String reason) {
+ if (DBG) Log.i("foo", "********************** closing dialogs: " + reason);
+ if (mSearchDialog == null) return;
+ mSearchDialog.closingSystemDialogs(reason);
+ }
};
/**
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
index 045b0c2..69ef98c 100644
--- a/core/java/android/server/search/SearchableInfo.java
+++ b/core/java/android/server/search/SearchableInfo.java
@@ -103,6 +103,14 @@ public final class SearchableInfo implements Parcelable {
}
/**
+ * Gets the name of the package where the suggestion provider lives,
+ * or {@code null}.
+ */
+ public String getSuggestPackage() {
+ return mSuggestProviderPackage;
+ }
+
+ /**
* Gets the component name of the searchable activity.
*/
public ComponentName getSearchActivity() {
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 8f8d976..b033c6a 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -18,6 +18,8 @@ package android.speech.tts;
import android.speech.tts.ITts;
import android.speech.tts.ITtsCallback;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -41,51 +43,60 @@ public class TextToSpeech {
/**
* Denotes a successful operation.
*/
- public static final int TTS_SUCCESS = 0;
+ public static final int SUCCESS = 0;
/**
* Denotes a generic operation failure.
*/
- public static final int TTS_ERROR = -1;
+ public static final int ERROR = -1;
/**
* Queue mode where all entries in the playback queue (media to be played
* and text to be synthesized) are dropped and replaced by the new entry.
*/
- public static final int TTS_QUEUE_FLUSH = 0;
+ public static final int QUEUE_FLUSH = 0;
/**
* Queue mode where the new entry is added at the end of the playback queue.
*/
- public static final int TTS_QUEUE_ADD = 1;
+ public static final int QUEUE_ADD = 1;
/**
* Denotes the language is available exactly as specified by the locale
*/
- public static final int TTS_LANG_COUNTRY_VAR_AVAILABLE = 2;
+ public static final int LANG_COUNTRY_VAR_AVAILABLE = 2;
/**
* Denotes the language is available for the language and country specified
* by the locale, but not the variant.
*/
- public static final int TTS_LANG_COUNTRY_AVAILABLE = 1;
+ public static final int LANG_COUNTRY_AVAILABLE = 1;
/**
* Denotes the language is available for the language by the locale,
* but not the country and variant.
*/
- public static final int TTS_LANG_AVAILABLE = 0;
+ public static final int LANG_AVAILABLE = 0;
/**
* Denotes the language data is missing.
*/
- public static final int TTS_LANG_MISSING_DATA = -1;
+ public static final int LANG_MISSING_DATA = -1;
/**
* Denotes the language is not supported by the current TTS engine.
*/
- public static final int TTS_LANG_NOT_SUPPORTED = -2;
+ public static final int LANG_NOT_SUPPORTED = -2;
+
+
+ /**
+ * Broadcast Action: The TextToSpeech synthesizer has completed processing
+ * of all the text in the speech queue.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
+ "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
/**
@@ -119,126 +130,167 @@ public class TextToSpeech {
/**
* {@hide}
*/
- public static final int FALLBACK_TTS_DEFAULT_RATE = 100; // 1x
+ public static final int DEFAULT_RATE = 100; // 1x
/**
* {@hide}
*/
- public static final int FALLBACK_TTS_DEFAULT_PITCH = 100;// 1x
+ public static final int DEFAULT_PITCH = 100;// 1x
/**
* {@hide}
*/
- public static final int FALLBACK_TTS_USE_DEFAULTS = 0; // false
+ public static final int USE_DEFAULTS = 0; // false
/**
* {@hide}
*/
- public static final String FALLBACK_TTS_DEFAULT_SYNTH = "com.svox.pico";
+ public static final String DEFAULT_SYNTH = "com.svox.pico";
// default values for rendering
- public static final int TTS_DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
+ public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
// return codes for a TTS engine's check data activity
/**
* Indicates success when checking the installation status of the resources used by the
- * text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent.
+ * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_PASS = 1;
/**
* Indicates failure when checking the installation status of the resources used by the
- * text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent.
+ * text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_FAIL = 0;
/**
* Indicates erroneous data when checking the installation status of the resources used by
- * the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent.
+ * the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
/**
* Indicates missing resources when checking the installation status of the resources used
- * by the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent.
+ * by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
/**
* Indicates missing storage volume when checking the installation status of the resources
- * used by the text-to-speech engine with the android.intent.action.CHECK_TTS_DATA intent.
+ * used by the text-to-speech engine with the {@link #ACTION_CHECK_TTS_DATA} intent.
*/
public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3;
- // return codes for a TTS engine's check data activity
+ // intents to ask engine to install data or check its data
+ /**
+ * Broadcast Action: Triggers the platform Text-To-Speech engine to
+ * start the activity that installs the resource files on the device
+ * that are required for TTS to be operational. Since the installation
+ * of the data can be interrupted or declined by the user, the application
+ * shouldn't expect successful installation upon return from that intent,
+ * and if need be, should check installation status with
+ * {@link #ACTION_CHECK_TTS_DATA}.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_INSTALL_TTS_DATA =
+ "android.speech.tts.engine.INSTALL_TTS_DATA";
+
+ /**
+ * Broadcast Action: Starts the activity from the platform Text-To-Speech
+ * engine to verify the proper installation and availability of the
+ * resource files on the system. Upon completion, the activity will
+ * return one of the following codes:
+ * {@link #CHECK_VOICE_DATA_PASS},
+ * {@link #CHECK_VOICE_DATA_FAIL},
+ * {@link #CHECK_VOICE_DATA_BAD_DATA},
+ * {@link #CHECK_VOICE_DATA_MISSING_DATA}, or
+ * {@link #CHECK_VOICE_DATA_MISSING_VOLUME}.
+ * <p> Moreover, the data received in the activity result will contain the following
+ * fields:
+ * <ul>
+ * <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which
+ * indicates the path to the location of the resource files</li>,
+ * <li>{@link #EXTRA_VOICE_DATA_FILES} which contains
+ * the list of all the resource files</li>,
+ * <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which
+ * contains, for each resource file, the description of the language covered by
+ * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code,
+ * and YYY is the 3-letter ISO country code.</li>
+ * </ul>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_CHECK_TTS_DATA =
+ "android.speech.tts.engine.CHECK_TTS_DATA";
+
+ // extras for a TTS engine's check data activity
/**
- * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where
+ * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
* the text-to-speech engine specifies the path to its resources.
*/
- public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
+ public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
/**
- * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where
+ * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
* the text-to-speech engine specifies the file names of its resources under the
* resource path.
*/
- public static final String VOICE_DATA_FILES = "dataFiles";
+ public static final String EXTRA_VOICE_DATA_FILES = "dataFiles";
/**
- * Extra information received with the android.intent.action.CHECK_TTS_DATA intent where
+ * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
* the text-to-speech engine specifies the locale associated with each resource file.
*/
- public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo";
+ public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
// keys for the parameters passed with speak commands. Hidden keys are used internally
// to maintain engine state for each TextToSpeech instance.
/**
* {@hide}
*/
- public static final String TTS_KEY_PARAM_RATE = "rate";
+ public static final String KEY_PARAM_RATE = "rate";
/**
* {@hide}
*/
- public static final String TTS_KEY_PARAM_LANGUAGE = "language";
+ public static final String KEY_PARAM_LANGUAGE = "language";
/**
* {@hide}
*/
- public static final String TTS_KEY_PARAM_COUNTRY = "country";
+ public static final String KEY_PARAM_COUNTRY = "country";
/**
* {@hide}
*/
- public static final String TTS_KEY_PARAM_VARIANT = "variant";
+ public static final String KEY_PARAM_VARIANT = "variant";
/**
* Parameter key to specify the audio stream type to be used when speaking text
* or playing back a file.
*/
- public static final String TTS_KEY_PARAM_STREAM = "streamType";
+ public static final String KEY_PARAM_STREAM = "streamType";
/**
* Parameter key to identify an utterance in the completion listener after text has been
* spoken, a file has been played back or a silence duration has elapsed.
*/
- public static final String TTS_KEY_PARAM_UTTERANCE_ID = "utteranceId";
+ public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId";
// key positions in the array of cached parameters
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_RATE = 0;
+ protected static final int PARAM_POSITION_RATE = 0;
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_LANGUAGE = 2;
+ protected static final int PARAM_POSITION_LANGUAGE = 2;
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_COUNTRY = 4;
+ protected static final int PARAM_POSITION_COUNTRY = 4;
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_VARIANT = 6;
+ protected static final int PARAM_POSITION_VARIANT = 6;
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_STREAM = 8;
+ protected static final int PARAM_POSITION_STREAM = 8;
/**
* {@hide}
*/
- protected static final int TTS_PARAM_POSITION_UTTERANCE_ID = 10;
+ protected static final int PARAM_POSITION_UTTERANCE_ID = 10;
/**
* {@hide}
*/
- protected static final int TTS_NB_CACHED_PARAMS = 6;
+ protected static final int NB_CACHED_PARAMS = 6;
}
/**
@@ -273,25 +325,25 @@ public class TextToSpeech {
mPackageName = mContext.getPackageName();
mInitListener = listener;
- mCachedParams = new String[2*Engine.TTS_NB_CACHED_PARAMS]; // store key and value
- mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE;
- mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE;
- mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY;
- mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT;
- mCachedParams[Engine.TTS_PARAM_POSITION_STREAM] = Engine.TTS_KEY_PARAM_STREAM;
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = Engine.TTS_KEY_PARAM_UTTERANCE_ID;
+ mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value
+ mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE;
+ mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE;
+ mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY;
+ mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT;
+ mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM;
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID;
- mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] =
- String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE);
+ mCachedParams[Engine.PARAM_POSITION_RATE + 1] =
+ String.valueOf(Engine.DEFAULT_RATE);
// initialize the language cached parameters with the current Locale
Locale defaultLoc = Locale.getDefault();
- mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language();
- mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country();
- mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant();
+ mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language();
+ mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country();
+ mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant();
- mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] =
- String.valueOf(Engine.TTS_DEFAULT_STREAM);
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = "";
+ mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
+ String.valueOf(Engine.DEFAULT_STREAM);
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = "";
initTts();
}
@@ -308,7 +360,7 @@ public class TextToSpeech {
mStarted = true;
if (mInitListener != null) {
// TODO manage failures and missing resources
- mInitListener.onInit(TTS_SUCCESS);
+ mInitListener.onInit(SUCCESS);
}
}
}
@@ -349,8 +401,7 @@ public class TextToSpeech {
/**
* Adds a mapping between a string of text and a sound resource in a
* package.
- *
- * @see #TTS.speak(String text, int queueMode, String[] params)
+ * @see #speak(String, int, HashMap)
*
* @param text
* Example: <b><code>"south_south_east"</code></b><br/>
@@ -371,16 +422,16 @@ public class TextToSpeech {
* @param resourceId
* Example: <b><code>R.raw.south_south_east</code></b>
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int addSpeech(String text, String packagename, int resourceId) {
synchronized(mStartLock) {
if (!mStarted) {
- return TTS_ERROR;
+ return ERROR;
}
try {
mITts.addSpeech(mPackageName, text, packagename, resourceId);
- return TTS_SUCCESS;
+ return SUCCESS;
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - addSpeech", "RemoteException");
@@ -400,7 +451,7 @@ public class TextToSpeech {
mStarted = false;
initTts();
}
- return TTS_ERROR;
+ return ERROR;
}
}
@@ -415,16 +466,16 @@ public class TextToSpeech {
* The full path to the sound file (for example:
* "/sdcard/mysounds/hello.wav")
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int addSpeech(String text, String filename) {
synchronized (mStartLock) {
if (!mStarted) {
- return TTS_ERROR;
+ return ERROR;
}
try {
mITts.addSpeechFile(mPackageName, text, filename);
- return TTS_SUCCESS;
+ return SUCCESS;
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - addSpeech", "RemoteException");
@@ -444,7 +495,7 @@ public class TextToSpeech {
mStarted = false;
initTts();
}
- return TTS_ERROR;
+ return ERROR;
}
}
@@ -453,7 +504,7 @@ public class TextToSpeech {
* Adds a mapping between a string of text and a sound resource in a
* package.
*
- * @see #TTS.playEarcon(String earcon, int queueMode, String[] params)
+ * @see #playEarcon(String, int, HashMap)
*
* @param earcon The name of the earcon
* Example: <b><code>"[tick]"</code></b><br/>
@@ -474,16 +525,16 @@ public class TextToSpeech {
* @param resourceId
* Example: <b><code>R.raw.tick_snd</code></b>
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int addEarcon(String earcon, String packagename, int resourceId) {
synchronized(mStartLock) {
if (!mStarted) {
- return TTS_ERROR;
+ return ERROR;
}
try {
mITts.addEarcon(mPackageName, earcon, packagename, resourceId);
- return TTS_SUCCESS;
+ return SUCCESS;
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - addEarcon", "RemoteException");
@@ -503,7 +554,7 @@ public class TextToSpeech {
mStarted = false;
initTts();
}
- return TTS_ERROR;
+ return ERROR;
}
}
@@ -518,16 +569,16 @@ public class TextToSpeech {
* The full path to the sound file (for example:
* "/sdcard/mysounds/tick.wav")
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int addEarcon(String earcon, String filename) {
synchronized (mStartLock) {
if (!mStarted) {
- return TTS_ERROR;
+ return ERROR;
}
try {
mITts.addEarconFile(mPackageName, earcon, filename);
- return TTS_SUCCESS;
+ return SUCCESS;
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - addEarcon", "RemoteException");
@@ -547,7 +598,7 @@ public class TextToSpeech {
mStarted = false;
initTts();
}
- return TTS_ERROR;
+ return ERROR;
}
}
@@ -563,29 +614,29 @@ public class TextToSpeech {
* The string of text to be spoken.
* @param queueMode
* The queuing strategy to use.
- * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
+ * See QUEUE_ADD and QUEUE_FLUSH.
* @param params
* The hashmap of speech parameters to be used.
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int speak(String text, int queueMode, HashMap<String,String> params)
{
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
Log.i("TTS received: ", text);
if (!mStarted) {
return result;
}
try {
if ((params != null) && (!params.isEmpty())) {
- String extra = params.get(Engine.TTS_KEY_PARAM_STREAM);
+ String extra = params.get(Engine.KEY_PARAM_STREAM);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
}
- extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
+ extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
}
}
result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
@@ -621,28 +672,28 @@ public class TextToSpeech {
* @param earcon
* The earcon that should be played
* @param queueMode
- * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
+ * See QUEUE_ADD and QUEUE_FLUSH.
* @param params
* The hashmap of parameters to be used.
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int playEarcon(String earcon, int queueMode,
HashMap<String,String> params) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
try {
if ((params != null) && (!params.isEmpty())) {
- String extra = params.get(Engine.TTS_KEY_PARAM_STREAM);
+ String extra = params.get(Engine.KEY_PARAM_STREAM);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra;
}
- extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
+ extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
}
}
result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
@@ -678,21 +729,21 @@ public class TextToSpeech {
* @param durationInMs
* A long that indicates how long the silence should last.
* @param queueMode
- * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
+ * See QUEUE_ADD and QUEUE_FLUSH.
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
try {
if ((params != null) && (!params.isEmpty())) {
- String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
+ String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
}
}
result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams);
@@ -760,11 +811,11 @@ public class TextToSpeech {
/**
* Stops speech from the TTS.
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int stop() {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
@@ -808,24 +859,24 @@ public class TextToSpeech {
* lower values slow down the speech (0.5 is half the normal speech rate),
* greater values accelerate it (2 is twice the normal speech rate).
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int setSpeechRate(float speechRate) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
try {
if (speechRate > 0) {
int rate = (int)(speechRate*100);
- mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(rate);
+ mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(rate);
// the rate is not set here, instead it is cached so it will be associated
// with all upcoming utterances.
if (speechRate > 0.0f) {
- result = TTS_SUCCESS;
+ result = SUCCESS;
} else {
- result = TTS_ERROR;
+ result = ERROR;
}
}
} catch (NullPointerException e) {
@@ -860,11 +911,11 @@ public class TextToSpeech {
* lower values lower the tone of the synthesized voice,
* greater values increase it.
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int setPitch(float pitch) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
@@ -907,27 +958,27 @@ public class TextToSpeech {
* @param loc
* The locale describing the language to be used.
*
- * @return code indicating the support status for the locale. See {@link #TTS_LANG_AVAILABLE},
- * {@link #TTS_LANG_COUNTRY_AVAILABLE}, {@link #TTS_LANG_COUNTRY_VAR_AVAILABLE},
- * {@link #TTS_LANG_MISSING_DATA} and {@link #TTS_LANG_NOT_SUPPORTED}.
+ * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE},
+ * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE},
+ * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}.
*/
public int setLanguage(Locale loc) {
synchronized (mStartLock) {
- int result = TTS_LANG_NOT_SUPPORTED;
+ int result = LANG_NOT_SUPPORTED;
if (!mStarted) {
return result;
}
try {
- mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language();
- mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
- mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant();
+ mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language();
+ mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
+ mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = loc.getVariant();
// the language is not set here, instead it is cached so it will be associated
// with all upcoming utterances. But we still need to report the language support,
// which is achieved by calling isLanguageAvailable()
result = mITts.isLanguageAvailable(
- mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1],
- mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1],
- mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] );
+ mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1],
+ mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1],
+ mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] );
} catch (RemoteException e) {
// TTS died; restart it.
Log.e("TextToSpeech.java - setLanguage", "RemoteException");
@@ -999,13 +1050,13 @@ public class TextToSpeech {
* @param loc
* The Locale describing the language to be used.
*
- * @return code indicating the support status for the locale. See {@link #TTS_LANG_AVAILABLE},
- * {@link #TTS_LANG_COUNTRY_AVAILABLE}, {@link #TTS_LANG_COUNTRY_VAR_AVAILABLE},
- * {@link #TTS_LANG_MISSING_DATA} and {@link #TTS_LANG_NOT_SUPPORTED}.
+ * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE},
+ * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE},
+ * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}.
*/
public int isLanguageAvailable(Locale loc) {
synchronized (mStartLock) {
- int result = TTS_LANG_NOT_SUPPORTED;
+ int result = LANG_NOT_SUPPORTED;
if (!mStarted) {
return result;
}
@@ -1048,25 +1099,25 @@ public class TextToSpeech {
* The string that gives the full output filename; it should be
* something like "/sdcard/myappsounds/mysound.wav".
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int synthesizeToFile(String text, HashMap<String,String> params,
String filename) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
try {
if ((params != null) && (!params.isEmpty())) {
// no need to read the stream type here
- String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
+ String extra = params.get(Engine.KEY_PARAM_UTTERANCE_ID);
if (extra != null) {
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra;
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra;
}
}
if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){
- result = TTS_SUCCESS;
+ result = SUCCESS;
}
} catch (RemoteException e) {
// TTS died; restart it.
@@ -1099,9 +1150,9 @@ public class TextToSpeech {
* if they are not persistent between calls to the service.
*/
private void resetCachedParams() {
- mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] =
- String.valueOf(Engine.TTS_DEFAULT_STREAM);
- mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = "";
+ mCachedParams[Engine.PARAM_POSITION_STREAM + 1] =
+ String.valueOf(Engine.DEFAULT_STREAM);
+ mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = "";
}
/**
@@ -1110,12 +1161,12 @@ public class TextToSpeech {
* @param listener
* The OnUtteranceCompletedListener
*
- * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
public int setOnUtteranceCompletedListener(
final OnUtteranceCompletedListener listener) {
synchronized (mStartLock) {
- int result = TTS_ERROR;
+ int result = ERROR;
if (!mStarted) {
return result;
}
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 911a23c..86ef5f6 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -33,17 +33,34 @@ public class ImageSpan extends DynamicDrawableSpan {
private Context mContext;
private String mSource;
+ /**
+ * @deprecated Use {@link #ImageSpan(Context, Bitmap)} instead.
+ */
public ImageSpan(Bitmap b) {
- this(b, ALIGN_BOTTOM);
+ this(null, b, ALIGN_BOTTOM);
+ }
+
+ /**
+ * @deprecated Use {@link #ImageSpan(Context, Bitmap, int) instead.
+ */
+ public ImageSpan(Bitmap b, int verticalAlignment) {
+ this(null, b, verticalAlignment);
+ }
+
+ public ImageSpan(Context context, Bitmap b) {
+ this(context, b, ALIGN_BOTTOM);
}
/**
* @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or
* {@link DynamicDrawableSpan#ALIGN_BASELINE}.
*/
- public ImageSpan(Bitmap b, int verticalAlignment) {
+ public ImageSpan(Context context, Bitmap b, int verticalAlignment) {
super(verticalAlignment);
- mDrawable = new BitmapDrawable(mContext.getResources(), b);
+ mContext = context;
+ mDrawable = context != null
+ ? new BitmapDrawable(context.getResources(), b)
+ : new BitmapDrawable(b);
int width = mDrawable.getIntrinsicWidth();
int height = mDrawable.getIntrinsicHeight();
mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0);
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 0f0be79..81dd96e 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -124,10 +124,6 @@ public class EventLog {
"A List must have fewer than "
+ Byte.MAX_VALUE + " items in it.");
}
- if (items.length < 1) {
- throw new IllegalArgumentException(
- "A List must have at least one item in it.");
- }
for (int i = 0; i < items.length; i++) {
final Object item = items[i];
if (item == null) {
@@ -223,7 +219,7 @@ public class EventLog {
case LIST:
if (mBuffer.remaining() < 1) return null;
int length = mBuffer.get();
- if (length <= 0) return null;
+ if (length < 0) return null;
Object[] array = new Object[length];
for (int i = 0; i < length; ++i) {
array[i] = decodeObject();
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index d46660c..ae84e1e 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -516,14 +516,14 @@ public final class MotionEvent implements Parcelable {
}
final int NS = (ev.mNumPointers=o.mNumPointers) * NT;
- if (ev.mStateSamples.length < NS) {
+ if (ev.mStateSamples.length >= NS) {
System.arraycopy(o.mStateSamples, 0, ev.mStateSamples, 0, NS);
} else {
ev.mStateSamples = (int[])o.mStateSamples.clone();
}
final int ND = NS * NUM_SAMPLE_DATA;
- if (ev.mDataSamples.length < ND) {
+ if (ev.mDataSamples.length >= ND) {
System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
} else {
ev.mDataSamples = (float[])o.mDataSamples.clone();
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 9178131..c4bf642 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -107,8 +107,14 @@ public class Surface implements Parcelable {
public static final int SURFACE_HIDDEN = 0x01;
/** Freeze the surface. Equivalent to calling freeze() */
+ public static final int SURFACE_FROZEN = 0x02;
+
+ /**
+ * @deprecated use {@link #SURFACE_FROZEN} instead.
+ */
+ @Deprecated
public static final int SURACE_FROZEN = 0x02;
-
+
/** Enable dithering when compositing this surface */
public static final int SURFACE_DITHER = 0x04;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7ed2712..829f68e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2983,6 +2983,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @param enabled True if this view is enabled, false otherwise.
*/
public void setEnabled(boolean enabled) {
+ if (enabled == isEnabled()) return;
+
setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
/*
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 46aea02..4baf612 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -16,6 +16,7 @@
package android.view;
+import android.util.Config;
import android.util.Log;
import android.util.DisplayMetrics;
import android.content.res.Resources;
@@ -140,7 +141,9 @@ public class ViewDebug {
public static boolean consistencyCheckEnabled = false;
static {
- Debug.setFieldsOn(ViewDebug.class, true);
+ if (Config.DEBUG) {
+ Debug.setFieldsOn(ViewDebug.class, true);
+ }
}
/**
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 884950f..0d44b4e 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -21,7 +21,6 @@ import com.android.internal.view.IInputMethodSession;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
-import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Region;
@@ -1220,6 +1219,8 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
}
+ canvas.setScreenDensity(scalingRequired
+ ? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
@@ -1328,6 +1329,8 @@ public final class ViewRoot extends Handler implements ViewParent,
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
}
+ canvas.setScreenDensity(scalingRequired
+ ? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
} finally {
mAttachInfo.mIgnoreDirtyState = false;
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index a573983..e21824e 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -23,7 +23,9 @@ import android.content.res.Resources;
import android.media.AudioManager;
import android.media.AudioService;
import android.media.AudioSystem;
+import android.media.RingtoneManager;
import android.media.ToneGenerator;
+import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
@@ -44,7 +46,7 @@ import android.widget.Toast;
public class VolumePanel extends Handler
{
private static final String TAG = "VolumePanel";
- private static boolean LOGD = false || Config.LOGD;
+ private static boolean LOGD = false;
/**
* The delay before playing a sound. This small period exists so the user
@@ -86,6 +88,7 @@ public class VolumePanel extends Handler
protected Context mContext;
private AudioManager mAudioManager;
protected AudioService mAudioService;
+ private boolean mRingIsSilent;
private final Toast mToast;
private final View mView;
@@ -138,7 +141,7 @@ public class VolumePanel extends Handler
onShowVolumeChanged(streamType, flags);
}
- if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) {
+ if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 && ! mRingIsSilent) {
removeMessages(MSG_PLAY_SOUND);
sendMessageDelayed(obtainMessage(MSG_PLAY_SOUND, streamType, flags), PLAY_SOUND_DELAY);
}
@@ -157,6 +160,7 @@ public class VolumePanel extends Handler
int index = mAudioService.getStreamVolume(streamType);
int message = UNKNOWN_VOLUME_TEXT;
int additionalMessage = 0;
+ mRingIsSilent = false;
if (LOGD) {
Log.d(TAG, "onShowVolumeChanged(streamType: " + streamType
@@ -169,8 +173,15 @@ public class VolumePanel extends Handler
switch (streamType) {
case AudioManager.STREAM_RING: {
+ setRingerIcon();
message = RINGTONE_VOLUME_TEXT;
- setRingerIcon(index);
+ Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_RINGTONE);
+ if (ringuri == null) {
+ additionalMessage =
+ com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
+ mRingIsSilent = true;
+ }
break;
}
@@ -208,6 +219,13 @@ public class VolumePanel extends Handler
case AudioManager.STREAM_NOTIFICATION: {
message = NOTIFICATION_VOLUME_TEXT;
setSmallIcon(index);
+ Uri ringuri = RingtoneManager.getActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_NOTIFICATION);
+ if (ringuri == null) {
+ additionalMessage =
+ com.android.internal.R.string.volume_music_hint_silent_ringtone_selected;
+ mRingIsSilent = true;
+ }
break;
}
@@ -254,7 +272,6 @@ public class VolumePanel extends Handler
mAudioService.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER)) {
sendMessageDelayed(obtainMessage(MSG_VIBRATE), VIBRATE_DELAY);
}
-
}
protected void onPlaySound(int streamType, int flags) {
@@ -337,17 +354,15 @@ public class VolumePanel extends Handler
/**
* Makes the ringer icon visible with an icon that is chosen
* based on the current ringer mode.
- *
- * @param index
*/
- private void setRingerIcon(int index) {
+ private void setRingerIcon() {
mSmallStreamIcon.setVisibility(View.GONE);
mLargeStreamIcon.setVisibility(View.VISIBLE);
int ringerMode = mAudioService.getRingerMode();
int icon;
- if (LOGD) Log.d(TAG, "setRingerIcon(index: " + index+ "), ringerMode: " + ringerMode);
+ if (LOGD) Log.d(TAG, "setRingerIcon(), ringerMode: " + ringerMode);
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
icon = com.android.internal.R.drawable.ic_volume_off;
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 3b67fb6..ed77ce8 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -72,38 +72,41 @@ class CallbackProxy extends Handler {
private final Context mContext;
// Message Ids
- private static final int PAGE_STARTED = 100;
- private static final int RECEIVED_ICON = 101;
- private static final int RECEIVED_TITLE = 102;
- private static final int OVERRIDE_URL = 103;
- private static final int AUTH_REQUEST = 104;
- private static final int SSL_ERROR = 105;
- private static final int PROGRESS = 106;
- private static final int UPDATE_VISITED = 107;
- private static final int LOAD_RESOURCE = 108;
- private static final int CREATE_WINDOW = 109;
- private static final int CLOSE_WINDOW = 110;
- private static final int SAVE_PASSWORD = 111;
- private static final int JS_ALERT = 112;
- private static final int JS_CONFIRM = 113;
- private static final int JS_PROMPT = 114;
- private static final int JS_UNLOAD = 115;
- private static final int ASYNC_KEYEVENTS = 116;
- private static final int TOO_MANY_REDIRECTS = 117;
- private static final int DOWNLOAD_FILE = 118;
- private static final int REPORT_ERROR = 119;
- private static final int RESEND_POST_DATA = 120;
- private static final int PAGE_FINISHED = 121;
- private static final int REQUEST_FOCUS = 122;
- private static final int SCALE_CHANGED = 123;
- private static final int RECEIVED_CERTIFICATE = 124;
- private static final int SWITCH_OUT_HISTORY = 125;
- private static final int EXCEEDED_DATABASE_QUOTA = 126;
- private static final int JS_TIMEOUT = 127;
- private static final int ADD_MESSAGE_TO_CONSOLE = 128;
+ private static final int PAGE_STARTED = 100;
+ private static final int RECEIVED_ICON = 101;
+ private static final int RECEIVED_TITLE = 102;
+ private static final int OVERRIDE_URL = 103;
+ private static final int AUTH_REQUEST = 104;
+ private static final int SSL_ERROR = 105;
+ private static final int PROGRESS = 106;
+ private static final int UPDATE_VISITED = 107;
+ private static final int LOAD_RESOURCE = 108;
+ private static final int CREATE_WINDOW = 109;
+ private static final int CLOSE_WINDOW = 110;
+ private static final int SAVE_PASSWORD = 111;
+ private static final int JS_ALERT = 112;
+ private static final int JS_CONFIRM = 113;
+ private static final int JS_PROMPT = 114;
+ private static final int JS_UNLOAD = 115;
+ private static final int ASYNC_KEYEVENTS = 116;
+ private static final int TOO_MANY_REDIRECTS = 117;
+ private static final int DOWNLOAD_FILE = 118;
+ private static final int REPORT_ERROR = 119;
+ private static final int RESEND_POST_DATA = 120;
+ private static final int PAGE_FINISHED = 121;
+ private static final int REQUEST_FOCUS = 122;
+ private static final int SCALE_CHANGED = 123;
+ private static final int RECEIVED_CERTIFICATE = 124;
+ private static final int SWITCH_OUT_HISTORY = 125;
+ private static final int EXCEEDED_DATABASE_QUOTA = 126;
+ private static final int REACHED_APPCACHE_MAXSIZE = 127;
+ private static final int JS_TIMEOUT = 128;
+ private static final int ADD_MESSAGE_TO_CONSOLE = 129;
+ private static final int GEOLOCATION_PERMISSIONS_SHOW_PROMPT = 130;
+ private static final int GEOLOCATION_PERMISSIONS_HIDE_PROMPT = 131;
// Message triggered by the client to resume execution
- private static final int NOTIFY = 200;
+ private static final int NOTIFY = 200;
// Result transportation object for returning results across thread
// boundaries.
@@ -410,11 +413,49 @@ class CallbackProxy extends Handler {
String url = (String) map.get("url");
long currentQuota =
((Long) map.get("currentQuota")).longValue();
+ long totalUsedQuota =
+ ((Long) map.get("totalUsedQuota")).longValue();
WebStorage.QuotaUpdater quotaUpdater =
(WebStorage.QuotaUpdater) map.get("quotaUpdater");
mWebChromeClient.onExceededDatabaseQuota(url,
- databaseIdentifier, currentQuota, quotaUpdater);
+ databaseIdentifier, currentQuota, totalUsedQuota,
+ quotaUpdater);
+ }
+ break;
+
+ case REACHED_APPCACHE_MAXSIZE:
+ if (mWebChromeClient != null) {
+ HashMap<String, Object> map =
+ (HashMap<String, Object>) msg.obj;
+ long spaceNeeded =
+ ((Long) map.get("spaceNeeded")).longValue();
+ long totalUsedQuota =
+ ((Long) map.get("totalUsedQuota")).longValue();
+ WebStorage.QuotaUpdater quotaUpdater =
+ (WebStorage.QuotaUpdater) map.get("quotaUpdater");
+
+ mWebChromeClient.onReachedMaxAppCacheSize(spaceNeeded,
+ totalUsedQuota, quotaUpdater);
+ }
+ break;
+
+ case GEOLOCATION_PERMISSIONS_SHOW_PROMPT:
+ if (mWebChromeClient != null) {
+ HashMap<String, Object> map =
+ (HashMap<String, Object>) msg.obj;
+ String origin = (String) map.get("origin");
+ GeolocationPermissions.Callback callback =
+ (GeolocationPermissions.Callback)
+ map.get("callback");
+ mWebChromeClient.onGeolocationPermissionsShowPrompt(origin,
+ callback);
+ }
+ break;
+
+ case GEOLOCATION_PERMISSIONS_HIDE_PROMPT:
+ if (mWebChromeClient != null) {
+ mWebChromeClient.onGeolocationPermissionsHidePrompt();
}
break;
@@ -1120,13 +1161,14 @@ class CallbackProxy extends Handler {
* @param databaseIdentifier The identifier of the database that the
* transaction that caused the overflow was running on.
* @param currentQuota The current quota the origin is allowed.
+ * @param totalUsedQuota is the sum of all origins' quota.
* @param quotaUpdater An instance of a class encapsulating a callback
* to WebViewCore to run when the decision to allow or deny more
* quota has been made.
*/
public void onExceededDatabaseQuota(
String url, String databaseIdentifier, long currentQuota,
- WebStorage.QuotaUpdater quotaUpdater) {
+ long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
if (mWebChromeClient == null) {
quotaUpdater.updateQuota(currentQuota);
return;
@@ -1137,12 +1179,78 @@ class CallbackProxy extends Handler {
map.put("databaseIdentifier", databaseIdentifier);
map.put("url", url);
map.put("currentQuota", currentQuota);
+ map.put("totalUsedQuota", totalUsedQuota);
map.put("quotaUpdater", quotaUpdater);
exceededQuota.obj = map;
sendMessage(exceededQuota);
}
/**
+ * Called by WebViewCore to inform the Java side that the appcache has
+ * exceeded its max size.
+ * @param spaceNeeded is the amount of disk space that would be needed
+ * in order for the last appcache operation to succeed.
+ * @param totalUsedQuota is the sum of all origins' quota.
+ * @param quotaUpdater An instance of a class encapsulating a callback
+ * to WebViewCore to run when the decision to allow or deny a bigger
+ * app cache size has been made.
+ * @hide pending API council approval.
+ */
+ public void onReachedMaxAppCacheSize(long spaceNeeded,
+ long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
+ if (mWebChromeClient == null) {
+ quotaUpdater.updateQuota(0);
+ return;
+ }
+
+ Message msg = obtainMessage(REACHED_APPCACHE_MAXSIZE);
+ HashMap<String, Object> map = new HashMap();
+ map.put("spaceNeeded", spaceNeeded);
+ map.put("totalUsedQuota", totalUsedQuota);
+ map.put("quotaUpdater", quotaUpdater);
+ msg.obj = map;
+ sendMessage(msg);
+ }
+
+ /**
+ * Called by WebViewCore to instruct the browser to display a prompt to ask
+ * the user to set the Geolocation permission state for the given origin.
+ * @param origin The origin requesting Geolocation permsissions.
+ * @param callback The callback to call once a permission state has been
+ * obtained.
+ * @hide pending API council review.
+ */
+ public void onGeolocationPermissionsShowPrompt(String origin,
+ GeolocationPermissions.Callback callback) {
+ if (mWebChromeClient == null) {
+ return;
+ }
+
+ Message showMessage =
+ obtainMessage(GEOLOCATION_PERMISSIONS_SHOW_PROMPT);
+ HashMap<String, Object> map = new HashMap();
+ map.put("origin", origin);
+ map.put("callback", callback);
+ showMessage.obj = map;
+ sendMessage(showMessage);
+ }
+
+ /**
+ * Called by WebViewCore to instruct the browser to hide the Geolocation
+ * permissions prompt.
+ * origin.
+ * @hide pending API council review.
+ */
+ public void onGeolocationPermissionsHidePrompt() {
+ if (mWebChromeClient == null) {
+ return;
+ }
+
+ Message hideMessage = obtainMessage(GEOLOCATION_PERMISSIONS_HIDE_PROMPT);
+ sendMessage(hideMessage);
+ }
+
+ /**
* Called by WebViewCore when we have a message to be added to the JavaScript
* error console. Sends a message to the Java side with the details.
* @param message The message to add to the console.
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
new file mode 100755
index 0000000..d06d7e2
--- /dev/null
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.Set;
+
+
+/**
+ * Implements the Java side of GeolocationPermissions. Simply marshalls calls
+ * from the UI thread to the WebKit thread.
+ * @hide
+ */
+public final class GeolocationPermissions {
+ /**
+ * Callback interface used by the browser to report a Geolocation permission
+ * state set by the user in response to a permissions prompt.
+ */
+ public interface Callback {
+ public void invoke(String origin, boolean allow, boolean remember);
+ };
+
+ // Log tag
+ private static final String TAG = "geolocationPermissions";
+
+ // Global instance
+ private static GeolocationPermissions sInstance;
+
+ private Handler mHandler;
+
+ // Members used to transfer the origins and permissions between threads.
+ private Set<String> mOrigins;
+ private boolean mAllowed;
+ private static Lock mLock = new ReentrantLock();
+ private static boolean mUpdated;
+ private static Condition mUpdatedCondition = mLock.newCondition();
+
+ // Message ids
+ static final int GET_ORIGINS = 0;
+ static final int GET_ALLOWED = 1;
+ static final int CLEAR = 2;
+ static final int CLEAR_ALL = 3;
+
+ /**
+ * Gets the singleton instance of the class.
+ */
+ public static GeolocationPermissions getInstance() {
+ if (sInstance == null) {
+ sInstance = new GeolocationPermissions();
+ }
+ return sInstance;
+ }
+
+ /**
+ * Creates the message handler. Must be called on the WebKit thread.
+ */
+ public void createHandler() {
+ if (mHandler == null) {
+ mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ // Runs on the WebKit thread.
+ switch (msg.what) {
+ case GET_ORIGINS:
+ getOriginsImpl();
+ break;
+ case GET_ALLOWED:
+ getAllowedImpl((String) msg.obj);
+ break;
+ case CLEAR:
+ nativeClear((String) msg.obj);
+ break;
+ case CLEAR_ALL:
+ nativeClearAll();
+ break;
+ }
+ }
+ };
+ }
+ }
+
+ /**
+ * Utility function to send a message to our handler.
+ */
+ private void postMessage(Message msg) {
+ assert(mHandler != null);
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Gets the set of origins for which Geolocation permissions are stored.
+ * Note that we represent the origins as strings. These are created using
+ * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
+ * (Database, Geolocation etc) do so, it's safe to match up origins for the
+ * purposes of displaying UI.
+ */
+ public Set getOrigins() {
+ // Called on the UI thread.
+ Set origins = null;
+ mLock.lock();
+ try {
+ mUpdated = false;
+ postMessage(Message.obtain(null, GET_ORIGINS));
+ while (!mUpdated) {
+ mUpdatedCondition.await();
+ }
+ origins = mOrigins;
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception while waiting for update", e);
+ } finally {
+ mLock.unlock();
+ }
+ return origins;
+ }
+
+ /**
+ * Helper method to get the set of origins.
+ */
+ private void getOriginsImpl() {
+ // Called on the WebKit thread.
+ mLock.lock();
+ mOrigins = nativeGetOrigins();
+ mUpdated = true;
+ mUpdatedCondition.signal();
+ mLock.unlock();
+ }
+
+ /**
+ * Gets the permission state for the specified origin.
+ */
+ public boolean getAllowed(String origin) {
+ // Called on the UI thread.
+ boolean allowed = false;
+ mLock.lock();
+ try {
+ mUpdated = false;
+ postMessage(Message.obtain(null, GET_ALLOWED, origin));
+ while (!mUpdated) {
+ mUpdatedCondition.await();
+ }
+ allowed = mAllowed;
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception while waiting for update", e);
+ } finally {
+ mLock.unlock();
+ }
+ return allowed;
+ }
+
+ /**
+ * Helper method to get the permission state.
+ */
+ private void getAllowedImpl(String origin) {
+ // Called on the WebKit thread.
+ mLock.lock();
+ mAllowed = nativeGetAllowed(origin);
+ mUpdated = true;
+ mUpdatedCondition.signal();
+ mLock.unlock();
+ }
+
+ /**
+ * Clears the permission state for the specified origin.
+ */
+ public void clear(String origin) {
+ // Called on the UI thread.
+ postMessage(Message.obtain(null, CLEAR, origin));
+ }
+
+ /**
+ * Clears the permission state for all origins.
+ */
+ public void clearAll() {
+ // Called on the UI thread.
+ postMessage(Message.obtain(null, CLEAR_ALL));
+ }
+
+ // Native functions, run on the WebKit thread.
+ private static native Set nativeGetOrigins();
+ private static native boolean nativeGetAllowed(String origin);
+ private static native void nativeClear(String origin);
+ private static native void nativeClearAll();
+}
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 3da5a3c..50436d8 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -74,6 +74,7 @@ class LoadListener extends Handler implements EventHandler {
static {
sCertificateMimeTypeMap = new HashSet<String>();
sCertificateMimeTypeMap.add("application/x-x509-ca-cert");
+ sCertificateMimeTypeMap.add("application/x-x509-user-cert");
sCertificateMimeTypeMap.add("application/x-pkcs12");
}
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index b2aa524..a55dbc8 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -330,6 +330,7 @@ public class MimeTypeMap {
sMimeTypeMap.loadEntry("application/x-wingz", "wz");
sMimeTypeMap.loadEntry("application/x-webarchive", "webarchive");
sMimeTypeMap.loadEntry("application/x-x509-ca-cert", "crt");
+ sMimeTypeMap.loadEntry("application/x-x509-user-cert", "crt");
sMimeTypeMap.loadEntry("application/x-xcf", "xcf");
sMimeTypeMap.loadEntry("application/x-xfig", "fig");
sMimeTypeMap.loadEntry("application/xhtml+xml", "xhtml");
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index dd43b8b..d52406d 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -198,17 +198,48 @@ public class WebChromeClient {
* @param databaseIdentifier The identifier of the database that caused the
* quota overflow.
* @param currentQuota The current quota for the origin.
+ * @param totalUsedQuota is the sum of all origins' quota.
* @param quotaUpdater A callback to inform the WebCore thread that a new
* quota is available. This callback must always be executed at some
* point to ensure that the sleeping WebCore thread is woken up.
*/
public void onExceededDatabaseQuota(String url, String databaseIdentifier,
- long currentQuota, WebStorage.QuotaUpdater quotaUpdater) {
+ long currentQuota, long totalUsedQuota,
+ WebStorage.QuotaUpdater quotaUpdater) {
// This default implementation passes the current quota back to WebCore.
// WebCore will interpret this that new quota was declined.
quotaUpdater.updateQuota(currentQuota);
}
+ /**
+ * Tell the client that the Application Cache has exceeded its max size.
+ * @param spaceNeeded is the amount of disk space that would be needed
+ * in order for the last appcache operation to succeed.
+ * @param totalUsedQuota is the sum of all origins' quota.
+ * @param quotaUpdater A callback to inform the WebCore thread that a new
+ * app cache size is available. This callback must always be executed at
+ * some point to ensure that the sleeping WebCore thread is woken up.
+ * @hide pending API council approval.
+ */
+ public void onReachedMaxAppCacheSize(long spaceNeeded, long totalUsedQuota,
+ WebStorage.QuotaUpdater quotaUpdater) {
+ quotaUpdater.updateQuota(0);
+ }
+
+ /**
+ * Instructs the client to show a prompt to ask the user to set the
+ * Geolocation permission state for the specified origin.
+ * @hide pending API council approval.
+ */
+ public void onGeolocationPermissionsShowPrompt(String origin,
+ GeolocationPermissions.Callback callback) {}
+
+ /**
+ * Instructs the client to hide the Geolocation permissions prompt.
+ * @hide pending API council approval.
+ */
+ public void onGeolocationPermissionsHidePrompt() {}
+
/**
* Tell the client that a JavaScript execution timeout has occured. And the
* client may decide whether or not to interrupt the execution. If the
@@ -232,6 +263,5 @@ public class WebChromeClient {
* @param sourceID The name of the source file that caused the error.
* @hide pending API council.
*/
- public void addMessageToConsole(String message, int lineNumber, String sourceID) {
- }
+ public void addMessageToConsole(String message, int lineNumber, String sourceID) {}
}
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 1a60dba..c3b359e 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -55,7 +55,8 @@ public final class WebStorage {
// that we protect via a lock and update in syncValues().
// This is needed to transfer this data across threads.
private static Lock mLock = new ReentrantLock();
- private static Condition mCacheUpdated = mLock.newCondition();
+ private static Condition mUpdateCondition = mLock.newCondition();
+ private static boolean mUpdateAvailable;
// Message ids
static final int UPDATE = 0;
@@ -133,8 +134,11 @@ public final class WebStorage {
Set ret = null;
mLock.lock();
try {
+ mUpdateAvailable = false;
update();
- mCacheUpdated.await();
+ while (!mUpdateAvailable) {
+ mUpdateCondition.await();
+ }
ret = mOrigins;
} catch (InterruptedException e) {
Log.e(TAG, "Exception while waiting on the updated origins", e);
@@ -155,8 +159,11 @@ public final class WebStorage {
}
mLock.lock();
try {
+ mUpdateAvailable = false;
update();
- mCacheUpdated.await();
+ while (!mUpdateAvailable) {
+ mUpdateCondition.await();
+ }
Long usage = mUsages.get(origin);
if (usage != null) {
ret = usage.longValue();
@@ -180,8 +187,11 @@ public final class WebStorage {
}
mLock.lock();
try {
+ mUpdateAvailable = false;
update();
- mCacheUpdated.await();
+ while (!mUpdateAvailable) {
+ mUpdateCondition.await();
+ }
Long quota = mQuotas.get(origin);
if (quota != null) {
ret = quota.longValue();
@@ -286,7 +296,8 @@ public final class WebStorage {
mQuotas.put(origin, new Long(nativeGetQuotaForOrigin(origin)));
mUsages.put(origin, new Long(nativeGetUsageForOrigin(origin)));
}
- mCacheUpdated.signal();
+ mUpdateAvailable = true;
+ mUpdateCondition.signal();
mLock.unlock();
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 7bc154b..f22adb7 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -81,6 +81,10 @@ import java.util.ArrayList;
// True if the most recent drag event has caused either the TextView to
// scroll or the web page to scroll. Gets reset after a touch down.
private boolean mScrolled;
+ // Gets set to true when the the IME jumps to the next textfield. When this
+ // happens, the next time the user hits a key it is okay for the focus
+ // pointer to not match the WebTextView's node pointer
+ private boolean mOkayForFocusNotToMatch;
// Array to store the final character added in onTextChanged, so that its
// KeyEvents may be determined.
private char[] mCharacter = new char[1];
@@ -99,7 +103,6 @@ import java.util.ArrayList;
super(context);
mWebView = webView;
mMaxLength = -1;
- setImeOptions(EditorInfo.IME_ACTION_NONE);
}
@Override
@@ -125,8 +128,8 @@ import java.util.ArrayList;
isArrowKey = true;
break;
}
-
- if (!isArrowKey && mWebView.nativeFocusNodePointer() != mNodePointer) {
+ if (!isArrowKey && !mOkayForFocusNotToMatch
+ && mWebView.nativeFocusNodePointer() != mNodePointer) {
mWebView.nativeClearCursor();
// Do not call remove() here, which hides the soft keyboard. If
// the soft keyboard is being displayed, the user will still want
@@ -135,6 +138,9 @@ import java.util.ArrayList;
mWebView.requestFocus();
return mWebView.dispatchKeyEvent(event);
}
+ // After a jump to next textfield and the first key press, the cursor
+ // and focus will once again match, so reset this value.
+ mOkayForFocusNotToMatch = false;
Spannable text = (Spannable) getText();
int oldLength = text.length();
@@ -305,6 +311,36 @@ import java.util.ArrayList;
}
@Override
+ public void onEditorAction(int actionCode) {
+ switch (actionCode) {
+ case EditorInfo.IME_ACTION_NEXT:
+ mWebView.nativeMoveCursorToNextTextInput();
+ // Preemptively rebuild the WebTextView, so that the action will
+ // be set properly.
+ mWebView.rebuildWebTextView();
+ // Since the cursor will no longer be in the same place as the
+ // focus, set the focus controller back to inactive
+ mWebView.setFocusControllerInactive();
+ mOkayForFocusNotToMatch = true;
+ break;
+ case EditorInfo.IME_ACTION_DONE:
+ super.onEditorAction(actionCode);
+ break;
+ case EditorInfo.IME_ACTION_GO:
+ // Send an enter and hide the soft keyboard
+ InputMethodManager.getInstance(mContext)
+ .hideSoftInputFromWindow(getWindowToken(), 0);
+ sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
+ KeyEvent.KEYCODE_ENTER));
+ sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
+ KeyEvent.KEYCODE_ENTER));
+
+ default:
+ break;
+ }
+ }
+
+ @Override
protected void onSelectionChanged(int selStart, int selEnd) {
if (mWebView != null) {
if (DebugFlags.WEB_TEXT_VIEW) {
@@ -659,10 +695,26 @@ import java.util.ArrayList;
public void setSingleLine(boolean single) {
int inputType = EditorInfo.TYPE_CLASS_TEXT
| EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
- if (!single) {
+ if (single) {
+ int action = mWebView.nativeTextFieldAction();
+ switch (action) {
+ // Keep in sync with CachedRoot::ImeAction
+ case 0: // NEXT
+ setImeOptions(EditorInfo.IME_ACTION_NEXT);
+ break;
+ case 1: // GO
+ setImeOptions(EditorInfo.IME_ACTION_GO);
+ break;
+ case -1: // FAILURE
+ case 2: // DONE
+ setImeOptions(EditorInfo.IME_ACTION_DONE);
+ break;
+ }
+ } else {
inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
| EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
| EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT;
+ setImeOptions(EditorInfo.IME_ACTION_NONE);
}
mSingle = single;
setHorizontallyScrolling(single);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 19df87f..de0b06d 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -206,11 +206,6 @@ public class WebView extends AbsoluteLayout
static final String LOGTAG = "webview";
- static class ScaleLimitData {
- int mMinScale;
- int mMaxScale;
- }
-
private static class ExtendedZoomControls extends FrameLayout {
public ExtendedZoomControls(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -351,6 +346,9 @@ public class WebView extends AbsoluteLayout
VelocityTracker mVelocityTracker;
private int mMaximumFling;
+ // use this flag to control whether enabling the new double tap zoom
+ static final boolean ENABLE_DOUBLETAP_ZOOM = true;
+
/**
* Touch mode
*/
@@ -370,6 +368,7 @@ public class WebView extends AbsoluteLayout
private static final int SCROLL_ZOOM_OUT = 11;
private static final int LAST_SCROLL_ZOOM = 11;
// end of touch mode values specific to scale+scroll
+ private static final int TOUCH_DOUBLE_TAP_MODE = 12;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -394,6 +393,8 @@ public class WebView extends AbsoluteLayout
*/
// pre-computed square of ViewConfiguration.getScaledTouchSlop()
private int mTouchSlopSquare;
+ // pre-computed square of ViewConfiguration.getScaledDoubleTapSlop()
+ private int mDoubleTapSlopSquare;
// pre-computed density adjusted navigation slop
private int mNavSlop;
// This should be ViewConfiguration.getTapTimeout()
@@ -450,6 +451,7 @@ public class WebView extends AbsoluteLayout
private static final int NEVER_REMEMBER_PASSWORD = 2;
private static final int SWITCH_TO_SHORTPRESS = 3;
private static final int SWITCH_TO_LONGPRESS = 4;
+ private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
private static final int SWITCH_TO_CLICK = 7;
private static final int RESUME_WEBCORE_UPDATE = 8;
@@ -465,7 +467,6 @@ public class WebView extends AbsoluteLayout
static final int UPDATE_TEXT_ENTRY_MSG_ID = 15;
static final int WEBCORE_INITIALIZED_MSG_ID = 16;
static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
- static final int DID_FIRST_LAYOUT_MSG_ID = 18;
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
@@ -482,7 +483,7 @@ public class WebView extends AbsoluteLayout
"NEVER_REMEMBER_PASSWORD", // = 2;
"SWITCH_TO_SHORTPRESS", // = 3;
"SWITCH_TO_LONGPRESS", // = 4;
- "5",
+ "RELEASE_SINGLE_TAP", // = 5;
"REQUEST_FORM_DATA", // = 6;
"SWITCH_TO_CLICK", // = 7;
"RESUME_WEBCORE_UPDATE", // = 8;
@@ -495,7 +496,7 @@ public class WebView extends AbsoluteLayout
"UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
"WEBCORE_INITIALIZED_MSG_ID", // = 16;
"UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
- "DID_FIRST_LAYOUT_MSG_ID", // = 18;
+ "18", // = 18;
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"21", // = 21;
@@ -521,6 +522,16 @@ public class WebView extends AbsoluteLayout
// initial scale in percent. 0 means using default.
private int mInitialScale = 0;
+ // while in the zoom overview mode, the page's width is fully fit to the
+ // current window. The page is alive, in another words, you can click to
+ // follow the links. Double tap will toggle between zoom overview mode and
+ // the last zoom scale.
+ boolean mInZoomOverview = false;
+ // ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
+ // engadget always have wider mContentWidth no matter what viewport size is.
+ int mZoomOverviewWidth = 0;
+ float mLastScale;
+
// default scale. Depending on the display density.
static int DEFAULT_SCALE_PERCENT;
private float mDefaultScale;
@@ -762,9 +773,11 @@ public class WebView extends AbsoluteLayout
setLongClickable(true);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
- final int slop = configuration.getScaledTouchSlop();
+ int slop = configuration.getScaledTouchSlop();
mTouchSlopSquare = slop * slop;
mMinLockSnapReverseDistance = slop;
+ slop = configuration.getScaledDoubleTapSlop();
+ mDoubleTapSlopSquare = slop * slop;
final float density = getContext().getResources().getDisplayMetrics().density;
// use one line height, 16 based on our current default font, for how
// far we allow a touch be away from the edge of a link
@@ -1124,6 +1137,9 @@ public class WebView extends AbsoluteLayout
b.putInt("scrollX", mScrollX);
b.putInt("scrollY", mScrollY);
b.putFloat("scale", mActualScale);
+ if (mInZoomOverview) {
+ b.putFloat("lastScale", mLastScale);
+ }
return true;
}
return false;
@@ -1168,6 +1184,13 @@ public class WebView extends AbsoluteLayout
// onSizeChanged() is called, the rest will be set
// correctly
mActualScale = scale;
+ float lastScale = b.getFloat("lastScale", -1.0f);
+ if (lastScale > 0) {
+ mInZoomOverview = true;
+ mLastScale = lastScale;
+ } else {
+ mInZoomOverview = false;
+ }
invalidate();
return true;
}
@@ -1863,6 +1886,13 @@ public class WebView extends AbsoluteLayout
r.bottom = viewToContent(r.bottom);
}
+ static class ViewSizeData {
+ int mWidth;
+ int mHeight;
+ int mTextWrapWidth;
+ float mScale;
+ }
+
/**
* Compute unzoomed width and height, and if they differ from the last
* values we sent, send them to webkit (to be used has new viewport)
@@ -1870,7 +1900,8 @@ public class WebView extends AbsoluteLayout
* @return true if new values were sent
*/
private boolean sendViewSizeZoom() {
- int newWidth = Math.round(getViewWidth() * mInvActualScale);
+ int viewWidth = getViewWidth();
+ int newWidth = Math.round(viewWidth * mInvActualScale);
int newHeight = Math.round(getViewHeight() * mInvActualScale);
/*
* Because the native side may have already done a layout before the
@@ -1885,8 +1916,16 @@ public class WebView extends AbsoluteLayout
}
// Avoid sending another message if the dimensions have not changed.
if (newWidth != mLastWidthSent || newHeight != mLastHeightSent) {
- mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED,
- newWidth, newHeight, new Float(mActualScale));
+ ViewSizeData data = new ViewSizeData();
+ data.mWidth = newWidth;
+ data.mHeight = newHeight;
+ // while in zoom overview mode, the text are wrapped to the screen
+ // width matching mLastScale. So that we don't trigger re-flow while
+ // toggling between overview mode and normal mode.
+ data.mTextWrapWidth = mInZoomOverview ? Math.round(viewWidth
+ / mLastScale) : newWidth;
+ data.mScale = mActualScale;
+ mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
mLastWidthSent = newWidth;
mLastHeightSent = newHeight;
return true;
@@ -3060,6 +3099,11 @@ public class WebView extends AbsoluteLayout
float y = mLastTouchY + (float) (mScrollY - lp.y);
mWebTextView.fakeTouchEvent(x, y);
}
+ if (mInZoomOverview) {
+ // if in zoom overview mode, call doDoubleTap() to bring it back
+ // to normal mode so that user can enter text.
+ doDoubleTap();
+ }
}
else { // used by plugins
imm.showSoftInput(this, 0);
@@ -3079,7 +3123,7 @@ public class WebView extends AbsoluteLayout
* mWebTextView to have the appropriate properties, such as password,
* multiline, and what text it contains. It also removes it if necessary.
*/
- private void rebuildWebTextView() {
+ /* package */ void rebuildWebTextView() {
// If the WebView does not have focus, do nothing until it gains focus.
if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())
|| (mTouchMode >= FIRST_SCROLL_ZOOM
@@ -3341,7 +3385,8 @@ public class WebView extends AbsoluteLayout
} else if (nativeCursorIsTextInput()) {
// This message will put the node in focus, for the DOM's notion
// of focus, and make the focuscontroller active
- mWebViewCore.sendMessage(EventHub.CLICK);
+ mWebViewCore.sendMessage(EventHub.CLICK, nativeCursorFramePointer(),
+ nativeCursorNodePointer());
// This will bring up the WebTextView and put it in focus, for
// our view system's notion of focus
rebuildWebTextView();
@@ -3582,7 +3627,7 @@ public class WebView extends AbsoluteLayout
* not draw the blinking cursor. It gets set to "active" to draw the cursor
* in WebViewCore.cpp, when the WebCore thread receives key events/clicks.
*/
- private void setFocusControllerInactive() {
+ /* package */ void setFocusControllerInactive() {
// Do not need to also check whether mWebViewCore is null, because
// mNativeClass is only set if mWebViewCore is non null
if (mNativeClass == 0) return;
@@ -3634,7 +3679,9 @@ public class WebView extends AbsoluteLayout
// update mMinZoomScale if the minimum zoom scale is not fixed
if (!mMinZoomScaleFixed) {
mMinZoomScale = (float) getViewWidth()
- / Math.max(ZOOM_OUT_WIDTH, mContentWidth);
+ / Math.max(ZOOM_OUT_WIDTH, mDrawHistory ? mHistoryPicture
+ .getWidth() : (mZoomOverviewWidth > 0 ?
+ mZoomOverviewWidth : mContentWidth));
}
// we always force, in case our height changed, in which case we still
@@ -3755,16 +3802,28 @@ public class WebView extends AbsoluteLayout
nativeMoveSelection(viewToContent(mSelectX)
, viewToContent(mSelectY), false);
mTouchSelection = mExtendSelection = true;
+ } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
+ mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
+ if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
+ mTouchMode = TOUCH_DOUBLE_TAP_MODE;
+ } else {
+ // commit the short press action for the previous tap
+ doShortPress();
+ // continue, mTouchMode should be still TOUCH_INIT_MODE
+ }
} else {
mTouchMode = TOUCH_INIT_MODE;
mPreventDrag = mForwardTouchEvents;
+ mWebViewCore.sendMessage(
+ EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
(eventTime - mLastTouchUpTime), eventTime);
}
}
// Trigger the link
- if (mTouchMode == TOUCH_INIT_MODE) {
+ if (mTouchMode == TOUCH_INIT_MODE
+ || mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.sendMessageDelayed(mPrivateHandler
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
}
@@ -3810,7 +3869,8 @@ public class WebView extends AbsoluteLayout
if (mTouchMode == TOUCH_SHORTPRESS_MODE
|| mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- } else if (mTouchMode == TOUCH_INIT_MODE) {
+ } else if (mTouchMode == TOUCH_INIT_MODE
+ || mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
}
@@ -3830,13 +3890,8 @@ public class WebView extends AbsoluteLayout
if (!mDragFromTextInput) {
nativeHideCursor();
}
- // remove the zoom anchor if there is any
- if (mZoomScale != 0) {
- mWebViewCore
- .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
- }
WebSettings settings = getSettings();
- if (settings.supportZoom()
+ if (settings.supportZoom() && !mInZoomOverview
&& settings.getBuiltInZoomControls()
&& !mZoomButtonsController.isVisible()
&& (canZoomScrollOut() ||
@@ -3905,7 +3960,7 @@ public class WebView extends AbsoluteLayout
mUserScroll = true;
}
- if (!getSettings().getBuiltInZoomControls()) {
+ if (!getSettings().getBuiltInZoomControls() && !mInZoomOverview) {
boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
boolean showMagnify = canZoomScrollOut();
if (mZoomControls != null && (showPlusMinus || showMagnify)) {
@@ -3929,7 +3984,22 @@ public class WebView extends AbsoluteLayout
case MotionEvent.ACTION_UP: {
mLastTouchUpTime = eventTime;
switch (mTouchMode) {
+ case TOUCH_DOUBLE_TAP_MODE: // double tap
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ doDoubleTap();
+ break;
case TOUCH_INIT_MODE: // tap
+ if (ENABLE_DOUBLETAP_ZOOM) {
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ if (!mPreventDrag) {
+ mPrivateHandler.sendMessageDelayed(
+ mPrivateHandler.obtainMessage(
+ RELEASE_SINGLE_TAP),
+ ViewConfiguration.getDoubleTapTimeout());
+ }
+ break;
+ }
+ // fall through
case TOUCH_SHORTPRESS_START_MODE:
case TOUCH_SHORTPRESS_MODE:
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
@@ -4365,6 +4435,9 @@ public class WebView extends AbsoluteLayout
mInvInitialZoomScale = 1.0f / oldScale;
mInvFinalZoomScale = 1.0f / mActualScale;
mZoomScale = mActualScale;
+ if (!mInZoomOverview) {
+ mLastScale = scale;
+ }
invalidate();
return true;
} else {
@@ -4470,6 +4543,9 @@ public class WebView extends AbsoluteLayout
public boolean zoomIn() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
return zoomWithPreview(mActualScale * 1.25f);
}
@@ -4480,6 +4556,9 @@ public class WebView extends AbsoluteLayout
public boolean zoomOut() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
return zoomWithPreview(mActualScale * 0.8f);
}
@@ -4571,6 +4650,50 @@ public class WebView extends AbsoluteLayout
}
}
+ private void doDoubleTap() {
+ if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
+ return;
+ }
+ mZoomCenterX = mLastTouchX;
+ mZoomCenterY = mLastTouchY;
+ mInZoomOverview = !mInZoomOverview;
+ if (mInZoomOverview) {
+ float newScale = (float) getViewWidth()
+ / (mZoomOverviewWidth > 0 ? mZoomOverviewWidth
+ : mContentWidth);
+ if (Math.abs(newScale - mActualScale) < 0.01) {
+ mInZoomOverview = !mInZoomOverview;
+ // as it is already full screen, do nothing.
+ return;
+ }
+ if (getSettings().getBuiltInZoomControls()) {
+ if (mZoomButtonsController.isVisible()) {
+ mZoomButtonsController.setVisible(false);
+ }
+ } else {
+ if (mZoomControlRunnable != null) {
+ mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+ }
+ if (mZoomControls != null) {
+ mZoomControls.hide();
+ }
+ }
+ zoomWithPreview(newScale);
+ } else {
+ // mLastTouchX and mLastTouchY are the point in the current viewport
+ int contentX = viewToContent((int) mLastTouchX + mScrollX);
+ int contentY = viewToContent((int) mLastTouchY + mScrollY);
+ int left = nativeGetBlockLeftEdge(contentX, contentY, mActualScale);
+ if (left != NO_LEFTEDGE) {
+ // add a 5pt padding to the left edge. Re-calculate the zoom
+ // center so that the new scroll x will be on the left edge.
+ mZoomCenterX = left < 5 ? 0 : (left - 5) * mLastScale
+ * mActualScale / (mLastScale - mActualScale);
+ }
+ zoomWithPreview(mLastScale);
+ }
+ }
+
// Called by JNI to handle a touch on a node representing an email address,
// address, or phone number
private void overrideLoading(String url) {
@@ -4791,6 +4914,8 @@ public class WebView extends AbsoluteLayout
if (mTouchMode == TOUCH_INIT_MODE) {
mTouchMode = TOUCH_SHORTPRESS_START_MODE;
updateSelection();
+ } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
+ mTouchMode = TOUCH_DONE_MODE;
}
break;
}
@@ -4802,6 +4927,13 @@ public class WebView extends AbsoluteLayout
}
break;
}
+ case RELEASE_SINGLE_TAP: {
+ if (!mPreventDrag) {
+ mTouchMode = TOUCH_DONE_MODE;
+ doShortPress();
+ }
+ break;
+ }
case SWITCH_TO_CLICK:
// The user clicked with the trackball, and did not click a
// second time, so perform the action of a trackball single
@@ -4854,22 +4986,39 @@ public class WebView extends AbsoluteLayout
break;
case NEW_PICTURE_MSG_ID:
// called for new content
+ final int viewWidth = getViewWidth();
final WebViewCore.DrawData draw =
(WebViewCore.DrawData) msg.obj;
final Point viewSize = draw.mViewPoint;
- if (mZoomScale > 0) {
- // use the same logic in sendViewSizeZoom() to make sure
- // the mZoomScale has matched the viewSize so that we
- // can clear mZoomScale
- if (Math.round(getViewWidth() / mZoomScale) == viewSize.x) {
- mZoomScale = 0;
- mWebViewCore.sendMessage(EventHub.SET_SNAP_ANCHOR,
- 0, 0);
+ boolean useWideViewport =
+ mWebViewCore.getSettings().getUseWideViewPort();
+ WebViewCore.RestoreState restoreState = draw.mRestoreState;
+ if (restoreState != null) {
+ mInZoomOverview = false;
+ mLastScale = restoreState.mTextWrapScale;
+ if (restoreState.mMinScale == 0) {
+ mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
+ mMinZoomScaleFixed = false;
+ } else {
+ mMinZoomScale = restoreState.mMinScale;
+ mMinZoomScaleFixed = true;
}
- }
- if (!mMinZoomScaleFixed) {
- mMinZoomScale = (float) getViewWidth()
- / Math.max(ZOOM_OUT_WIDTH, draw.mWidthHeight.x);
+ if (restoreState.mMaxScale == 0) {
+ mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
+ } else {
+ mMaxZoomScale = restoreState.mMaxScale;
+ }
+ if (useWideViewport && restoreState.mViewScale == 0) {
+ mInZoomOverview = ENABLE_DOUBLETAP_ZOOM;
+ }
+ setNewZoomScale(mLastScale, false);
+ setContentScrollTo(restoreState.mScrollX,
+ restoreState.mScrollY);
+ // As we are on a new page, remove the WebTextView. This
+ // is necessary for page loads driven by webkit, and in
+ // particular when the user was on a password field, so
+ // the WebTextView was visible.
+ clearTextEntry();
}
// We update the layout (i.e. request a layout from the
// view system) if the last view size that we sent to
@@ -4888,6 +5037,25 @@ public class WebView extends AbsoluteLayout
if (mPictureListener != null) {
mPictureListener.onNewPicture(WebView.this, capturePicture());
}
+ if (useWideViewport) {
+ mZoomOverviewWidth = Math.max(draw.mMinPrefWidth,
+ draw.mViewPoint.x);
+ }
+ if (!mMinZoomScaleFixed) {
+ mMinZoomScale = (float) viewWidth
+ / Math.max(ZOOM_OUT_WIDTH,
+ mZoomOverviewWidth > 0 ? mZoomOverviewWidth
+ : mContentWidth);
+ }
+ if (!mDrawHistory && mInZoomOverview) {
+ // fit the content width to the current view. Ignore
+ // the rounding error case.
+ if (Math.abs((viewWidth * mInvActualScale)
+ - mZoomOverviewWidth) > 1) {
+ zoomWithPreview((float) viewWidth
+ / mZoomOverviewWidth);
+ }
+ }
break;
case WEBCORE_INITIALIZED_MSG_ID:
// nativeCreate sets mNativeClass to a non-zero value
@@ -4916,63 +5084,6 @@ public class WebView extends AbsoluteLayout
}
}
break;
- case DID_FIRST_LAYOUT_MSG_ID:
- if (mNativeClass == 0) {
- break;
- }
- ScaleLimitData scaleLimit = (ScaleLimitData) msg.obj;
- int minScale = scaleLimit.mMinScale;
- if (minScale == 0) {
- mMinZoomScale = DEFAULT_MIN_ZOOM_SCALE;
- mMinZoomScaleFixed = false;
- } else {
- mMinZoomScale = (float) (minScale / 100.0);
- mMinZoomScaleFixed = true;
- }
- int maxScale = scaleLimit.mMaxScale;
- if (maxScale == 0) {
- mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
- } else {
- mMaxZoomScale = (float) (maxScale / 100.0);
- }
- // If history Picture is drawn, don't update zoomWidth
- if (mDrawHistory) {
- break;
- }
- int width = getViewWidth();
- if (width == 0) {
- break;
- }
- int initialScale = msg.arg1;
- int viewportWidth = msg.arg2;
- // start a new page with DEFAULT_SCALE zoom scale.
- float scale = mDefaultScale;
- if (mInitialScale > 0) {
- scale = mInitialScale / 100.0f;
- } else {
- if (initialScale < 0) break;
- if (mWebViewCore.getSettings().getUseWideViewPort()) {
- // force viewSizeChanged by setting mLastWidthSent
- // to 0
- mLastWidthSent = 0;
- }
- if (initialScale == 0) {
- // if viewportWidth is defined and it is smaller
- // than the view width, zoom in to fill the view
- if (viewportWidth > 0 && viewportWidth < width) {
- scale = (float) width / viewportWidth;
- }
- } else {
- scale = initialScale / 100.0f;
- }
- }
- setNewZoomScale(scale, false);
- // As we are on a new page, remove the WebTextView. This
- // is necessary for page loads driven by webkit, and in
- // particular when the user was on a password field, so
- // the WebTextView was visible.
- clearTextEntry();
- break;
case MOVE_OUT_OF_PLUGIN:
if (nativePluginEatsNavKey()) {
navHandledKey(msg.arg1, 1, false, 0, true);
@@ -5519,6 +5630,7 @@ public class WebView extends AbsoluteLayout
private native void nativeHideCursor();
private native String nativeImageURI(int x, int y);
private native void nativeInstrumentReport();
+ /* package */ native void nativeMoveCursorToNextTextInput();
// return true if the page has been scrolled
private native boolean nativeMotionUp(int x, int y, int slop);
// returns false if it handled the key
@@ -5536,10 +5648,15 @@ public class WebView extends AbsoluteLayout
private native void nativeSetFindIsDown();
private native void nativeSetFollowedLink(boolean followed);
private native void nativeSetHeightCanMeasure(boolean measure);
+ // Returns a value corresponding to CachedFrame::ImeAction
+ /* package */ native int nativeTextFieldAction();
private native int nativeTextGeneration();
// Never call this version except by updateCachedTextfield(String) -
// we always want to pass in our generation number.
private native void nativeUpdateCachedTextfield(String updatedText,
int generation);
private native void nativeUpdatePluginReceivesEvents();
+ // return NO_LEFTEDGE means failure.
+ private static final int NO_LEFTEDGE = -1;
+ private native int nativeGetBlockLeftEdge(int x, int y, float scale);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4993fcf..2f9e153 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -36,6 +36,7 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
+import java.util.Set;
import junit.framework.Assert;
@@ -96,7 +97,8 @@ final class WebViewCore {
private boolean mViewportUserScalable = true;
- private int mRestoredScale = WebView.DEFAULT_SCALE_PERCENT;
+ private int mRestoredScale = 0;
+ private int mRestoredScreenWidthScale = 0;
private int mRestoredX = 0;
private int mRestoredY = 0;
@@ -165,6 +167,8 @@ final class WebViewCore {
WebIconDatabase.getInstance().createHandler();
// Create the handler for WebStorage
WebStorage.getInstance().createHandler();
+ // Create the handler for GeolocationPermissions.
+ GeolocationPermissions.getInstance().createHandler();
// The transferMessages call will transfer all pending messages to the
// WebCore thread handler.
mEventHub.transferMessages();
@@ -246,7 +250,7 @@ final class WebViewCore {
}
/**
- * Notify the user that the origin has exceeded it's database quota.
+ * Notify the browser that the origin has exceeded it's database quota.
* @param url The URL that caused the overflow.
* @param databaseIdentifier The identifier of the database.
* @param currentQuota The current quota for the origin.
@@ -259,14 +263,55 @@ final class WebViewCore {
// awaken the sleeping webcore thread when a decision from the
// client to allow or deny quota is available.
mCallbackProxy.onExceededDatabaseQuota(url, databaseIdentifier,
- currentQuota, new WebStorage.QuotaUpdater() {
+ currentQuota, getUsedQuota(), new WebStorage.QuotaUpdater() {
public void updateQuota(long quota) {
- nativeSetDatabaseQuota(quota);
+ nativeSetNewStorageLimit(quota);
}
});
}
/**
+ * Notify the browser that the appcache has exceeded its max size.
+ * @param spaceNeeded is the amount of disk space that would be needed
+ * in order for the last appcache operation to succeed.
+ */
+ protected void reachedMaxAppCacheSize(long spaceNeeded) {
+ mCallbackProxy.onReachedMaxAppCacheSize(spaceNeeded, getUsedQuota(),
+ new WebStorage.QuotaUpdater() {
+ public void updateQuota(long quota) {
+ nativeSetNewStorageLimit(quota);
+ }
+ });
+ }
+
+ /**
+ * Shows a prompt to ask the user to set the Geolocation permission state
+ * for the given origin.
+ * @param origin The origin for which Geolocation permissions are
+ * requested.
+ */
+ protected void geolocationPermissionsShowPrompt(String origin) {
+ mCallbackProxy.onGeolocationPermissionsShowPrompt(origin,
+ new GeolocationPermissions.Callback() {
+ public void invoke(String origin, boolean allow, boolean remember) {
+ GeolocationPermissionsData data = new GeolocationPermissionsData();
+ data.mOrigin = origin;
+ data.mAllow = allow;
+ data.mRemember = remember;
+ // Marshall to WebCore thread.
+ sendMessage(EventHub.GEOLOCATION_PERMISSIONS_PROVIDE, data);
+ }
+ });
+ }
+
+ /**
+ * Hides the Geolocation permissions prompt.
+ */
+ protected void geolocationPermissionsHidePrompt() {
+ mCallbackProxy.onGeolocationPermissionsHidePrompt();
+ }
+
+ /**
* Invoke a javascript confirm dialog.
* @param message The message displayed in the dialog.
* @return True if the user confirmed or false if the user cancelled.
@@ -398,10 +443,6 @@ final class WebViewCore {
private native void nativeUpdateFrameCache();
- private native void nativeSetSnapAnchor(int x, int y);
-
- private native void nativeSnapToAnchor();
-
private native void nativeSetBackgroundColor(int color);
private native void nativeDumpDomTree(boolean useFile);
@@ -439,14 +480,24 @@ final class WebViewCore {
/*
* Inform webcore that the user has decided whether to allow or deny new
- * quota for the current origin and that the main thread should wake up
- * now.
- * @param quota The new quota.
+ * quota for the current origin or more space for the app cache, and that
+ * the main thread should wake up now.
+ * @param limit Is the new quota for an origin or new app cache max size.
*/
- private native void nativeSetDatabaseQuota(long quota);
+ private native void nativeSetNewStorageLimit(long limit);
private native void nativeUpdatePluginState(int framePtr, int nodePtr, int state);
+ /**
+ * Provide WebCore with a Geolocation permission state for the specified
+ * origin.
+ * @param origin The origin for which Geolocation permissions are provided.
+ * @param allow Whether Geolocation permissions are allowed.
+ * @param remember Whether this decision should be remembered beyond the
+ * life of the current page.
+ */
+ private native void nativeGeolocationPermissionsProvide(String origin, boolean allow, boolean remember);
+
// EventHub for processing messages
private final EventHub mEventHub;
// WebCore thread handler
@@ -590,7 +641,14 @@ final class WebViewCore {
int mState;
}
+ static class GeolocationPermissionsData {
+ String mOrigin;
+ boolean mAllow;
+ boolean mRemember;
+ }
+
static final String[] HandlerDebugString = {
+ "UPDATE_FRAME_CACHE_IF_LOADING", // = 98
"SCROLL_TEXT_INPUT", // = 99
"LOAD_URL", // = 100;
"STOP_LOADING", // = 101;
@@ -613,7 +671,7 @@ final class WebViewCore {
"CLICK", // = 118;
"SET_NETWORK_STATE", // = 119;
"DOC_HAS_IMAGES", // = 120;
- "SET_SNAP_ANCHOR", // = 121;
+ "121", // = 121;
"DELETE_SELECTION", // = 122;
"LISTBOX_CHOICES", // = 123;
"SINGLE_LISTBOX_CHOICE", // = 124;
@@ -642,6 +700,7 @@ final class WebViewCore {
class EventHub {
// Message Ids
+ static final int UPDATE_FRAME_CACHE_IF_LOADING = 98;
static final int SCROLL_TEXT_INPUT = 99;
static final int LOAD_URL = 100;
static final int STOP_LOADING = 101;
@@ -664,7 +723,6 @@ final class WebViewCore {
static final int CLICK = 118;
static final int SET_NETWORK_STATE = 119;
static final int DOC_HAS_IMAGES = 120;
- static final int SET_SNAP_ANCHOR = 121;
static final int DELETE_SELECTION = 122;
static final int LISTBOX_CHOICES = 123;
static final int SINGLE_LISTBOX_CHOICE = 124;
@@ -715,6 +773,8 @@ final class WebViewCore {
static final int DUMP_NAVTREE = 172;
static final int SET_JS_FLAGS = 173;
+ // Geolocation
+ static final int GEOLOCATION_PERMISSIONS_PROVIDE = 180;
// private message ids
private static final int DESTROY = 200;
@@ -747,10 +807,11 @@ final class WebViewCore {
@Override
public void handleMessage(Message msg) {
if (DebugFlags.WEB_VIEW_CORE) {
- Log.v(LOGTAG, (msg.what < SCROLL_TEXT_INPUT || msg.what
+ Log.v(LOGTAG, (msg.what < UPDATE_FRAME_CACHE_IF_LOADING
+ || msg.what
> FREE_MEMORY ? Integer.toString(msg.what)
: HandlerDebugString[msg.what
- - SCROLL_TEXT_INPUT])
+ - UPDATE_FRAME_CACHE_IF_LOADING])
+ " arg1=" + msg.arg1 + " arg2=" + msg.arg2
+ " obj=" + msg.obj);
}
@@ -767,6 +828,10 @@ final class WebViewCore {
mNativeClass = 0;
break;
+ case UPDATE_FRAME_CACHE_IF_LOADING:
+ nativeUpdateFrameCacheIfLoading();
+ break;
+
case SCROLL_TEXT_INPUT:
nativeScrollFocusedTextInput(msg.arg1, msg.arg2);
break;
@@ -841,11 +906,13 @@ final class WebViewCore {
nativeClick(msg.arg1, msg.arg2);
break;
- case VIEW_SIZE_CHANGED:
- viewSizeChanged(msg.arg1, msg.arg2,
- ((Float) msg.obj).floatValue());
+ case VIEW_SIZE_CHANGED: {
+ WebView.ViewSizeData data =
+ (WebView.ViewSizeData) msg.obj;
+ viewSizeChanged(data.mWidth, data.mHeight,
+ data.mTextWrapWidth, data.mScale);
break;
-
+ }
case SET_SCROLL_OFFSET:
// note: these are in document coordinates
// (inv-zoom)
@@ -1044,10 +1111,6 @@ final class WebViewCore {
imageResult.sendToTarget();
break;
- case SET_SNAP_ANCHOR:
- nativeSetSnapAnchor(msg.arg1, msg.arg2);
- break;
-
case DELETE_SELECTION:
DeleteSelectionData deleteSelectionData
= (DeleteSelectionData) msg.obj;
@@ -1101,6 +1164,12 @@ final class WebViewCore {
case SET_JS_FLAGS:
nativeSetJsFlags((String)msg.obj);
+
+ case GEOLOCATION_PERMISSIONS_PROVIDE:
+ GeolocationPermissionsData data =
+ (GeolocationPermissionsData) msg.obj;
+ nativeGeolocationPermissionsProvide(data.mOrigin,
+ data.mAllow, data.mRemember);
break;
case SYNC_SCROLL:
@@ -1332,17 +1401,20 @@ final class WebViewCore {
// These values are used to avoid requesting a layout based on old values
private int mCurrentViewWidth = 0;
private int mCurrentViewHeight = 0;
+ private float mCurrentViewScale = 1.0f;
// notify webkit that our virtual view size changed size (after inv-zoom)
- private void viewSizeChanged(int w, int h, float scale) {
- if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "CORE onSizeChanged");
+ private void viewSizeChanged(int w, int h, int textwrapWidth, float scale) {
+ if (DebugFlags.WEB_VIEW_CORE) {
+ Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
+ + "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
+ }
if (w == 0) {
Log.w(LOGTAG, "skip viewSizeChanged as w is 0");
return;
}
- if (mSettings.getUseWideViewPort()
- && (w < mViewportWidth || mViewportWidth == -1)) {
- int width = mViewportWidth;
+ int width = w;
+ if (mSettings.getUseWideViewPort()) {
if (mViewportWidth == -1) {
if (mSettings.getLayoutAlgorithm() ==
WebSettings.LayoutAlgorithm.NORMAL) {
@@ -1362,16 +1434,17 @@ final class WebViewCore {
*/
width = Math.max(w, nativeGetContentMinPrefWidth());
}
+ } else {
+ width = Math.max(w, mViewportWidth);
}
- nativeSetSize(width, Math.round((float) width * h / w), w, scale,
- w, h);
- } else {
- nativeSetSize(w, h, w, scale, w, h);
}
+ nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
+ textwrapWidth, scale, w, h);
// Remember the current width and height
boolean needInvalidate = (mCurrentViewWidth == 0);
mCurrentViewWidth = w;
mCurrentViewHeight = h;
+ mCurrentViewScale = scale;
if (needInvalidate) {
// ensure {@link #webkitDraw} is called as we were blocking in
// {@link #contentDraw} when mCurrentViewWidth is 0
@@ -1389,6 +1462,21 @@ final class WebViewCore {
}
}
+ // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
+ // callbacks. Computes the sum of database quota for all origins.
+ private long getUsedQuota() {
+ WebStorage webStorage = WebStorage.getInstance();
+ Set<String> origins = webStorage.getOrigins();
+ if (origins == null) {
+ return 0;
+ }
+ long usedQuota = 0;
+ for (String origin : origins) {
+ usedQuota += webStorage.getQuotaForOrigin(origin);
+ }
+ return usedQuota;
+ }
+
// Used to avoid posting more than one draw message.
private boolean mDrawIsScheduled;
@@ -1401,14 +1489,30 @@ final class WebViewCore {
// Used to end scale+scroll mode, accessed by both threads
boolean mEndScaleZoom = false;
- public class DrawData {
- public DrawData() {
+ // mRestoreState is set in didFirstLayout(), and reset in the next
+ // webkitDraw after passing it to the UI thread.
+ private RestoreState mRestoreState = null;
+
+ static class RestoreState {
+ float mMinScale;
+ float mMaxScale;
+ float mViewScale;
+ float mTextWrapScale;
+ int mScrollX;
+ int mScrollY;
+ }
+
+ static class DrawData {
+ DrawData() {
mInvalRegion = new Region();
mWidthHeight = new Point();
}
- public Region mInvalRegion;
- public Point mViewPoint;
- public Point mWidthHeight;
+ Region mInvalRegion;
+ Point mViewPoint;
+ Point mWidthHeight;
+ int mMinPrefWidth;
+ RestoreState mRestoreState; // only non-null if it is for the first
+ // picture set after the first layout
}
private void webkitDraw() {
@@ -1424,6 +1528,13 @@ final class WebViewCore {
// Send the native view size that was used during the most recent
// layout.
draw.mViewPoint = new Point(mCurrentViewWidth, mCurrentViewHeight);
+ if (WebView.ENABLE_DOUBLETAP_ZOOM && mSettings.getUseWideViewPort()) {
+ draw.mMinPrefWidth = nativeGetContentMinPrefWidth();
+ }
+ if (mRestoreState != null) {
+ draw.mRestoreState = mRestoreState;
+ mRestoreState = null;
+ }
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
Message.obtain(mWebView.mPrivateHandler,
WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
@@ -1434,9 +1545,6 @@ final class WebViewCore {
mWebkitScrollY).sendToTarget();
mWebkitScrollX = mWebkitScrollY = 0;
}
- // nativeSnapToAnchor() needs to be called after NEW_PICTURE_MSG_ID
- // is sent, so that scroll will be based on the new content size.
- nativeSnapToAnchor();
}
}
@@ -1658,17 +1766,8 @@ final class WebViewCore {
// called by JNI
private void didFirstLayout(boolean standardLoad) {
- // Trick to ensure that the Picture has the exact height for the content
- // by forcing to layout with 0 height after the page is ready, which is
- // indicated by didFirstLayout. This is essential to get rid of the
- // white space in the GMail which uses WebView for message view.
- if (mWebView != null && mWebView.mHeightCanMeasure) {
- mWebView.mLastHeightSent = 0;
- // Send a negative scale to indicate that WebCore should reuse the
- // current scale
- mEventHub.sendMessage(Message.obtain(null,
- EventHub.VIEW_SIZE_CHANGED, mWebView.mLastWidthSent,
- mWebView.mLastHeightSent, -1.0f));
+ if (DebugFlags.WEB_VIEW_CORE) {
+ Log.v(LOGTAG, "didFirstLayout standardLoad =" + standardLoad);
}
mBrowserFrame.didFirstLayout();
@@ -1676,6 +1775,9 @@ final class WebViewCore {
// reset the scroll position as it is a new page now
mWebkitScrollX = mWebkitScrollY = 0;
+ // for non-standard load, we only adjust scale if mRestoredScale > 0
+ if (mWebView == null || (mRestoredScale == 0 && !standardLoad)) return;
+
// set the viewport settings from WebKit
setViewportSettingsFromNative();
@@ -1727,46 +1829,74 @@ final class WebViewCore {
}
// now notify webview
- if (mWebView != null) {
- WebView.ScaleLimitData scaleLimit = new WebView.ScaleLimitData();
- scaleLimit.mMinScale = mViewportMinimumScale;
- scaleLimit.mMaxScale = mViewportMaximumScale;
-
- if (mRestoredScale > 0) {
- Message.obtain(mWebView.mPrivateHandler,
- WebView.DID_FIRST_LAYOUT_MSG_ID, mRestoredScale, 0,
- scaleLimit).sendToTarget();
- mRestoredScale = 0;
+ int webViewWidth = Math.round(mCurrentViewWidth * mCurrentViewScale);
+ mRestoreState = new RestoreState();
+ mRestoreState.mMinScale = mViewportMinimumScale / 100.0f;
+ mRestoreState.mMaxScale = mViewportMaximumScale / 100.0f;
+ mRestoreState.mScrollX = mRestoredX;
+ mRestoreState.mScrollY = mRestoredY;
+ if (mRestoredScale > 0) {
+ if (mRestoredScreenWidthScale > 0) {
+ mRestoreState.mTextWrapScale =
+ mRestoredScreenWidthScale / 100.0f;
+ // 0 will trigger WebView to turn on zoom overview mode
+ mRestoreState.mViewScale = 0;
} else {
- // if standardLoad is true, use mViewportInitialScale, otherwise
- // pass -1 to the WebView to indicate no change of the scale.
- Message.obtain(mWebView.mPrivateHandler,
- WebView.DID_FIRST_LAYOUT_MSG_ID,
- standardLoad ? mViewportInitialScale : -1,
- mViewportWidth, scaleLimit).sendToTarget();
+ mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+ mRestoredScale / 100.0f;
}
-
- // force an early draw for quick feedback after the first layout
- if (mCurrentViewWidth != 0) {
- synchronized (this) {
- if (mDrawIsScheduled) {
- mEventHub.removeMessages(EventHub.WEBKIT_DRAW);
- }
- mDrawIsScheduled = true;
- // if no restored offset, move the new page to (0, 0)
- mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
- EventHub.MESSAGE_RELAY, Message.obtain(
- mWebView.mPrivateHandler,
- WebView.SCROLL_TO_MSG_ID, mRestoredX,
- mRestoredY)));
- mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
- EventHub.WEBKIT_DRAW));
- }
+ } else {
+ if (mViewportInitialScale > 0) {
+ mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+ mViewportInitialScale / 100.0f;
+ } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth) {
+ mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
+ (float) webViewWidth / mViewportWidth;
+ } else {
+ mRestoreState.mTextWrapScale =
+ WebView.DEFAULT_SCALE_PERCENT / 100.0f;
+ // 0 will trigger WebView to turn on zoom overview mode
+ mRestoreState.mViewScale = 0;
}
+ }
- // reset restored offset
- mRestoredX = mRestoredY = 0;
+ if (mWebView.mHeightCanMeasure) {
+ // Trick to ensure that the Picture has the exact height for the
+ // content by forcing to layout with 0 height after the page is
+ // ready, which is indicated by didFirstLayout. This is essential to
+ // get rid of the white space in the GMail which uses WebView for
+ // message view.
+ mWebView.mLastHeightSent = 0;
+ // Send a negative scale to indicate that WebCore should reuse
+ // the current scale
+ WebView.ViewSizeData data = new WebView.ViewSizeData();
+ data.mWidth = mWebView.mLastWidthSent;
+ data.mHeight = 0;
+ // if mHeightCanMeasure is true, getUseWideViewPort() can't be
+ // true. It is safe to use mWidth for mTextWrapWidth.
+ data.mTextWrapWidth = data.mWidth;
+ data.mScale = -1.0f;
+ mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
+ EventHub.VIEW_SIZE_CHANGED, data));
+ } else if (mSettings.getUseWideViewPort() && mCurrentViewWidth > 0) {
+ WebView.ViewSizeData data = new WebView.ViewSizeData();
+ // mViewScale as 0 means it is in zoom overview mode. So we don't
+ // know the exact scale. If mRestoredScale is non-zero, use it;
+ // otherwise just use mTextWrapScale as the initial scale.
+ data.mScale = mRestoreState.mViewScale == 0
+ ? (mRestoredScale > 0 ? mRestoredScale
+ : mRestoreState.mTextWrapScale)
+ : mRestoreState.mViewScale;
+ data.mWidth = Math.round(webViewWidth / data.mScale);
+ data.mHeight = mCurrentViewHeight * data.mWidth
+ / mCurrentViewWidth;
+ data.mTextWrapWidth = Math.round(webViewWidth
+ / mRestoreState.mTextWrapScale);
+ mEventHub.sendMessageAtFrontOfQueue(Message.obtain(null,
+ EventHub.VIEW_SIZE_CHANGED, data));
}
+ // reset restored offset, scale
+ mRestoredX = mRestoredY = mRestoredScale = mRestoredScreenWidthScale = 0;
}
// called by JNI
@@ -1777,6 +1907,17 @@ final class WebViewCore {
}
// called by JNI
+ private void restoreScreenWidthScale(int scale) {
+ if (!WebView.ENABLE_DOUBLETAP_ZOOM || !mSettings.getUseWideViewPort()) {
+ return;
+ }
+
+ if (mBrowserFrame.firstLayoutDone() == false) {
+ mRestoredScreenWidthScale = scale;
+ }
+ }
+
+ // called by JNI
private void needTouchEvents(boolean need) {
if (mWebView != null) {
Message.obtain(mWebView.mPrivateHandler,
@@ -1804,6 +1945,8 @@ final class WebViewCore {
WebView.CLEAR_TEXT_ENTRY).sendToTarget();
}
+ private native void nativeUpdateFrameCacheIfLoading();
+
/**
* Scroll the focused textfield to (x, y) in document space
*/
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index e613ec4..ea88b5b 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -104,6 +104,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
private View mDropDownAnchorView; // view is retrieved lazily from id once needed
private int mDropDownWidth;
private int mDropDownHeight;
+ private final Rect mTempRect = new Rect();
private Drawable mDropDownListHighlight;
@@ -209,8 +210,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
private void onClickImpl() {
// If the dropdown is showing, bring it back in front of the soft
// keyboard when the user touches the text field.
- if (mPopup.isShowing() &&
- mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) {
+ if (mPopup.isShowing() && isInputMethodNotNeeded()) {
ensureImeVisible();
}
}
@@ -1089,6 +1089,13 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
}
/**
+ * @hide internal used only here and SearchDialog
+ */
+ public boolean isInputMethodNotNeeded() {
+ return mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
+ }
+
+ /**
* <p>Displays the drop down on screen.</p>
*/
public void showDropDown() {
@@ -1097,7 +1104,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
int widthSpec = 0;
int heightSpec = 0;
- boolean noInputMethod = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
+ boolean noInputMethod = isInputMethodNotNeeded();
if (mPopup.isShowing()) {
if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
@@ -1303,7 +1310,15 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
if (mDropDownAlwaysVisible) {
- return maxHeight;
+ // getMaxAvailableHeight() subtracts the padding, so we put it back,
+ // to get the available height for the whole window
+ int padding = 0;
+ Drawable background = mPopup.getBackground();
+ if (background != null) {
+ background.getPadding(mTempRect);
+ padding = mTempRect.top + mTempRect.bottom;
+ }
+ return maxHeight + padding;
}
return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 6a9bcfb..b8f0a7e 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -463,6 +463,7 @@ public class ImageView extends View {
if (matrix == null && !mMatrix.isIdentity() ||
matrix != null && !mMatrix.equals(matrix)) {
mMatrix.set(matrix);
+ configureBounds();
invalidate();
}
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 24c0e2a..e19a93d 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -432,7 +432,7 @@ public class RelativeLayout extends ViewGroup {
width = resolveSize(width, widthMeasureSpec);
if (offsetHorizontalAxis) {
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
@@ -486,10 +486,14 @@ public class RelativeLayout extends ViewGroup {
View child = getChildAt(i);
if (child.getVisibility() != GONE && child != ignore) {
LayoutParams params = (LayoutParams) child.getLayoutParams();
- params.mLeft += horizontalOffset;
- params.mRight += horizontalOffset;
- params.mTop += verticalOffset;
- params.mBottom += verticalOffset;
+ if (horizontalGravity) {
+ params.mLeft += horizontalOffset;
+ params.mRight += horizontalOffset;
+ }
+ if (verticalGravity) {
+ params.mTop += verticalOffset;
+ params.mBottom += verticalOffset;
+ }
}
}
}
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index a26bfa2..47f5c6c 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -277,7 +277,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
if (child.getLayoutParams() == null) {
final LinearLayout.LayoutParams lp = new LayoutParams(
0,
- ViewGroup.LayoutParams.WRAP_CONTENT, 1);
+ ViewGroup.LayoutParams.FILL_PARENT, 1.0f);
lp.setMargins(0, 0, 0, 0);
child.setLayoutParams(lp);
}
@@ -289,10 +289,10 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener {
// If we have dividers between the tabs and we already have at least one
// tab, then add a divider before adding the next tab.
if (mDividerDrawable != null && getTabCount() > 0) {
- View divider = new View(mContext);
+ ImageView divider = new ImageView(mContext);
final LinearLayout.LayoutParams lp = new LayoutParams(
mDividerDrawable.getIntrinsicWidth(),
- mDividerDrawable.getIntrinsicHeight());
+ LayoutParams.FILL_PARENT);
lp.setMargins(0, 0, 0, 0);
divider.setLayoutParams(lp);
divider.setBackgroundDrawable(mDividerDrawable);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0421612..591f9bb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6916,6 +6916,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ boolean hasLetter = false;
+ for (int i = start; i < end; i++) {
+ if (Character.isLetter(mTransformed.charAt(i))) {
+ hasLetter = true;
+ break;
+ }
+ }
+ if (!hasLetter) {
+ return null;
+ }
+
if (start == end) {
return null;
}
diff --git a/core/java/com/android/internal/backup/SystemBackupAgent.java b/core/java/com/android/internal/backup/SystemBackupAgent.java
deleted file mode 100644
index 6b396d7..0000000
--- a/core/java/com/android/internal/backup/SystemBackupAgent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.backup;
-
-import android.backup.AbsoluteFileBackupHelper;
-import android.backup.BackupHelperAgent;
-
-/**
- * Backup agent for various system-managed data
- */
-public class SystemBackupAgent extends BackupHelperAgent {
- // the set of files that we back up whole, as absolute paths
- String[] mFiles = {
- /* WallpaperService.WALLPAPER_FILE */
- "/data/data/com.android.settings/files/wallpaper",
- };
-
- public void onCreate() {
- addHelper("system_files", new AbsoluteFileBackupHelper(this, mFiles));
- }
-}
diff --git a/core/java/com/google/android/gdata/client/QueryParamsImpl.java b/core/java/com/google/android/gdata/client/QueryParamsImpl.java
index e27b36f..fbe0d22 100644
--- a/core/java/com/google/android/gdata/client/QueryParamsImpl.java
+++ b/core/java/com/google/android/gdata/client/QueryParamsImpl.java
@@ -60,6 +60,8 @@ public class QueryParamsImpl extends QueryParams {
sb.append('?');
}
for (String param : params) {
+ String value = mParams.get(param);
+ if (value == null) continue;
if (first) {
first = false;
} else {
@@ -67,7 +69,7 @@ public class QueryParamsImpl extends QueryParams {
}
sb.append(param);
sb.append('=');
- String value = mParams.get(param);
+
String encodedValue = null;
try {
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index c16a75e..dc72008 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -464,13 +464,22 @@ public:
SkCanvas* canvas, SkBitmap* bitmap,
jfloat left, jfloat top,
SkPaint* paint, jint canvasDensity,
- jint bitmapDensity) {
+ jint screenDensity, jint bitmapDensity) {
SkScalar left_ = SkFloatToScalar(left);
SkScalar top_ = SkFloatToScalar(top);
if (canvasDensity == bitmapDensity || canvasDensity == 0
|| bitmapDensity == 0) {
- canvas->drawBitmap(*bitmap, left_, top_, paint);
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterBitmap(true);
+ canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
+ } else {
+ canvas->drawBitmap(*bitmap, left_, top_, paint);
+ }
} else {
canvas->save();
SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
@@ -490,30 +499,45 @@ public:
}
static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
- jobject srcIRect, const SkRect& dst, SkPaint* paint) {
+ jobject srcIRect, const SkRect& dst, SkPaint* paint,
+ jint screenDensity, jint bitmapDensity) {
SkIRect src, *srcPtr = NULL;
if (NULL != srcIRect) {
GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
srcPtr = &src;
}
- canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
+
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterBitmap(true);
+ canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
+ } else {
+ canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
+ }
}
static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
SkBitmap* bitmap, jobject srcIRect,
- jobject dstRectF, SkPaint* paint) {
+ jobject dstRectF, SkPaint* paint,
+ jint screenDensity, jint bitmapDensity) {
SkRect dst;
GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
- doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
+ doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+ screenDensity, bitmapDensity);
}
static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
SkBitmap* bitmap, jobject srcIRect,
- jobject dstRect, SkPaint* paint) {
+ jobject dstRect, SkPaint* paint,
+ jint screenDensity, jint bitmapDensity) {
SkRect dst;
GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
- doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint);
+ doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+ screenDensity, bitmapDensity);
}
static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
@@ -907,11 +931,11 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
(void*) SkCanvasGlue::drawRoundRect},
{"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
- {"native_drawBitmap","(IIFFIII)V",
+ {"native_drawBitmap","(IIFFIIII)V",
(void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
- {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;I)V",
+ {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V",
(void*) SkCanvasGlue::drawBitmapRF},
- {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;I)V",
+ {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V",
(void*) SkCanvasGlue::drawBitmapRR},
{"native_drawBitmap", "(I[IIIFFIIZI)V",
(void*)SkCanvasGlue::drawBitmapArray},
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index e6048cd..0f8dff1 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -4,15 +4,23 @@
#include <jni.h>
+static void ThrowIAE_IfNull(JNIEnv* env, void* ptr) {
+ if (NULL == ptr) {
+ doThrowIAE(env);
+ }
+}
+
class SkMaskFilterGlue {
public:
static void destructor(JNIEnv* env, jobject, SkMaskFilter* filter) {
- SkASSERT(filter);
- filter->unref();
+ filter->safeUnref();
}
static SkMaskFilter* createBlur(JNIEnv* env, jobject, float radius, int blurStyle) {
- return SkBlurMaskFilter::Create(SkFloatToScalar(radius), (SkBlurMaskFilter::BlurStyle)blurStyle);
+ SkMaskFilter* filter = SkBlurMaskFilter::Create(SkFloatToScalar(radius),
+ (SkBlurMaskFilter::BlurStyle)blurStyle);
+ ThrowIAE_IfNull(env, filter);
+ return filter;
}
static SkMaskFilter* createEmboss(JNIEnv* env, jobject, jfloatArray dirArray, float ambient, float specular, float radius) {
@@ -24,8 +32,12 @@ public:
direction[i] = SkFloatToScalar(values[i]);
}
- return SkBlurMaskFilter::CreateEmboss(direction, SkFloatToScalar(ambient),
- SkFloatToScalar(specular), SkFloatToScalar(radius));
+ SkMaskFilter* filter = SkBlurMaskFilter::CreateEmboss(direction,
+ SkFloatToScalar(ambient),
+ SkFloatToScalar(specular),
+ SkFloatToScalar(radius));
+ ThrowIAE_IfNull(env, filter);
+ return filter;
}
};
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b28eb90..b09c62b 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -43,25 +43,23 @@ static int Color_HSVToColor(JNIEnv* env, jobject, int alpha, jfloatArray hsvArra
static void Shader_destructor(JNIEnv* env, jobject, SkShader* shader)
{
- SkASSERT(shader != NULL);
- shader->unref();
+ shader->safeUnref();
}
static bool Shader_getLocalMatrix(JNIEnv* env, jobject, const SkShader* shader, SkMatrix* matrix)
{
- SkASSERT(shader != NULL);
- return shader->getLocalMatrix(matrix);
+ return shader ? shader->getLocalMatrix(matrix) : false;
}
static void Shader_setLocalMatrix(JNIEnv* env, jobject, SkShader* shader, const SkMatrix* matrix)
{
- SkASSERT(shader != NULL);
-
- if (NULL == matrix) {
- shader->resetLocalMatrix();
- }
- else {
- shader->setLocalMatrix(*matrix);
+ if (shader) {
+ if (NULL == matrix) {
+ shader->resetLocalMatrix();
+ }
+ else {
+ shader->setLocalMatrix(*matrix);
+ }
}
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 6449147..65c0435 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -53,10 +53,11 @@ struct fields_t {
int STREAM_MUSIC; //... stream type constants
int STREAM_ALARM; //... stream type constants
int STREAM_NOTIFICATION; //... stream type constants
- int STREAM_BLUETOOTH_SCO; //... stream type constants
+ int STREAM_BLUETOOTH_SCO; //... stream type constants
+ int STREAM_DTMF; //... stream type constants
int MODE_STREAM; //... memory mode
int MODE_STATIC; //... memory mode
- jfieldID nativeTrackInJavaObj; // stores in Java the native AudioTrack object
+ jfieldID nativeTrackInJavaObj; // stores in Java the native AudioTrack object
jfieldID jniData; // stores in Java additional resources used by the native AudioTrack
};
static fields_t javaAudioTrackFields;
@@ -203,6 +204,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
atStreamType = AudioSystem::NOTIFICATION;
} else if (streamType == javaAudioTrackFields.STREAM_BLUETOOTH_SCO) {
atStreamType = AudioSystem::BLUETOOTH_SCO;
+ } else if (streamType == javaAudioTrackFields.STREAM_DTMF) {
+ atStreamType = AudioSystem::DTMF;
} else {
LOGE("Error creating AudioTrack: unknown stream type.");
return AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE;
@@ -727,6 +730,8 @@ static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env, jobjec
nativeStreamType = AudioSystem::NOTIFICATION;
} else if (javaStreamType == javaAudioTrackFields.STREAM_BLUETOOTH_SCO) {
nativeStreamType = AudioSystem::BLUETOOTH_SCO;
+ } else if (javaStreamType == javaAudioTrackFields.STREAM_DTMF) {
+ nativeStreamType = AudioSystem::DTMF;
} else {
nativeStreamType = AudioSystem::DEFAULT;
}
@@ -822,6 +827,7 @@ static JNINativeMethod gMethods[] = {
#define JAVA_CONST_STREAM_ALARM_NAME "STREAM_ALARM"
#define JAVA_CONST_STREAM_NOTIFICATION_NAME "STREAM_NOTIFICATION"
#define JAVA_CONST_STREAM_BLUETOOTH_SCO_NAME "STREAM_BLUETOOTH_SCO"
+#define JAVA_CONST_STREAM_DTMF_NAME "STREAM_DTMF"
#define JAVA_CONST_MODE_STREAM_NAME "MODE_STREAM"
#define JAVA_CONST_MODE_STATIC_NAME "MODE_STATIC"
#define JAVA_NATIVETRACKINJAVAOBJ_FIELD_NAME "mNativeTrackInJavaObj"
@@ -943,8 +949,10 @@ int register_android_media_AudioTrack(JNIEnv *env)
JAVA_CONST_STREAM_NOTIFICATION_NAME, &(javaAudioTrackFields.STREAM_NOTIFICATION))
|| !android_media_getIntConstantFromClass(env, audioManagerClass,
JAVA_AUDIOMANAGER_CLASS_NAME,
- JAVA_CONST_STREAM_BLUETOOTH_SCO_NAME,
- &(javaAudioTrackFields.STREAM_BLUETOOTH_SCO))) {
+ JAVA_CONST_STREAM_BLUETOOTH_SCO_NAME, &(javaAudioTrackFields.STREAM_BLUETOOTH_SCO))
+ || !android_media_getIntConstantFromClass(env, audioManagerClass,
+ JAVA_AUDIOMANAGER_CLASS_NAME,
+ JAVA_CONST_STREAM_DTMF_NAME, &(javaAudioTrackFields.STREAM_DTMF))) {
// error log performed in android_media_getIntConstantFromClass()
return -1;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 59f4067..66b2506 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -74,12 +74,13 @@ static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
}
enum {
- STYLE_NUM_ENTRIES = 5,
+ STYLE_NUM_ENTRIES = 6,
STYLE_TYPE = 0,
STYLE_DATA = 1,
STYLE_ASSET_COOKIE = 2,
STYLE_RESOURCE_ID = 3,
- STYLE_CHANGING_CONFIGURATIONS = 4
+ STYLE_CHANGING_CONFIGURATIONS = 4,
+ STYLE_DENSITY = 5
};
static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
@@ -896,6 +897,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
ResTable::Theme* theme = (ResTable::Theme*)themeToken;
const ResTable& res = theme->getResTable();
ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+ ResTable_config config;
Res_value value;
const jsize NI = env->GetArrayLength(attrs);
@@ -995,6 +997,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
value.dataType = Res_value::TYPE_NULL;
value.data = 0;
typeSetFlags = 0;
+ config.density = 0;
// Skip through XML attributes until the end or the next possible match.
while (ix < NX && curIdent > curXmlAttr) {
@@ -1042,7 +1045,8 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
//printf("Resolving attribute reference\n");
- ssize_t newBlock = theme->resolveAttributeReference(&value, block, &resid, &typeSetFlags);
+ ssize_t newBlock = theme->resolveAttributeReference(&value, block,
+ &resid, &typeSetFlags, &config);
if (newBlock >= 0) block = newBlock;
} else {
// If we still don't have a value for this attribute, try to find
@@ -1051,7 +1055,8 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
if (newBlock >= 0) {
//printf("Resolving resource reference\n");
- newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+ newBlock = res.resolveReference(&value, block, &resid,
+ &typeSetFlags, &config);
if (newBlock >= 0) block = newBlock;
}
}
@@ -1070,6 +1075,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
dest[STYLE_RESOURCE_ID] = resid;
dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+ dest[STYLE_DENSITY] = config.density;
if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
indicesIdx++;
@@ -1108,6 +1114,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
}
const ResTable& res(am->getResources());
ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
+ ResTable_config config;
Res_value value;
const jsize NI = env->GetArrayLength(attrs);
@@ -1160,6 +1167,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
value.dataType = Res_value::TYPE_NULL;
value.data = 0;
typeSetFlags = 0;
+ config.density = 0;
// Skip through XML attributes until the end or the next possible match.
while (ix < NX && curIdent > curXmlAttr) {
@@ -1179,7 +1187,8 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
//printf("Resolving attribute reference\n");
- ssize_t newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+ ssize_t newBlock = res.resolveReference(&value, block, &resid,
+ &typeSetFlags, &config);
if (newBlock >= 0) block = newBlock;
}
@@ -1197,6 +1206,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
dest[STYLE_RESOURCE_ID] = resid;
dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+ dest[STYLE_DENSITY] = config.density;
if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
indicesIdx++;
@@ -1250,6 +1260,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
return JNI_FALSE;
}
const ResTable& res(am->getResources());
+ ResTable_config config;
Res_value value;
ssize_t block;
@@ -1276,13 +1287,15 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
while (i < NV && arrayEnt < endArrayEnt) {
block = arrayEnt->stringBlock;
typeSetFlags = arrayTypeSetFlags;
+ config.density = 0;
value = arrayEnt->map.value;
uint32_t resid = 0;
if (value.dataType != Res_value::TYPE_NULL) {
// Take care of resolving the found resource to its final value.
//printf("Resolving attribute reference\n");
- ssize_t newBlock = res.resolveReference(&value, block, &resid, &typeSetFlags);
+ ssize_t newBlock = res.resolveReference(&value, block, &resid,
+ &typeSetFlags, &config);
if (newBlock >= 0) block = newBlock;
}
@@ -1299,6 +1312,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
dest[STYLE_ASSET_COOKIE] = (jint)res.getTableCookie(block);
dest[STYLE_RESOURCE_ID] = resid;
dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
+ dest[STYLE_DENSITY] = config.density;
dest += STYLE_NUM_ENTRIES;
i+= STYLE_NUM_ENTRIES;
arrayEnt++;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 17704ae..69ef96c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -863,7 +863,8 @@
android:protectionLevel="signature" />
<!-- Allows an application to call the activity manager shutdown() API
- to put the higher-level system there into a shutdown state. -->
+ to put the higher-level system there into a shutdown state.
+ @hide -->
<permission android:name="android.permission.SHUTDOWN"
android:label="@string/permlab_shutdown"
android:description="@string/permdesc_shutdown"
@@ -872,7 +873,8 @@
<!-- Allows an application to tell the activity manager to temporarily
stop application switches, putting it into a special mode that
prevents applications from immediately switching away from some
- critical UI such as the home screen. -->
+ critical UI such as the home screen.
+ @hide -->
<permission android:name="android.permission.STOP_APP_SWITCHES"
android:label="@string/permlab_stopAppSwitches"
android:description="@string/permdesc_stopAppSwitches"
@@ -1085,7 +1087,7 @@
android:hasCode="false"
android:label="@string/android_system_label"
android:allowClearUserData="false"
- android:backupAgent="com.android.internal.backup.SystemBackupAgent"
+ android:backupAgent="com.android.server.SystemBackupAgent"
android:icon="@drawable/ic_launcher_android">
<activity android:name="com.android.internal.app.ChooserActivity"
android:theme="@style/Theme.Dialog.Alert"
@@ -1128,6 +1130,15 @@
android:exported="true">
</activity>
+ <activity android:name="com.android.server.ShutdownActivity"
+ android:permission="android.permission.SHUTDOWN"
+ android:excludeFromRecents="true">
+ <intent-filter>
+ <action android:name="android.intent.action.ACTION_REQUEST_SHUTDOWN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<service android:name="com.android.server.LoadAverageService"
android:exported="true" />
diff --git a/core/res/res/drawable/expander_ic_maximized.9.png b/core/res/res/drawable/expander_ic_maximized.9.png
index 778255a..465cabd 100644
--- a/core/res/res/drawable/expander_ic_maximized.9.png
+++ b/core/res/res/drawable/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable/expander_ic_minimized.9.png b/core/res/res/drawable/expander_ic_minimized.9.png
index 5235c18..9967ecb 100644
--- a/core/res/res/drawable/expander_ic_minimized.9.png
+++ b/core/res/res/drawable/expander_ic_minimized.9.png
Binary files differ
diff --git a/packages/SettingsProvider/res/values-fr/defaults.xml b/core/res/res/layout/preference_dialog.xml
index 56334cc..5cf0f6e 100644
--- a/packages/SettingsProvider/res/values-fr/defaults.xml
+++ b/core/res/res/layout/preference_dialog.xml
@@ -1,22 +1,26 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"cellulaire, Bluetooth, Wi-Fi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
+
+<!-- Layout used by DialogPreference widgets. This is inflated inside
+ android.R.layout.preference. -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4dip"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/btn_circle"
+ android:src="@drawable/ic_btn_round_more" />
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0e84839..558d91e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -916,12 +916,12 @@
you.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_readPhoneState">read phone state</string>
+ <string name="permlab_readPhoneState">read phone state and identity</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readPhoneState">Allows the application to access the phone
features of the device. An application with this permission can determine the phone
- number of this phone, whether a call is active, the number that call is connected to
- and the like.</string>
+ number and serial number of this phone, whether a call is active, the number that call
+ is connected to and the like.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock">prevent phone from sleeping</string>
@@ -1709,6 +1709,8 @@
<string name="volume_music">Media volume</string>
<!-- Hint shown in the volume toast to inform the user that the media audio is playing through Bluetooth. -->
<string name="volume_music_hint_playing_through_bluetooth">Playing through Bluetooth</string>
+ <!-- Hint shown in the volume toast to inform the user that the current ringtone is the silent ringtone. -->
+ <string name="volume_music_hint_silent_ringtone_selected">Silent ringtone selected</string>
<!-- Title of the dialog where the user is adjusting the phone call volume -->
<string name="volume_call">In-call volume</string>
<!-- Title of the dialog where the user is adjusting the phone call volume when connected on bluetooth-->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6df8b0a..4aa4210 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -659,12 +659,12 @@
</style>
<style name="Preference.PreferenceScreen">
- <item name="android:widgetLayout">@android:layout/preferences</item>
</style>
<style name="Preference.DialogPreference">
<item name="android:positiveButtonText">@android:string/ok</item>
<item name="android:negativeButtonText">@android:string/cancel</item>
+ <item name="android:widgetLayout">@android:layout/preference_dialog</item>
</style>
<style name="Preference.DialogPreference.YesNoPreference">
@@ -680,6 +680,7 @@
<item name="android:ringtoneType">ringtone</item>
<item name="android:showSilent">true</item>
<item name="android:showDefault">true</item>
+ <item name="android:widgetLayout">@android:layout/preference_dialog</item>
</style>
<!-- Other Misc Styles -->
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bc2e42e..345f810 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -50,6 +50,9 @@ public class Canvas {
// Package-scoped for quick access.
/*package*/ int mDensity = Bitmap.DENSITY_NONE;
+
+ // Used to determine when compatibility scaling is in effect.
+ private int mScreenDensity = Bitmap.DENSITY_NONE;
// Used by native code
@SuppressWarnings({"UnusedDeclaration"})
@@ -219,6 +222,11 @@ public class Canvas {
mDensity = density;
}
+ /** @hide */
+ public void setScreenDensity(int density) {
+ mScreenDensity = density;
+ }
+
// the SAVE_FLAG constants must match their native equivalents
/** restore the current matrix when restore() is called */
@@ -971,7 +979,8 @@ public class Canvas {
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
throwIfRecycled(bitmap);
native_drawBitmap(mNativeCanvas, bitmap.ni(), left, top,
- paint != null ? paint.mNativePaint : 0, mDensity, bitmap.mDensity);
+ paint != null ? paint.mNativePaint : 0, mDensity, mScreenDensity,
+ bitmap.mDensity);
}
/**
@@ -1002,7 +1011,8 @@ public class Canvas {
}
throwIfRecycled(bitmap);
native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
- paint != null ? paint.mNativePaint : 0);
+ paint != null ? paint.mNativePaint : 0,
+ mScreenDensity, bitmap.mDensity);
}
/**
@@ -1033,7 +1043,8 @@ public class Canvas {
}
throwIfRecycled(bitmap);
native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
- paint != null ? paint.mNativePaint : 0);
+ paint != null ? paint.mNativePaint : 0,
+ mScreenDensity, bitmap.mDensity);
}
/**
@@ -1513,13 +1524,19 @@ public class Canvas {
private native void native_drawBitmap(int nativeCanvas, int bitmap,
float left, float top,
int nativePaintOrZero,
- int canvasDensity, int bitmapDensity);
+ int canvasDensity,
+ int screenDensity,
+ int bitmapDensity);
private native void native_drawBitmap(int nativeCanvas, int bitmap,
Rect src, RectF dst,
- int nativePaintOrZero);
+ int nativePaintOrZero,
+ int screenDensity,
+ int bitmapDensity);
private static native void native_drawBitmap(int nativeCanvas, int bitmap,
Rect src, Rect dst,
- int nativePaintOrZero);
+ int nativePaintOrZero,
+ int screenDensity,
+ int bitmapDensity);
private static native void native_drawBitmap(int nativeCanvas, int[] colors,
int offset, int stride, float x,
float y, int width, int height,
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index f829b08..904361f 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -23,6 +23,12 @@ package android.renderscript;
import java.io.InputStream;
import java.io.IOException;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.Color;
+
import android.os.Bundle;
import android.content.res.Resources;
import android.util.Log;
@@ -32,8 +38,6 @@ import android.view.MenuItem;
import android.view.Window;
import android.view.View;
import android.view.Surface;
-import android.graphics.Bitmap;
-import android.graphics.Color;
/**
* @hide
@@ -53,6 +57,8 @@ public class RenderScript {
private static boolean sInitialized;
native private static void _nInit();
+ private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
+
static {
sInitialized = false;
try {
@@ -62,6 +68,7 @@ public class RenderScript {
} catch (UnsatisfiedLinkError e) {
Log.d(LOG_TAG, "RenderScript JNI library not found!");
}
+ mBitmapOptions.inScaled = false;
}
native private int nDeviceCreate();
@@ -96,6 +103,7 @@ public class RenderScript {
native private int nAllocationCreatePredefSized(int predef, int count);
native private int nAllocationCreateSized(int elem, int count);
native private int nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp);
+ native private int nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp);
native private void nAllocationUploadToTexture(int alloc, int baseMioLevel);
native private void nAllocationDestroy(int alloc);
@@ -131,6 +139,7 @@ public class RenderScript {
native private void nScriptCSetClearColor(float r, float g, float b, float a);
native private void nScriptCSetClearDepth(float depth);
native private void nScriptCSetClearStencil(int stencil);
+ native private void nScriptCSetTimeZone(byte[] timeZone);
native private void nScriptCAddType(int type);
native private void nScriptCSetRoot(boolean isRoot);
native private void nScriptCSetScript(byte[] script, int offset, int length);
@@ -529,10 +538,26 @@ public class RenderScript {
}
public Allocation allocationCreateFromBitmap(Bitmap b, ElementPredefined dstFmt, boolean genMips) {
- int id = nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
+ int id = nAllocationCreateFromBitmap(dstFmt.mID, genMips, b);
return new Allocation(id);
}
+ public Allocation allocationCreateFromBitmapBoxed(Bitmap b, ElementPredefined dstFmt, boolean genMips) {
+ int id = nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b);
+ return new Allocation(id);
+ }
+
+ public Allocation allocationCreateFromBitmapResource(Resources res, int id, ElementPredefined internalElement, boolean genMips) {
+ Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
+ return allocationCreateFromBitmap(b, internalElement, genMips);
+ }
+
+ public Allocation allocationCreateFromBitmapResourceBoxed(Resources res, int id, ElementPredefined internalElement, boolean genMips) {
+ Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
+ return allocationCreateFromBitmapBoxed(b, internalElement, genMips);
+ }
+
+
//////////////////////////////////////////////////////////////////////////////////
// Adapter1D
@@ -646,6 +671,15 @@ public class RenderScript {
nScriptCBegin();
}
+ public void scriptCSetTimeZone(String timeZone) {
+ try {
+ byte[] bytes = timeZone.getBytes("UTF-8");
+ nScriptCSetTimeZone(bytes);
+ } catch (java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public void scriptCSetClearColor(float r, float g, float b, float a) {
nScriptCSetClearColor(r, g, b, a);
}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 573610c..a02abca 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -291,6 +291,29 @@ nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jint dstFmt, jboolean g
return 0;
}
+static int
+nAllocationCreateFromBitmapBoxed(JNIEnv *_env, jobject _this, jint dstFmt, jboolean genMips, jobject jbitmap)
+{
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ SkBitmap const * nativeBitmap =
+ (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
+ const SkBitmap& bitmap(*nativeBitmap);
+ SkBitmap::Config config = bitmap.getConfig();
+
+ RsElementPredefined e = SkBitmapToPredefined(config);
+
+ if (e != RS_ELEMENT_USER_U8) {
+ bitmap.lockPixels();
+ const int w = bitmap.width();
+ const int h = bitmap.height();
+ const void* ptr = bitmap.getPixels();
+ jint id = (jint)rsAllocationCreateFromBitmapBoxed(w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+ bitmap.unlockPixels();
+ return id;
+ }
+ return 0;
+}
+
static void
nAllocationDestroy(JNIEnv *_env, jobject _this, jint a)
@@ -563,7 +586,7 @@ static void
nScriptCSetClearDepth(JNIEnv *_env, jobject _this, jfloat d)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
- LOG_API("nScriptCSetClearColor, con(%p), depth(%f)", con, d);
+ LOG_API("nScriptCSetClearDepth, con(%p), depth(%f)", con, d);
rsScriptCSetClearDepth(d);
}
@@ -576,6 +599,23 @@ nScriptCSetClearStencil(JNIEnv *_env, jobject _this, jint stencil)
}
static void
+nScriptCSetTimeZone(JNIEnv *_env, jobject _this, jbyteArray timeZone)
+{
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ LOG_API("nScriptCSetTimeZone, con(%p), timeZone(%s)", con, timeZone);
+
+ jint length = _env->GetArrayLength(timeZone);
+ jbyte* timeZone_ptr;
+ timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
+
+ rsScriptCSetTimeZone((const char *)timeZone_ptr, length);
+
+ if (timeZone_ptr) {
+ _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
+ }
+}
+
+static void
nScriptCAddType(JNIEnv *_env, jobject _this, jint type)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -994,6 +1034,7 @@ static JNINativeMethod methods[] = {
{"nAllocationCreatePredefSized", "(II)I", (void*)nAllocationCreatePredefSized },
{"nAllocationCreateSized", "(II)I", (void*)nAllocationCreateSized },
{"nAllocationCreateFromBitmap", "(IZLandroid/graphics/Bitmap;)I", (void*)nAllocationCreateFromBitmap },
+{"nAllocationCreateFromBitmapBoxed","(IZLandroid/graphics/Bitmap;)I", (void*)nAllocationCreateFromBitmapBoxed },
{"nAllocationUploadToTexture", "(II)V", (void*)nAllocationUploadToTexture },
{"nAllocationDestroy", "(I)V", (void*)nAllocationDestroy },
{"nAllocationData", "(I[I)V", (void*)nAllocationData_i },
@@ -1028,6 +1069,7 @@ static JNINativeMethod methods[] = {
{"nScriptCSetClearColor", "(FFFF)V", (void*)nScriptCSetClearColor },
{"nScriptCSetClearDepth", "(F)V", (void*)nScriptCSetClearDepth },
{"nScriptCSetClearStencil", "(I)V", (void*)nScriptCSetClearStencil },
+{"nScriptCSetTimeZone", "([B)V", (void*)nScriptCSetTimeZone },
{"nScriptCAddType", "(I)V", (void*)nScriptCAddType },
{"nScriptCSetRoot", "(Z)V", (void*)nScriptCSetRoot },
{"nScriptCSetScript", "([BII)V", (void*)nScriptCSetScript },
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index ad27903..13316a9 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -93,10 +93,6 @@ enum video_encoder {
VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
};
-
-// Maximum frames per second is 24
-#define MEDIA_RECORDER_MAX_FRAME_RATE 24
-
/*
* The state machine of the media_recorder uses a set of different state names.
* The mapping between the media_recorder and the pvauthorengine is shown below:
diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h
index 0859457..e76fd4c 100644
--- a/include/media/stagefright/OMXDecoder.h
+++ b/include/media/stagefright/OMXDecoder.h
@@ -26,6 +26,8 @@
#include <utils/List.h>
#include <utils/threads.h>
+#include <OMX_Video.h>
+
namespace android {
class OMXMediaBuffer;
@@ -35,10 +37,8 @@ class OMXDecoder : public MediaSource,
public MediaBufferObserver {
public:
static OMXDecoder *Create(
- OMXClient *client, const sp<MetaData> &data);
-
- static OMXDecoder *CreateEncoder(
- OMXClient *client, const sp<MetaData> &data);
+ OMXClient *client, const sp<MetaData> &data,
+ bool createEncoder = false);
virtual ~OMXDecoder();
@@ -68,10 +68,23 @@ private:
};
enum PortStatus {
- kPortStatusActive = 0,
- kPortStatusDisabled = 1,
- kPortStatusShutdown = 2,
- kPortStatusFlushing = 3
+ kPortStatusActive = 0,
+ kPortStatusDisabled = 1,
+ kPortStatusShutdown = 2,
+ kPortStatusFlushing = 3,
+ kPortStatusFlushingToDisabled = 4,
+ kPortStatusFlushingToShutdown = 5,
+ };
+
+ enum Quirks {
+ kWantsRawNALFrames = 1,
+ kDoesntReturnBuffersOnDisable = 2,
+ kDoesntFlushOnExecutingToIdle = 4,
+ kDoesntProperlyFlushAllPortsAtOnce = 8,
+ kRequiresAllocateBufferOnInputPorts = 16,
+ kRequiresAllocateBufferOnOutputPorts = 32,
+ kRequiresLoadedToIdleAfterAllocation = 64,
+ kMeasuresTimeInMilliseconds = 128,
};
OMXClient *mClient;
@@ -79,6 +92,8 @@ private:
IOMX::node_id mNode;
char *mComponentName;
bool mIsMP3;
+ bool mIsAVC;
+ uint32_t mQuirks;
MediaSource *mSource;
sp<MetaData> mOutputFormat;
@@ -116,7 +131,8 @@ private:
bool mReachedEndOfInput;
OMXDecoder(OMXClient *client, IOMX::node_id node,
- const char *mime, const char *codec);
+ const char *mime, const char *codec,
+ uint32_t quirks);
void setPortStatus(OMX_U32 port_index, PortStatus status);
PortStatus getPortStatus(OMX_U32 port_index) const;
@@ -125,7 +141,13 @@ private:
void setAMRFormat();
void setAACFormat();
- void setVideoOutputFormat(OMX_U32 width, OMX_U32 height);
+
+ status_t setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat);
+
+ void setVideoOutputFormat(const char *mime, OMX_U32 width, OMX_U32 height);
void setup();
void dumpPortDefinition(OMX_U32 port_index);
@@ -144,6 +166,7 @@ private:
void freeInputBuffer(IOMX::buffer_id buffer);
void freeOutputBuffer(IOMX::buffer_id buffer);
+ void freePortBuffers(OMX_U32 port_index);
void postStart();
void postEmptyBufferDone(IOMX::buffer_id buffer);
diff --git a/include/media/stagefright/TIHardwareRenderer.h b/include/media/stagefright/TIHardwareRenderer.h
new file mode 100644
index 0000000..f7fa81b
--- /dev/null
+++ b/include/media/stagefright/TIHardwareRenderer.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef TI_HARDWARE_RENDERER_H_
+
+#define TI_HARDWARE_RENDERER_H_
+
+#include <media/stagefright/VideoRenderer.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class ISurface;
+class Overlay;
+
+class TIHardwareRenderer : public VideoRenderer {
+public:
+ TIHardwareRenderer(
+ const sp<ISurface> &surface,
+ size_t displayWidth, size_t displayHeight,
+ size_t decodedWidth, size_t decodedHeight);
+
+ virtual ~TIHardwareRenderer();
+
+ virtual void render(
+ const void *data, size_t size, void *platformPrivate);
+
+private:
+ sp<ISurface> mISurface;
+ size_t mDisplayWidth, mDisplayHeight;
+ size_t mDecodedWidth, mDecodedHeight;
+ size_t mFrameSize;
+ sp<Overlay> mOverlay;
+ Vector<void *> mOverlayAddresses;
+ size_t mIndex;
+
+ TIHardwareRenderer(const TIHardwareRenderer &);
+ TIHardwareRenderer &operator=(const TIHardwareRenderer &);
+};
+
+} // namespace android
+
+#endif // TI_HARDWARE_RENDERER_H_
+
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index e72357a..cb9bf94 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -62,6 +62,7 @@ private:
static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+ static int query(android_native_window_t* window, int what, int* value);
framebuffer_device_t* fbDev;
alloc_device_t* grDev;
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index acc9bea..a9ae1c4 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -82,10 +82,16 @@ public:
/* release the overlay buffer and post it */
status_t queueBuffer(overlay_buffer_t buffer);
+ /* change the width and height of the overlay */
+ status_t resizeInput(uint32_t width, uint32_t height);
+
status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;
status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;
+ /* set the buffer attributes */
+ status_t setParameter(int param, int value);
+
/* returns the address of a given buffer if supported, NULL otherwise. */
void* getBufferAddress(overlay_buffer_t buffer);
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 8c4f63d..156d453 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -115,6 +115,8 @@ private:
sp<ISurface> mSurface;
SurfaceID mToken;
uint32_t mIdentity;
+ uint32_t mWidth;
+ uint32_t mHeight;
PixelFormat mFormat;
uint32_t mFlags;
mutable Mutex mLock;
@@ -192,10 +194,12 @@ private:
static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer);
static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
+ static int query(android_native_window_t* window, int what, int* value);
int dequeueBuffer(android_native_buffer_t** buffer);
int lockBuffer(android_native_buffer_t* buffer);
int queueBuffer(android_native_buffer_t* buffer);
+ int query(int what, int* value);
status_t dequeueBuffer(sp<SurfaceBuffer>* buffer);
status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
@@ -209,6 +213,8 @@ private:
sp<SurfaceBuffer> mLockedBuffer;
SurfaceID mToken;
uint32_t mIdentity;
+ uint32_t mWidth;
+ uint32_t mHeight;
PixelFormat mFormat;
uint32_t mFlags;
mutable Region mDirtyRegion;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 0398ea7..a3a1316 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -60,6 +60,12 @@ struct android_native_base_t
// ---------------------------------------------------------------------------
+/* attributes queriable with query() */
+enum {
+ NATIVE_WINDOW_WIDTH = 0,
+ NATIVE_WINDOW_HEIGHT = 1
+};
+
struct android_native_window_t
{
#ifdef __cplusplus
@@ -129,8 +135,15 @@ struct android_native_window_t
int (*queueBuffer)(struct android_native_window_t* window,
struct android_native_buffer_t* buffer);
+ /*
+ * hook used to retrieve information about the native window.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*query)(struct android_native_window_t* window,
+ int what, int* value);
- void* reserved_proc[5];
+ void* reserved_proc[4];
};
// ---------------------------------------------------------------------------
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index edd0cae..e524e2a 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1655,7 +1655,8 @@ public:
ssize_t resolveReference(Res_value* inOutValue,
ssize_t blockIndex,
uint32_t* outLastRef = NULL,
- uint32_t* inoutTypeSpecFlags = NULL) const;
+ uint32_t* inoutTypeSpecFlags = NULL,
+ ResTable_config* outConfig = NULL) const;
enum {
TMP_BUFFER_SIZE = 16
@@ -1729,7 +1730,8 @@ public:
*/
ssize_t resolveAttributeReference(Res_value* inOutValue,
ssize_t blockIndex, uint32_t* outLastRef = NULL,
- uint32_t* inoutTypeSpecFlags = NULL) const;
+ uint32_t* inoutTypeSpecFlags = NULL,
+ ResTable_config* inoutConfig = NULL) const;
void dumpToLog() const;
diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java
index 1de007d..b1b78ea 100644
--- a/keystore/java/android/security/CertTool.java
+++ b/keystore/java/android/security/CertTool.java
@@ -140,7 +140,7 @@ public class CertTool {
private void addExtraIntentInfo(Intent intent, String namespace,
String data) {
- intent.putExtra(KEY_ITEM + "1", data);
+ intent.putExtra(KEY_ITEM + "1", data.getBytes());
intent.putExtra(KEY_NAMESPACE + "1", namespace);
}
diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c
index ea21b7d..006a0a3 100644
--- a/keystore/jni/cert.c
+++ b/keystore/jni/cert.c
@@ -46,7 +46,7 @@ static void save_in_store(EVP_PKEY *pkey)
RSA *rsa = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_set1_RSA(newpkey, rsa);
PKEY_STORE_free(pkey_store[store_index]);
- pkey_store[store_index].key_len = i2d_RSAPublicKey(rsa, &pkey_store[store_index].public_key);
+ pkey_store[store_index].key_len = i2d_RSA_PUBKEY(rsa, &pkey_store[store_index].public_key);
pkey_store[store_index++].pkey = newpkey;
store_index %= KEYGEN_STORE_SIZE;
RSA_free(rsa);
diff --git a/keystore/jni/certtool.c b/keystore/jni/certtool.c
index 1ae8dab..b36b34a 100644
--- a/keystore/jni/certtool.c
+++ b/keystore/jni/certtool.c
@@ -30,13 +30,17 @@ jstring
android_security_CertTool_generateCertificateRequest(JNIEnv* env,
jobject thiz,
jint bits,
- jstring subject)
+ jstring jChallenge)
{
+ int ret = -1;
+ jboolean bIsCopy;
char csr[REPLY_MAX];
- if (gen_csr(bits, subject, csr) == 0) {
- return (*env)->NewStringUTF(env, csr);
- }
+ const char* challenge = (*env)->GetStringUTFChars(env, jChallenge, &bIsCopy);
+
+ ret = gen_csr(bits, challenge , csr);
+ (*env)->ReleaseStringUTFChars(env, jChallenge, challenge);
+ if (ret == 0) return (*env)->NewStringUTF(env, csr);
return NULL;
}
diff --git a/libs/audioflinger/Android.mk b/libs/audioflinger/Android.mk
index c10e02b..f5c03bb 100644
--- a/libs/audioflinger/Android.mk
+++ b/libs/audioflinger/Android.mk
@@ -107,6 +107,7 @@ LOCAL_MODULE:= libaudioflinger
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
+ LOCAL_SHARED_LIBRARIES += liba2dp
endif
ifeq ($(AUDIO_POLICY_TEST),true)
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 1336131..232ffb0 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -3443,8 +3443,8 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, void *output)
srcThread->getTracks(tracks, activeTracks, stream);
if (tracks.size()) {
dstThread->putTracks(tracks, activeTracks);
- dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
}
+ dstThread->sendConfigEvent(AudioSystem::STREAM_CONFIG_CHANGED, stream);
}
}
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 855ea63..1d14f70 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -146,26 +146,26 @@ enum RsDepthFunc {
};
enum RsBlendSrcFunc {
- RS_BLEND_SRC_ZERO,
- RS_BLEND_SRC_ONE,
- RS_BLEND_SRC_DST_COLOR,
- RS_BLEND_SRC_ONE_MINUS_DST_COLOR,
- RS_BLEND_SRC_SRC_ALPHA,
- RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA,
- RS_BLEND_SRC_DST_ALPHA,
- RS_BLEND_SRC_ONE_MINUS_DST_ALPHA,
- RS_BLEND_SRC_SRC_ALPHA_SATURATE
+ RS_BLEND_SRC_ZERO, // 0
+ RS_BLEND_SRC_ONE, // 1
+ RS_BLEND_SRC_DST_COLOR, // 2
+ RS_BLEND_SRC_ONE_MINUS_DST_COLOR, // 3
+ RS_BLEND_SRC_SRC_ALPHA, // 4
+ RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_SRC_DST_ALPHA, // 6
+ RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, // 7
+ RS_BLEND_SRC_SRC_ALPHA_SATURATE // 8
};
enum RsBlendDstFunc {
- RS_BLEND_DST_ZERO,
- RS_BLEND_DST_ONE,
- RS_BLEND_DST_SRC_COLOR,
- RS_BLEND_DST_ONE_MINUS_SRC_COLOR,
- RS_BLEND_DST_SRC_ALPHA,
- RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
- RS_BLEND_DST_DST_ALPHA,
- RS_BLEND_DST_ONE_MINUS_DST_ALPHA
+ RS_BLEND_DST_ZERO, // 0
+ RS_BLEND_DST_ONE, // 1
+ RS_BLEND_DST_SRC_COLOR, // 2
+ RS_BLEND_DST_ONE_MINUS_SRC_COLOR, // 3
+ RS_BLEND_DST_SRC_ALPHA, // 4
+ RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, // 5
+ RS_BLEND_DST_DST_ALPHA, // 6
+ RS_BLEND_DST_ONE_MINUS_DST_ALPHA // 7
};
enum RsTexEnvMode {
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index 0789301..7a5556e 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -30,11 +30,3 @@ typedef struct {
#define RS_PROGRAM_VERTEX_PROJECTION_OFFSET 16
#define RS_PROGRAM_VERTEX_TEXTURE_OFFSET 32
-//typedef int (*rsc_RunScript)(uint32_t launchIndex, const rsc_FunctionTable *);
-
-
-/* EnableCap */
-#define GL_LIGHTING 0x0B50
-
-/* LightName */
-#define GL_LIGHT0 0x4000
diff --git a/libs/rs/java/Film/res/drawable/p01.png b/libs/rs/java/Film/res/drawable/p01.png
new file mode 100644
index 0000000..a9b9bdb
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p01.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p02.png b/libs/rs/java/Film/res/drawable/p02.png
new file mode 100644
index 0000000..8162c82
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p02.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p03.png b/libs/rs/java/Film/res/drawable/p03.png
new file mode 100644
index 0000000..e3e26c0
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p03.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p04.png b/libs/rs/java/Film/res/drawable/p04.png
new file mode 100644
index 0000000..daee603
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p04.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p05.png b/libs/rs/java/Film/res/drawable/p05.png
new file mode 100644
index 0000000..fac5248
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p05.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p06.png b/libs/rs/java/Film/res/drawable/p06.png
new file mode 100644
index 0000000..3b51261
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p06.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p07.png b/libs/rs/java/Film/res/drawable/p07.png
new file mode 100644
index 0000000..d8bd938
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p07.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p08.png b/libs/rs/java/Film/res/drawable/p08.png
new file mode 100644
index 0000000..ef175e8
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p08.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p09.png b/libs/rs/java/Film/res/drawable/p09.png
new file mode 100644
index 0000000..7bf3874
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p09.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p10.png b/libs/rs/java/Film/res/drawable/p10.png
new file mode 100644
index 0000000..908827d
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p10.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p11.png b/libs/rs/java/Film/res/drawable/p11.png
new file mode 100644
index 0000000..1289f71
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p11.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p12.png b/libs/rs/java/Film/res/drawable/p12.png
new file mode 100644
index 0000000..e1af16a
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p12.png
Binary files differ
diff --git a/libs/rs/java/Film/res/drawable/p13.png b/libs/rs/java/Film/res/drawable/p13.png
new file mode 100644
index 0000000..d08bcbe
--- /dev/null
+++ b/libs/rs/java/Film/res/drawable/p13.png
Binary files differ
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
index 6885251..ac694ab 100644
--- a/libs/rs/java/Film/res/raw/filmstrip.c
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -11,29 +11,29 @@ typedef struct FilmScriptUserEnvRec {
int32_t triangleOffsets[64];
float triangleOffsetsTex[64];
int32_t triangleOffsetsCount;
-} FilmScriptUserEnv;
-*/
+} FilmScriptUserEnv;
+*/
+
+#define POS_TRANSLATE 0
+#define POS_ROTATE 1
+#define POS_FOCUS 2
+
+#define STATE_TRIANGLE_OFFSET_COUNT 0
+#define STATE_LAST_FOCUS 1
+
// The script enviroment has 3 env allocations.
// bank0: (r) The enviroment structure
// bank1: (r) The position information
// bank2: (rw) The temporary texture state
-int main(int index)
+int main(int index)
{
int f1,f2,f3,f4, f5,f6,f7,f8, f9,f10,f11,f12, f13,f14,f15,f16;
int g1,g2,g3,g4, g5,g6,g7,g8, g9,g10,g11,g12, g13,g14,g15,g16;
- float trans;
- float rot;
- int x;
- float focusPos; // float
- int focusID;
- int lastFocusID;
- int imgCount;
-
- trans = loadF(1, 0);
- rot = loadF(1, 1);
+ float trans = loadF(1, POS_TRANSLATE);
+ float rot = loadF(1, POS_ROTATE);
matrixLoadScale(&f16, 2.f, 2.f, 2.f);
matrixTranslate(&f16, 0.f, 0.f, trans);
matrixRotate(&f16, 90.f, 0.f, 0.f, 1.f);
@@ -46,24 +46,18 @@ int main(int index)
drawTriangleMesh(NAMED_mesh);
-
- //int imgId = 0;
-
- bindProgramFragmentStore(NAMED_PFImages);
- bindProgramFragment(NAMED_PFSImages);
+ // Start of images.
+ bindProgramFragmentStore(NAMED_PFSImages);
+ bindProgramFragment(NAMED_PFImages);
bindProgramVertex(NAMED_PVImages);
- //focusPos = loadF(1, 2);
- //focusID = 0;
- //lastFocusID = loadI32(2, 0);
- //imgCount = 13;
-
- /*
- disable(GL_LIGHTING);
-
+ float focusPos = loadF(1, POS_FOCUS);
+ int focusID = 0;
+ int lastFocusID = loadI32(2, STATE_LAST_FOCUS);
+ int imgCount = 13;
- if (trans > (-.3)) {
- focusID = -1.0 - focusPos;
+ if (trans > (-.3f)) {
+ focusID = -1.0f - focusPos;
if (focusID >= imgCount) {
focusID = -1;
}
@@ -71,6 +65,7 @@ int main(int index)
focusID = -1;
}
+ /*
if (focusID != lastFocusID) {
if (lastFocusID >= 0) {
uploadToTexture(con, env->tex[lastFocusID], 1);
@@ -79,36 +74,45 @@ int main(int index)
uploadToTexture(con, env->tex[focusID], 0);
}
}
- storeEnvI32(con, 2, 0, focusID);
+ */
+ storeI32(2, STATE_LAST_FOCUS, focusID);
+ int triangleOffsetsCount = loadI32(2, STATE_TRIANGLE_OFFSET_COUNT);
+ int imgId = 0;
for (imgId=1; imgId <= imgCount; imgId++) {
- float pos = focusPos + imgId + .4f;
- int offset = (int)floor(pos*2);
- pos -= 0.75;
-
- offset += env->triangleOffsetsCount / 2;
-
- if ((offset < 0) || (offset >= env->triangleOffsetsCount)) {
- continue;
- }
-
- int start = offset -2;
- int end = offset + 2;
-
- if (start < 0) {
- start = 0;
- }
- if (end > env->triangleOffsetsCount) {
- end = env->triangleOffsetsCount;
+ float pos = focusPos + imgId + 0.4f;
+ int offset = (int)floorf(pos * 2.f);
+ pos = pos - 0.75f;
+
+ offset = offset + triangleOffsetsCount / 2;
+
+ int drawit = 1;
+ if (offset < 0) {
+ drawit = 0;
+ }
+ if (offset >= triangleOffsetsCount) {
+ drawit = 0;
+ }
+
+ //if (!((offset < 0) || (offset >= triangleOffsetsCount))) {
+ if (drawit) {
+ int start = offset -2;
+ int end = offset + 2;
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (end > triangleOffsetsCount) {
+ end = triangleOffsetsCount;
+ }
+
+ bindTexture(NAMED_PFImages, 0, loadI32(0, imgId - 1));
+ matrixLoadTranslate(&f16, -pos - loadF(5, triangleOffsetsCount / 2), 0, 0);
+ vpLoadTextureMatrix(&f16);
+ drawTriangleMeshRange(NAMED_mesh, loadI32(4, start), loadI32(4, end) - loadI32(4, start));
}
-
- programFragmentBindTexture(con, env->fpImages, 0, env->tex[imgId - 1]);
- matrixLoadTranslate(con, &m, -pos - env->triangleOffsetsTex[env->triangleOffsetsCount / 2], 0, 0);
- storeEnvMatrix(con, 3, RS_PROGRAM_VERTEX_TEXTURE_OFFSET, &m);
- renderTriangleMeshRange(con, env->mesh, env->triangleOffsets[start], env->triangleOffsets[end] - env->triangleOffsets[start]);
- }
-*/
+ }
return 0;
}
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index fca0818..12a14e3 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -18,26 +18,33 @@ package com.android.film;
import java.io.Writer;
-import android.renderscript.RenderScript;
-import android.renderscript.ProgramVertexAlloc;
-import android.renderscript.Matrix;
-
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
+import android.renderscript.Matrix;
+import android.renderscript.ProgramVertexAlloc;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScript.ElementPredefined;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
public class FilmRS {
+ private final int POS_TRANSLATE = 0;
+ private final int POS_ROTATE = 1;
+ private final int POS_FOCUS = 2;
+
+ private final int STATE_TRIANGLE_OFFSET_COUNT = 0;
+ private final int STATE_LAST_FOCUS = 1;
public FilmRS() {
}
@@ -56,11 +63,11 @@ public class FilmRS {
if (x > 270) {
x = 270;
}
-
+
float anim = ((float)x-50) / 270.f;
- mBufferPos[0] = 2f * anim + 0.5f; // translation
- mBufferPos[1] = (anim * 40); // rotation
- mBufferPos[2] = ((float)y) / 16.f - 8; // focusPos
+ mBufferPos[POS_TRANSLATE] = 2f * anim + 0.5f; // translation
+ mBufferPos[POS_ROTATE] = (anim * 40); // rotation
+ mBufferPos[POS_FOCUS] = ((float)y) / 16.f - 10.f; // focusPos
mAllocPos.data(mBufferPos);
}
@@ -80,31 +87,28 @@ public class FilmRS {
private RenderScript.ProgramVertex mPVImages;
private ProgramVertexAlloc mPVA;
- private RenderScript.Allocation mAllocEnv;
+ private RenderScript.Allocation mImages[];
+ private RenderScript.Allocation mAllocIDs;
private RenderScript.Allocation mAllocPos;
private RenderScript.Allocation mAllocState;
private RenderScript.Allocation mAllocPV;
+ private RenderScript.Allocation mAllocOffsetsTex;
+ private RenderScript.Allocation mAllocOffsets;
+
private RenderScript.TriangleMesh mMesh;
private RenderScript.Light mLight;
- private float[] mBufferPos;
- private float[] mBufferPV;
+ private FilmStripMesh mFSM;
- private void initSamplers() {
- mRS.samplerBegin();
- mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
- RenderScript.SamplerValue.LINEAR_MIP_LINEAR);
- mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_S,
- RenderScript.SamplerValue.CLAMP);
- mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_T,
- RenderScript.SamplerValue.CLAMP);
- mSampler = mRS.samplerCreate();
- }
+ private int[] mBufferIDs;
+ private float[] mBufferPos = new float[3];
+ private int[] mBufferState;
private void initPFS() {
mRS.programFragmentStoreBegin(null, null);
mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
mRS.programFragmentStoreDitherEnable(true);
+ mRS.programFragmentStoreDepthMask(true);
mPFSBackground = mRS.programFragmentStoreCreate();
mPFSBackground.setName("PFSBackground");
@@ -112,22 +116,34 @@ public class FilmRS {
mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.EQUAL);
mRS.programFragmentStoreDitherEnable(false);
mRS.programFragmentStoreDepthMask(false);
- mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
+ mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
RenderScript.BlendDstFunc.ONE);
mPFSImages = mRS.programFragmentStoreCreate();
mPFSImages.setName("PFSImages");
}
private void initPF() {
+ mRS.samplerBegin();
+ mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
+ RenderScript.SamplerValue.LINEAR);//_MIP_LINEAR);
+ mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG,
+ RenderScript.SamplerValue.LINEAR);
+ mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_S,
+ RenderScript.SamplerValue.CLAMP);
+ mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_T,
+ RenderScript.SamplerValue.WRAP);
+ mSampler = mRS.samplerCreate();
+
+
mRS.programFragmentBegin(null, null);
mPFBackground = mRS.programFragmentCreate();
mPFBackground.setName("PFBackground");
mRS.programFragmentBegin(null, null);
mRS.programFragmentSetTexEnable(0, true);
- //mRS.programFragmentSetEnvMode(0, RS_TEX_ENV_MODE_REPLACE);
- //rsProgramFragmentSetType(0, gEnv.tex[0]->getType());
+ mRS.programFragmentSetTexEnvMode(0, RenderScript.EnvMode.REPLACE);
mPFImages = mRS.programFragmentCreate();
+ mPFImages.bindSampler(mSampler, 0);
mPFImages.setName("PFImages");
}
@@ -137,18 +153,59 @@ public class FilmRS {
mLight.setPosition(0, -0.5f, -1.0f);
mRS.programVertexBegin(null, null);
- mRS.programVertexSetTextureMatrixEnable(true);
mRS.programVertexAddLight(mLight);
mPVBackground = mRS.programVertexCreate();
mPVBackground.setName("PVBackground");
mRS.programVertexBegin(null, null);
+ mRS.programVertexSetTextureMatrixEnable(true);
mPVImages = mRS.programVertexCreate();
mPVImages.setName("PVImages");
}
+ private void loadImages() {
+ mBufferIDs = new int[13];
+ mImages = new RenderScript.Allocation[13];
+ mAllocIDs = mRS.allocationCreatePredefSized(
+ RenderScript.ElementPredefined.USER_FLOAT,
+ mBufferIDs.length);
+
+ RenderScript.ElementPredefined ie =
+ RenderScript.ElementPredefined.RGB_565;
+
+ mImages[0] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p01, ie, true);
+ mImages[1] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p02, ie, true);
+ mImages[2] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p03, ie, true);
+ mImages[3] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p04, ie, true);
+ mImages[4] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p05, ie, true);
+ mImages[5] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p06, ie, true);
+ mImages[6] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p07, ie, true);
+ mImages[7] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p08, ie, true);
+ mImages[8] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p09, ie, true);
+ mImages[9] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p10, ie, true);
+ mImages[10] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p11, ie, true);
+ mImages[11] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p12, ie, true);
+ mImages[12] = mRS.allocationCreateFromBitmapResourceBoxed(mRes, R.drawable.p13, ie, true);
+
+ for(int ct=0; ct < mImages.length; ct++) {
+ mImages[ct].uploadToTexture(1);
+ mBufferIDs[ct] = mImages[ct].getID();
+ }
+ mAllocIDs.data(mBufferIDs);
+ }
+
+ private void initState()
+ {
+ mBufferState = new int[10];
+ mAllocState = mRS.allocationCreatePredefSized(
+ RenderScript.ElementPredefined.USER_FLOAT,
+ mBufferState.length);
+
+ mBufferState[STATE_TRIANGLE_OFFSET_COUNT] = mFSM.mTriangleOffsetsCount;
+ mBufferState[STATE_LAST_FOCUS] = -1;
- int mParams[] = new int[10];
+ mAllocState.data(mBufferState);
+ }
private void initRS() {
mElementVertex = mRS.elementGetPredefined(
@@ -157,16 +214,14 @@ public class FilmRS {
RenderScript.ElementPredefined.INDEX_16);
mRS.triangleMeshBegin(mElementVertex, mElementIndex);
- FilmStripMesh fsm = new FilmStripMesh();
- fsm.init(mRS);
+ mFSM = new FilmStripMesh();
+ mFSM.init(mRS);
mMesh = mRS.triangleMeshCreate();
mMesh.setName("mesh");
initPFS();
- initSamplers();
initPF();
initPV();
- mPFImages.bindSampler(mSampler, 0);
Log.e("rs", "Done loading named");
@@ -176,44 +231,38 @@ public class FilmRS {
mRS.scriptCSetRoot(true);
mScriptStrip = mRS.scriptCCreate();
- mBufferPos = new float[3];
mAllocPos = mRS.allocationCreatePredefSized(
- RenderScript.ElementPredefined.USER_FLOAT,
+ RenderScript.ElementPredefined.USER_FLOAT,
mBufferPos.length);
+ loadImages();
+ initState();
+
mPVA = new ProgramVertexAlloc(mRS);
mPVBackground.bindAllocation(0, mPVA.mAlloc);
mPVImages.bindAllocation(0, mPVA.mAlloc);
mPVA.setupProjectionNormalized(320, 480);
+ mScriptStrip.bindAllocation(mAllocIDs, 0);
mScriptStrip.bindAllocation(mAllocPos, 1);
- //mScriptStrip.bindAllocation(gStateAlloc, 2);
+ mScriptStrip.bindAllocation(mAllocState, 2);
mScriptStrip.bindAllocation(mPVA.mAlloc, 3);
-/*
- {
- Resources res = getResources();
- Drawable d = res.getDrawable(R.drawable.gadgets_clock_mp3);
- BitmapDrawable bd = (BitmapDrawable)d;
- Bitmap b = bd.getBitmap();
- mTexture = mRS.allocationCreateFromBitmap(b,
- RenderScript.ElementPredefined.RGB_565,
- true);
- mTexture.uploadToTexture(0);
- }
+ mAllocOffsets = mRS.allocationCreatePredefSized(
+ RenderScript.ElementPredefined.USER_I32,
+ mFSM.mTriangleOffsets.length);
+ mAllocOffsets.data(mFSM.mTriangleOffsets);
+ mScriptStrip.bindAllocation(mAllocOffsets, 4);
- mRS.programFragmentStoreBegin(null, null);
- mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA, RenderScript.BlendDstFunc.ONE);
- mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
- mPFS = mRS.programFragmentStoreCreate();
- mPFS.setName("MyBlend");
- mRS.contextBindProgramFragmentStore(mPFS);
- */
+ mAllocOffsetsTex = mRS.allocationCreatePredefSized(
+ RenderScript.ElementPredefined.USER_FLOAT,
+ mFSM.mTriangleOffsetsTex.length);
+ mAllocOffsetsTex.data(mFSM.mTriangleOffsetsTex);
+ mScriptStrip.bindAllocation(mAllocOffsetsTex, 5);
setFilmStripPosition(0, 0);
-
mRS.contextBindRootScript(mScriptStrip);
}
}
diff --git a/libs/rs/java/Film/src/com/android/film/FilmView.java b/libs/rs/java/Film/src/com/android/film/FilmView.java
index a743b1b..73b7414 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmView.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmView.java
@@ -74,7 +74,7 @@ public class FilmView extends RSSurfaceView {
if (act == ev.ACTION_UP) {
ret = false;
}
- mRender.setFilmStripPosition((int)ev.getX(), (int)ev.getY());
+ mRender.setFilmStripPosition((int)ev.getX(), (int)ev.getY() / 5);
return ret;
}
}
diff --git a/libs/rs/java/Grass/Android.mk b/libs/rs/java/Grass/Android.mk
new file mode 100644
index 0000000..ce5294e
--- /dev/null
+++ b/libs/rs/java/Grass/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := GrassRS
+
+include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Grass/AndroidManifest.xml b/libs/rs/java/Grass/AndroidManifest.xml
new file mode 100644
index 0000000..a40f378
--- /dev/null
+++ b/libs/rs/java/Grass/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.grass.rs">
+
+ <application android:label="GrassRS">
+
+ <activity
+ android:name="Grass"
+ android:theme="@android:style/Theme.NoTitleBar">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/night.jpg b/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
new file mode 100644
index 0000000..9989abf
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
new file mode 100644
index 0000000..a12fe20
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
new file mode 100644
index 0000000..db016b2
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
new file mode 100644
index 0000000..49bb0c6
--- /dev/null
+++ b/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
Binary files differ
diff --git a/libs/rs/java/Grass/res/raw/grass.c b/libs/rs/java/Grass/res/raw/grass.c
new file mode 100644
index 0000000..b1b89f0
--- /dev/null
+++ b/libs/rs/java/Grass/res/raw/grass.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008 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 stateVertex(default)
+#pragma stateFragment(PFBackground)
+#pragma stateFragmentStore(PFSBackground)
+
+#define WVGA_PORTRAIT_WIDTH 480.0f
+#define WVGA_PORTRAIT_HEIGHT 762.0f
+
+#define RSID_STATE 0
+#define RSID_FRAMECOUNT 0
+
+#define RSID_SKY_TEXTURES 1
+#define RSID_SKY_TEXTURE_NIGHT 0
+#define RSID_SKY_TEXTURE_SUNRISE 1
+#define RSID_SKY_TEXTURE_NOON 2
+#define RSID_SKY_TEXTURE_SUNSET 3
+
+#define MIDNIGHT 0.0f
+#define MORNING 0.375f
+#define AFTERNOON 0.6f
+#define DUSK 0.8f
+
+#define SECONDS_IN_DAY 24.0f * 3600.0f
+
+#define REAL_TIME 0
+
+float time(int frameCount) {
+ if (REAL_TIME) {
+ return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
+ }
+ return (frameCount % 180) / 180.0f;
+}
+
+void alpha(float a) {
+ color(1.0f, 1.0f, 1.0f, a);
+}
+
+float norm(float a, float start, float end) {
+ return (a - start) / (end - start);
+}
+
+void drawNight() {
+ bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_NIGHT));
+ // NOTE: Hacky way to draw the night sky
+ drawRect(WVGA_PORTRAIT_WIDTH - 512.0f, -32.0f, WVGA_PORTRAIT_WIDTH, 1024.0f - 32.0f, 0.0f);
+}
+
+void drawSunrise() {
+ bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_SUNRISE));
+ drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+void drawNoon() {
+ bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_NOON));
+ drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+void drawSunset() {
+ bindTexture(NAMED_PFBackground, 0, loadI32(RSID_SKY_TEXTURES, RSID_SKY_TEXTURE_SUNSET));
+ drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+}
+
+int main(int launchID) {
+ int frameCount = loadI32(RSID_STATE, RSID_FRAMECOUNT);
+ float now = time(frameCount);
+ alpha(1.0f);
+
+ if (now >= MIDNIGHT && now < MORNING) {
+ drawNight();
+ alpha(norm(now, MIDNIGHT, MORNING));
+ drawSunrise();
+ }
+
+ if (now >= MORNING && now < AFTERNOON) {
+ drawSunrise();
+ alpha(norm(now, MORNING, AFTERNOON));
+ drawNoon();
+ }
+
+ if (now >= AFTERNOON && now < DUSK) {
+ drawNoon();
+ alpha(norm(now, AFTERNOON, DUSK));
+ drawSunset();
+ }
+
+ if (now >= DUSK) {
+ drawSunset();
+ alpha(norm(now, DUSK, 1.0f));
+ drawNight();
+ }
+
+ frameCount++;
+ storeI32(RSID_STATE, RSID_FRAMECOUNT, frameCount);
+
+ return 1;
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java b/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
new file mode 100644
index 0000000..260fcee
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.grass.rs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Grass extends Activity {
+ private GrassView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mView = new GrassView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mView.onPause();
+
+ Runtime.getRuntime().exit(0);
+ }
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
new file mode 100644
index 0000000..bb13051
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.grass.rs;
+
+import android.content.res.Resources;
+import android.renderscript.RenderScript;
+import static android.renderscript.RenderScript.ElementPredefined.*;
+import static android.renderscript.RenderScript.SamplerParam.*;
+import static android.renderscript.RenderScript.SamplerValue.*;
+import static android.renderscript.RenderScript.EnvMode.*;
+import static android.renderscript.RenderScript.DepthFunc.*;
+import static android.renderscript.RenderScript.BlendSrcFunc;
+import static android.renderscript.RenderScript.BlendDstFunc;
+
+import java.util.TimeZone;
+
+class GrassRS {
+ private static final int RSID_STATE = 0;
+ private static final int RSID_SKY_TEXTURES = 1;
+ private static final int SKY_TEXTURES_COUNT = 4;
+
+ private Resources mResources;
+ private RenderScript mRS;
+
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.Script mScript;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.Sampler mSampler;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.ProgramFragment mPfBackground;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.ProgramFragmentStore mPfsBackground;
+
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.Allocation mSkyTexturesIDs;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.Allocation[] mSkyTextures;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private int[] mSkyBufferIDs;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.Allocation mState;
+
+ public GrassRS() {
+ }
+
+ public void init(RenderScript rs, Resources res) {
+ mRS = rs;
+ mResources = res;
+ initRS();
+ }
+
+ private void initRS() {
+ createProgramVertex();
+ createProgramFragmentStore();
+ createProgramFragment();
+ createScriptStructures();
+
+ mRS.scriptCBegin();
+ mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ mRS.scriptCSetScript(mResources, R.raw.grass);
+ mRS.scriptCSetTimeZone(TimeZone.getDefault().getID());
+ mRS.scriptCSetRoot(true);
+
+ mScript = mRS.scriptCCreate();
+
+ loadSkyTextures();
+ mScript.bindAllocation(mState, RSID_STATE);
+ mScript.bindAllocation(mSkyTexturesIDs, RSID_SKY_TEXTURES);
+
+ mRS.contextBindRootScript(mScript);
+ }
+
+ private void createScriptStructures() {
+ mState = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, 1);
+ mState.data(new int[1]);
+ }
+
+ private void loadSkyTextures() {
+ mSkyBufferIDs = new int[SKY_TEXTURES_COUNT];
+ mSkyTextures = new RenderScript.Allocation[SKY_TEXTURES_COUNT];
+ mSkyTexturesIDs = mRS.allocationCreatePredefSized(
+ USER_FLOAT, SKY_TEXTURES_COUNT);
+
+ final RenderScript.Allocation[] textures = mSkyTextures;
+ textures[0] = loadTexture(R.drawable.night, "night");
+ textures[1] = loadTexture(R.drawable.sunrise, "sunrise");
+ textures[2] = loadTexture(R.drawable.sky, "sky");
+ textures[3] = loadTexture(R.drawable.sunset, "sunset");
+
+ final int[] bufferIds = mSkyBufferIDs;
+ final int count = textures.length;
+
+ for (int i = 0; i < count; i++) {
+ final RenderScript.Allocation texture = textures[i];
+ texture.uploadToTexture(0);
+ bufferIds[i] = texture.getID();
+ }
+
+ mSkyTexturesIDs.data(bufferIds);
+ }
+
+ private RenderScript.Allocation loadTexture(int id, String name) {
+ RenderScript.Allocation allocation = mRS.allocationCreateFromBitmapResource(mResources, id,
+ RGB_565, false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private void createProgramFragment() {
+ mRS.samplerBegin();
+ mRS.samplerSet(FILTER_MIN, LINEAR);
+ mRS.samplerSet(FILTER_MAG, LINEAR);
+ mRS.samplerSet(WRAP_MODE_S, CLAMP);
+ mRS.samplerSet(WRAP_MODE_T, CLAMP);
+ mSampler = mRS.samplerCreate();
+
+ mRS.programFragmentBegin(null, null);
+ mRS.programFragmentSetTexEnable(0, true);
+ mRS.programFragmentSetTexEnvMode(0, REPLACE);
+ mPfBackground = mRS.programFragmentCreate();
+ mPfBackground.setName("PFBackground");
+ mPfBackground.bindSampler(mSampler, 0);
+ }
+
+ private void createProgramFragmentStore() {
+ mRS.programFragmentStoreBegin(null, null);
+ mRS.programFragmentStoreDepthFunc(ALWAYS);
+ mRS.programFragmentStoreBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+ mRS.programFragmentStoreDitherEnable(true);
+ mRS.programFragmentStoreDepthMask(false);
+ mPfsBackground = mRS.programFragmentStoreCreate();
+ mPfsBackground.setName("PFSBackground");
+ }
+
+ private void createProgramVertex() {
+ }
+}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
new file mode 100644
index 0000000..a641e1e
--- /dev/null
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.grass.rs;
+
+import android.content.Context;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.view.SurfaceHolder;
+
+class GrassView extends RSSurfaceView {
+ public GrassView(Context context) {
+ super(context);
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+
+ RenderScript RS = createRenderScript();
+ GrassRS render = new GrassRS();
+ render.init(RS, getResources());
+ }
+}
diff --git a/libs/rs/java/Rollo/res/raw/calendar.png b/libs/rs/java/Rollo/res/raw/calendar.png
new file mode 100644
index 0000000..030ae73
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/calendar.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/g1155.png b/libs/rs/java/Rollo/res/raw/g1155.png
new file mode 100644
index 0000000..68e1843
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/g1155.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/g2140.png b/libs/rs/java/Rollo/res/raw/g2140.png
new file mode 100644
index 0000000..8c4e853
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/g2140.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/maps.png b/libs/rs/java/Rollo/res/raw/maps.png
new file mode 100644
index 0000000..fd5fc39
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/maps.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path1920.png b/libs/rs/java/Rollo/res/raw/path1920.png
new file mode 100644
index 0000000..3510665
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path1920.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path1927.png b/libs/rs/java/Rollo/res/raw/path1927.png
new file mode 100644
index 0000000..fccc846
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path1927.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path3099.png b/libs/rs/java/Rollo/res/raw/path3099.png
new file mode 100644
index 0000000..527ebf6
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path3099.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path3950.png b/libs/rs/java/Rollo/res/raw/path3950.png
new file mode 100644
index 0000000..59a646a
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path3950.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path431.png b/libs/rs/java/Rollo/res/raw/path431.png
new file mode 100644
index 0000000..5d2ed75
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path431.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path4481.png b/libs/rs/java/Rollo/res/raw/path4481.png
new file mode 100644
index 0000000..78be0fc
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path4481.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path5168.png b/libs/rs/java/Rollo/res/raw/path5168.png
new file mode 100644
index 0000000..a7c3a19
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path5168.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path676.png b/libs/rs/java/Rollo/res/raw/path676.png
new file mode 100644
index 0000000..2099690
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path676.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path754.png b/libs/rs/java/Rollo/res/raw/path754.png
new file mode 100644
index 0000000..88aed5b
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path754.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/path815.png b/libs/rs/java/Rollo/res/raw/path815.png
new file mode 100644
index 0000000..407570f
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/path815.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/polygon2408.png b/libs/rs/java/Rollo/res/raw/polygon2408.png
new file mode 100644
index 0000000..4413954
--- /dev/null
+++ b/libs/rs/java/Rollo/res/raw/polygon2408.png
Binary files differ
diff --git a/libs/rs/java/Rollo/res/raw/rollo.c b/libs/rs/java/Rollo/res/raw/rollo.c
index d338d0d..8763a34 100644
--- a/libs/rs/java/Rollo/res/raw/rollo.c
+++ b/libs/rs/java/Rollo/res/raw/rollo.c
@@ -19,6 +19,7 @@
#define STATE_COUNT 8
#define STATE_TOUCH 9
+
float filter(float val, float target, float str)
{
float delta = (target - val);
@@ -51,7 +52,7 @@ int main(void* con, int ft, int launchID)
float touchCut = 1.f;
if (loadI32(0, STATE_TOUCH)) {
- touchCut = 5.f;
+ touchCut = 4.f;
}
@@ -60,46 +61,126 @@ int main(void* con, int ft, int launchID)
storeF(2, SCRATCH_ZOOM, zoom);
float targetRot = loadI32(0, STATE_FIRST_VISIBLE) / 180.0f * 3.14f;
- float rot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
- storeF(2, SCRATCH_ROT, rot);
+ float drawRot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
+ storeF(2, SCRATCH_ROT, drawRot);
- float diam = 8.f;// + curve * 2.f;
+ float diam = 8.f;
float scale = 1.0f / zoom;
- rot = rot * scale;
- float rotStep = 20.0f / 180.0f * 3.14f * scale;
+ // Bug makes 1.0f alpha fail.
+ color(1.0f, 1.0f, 1.0f, 0.99f);
+
+ float rot = drawRot * scale;
+ float rotStep = 16.0f / 180.0f * 3.14f * scale;
rowCount = 4;
int index = 0;
int iconCount = loadI32(0, STATE_COUNT);
while (iconCount) {
float tmpSin = sinf(rot);
float tmpCos = cosf(rot);
+ //debugF("rot", rot);
- float tx1 = tmpSin * diam - (tmpCos * scale);
- float tx2 = tx1 + (tmpCos * scale * 2.f);
- float tz1 = tmpCos * diam + (tmpSin * scale);
- float tz2 = tz1 - (tmpSin * scale * 2.f);
+ float tx1 = tmpSin * diam - (tmpCos * scale * 0.9f);
+ float tx2 = tx1 + (tmpCos * scale * 1.8f);
+ float tz1 = tmpCos * diam + (tmpSin * scale * 0.9f);
+ float tz2 = tz1 - (tmpSin * scale * 1.8f);
int y;
for (y = rowCount -1; (y >= 0) && iconCount; y--) {
- float ty1 = ((y * 3.0f) - 4.5f) * scale;
- float ty2 = ty1 + scale * 2.f;
- bindTexture(NAMED_PF, 0, loadI32(1, y));
- color(1.0f, 1.0f, 1.0f, 1.0f);
- if (done && (index != selectedID)) {
- color(0.4f, 0.4f, 0.4f, 1.0f);
- }
+ float ty1 = ((y * 3.1f) - 5.f) * scale;
+ float ty2 = ty1 + scale * 1.8f;
+ bindTexture(NAMED_PF, 0, loadI32(1, index));
+ //if (done && (index != selectedID)) {
+ //color(0.4f, 0.4f, 0.4f, 1.0f);
+ //}
drawQuad(tx1, ty1, tz1,
tx2, ty1, tz2,
tx2, ty2, tz2,
tx1, ty2, tz1);
+
+ iconCount--;
+ index++;
+ }
+ rot = rot + rotStep;
+ }
+
+ if ((zoom < 1.1f) && (zoom > 0.9f)) {
+ bindProgramVertex(NAMED_PVOrtho);
+ bindProgramFragment(NAMED_PFText);
+ bindProgramFragmentStore(NAMED_PFSText);
+
+ rot = drawRot * scale;
+ index = 0;
+ iconCount = loadI32(0, STATE_COUNT);
+ while (iconCount) {
+ int y;
+
+ float tx = 240.f + floorf(sinf(rot) * 430.f) - 64.f + 16.f;
+
+ float alpha = 2.4f - (fabsf(tx - 240.f + 48.f) / 76.f);
+ if (alpha > 0.99f) {
+ alpha = 0.99f;
+ }
+ alpha = alpha * (1.f - (fabsf(zoom - 1.f) * 10.f));
+
+ tx = tx + 0.25f;
+
+ for (y = rowCount -1; (y >= 0) && iconCount; y--) {
+
+ if (alpha > 0) {
+ color(1.0f, 1.0f, 1.0f, alpha);
+
+ float ty = 605.f - y * 150.f;
+
+ ty = ty + 0.25f;
+
+ bindTexture(NAMED_PFText, 0, loadI32(3, index));
+ drawRect(tx, ty, tx + 128.f, ty + 32.f, 0.5f);
+ }
+ iconCount--;
+ index++;
+ }
+ rot = rot + rotStep;
+ }
+
+
+ bindProgramVertex(NAMED_PV);
+ bindProgramFragment(NAMED_PF);
+ bindProgramFragmentStore(NAMED_PFS);
+ }
+
+ // Draw the selected icon
+ color(1.0f, 1.0f, 1.0f, 0.9f);
+ rot = drawRot * scale;
+ index = 0;
+ iconCount = loadI32(0, STATE_COUNT);
+ while (iconCount) {
+ int y;
+ for (y = rowCount -1; (y >= 0) && iconCount; y--) {
+ if (index == selectedID) {
+
+ float tmpSin = sinf(rot) * scale;
+ float tmpCos = cosf(rot) * scale;
+ float tx1 = tmpSin * diam * 0.9f - tmpCos * 2.f;
+ float tx2 = tx1 + (tmpCos * 4.f);
+ float tz1 = tmpCos * diam * 0.9f + tmpSin * 2.f;
+ float tz2 = tz1 - (tmpSin * 4.f);
+
+ float ty1 = ((y * 3.1f) - 4.5f) * scale;
+ float ty2 = ty1 + scale * 4.f;
+ bindTexture(NAMED_PF, 0, loadI32(1, index));
+ drawQuad(tx1, ty1, tz1,
+ tx2, ty1, tz2,
+ tx2, ty2, tz2,
+ tx1, ty2, tz1);
+ }
iconCount--;
index++;
}
rot = rot + rotStep;
}
- return 0;
+ return 1;
}
diff --git a/libs/rs/java/Rollo/res/raw/rollo2.c b/libs/rs/java/Rollo/res/raw/rollo2.c
index b04ea73..256fa3c 100644
--- a/libs/rs/java/Rollo/res/raw/rollo2.c
+++ b/libs/rs/java/Rollo/res/raw/rollo2.c
@@ -3,65 +3,153 @@
#pragma stateFragment(PF)
#pragma stateFragmentStore(PFS)
-void drawLoop(int x, int y, int z, int rot)
+// Scratch buffer layout
+#define SCRATCH_FADE 0
+#define SCRATCH_ZOOM 1
+#define SCRATCH_ROT 2
+
+//#define STATE_POS_X 0
+#define STATE_DONE 1
+//#define STATE_PRESSURE 2
+#define STATE_ZOOM 3
+//#define STATE_WARP 4
+#define STATE_ORIENTATION 5
+#define STATE_SELECTION 6
+#define STATE_FIRST_VISIBLE 7
+#define STATE_COUNT 8
+#define STATE_TOUCH 9
+
+float filter(float val, float target, float str)
{
- int ct;
- int tx;
- int ty;
- int tmpSin;
- int tmpCos;
- int sz;
-
- for (ct = 0; ct < 10; ct ++) {
- tmpSin = sinx((ct * 36 + rot) * 0x10000);
- tmpCos = cosx((ct * 36 + rot) * 0x10000);
-
- ty = y + tmpCos * 4;
- tx = x + tmpSin * 4;
- pfBindTexture(NAMED_PF, 0, loadI32(1, ct & 3));
-
- sz = 0xc000;
- drawQuad(tx - sz, ty - sz, z,
- tx + sz, ty - sz, z,
- tx + sz, ty + sz, z,
- tx - sz, ty + sz, z);
- }
+ float delta = (target - val);
+ return val + delta * str;
}
+
int main(void* con, int ft, int launchID)
{
int rowCount;
- int x;
- int y;
+ int imageID;
+ int done = loadI32(0, STATE_DONE);
+ int selectedID = loadI32(0, STATE_SELECTION);
+ int iconCount = loadI32(0, STATE_COUNT);
+
+ float f = loadF(2, 0);
+
+ float iconSize = 1.f;
+ float iconSpacing = 0.2f;
+ float z = 4.f;
+
+ pfClearColor(0.0f, 0.0f, 0.0f, f);
+ if (done) {
+ } else {
+ if (f < 0.8f) {
+ f = f + 0.02f;
+ storeF(2, 0, f);
+ }
+ }
+
+ float touchCut = 1.f;
+ if (loadI32(0, STATE_TOUCH)) {
+ touchCut = 5.f;
+ }
+
+
+ float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 1000.f;
+ float zoom = filter(loadF(2, SCRATCH_ZOOM), targetZoom, 0.15 * touchCut);
+ storeF(2, SCRATCH_ZOOM, zoom);
+
+ float targetPos = loadI32(0, STATE_FIRST_VISIBLE) / (-20.0f);
+ float pos = filter(loadF(2, SCRATCH_ROT), targetPos, 0.1f * touchCut);
+ storeF(2, SCRATCH_ROT, pos);
+ pos = pos - 1.f;
+
+ color(1.0f, 1.0f, 1.0f, 1.0f);
+
+
+ // Draw flat icons first
+ int index = ((int)pos) * 4;
int row;
int col;
- int imageID;
- int tx1;
- int ty1;
- int tz1;
- int tx2;
- int ty2;
- int tz2;
- int tmpSin;
- int tmpCos;
- int iconCount;
- int pressure;
+ float xoffset = -0.3f;
+ float gridSize = iconSize * 4.f + iconSpacing * 3.f;
+ float yoffset = (pos - ((int)pos));
+ for (row = 0; row < 4; row ++) {
+ float ty1 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing) - iconSize;
+ float ty2 = ty1 + iconSize;
- int ringCount;
+ for (col = 0; (col < 4) && (index < iconCount); col ++) {
+ if (index >= 0) {
+ bindTexture(NAMED_PF, 0, loadI32(1, index));
+ float fcol = col;
+ float tx1 = xoffset + (-gridSize / 2.f) + (fcol * (iconSize + iconSpacing));
+ float tx2 = tx1 + iconSize;
+
+ drawQuad(tx1, ty1, z,
+ tx2, ty1, z,
+ tx2, ty2, z,
+ tx1, ty2, z);
+ }
+ index++;
+ }
+ }
+ // bottom roller
+ {
+ float roll = (1.f - yoffset) * 0.5f * 3.14f;
+ float tmpSin = sinf(roll);
+ float tmpCos = cosf(roll);
+ for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
+ float ty2 = (gridSize / 2.f) - ((float)row - yoffset) * (iconSize + iconSpacing);
+ float ty1 = ty2 - tmpCos * iconSize;
- rotStep = 16 * 0x10000;
- pressure = loadI32(0, 2);
- rowCount = 4;
+ float tz1 = z + tmpSin * iconSize;
+ float tz2 = z;
- iconCount = loadI32(0, 1);
- rot = (-20 + loadI32(0, 0)) * 0x10000;
+ float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
+ float tx2 = tx1 + iconSize;
- for (ringCount = 0; ringCount < 5; ringCount++) {
- drawLoop(0, 0, 0x90000 + (ringCount * 0x80000));
+ bindTexture(NAMED_PF, 0, loadI32(1, index));
+ drawQuad(tx1, ty1, tz1,
+ tx2, ty1, tz1,
+ tx2, ty2, tz2,
+ tx1, ty2, tz2);
+ index++;
+ }
}
- return 0;
+ // Top roller
+ {
+ index = (((int)pos) * 4) - 4;
+ float roll = yoffset * 0.5f * 3.14f;
+ float tmpSin = sinf(roll);
+ float tmpCos = cosf(roll);
+
+ for (col = 0; (col < 4) && (index < iconCount) && (index >= 0); col ++) {
+ float ty1 = (gridSize / 2.f) - ((float)-1.f - yoffset) * (iconSize + iconSpacing) - iconSize;
+ float ty2 = ty1 + tmpCos * iconSize;
+
+ float tz1 = z;
+ float tz2 = z + tmpSin * iconSize;
+
+ float tx1 = xoffset + (-gridSize / 2.f) + ((float)col * (iconSize + iconSpacing));
+ float tx2 = tx1 + iconSize;
+
+ bindTexture(NAMED_PF, 0, loadI32(1, index));
+ drawQuad(tx1, ty1, tz1,
+ tx2, ty1, tz1,
+ tx2, ty2, tz2,
+ tx1, ty2, tz2);
+ index++;
+ }
+ }
+
+
+
+
+ return 1;
}
+
+
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
index 8f48335..039d4e9 100644
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
+++ b/libs/rs/java/Rollo/src/com/android/rollo/RolloRS.java
@@ -25,17 +25,14 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.graphics.Typeface;
import android.os.Handler;
import android.os.Message;
-import android.util.AttributeSet;
import android.util.Log;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
public class RolloRS {
//public static final int STATE_SELECTED_ID = 0;
@@ -56,6 +53,8 @@ public class RolloRS {
public void init(RenderScript rs, Resources res, int width, int height) {
mRS = rs;
mRes = res;
+ mWidth = width;
+ mHeight = height;
initNamed();
initRS();
}
@@ -78,25 +77,31 @@ public class RolloRS {
}
public void setSelected(int index) {
- Log.e("rs", "setSelected " + Integer.toString(index));
+ //Log.e("rs", "setSelected " + Integer.toString(index));
mAllocStateBuf[STATE_SELECTION] = index;
mAllocStateBuf[STATE_DONE] = 1;
mAllocState.data(mAllocStateBuf);
}
+ private int mWidth;
+ private int mHeight;
private Resources mRes;
private RenderScript mRS;
private RenderScript.Script mScript;
private RenderScript.Sampler mSampler;
+ private RenderScript.Sampler mSamplerText;
private RenderScript.ProgramFragmentStore mPFSBackground;
- private RenderScript.ProgramFragment mPFBackground;
+ private RenderScript.ProgramFragmentStore mPFSText;
private RenderScript.ProgramFragment mPFImages;
+ private RenderScript.ProgramFragment mPFText;
private RenderScript.ProgramVertex mPV;
private ProgramVertexAlloc mPVAlloc;
+ private RenderScript.ProgramVertex mPVOrtho;
+ private ProgramVertexAlloc mPVOrthoAlloc;
private RenderScript.Allocation[] mIcons;
- private RenderScript.Allocation mIconPlate;
+ private RenderScript.Allocation[] mLabels;
private int[] mAllocStateBuf;
private RenderScript.Allocation mAllocState;
@@ -104,6 +109,9 @@ public class RolloRS {
private int[] mAllocIconIDBuf;
private RenderScript.Allocation mAllocIconID;
+ private int[] mAllocLabelIDBuf;
+ private RenderScript.Allocation mAllocLabelID;
+
private int[] mAllocScratchBuf;
private RenderScript.Allocation mAllocScratch;
@@ -119,6 +127,17 @@ public class RolloRS {
RenderScript.SamplerValue.CLAMP);
mSampler = mRS.samplerCreate();
+ mRS.samplerBegin();
+ mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN,
+ RenderScript.SamplerValue.NEAREST);
+ mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG,
+ RenderScript.SamplerValue.NEAREST);
+ mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_S,
+ RenderScript.SamplerValue.CLAMP);
+ mRS.samplerSet(RenderScript.SamplerParam.WRAP_MODE_T,
+ RenderScript.SamplerValue.CLAMP);
+ mSamplerText = mRS.samplerCreate();
+
mRS.programFragmentBegin(null, null);
mRS.programFragmentSetTexEnable(0, true);
@@ -127,32 +146,50 @@ public class RolloRS {
mPFImages.setName("PF");
mPFImages.bindSampler(mSampler, 0);
+ mRS.programFragmentBegin(null, null);
+ mRS.programFragmentSetTexEnable(0, true);
+ mRS.programFragmentSetTexEnvMode(0, RenderScript.EnvMode.MODULATE);
+ mPFText = mRS.programFragmentCreate();
+ mPFText.setName("PFText");
+ mPFText.bindSampler(mSamplerText, 0);
+
mRS.programFragmentStoreBegin(null, null);
mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.LESS);
mRS.programFragmentStoreDitherEnable(false);
- mRS.programFragmentStoreDepthMask(false);
- mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.ONE,
- RenderScript.BlendDstFunc.ONE);
+ mRS.programFragmentStoreDepthMask(true);
+ mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA,
+ RenderScript.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
mPFSBackground = mRS.programFragmentStoreCreate();
mPFSBackground.setName("PFS");
+ mRS.programFragmentStoreBegin(null, null);
+ mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+ mRS.programFragmentStoreDitherEnable(false);
+ mRS.programFragmentStoreDepthMask(false);
+ mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA,
+ RenderScript.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+ mPFSText = mRS.programFragmentStoreCreate();
+ mPFSText.setName("PFSText");
+
mPVAlloc = new ProgramVertexAlloc(mRS);
mRS.programVertexBegin(null, null);
- mRS.programVertexSetTextureMatrixEnable(true);
+ mRS.programVertexSetTextureMatrixEnable(false);
mPV = mRS.programVertexCreate();
mPV.setName("PV");
mPV.bindAllocation(0, mPVAlloc.mAlloc);
+ mPVAlloc.setupProjectionNormalized(mWidth, mHeight);
+ mPVOrthoAlloc = new ProgramVertexAlloc(mRS);
+ mRS.programVertexBegin(null, null);
+ mRS.programVertexSetTextureMatrixEnable(true);
+ mPVOrtho = mRS.programVertexCreate();
+ mPVOrtho.setName("PVOrtho");
+ mPVOrtho.bindAllocation(0, mPVOrthoAlloc.mAlloc);
+ mPVOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
-
- mPVAlloc.setupProjectionNormalized(320, 480);
- //mPVAlloc.setupOrthoNormalized(320, 480);
mRS.contextBindProgramVertex(mPV);
mAllocScratchBuf = new int[32];
- for(int ct=0; ct < mAllocScratchBuf.length; ct++) {
- mAllocScratchBuf[ct] = 0;
- }
mAllocScratch = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_I32, mAllocScratchBuf.length);
mAllocScratch.data(mAllocScratchBuf);
@@ -162,65 +199,119 @@ public class RolloRS {
{
- mIcons = new RenderScript.Allocation[4];
+ mIcons = new RenderScript.Allocation[29];
mAllocIconIDBuf = new int[mIcons.length];
mAllocIconID = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_I32, mAllocIconIDBuf.length);
-
- Bitmap b;
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inScaled = false;
-
- b = BitmapFactory.decodeResource(mRes, R.raw.browser, opts);
- mIcons[0] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
+ mLabels = new RenderScript.Allocation[29];
+ mAllocLabelIDBuf = new int[mLabels.length];
+ mAllocLabelID = mRS.allocationCreatePredefSized(
+ RenderScript.ElementPredefined.USER_I32, mLabels.length);
+
+ RenderScript.ElementPredefined ie565 =
+ RenderScript.ElementPredefined.RGB_565;
+ RenderScript.ElementPredefined ie8888 =
+ RenderScript.ElementPredefined.RGBA_8888;
+
+ mIcons[0] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.browser, ie8888, true);
+ mIcons[1] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.market, ie8888, true);
+ mIcons[2] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.photos, ie8888, true);
+ mIcons[3] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.settings, ie8888, true);
+ mIcons[4] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.calendar, ie8888, true);
+ mIcons[5] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.g1155, ie8888, true);
+ mIcons[6] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.g2140, ie8888, true);
+ mIcons[7] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.maps, ie8888, true);
+ mIcons[8] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path431, ie8888, true);
+ mIcons[9] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path676, ie8888, true);
+ mIcons[10] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path754, ie8888, true);
+ mIcons[11] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path815, ie8888, true);
+ mIcons[12] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path1920, ie8888, true);
+ mIcons[13] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path1927, ie8888, true);
+ mIcons[14] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path3099, ie8888, true);
+ mIcons[15] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path3950, ie8888, true);
+ mIcons[16] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path4481, ie8888, true);
+ mIcons[17] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.path5168, ie8888, true);
+ mIcons[18] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.polygon2408, ie8888, true);
+
+ mLabels[0] = makeTextBitmap("browser");
+ mLabels[1] = makeTextBitmap("market");
+ mLabels[2] = makeTextBitmap("photos");
+ mLabels[3] = makeTextBitmap("settings");
+ mLabels[4] = makeTextBitmap("calendar");
+ mLabels[5] = makeTextBitmap("g1155");
+ mLabels[6] = makeTextBitmap("g2140");
+ mLabels[7] = makeTextBitmap("maps");
+ mLabels[8] = makeTextBitmap("path431");
+ mLabels[9] = makeTextBitmap("path676");
+ mLabels[10] = makeTextBitmap("path754");
+ mLabels[11] = makeTextBitmap("path815");
+ mLabels[12] = makeTextBitmap("path1920");
+ mLabels[13] = makeTextBitmap("path1927");
+ mLabels[14] = makeTextBitmap("path3099");
+ mLabels[15] = makeTextBitmap("path3950");
+ mLabels[16] = makeTextBitmap("path4481");
+ mLabels[17] = makeTextBitmap("path5168");
+ mLabels[18] = makeTextBitmap("polygon2408");
+
+ mIcons[19] = mIcons[0];
+ mIcons[20] = mIcons[1];
+ mIcons[21] = mIcons[2];
+ mIcons[22] = mIcons[3];
+ mIcons[23] = mIcons[4];
+ mIcons[24] = mIcons[5];
+ mIcons[25] = mIcons[6];
+ mIcons[26] = mIcons[7];
+ mIcons[27] = mIcons[8];
+ mIcons[28] = mIcons[9];
+
+ mLabels[19] = mLabels[0];
+ mLabels[20] = mLabels[1];
+ mLabels[21] = mLabels[2];
+ mLabels[22] = mLabels[3];
+ mLabels[23] = mLabels[4];
+ mLabels[24] = mLabels[5];
+ mLabels[25] = mLabels[6];
+ mLabels[26] = mLabels[7];
+ mLabels[27] = mLabels[8];
+ mLabels[28] = mLabels[9];
- b = BitmapFactory.decodeResource(mRes, R.raw.market, opts);
- mIcons[1] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
-
- b = BitmapFactory.decodeResource(mRes, R.raw.photos, opts);
- mIcons[2] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
+/*
+ mIcons[19] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.solitaire, ie8888, true);
+ mIcons[20] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.sudoku, ie8888, true);
+ mIcons[21] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.taptaprevenge, ie8888, true);
+ mIcons[22] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tetris, ie8888, true);
+ mIcons[23] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tictactoe, ie8888, true);
+ mIcons[24] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.tweetie, ie8888, true);
+ mIcons[25] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.urbanspoon, ie8888, true);
+ mIcons[26] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.waterslide_extreme, ie8888, true);
+ mIcons[27] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.weather_channel, ie8888, true);
+ mIcons[28] = mRS.allocationCreateFromBitmapResource(mRes, R.raw.zippo, ie8888, true);
+*/
- b = BitmapFactory.decodeResource(mRes, R.raw.settings, opts);
- mIcons[3] = mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGB_565, true);
for(int ct=0; ct < mIcons.length; ct++) {
mIcons[ct].uploadToTexture(0);
+ mLabels[ct].uploadToTexture(0);
mAllocIconIDBuf[ct] = mIcons[ct].getID();
+ mAllocLabelIDBuf[ct] = mLabels[ct].getID();
}
mAllocIconID.data(mAllocIconIDBuf);
-
- RenderScript.Element e = mRS.elementGetPredefined(RenderScript.ElementPredefined.RGB_565);
- mRS.typeBegin(e);
- mRS.typeAdd(RenderScript.Dimension.X, 64);
- mRS.typeAdd(RenderScript.Dimension.Y, 64);
- RenderScript.Type t = mRS.typeCreate();
- mIconPlate = mRS.allocationCreateTyped(t);
- //t.destroy();
- //e.destroy();
-
- int tmp[] = new int[64 * 32];
- for(int ct = 0; ct < (64*32); ct++) {
- tmp[ct] = 7 | (13 << 5) | (7 << 11);
- tmp[ct] = tmp[ct] | (tmp[ct] << 16);
- }
- for(int ct = 0; ct < 32; ct++) {
- tmp[ct] = 0;
- tmp[ct + (63*32)] = 0;
- }
- for(int ct = 0; ct < 64; ct++) {
- tmp[ct * 32] = 0;
- tmp[ct * 32 + 31] = 0;
- }
- mIconPlate.data(tmp);
- Log.e("xx", "plate");
- mIconPlate.uploadToTexture(0);
- mIconPlate.setName("Plate");
- mPFImages.bindTexture(mIconPlate, 0);
+ mAllocLabelID.data(mAllocLabelIDBuf);
}
}
+ RenderScript.Allocation makeTextBitmap(String t) {
+ Bitmap b = Bitmap.createBitmap(128, 32, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(b);
+ Paint p = new Paint();
+ p.setTypeface(Typeface.DEFAULT_BOLD);
+ p.setTextSize(20);
+ p.setColor(0xffffffff);
+ c.drawText(t, 2, 26, p);
+ return mRS.allocationCreateFromBitmap(b, RenderScript.ElementPredefined.RGBA_8888, true);
+ }
private void initRS() {
@@ -229,15 +320,15 @@ public class RolloRS {
mRS.scriptCSetScript(mRes, R.raw.rollo);
//mRS.scriptCSetScript(mRes, R.raw.rollo2);
mRS.scriptCSetRoot(true);
- //mRS.scriptCSetClearDepth(0);
mScript = mRS.scriptCCreate();
- mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, 0, 0, 38, 0, 0};
+ mAllocStateBuf = new int[] {0, 0, 0, 8, 0, 0, -1, 0, mAllocIconIDBuf.length, 0, 0};
mAllocState = mRS.allocationCreatePredefSized(
RenderScript.ElementPredefined.USER_I32, mAllocStateBuf.length);
mScript.bindAllocation(mAllocState, 0);
mScript.bindAllocation(mAllocIconID, 1);
mScript.bindAllocation(mAllocScratch, 2);
+ mScript.bindAllocation(mAllocLabelID, 3);
setPosition(0);
setZoom(1);
@@ -248,4 +339,3 @@ public class RolloRS {
}
-
diff --git a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java b/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
index b5e02af..71d6c7e 100644
--- a/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
+++ b/libs/rs/java/Rollo/src/com/android/rollo/RolloView.java
@@ -76,7 +76,7 @@ public class RolloView extends RSSurfaceView {
float mOldColumn;
float mZoom = 1;
- int mIconCount = 38;
+ int mIconCount = 29;
int mRows = 4;
int mColumns = (mIconCount + mRows - 1) / mRows;
@@ -90,8 +90,8 @@ public class RolloView extends RSSurfaceView {
if(c > (mColumns -2)) {
c = (mColumns -2);
}
- if(c < 1) {
- c = 1;
+ if(c < 0) {
+ c = 0;
}
mRender.setPosition(c);
if(clamp) {
@@ -101,11 +101,11 @@ public class RolloView extends RSSurfaceView {
void computeSelection(float x, float y)
{
- float col = mColumn + (x - 0.5f) * 3;
+ float col = mColumn + (x - 0.5f) * 4 + 1.25f;
int iCol = (int)(col + 0.25f);
float row = (y / 0.8f) * mRows;
- int iRow = (int)(row - 0.25f);
+ int iRow = (int)(row - 0.5f);
mRender.setSelected(iCol * mRows + iRow);
}
@@ -122,6 +122,9 @@ public class RolloView extends RSSurfaceView {
float nx = ev.getX() / getWidth();
float ny = ev.getY() / getHeight();
+ //Log.e("rs", "width=" + Float.toString(getWidth()));
+ //Log.e("rs", "height=" + Float.toString(getHeight()));
+
mRender.setTouch(ret);
if((ny > 0.85f) || mControlMode) {
@@ -158,13 +161,14 @@ public class RolloView extends RSSurfaceView {
mZoom = zoom;
mFlingX = nx;
mRender.setZoom(zoom);
- } else {
- if(mControlMode && (mZoom < 1.01f)) {
+ if(mZoom < 1.01f) {
computeSelection(nx, ny);
}
+ } else {
mControlMode = false;
mColumn = mOldColumn;
mRender.setZoom(1.f);
+ mRender.setSelected(-1);
}
} else {
// Do something with corners here....
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 2f99808..d9a6456 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -99,6 +99,16 @@ AllocationCreateFromBitmap {
ret RsAllocation
}
+AllocationCreateFromBitmapBoxed {
+ param uint32_t width
+ param uint32_t height
+ param RsElementPredefined dstFmt
+ param RsElementPredefined srcFmt
+ param bool genMips
+ param const void * data
+ ret RsAllocation
+ }
+
AllocationUploadToTexture {
param RsAllocation alloc
@@ -270,6 +280,11 @@ ScriptCSetClearColor {
param float a
}
+ScriptCSetTimeZone {
+ param const char * timeZone
+ param uint32_t length
+ }
+
ScriptCSetClearDepth {
param float depth
}
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index c143307..ca277ef 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -204,12 +204,12 @@ static void mip565(const Adapter2D &out, const Adapter2D &in)
uint32_t w = out.getDimX();
uint32_t h = out.getDimY();
- for (uint32_t y=0; y < w; y++) {
+ for (uint32_t y=0; y < h; y++) {
uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
- for (uint32_t x=0; x < h; x++) {
+ for (uint32_t x=0; x < w; x++) {
*oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
oPtr ++;
i1 += 2;
@@ -223,21 +223,33 @@ static void mip8888(const Adapter2D &out, const Adapter2D &in)
uint32_t w = out.getDimX();
uint32_t h = out.getDimY();
- for (uint32_t y=0; y < w; y++) {
+ for (uint32_t y=0; y < h; y++) {
uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
- for (uint32_t x=0; x < h; x++) {
+ for (uint32_t x=0; x < w; x++) {
*oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
oPtr ++;
i1 += 2;
i2 += 2;
}
}
-
}
+static void mip(const Adapter2D &out, const Adapter2D &in)
+{
+ switch(out.getBaseType()->getElement()->getSizeBits()) {
+ case 32:
+ mip8888(out, in);
+ break;
+ case 16:
+ mip565(out, in);
+ break;
+
+ }
+
+}
typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
@@ -301,14 +313,18 @@ static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPre
return elementConverter_cpy_32;
}
- LOGE("pickConverter, unsuported combo");
+ LOGE("pickConverter, unsuported combo, src %i, dst %i", srcFmt, dstFmt);
return 0;
}
RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
{
- rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
+ rsAssert(!(w & (w-1)));
+ rsAssert(!(h & (h-1)));
+
+ //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
+ rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, dstFmt));
rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
if (genMips) {
@@ -333,13 +349,49 @@ RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h
for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
adapt.setLOD(lod);
adapt2.setLOD(lod + 1);
- mip565(adapt2, adapt);
+ mip(adapt2, adapt);
}
}
return texAlloc;
}
+static uint32_t fmtToBits(RsElementPredefined fmt)
+{
+ return 16;
+}
+
+RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data)
+{
+ uint32_t w2 = rsHigherPow2(w);
+ uint32_t h2 = rsHigherPow2(h);
+
+ if ((w2 == w) && (h2 == h)) {
+ return rsi_AllocationCreateFromBitmap(rsc, w, h, dstFmt, srcFmt, genMips, data);
+ }
+
+ uint32_t bpp = fmtToBits(srcFmt) >> 3;
+ size_t size = w2 * h2 * bpp;
+ uint8_t *tmp = static_cast<uint8_t *>(malloc(size));
+ memset(tmp, 0, size);
+
+ const uint8_t * src = static_cast<const uint8_t *>(data);
+ for (uint32_t y = 0; y < h; y++) {
+ uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp];
+ memcpy(&ydst[(w2 - w) >> 1], src, w * bpp);
+ src += w * bpp;
+ }
+
+ RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, dstFmt, srcFmt, genMips, tmp);
+ free(tmp);
+ return ret;
+
+
+
+
+}
+
+
RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool genMips)
{
bool use32bpp = false;
@@ -442,11 +494,7 @@ RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool g
for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
adapt.setLOD(lod);
adapt2.setLOD(lod + 1);
- if (use32bpp) {
- mip8888(adapt2, adapt);
- } else {
- mip565(adapt2, adapt);
- }
+ mip(adapt2, adapt);
}
}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 78b8bf8..e52b0e0 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -79,8 +79,7 @@ bool Context::runScript(Script *s, uint32_t launchID)
mFragment.set(frag);
mVertex.set(vtx);
mFragmentStore.set(store);
- return true;
-
+ return ret;
}
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 497dbcf..a00b8e8 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -83,6 +83,7 @@ public:
const ProgramFragment * getFragment() {return mFragment.get();}
const ProgramFragmentStore * getFragmentStore() {return mFragmentStore.get();}
+ const ProgramVertex * getVertex() {return mVertex.get();}
void setupCheck();
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 417ba6a..792135d 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -55,8 +55,6 @@ void ProgramVertex::setupGL()
glLoadIdentity();
}
-
- LOGE("lights %i ", mLightCount);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (mLightCount) {
@@ -103,6 +101,25 @@ void ProgramVertex::addLight(const Light *l)
}
}
+void ProgramVertex::setProjectionMatrix(const rsc_Matrix *m) const
+{
+ float *f = static_cast<float *>(mConstants[0]->getPtr());
+ memcpy(&f[RS_PROGRAM_VERTEX_PROJECTION_OFFSET], m, sizeof(rsc_Matrix));
+}
+
+void ProgramVertex::setModelviewMatrix(const rsc_Matrix *m) const
+{
+ float *f = static_cast<float *>(mConstants[0]->getPtr());
+ memcpy(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET], m, sizeof(rsc_Matrix));
+}
+
+void ProgramVertex::setTextureMatrix(const rsc_Matrix *m) const
+{
+ float *f = static_cast<float *>(mConstants[0]->getPtr());
+ memcpy(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET], m, sizeof(rsc_Matrix));
+}
+
+
ProgramVertexState::ProgramVertexState()
{
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
index ac15b70..da5ed81 100644
--- a/libs/rs/rsProgramVertex.h
+++ b/libs/rs/rsProgramVertex.h
@@ -41,6 +41,10 @@ public:
void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
void addLight(const Light *);
+ void setProjectionMatrix(const rsc_Matrix *) const;
+ void setModelviewMatrix(const rsc_Matrix *) const;
+ void setTextureMatrix(const rsc_Matrix *) const;
+
protected:
bool mDirty;
uint32_t mLightCount;
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 7dd2b61..a8e04a6 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -43,6 +43,9 @@ public:
float mClearDepth;
uint32_t mClearStencil;
+ uint32_t mStartTimeMillis;
+ const char* mTimeZone;
+
ObjectBaseRef<ProgramVertex> mVertex;
ObjectBaseRef<ProgramFragment> mFragment;
//ObjectBaseRef<ProgramRaster> mRaster;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 842c836..3b9d27a 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -230,6 +230,12 @@ void rsi_ScriptCSetClearColor(Context * rsc, float r, float g, float b, float a)
ss->mEnviroment.mClearColor[3] = a;
}
+void rsi_ScriptCSetTimeZone(Context * rsc, const char * timeZone, uint32_t length)
+{
+ ScriptCState *ss = &rsc->mScriptC;
+ ss->mEnviroment.mTimeZone = timeZone;
+}
+
void rsi_ScriptCSetClearDepth(Context * rsc, float v)
{
ScriptCState *ss = &rsc->mScriptC;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 129b19f..ca05114 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -24,6 +24,9 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+#include <time.h>
+#include <cutils/tztime.h>
+
using namespace android;
using namespace android::renderscript;
@@ -133,8 +136,63 @@ static float SC_randf(float max)
}
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+static uint32_t SC_second()
+{
+ GET_TLS();
+ time_t rawtime;
+ time(&rawtime);
+
+ if (sc->mEnviroment.mTimeZone) {
+ struct tm timeinfo;
+ localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+ return timeinfo.tm_sec;
+ } else {
+ struct tm *timeinfo;
+ timeinfo = localtime(&rawtime);
+ return timeinfo->tm_sec;
+ }
+}
+
+static uint32_t SC_minute()
+{
+ GET_TLS();
+
+ time_t rawtime;
+ time(&rawtime);
+
+ if (sc->mEnviroment.mTimeZone) {
+ struct tm timeinfo;
+ localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+ return timeinfo.tm_min;
+ } else {
+ struct tm *timeinfo;
+ timeinfo = localtime(&rawtime);
+ return timeinfo->tm_min;
+ }
+}
+
+static uint32_t SC_hour()
+{
+ GET_TLS();
+
+ time_t rawtime;
+ time(&rawtime);
+
+ if (sc->mEnviroment.mTimeZone) {
+ struct tm timeinfo;
+ localtime_tz(&rawtime, &timeinfo, sc->mEnviroment.mTimeZone);
+ return timeinfo.tm_hour;
+ } else {
+ struct tm *timeinfo;
+ timeinfo = localtime(&rawtime);
+ return timeinfo->tm_hour;
+ }
+}
//////////////////////////////////////////////////////////////////////////////
// Matrix routines
@@ -257,6 +315,24 @@ static void SC_bindProgramVertex(RsProgramVertex pv)
}
//////////////////////////////////////////////////////////////////////////////
+// VP
+//////////////////////////////////////////////////////////////////////////////
+
+static void SC_vpLoadModelMatrix(const rsc_Matrix *m)
+{
+ GET_TLS();
+ rsc->getVertex()->setModelviewMatrix(m);
+}
+
+static void SC_vpLoadTextureMatrix(const rsc_Matrix *m)
+{
+ GET_TLS();
+ rsc->getVertex()->setTextureMatrix(m);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////////////////////////
@@ -339,24 +415,25 @@ static void SC_drawQuad(float x1, float y1, float z1,
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-
-extern "C" const void * loadVp(uint32_t bank, uint32_t offset)
+static void SC_drawRect(float x1, float y1,
+ float x2, float y2, float z)
{
- GET_TLS();
- return &static_cast<const uint8_t *>(sc->mSlots[bank]->getPtr())[offset];
+ SC_drawQuad(x1, y2, z,
+ x2, y2, z,
+ x2, y1, z,
+ x1, y1, z);
}
-
+//////////////////////////////////////////////////////////////////////////////
+//
+//////////////////////////////////////////////////////////////////////////////
static void SC_color(float r, float g, float b, float a)
{
glColor4f(r, g, b, a);
}
-
+/*
extern "C" void materialDiffuse(float r, float g, float b, float a)
{
float v[] = {r, g, b, a};
@@ -369,35 +446,18 @@ extern "C" void materialSpecular(float r, float g, float b, float a)
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v);
}
-extern "C" void lightPosition(float x, float y, float z, float w)
-{
- float v[] = {x, y, z, w};
- glLightfv(GL_LIGHT0, GL_POSITION, v);
-}
-
extern "C" void materialShininess(float s)
{
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &s);
}
+*/
-extern "C" void uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
+static void SC_uploadToTexture(RsAllocation va, uint32_t baseMipLevel)
{
GET_TLS();
rsi_AllocationUploadToTexture(rsc, va, baseMipLevel);
}
-extern "C" void enable(uint32_t p)
-{
- glEnable(p);
-}
-
-extern "C" void disable(uint32_t p)
-{
- glDisable(p);
-}
-
-
-
static void SC_ClearColor(float r, float g, float b, float a)
{
//LOGE("c %f %f %f %f", r, g, b, a);
@@ -408,6 +468,16 @@ static void SC_ClearColor(float r, float g, float b, float a)
sc->mEnviroment.mClearColor[3] = a;
}
+static void SC_debugF(const char *s, float f)
+{
+ LOGE("%s %f", s, f);
+}
+
+static void SC_debugI32(const char *s, int32_t i)
+{
+ LOGE("%s %i", s, i);
+}
+
//////////////////////////////////////////////////////////////////////////////
@@ -440,10 +510,22 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
"float", "(float)" },
{ "cosf", (void *)&cosf,
"float", "(float)" },
- { "fabs", (void *)&fabs,
+ { "fabsf", (void *)&fabsf,
"float", "(float)" },
{ "randf", (void *)&SC_randf,
"float", "(float)" },
+ { "floorf", (void *)&floorf,
+ "float", "(float)" },
+ { "ceilf", (void *)&ceilf,
+ "float", "(float)" },
+
+ // time
+ { "second", (void *)&SC_second,
+ "int", "()" },
+ { "minute", (void *)&SC_minute,
+ "int", "()" },
+ { "hour", (void *)&SC_hour,
+ "int", "()" },
// matrix
{ "matrixLoadIdentity", (void *)&SC_matrixLoadIdentity,
@@ -481,7 +563,17 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
{ "bindTexture", (void *)&SC_bindTexture,
"void", "(int, int, int)" },
+ // vp
+ { "vpLoadModelMatrix", (void *)&SC_vpLoadModelMatrix,
+ "void", "(void *)" },
+ { "vpLoadTextureMatrix", (void *)&SC_vpLoadTextureMatrix,
+ "void", "(void *)" },
+
+
+
// drawing
+ { "drawRect", (void *)&SC_drawRect,
+ "void", "(float x1, float y1, float x2, float y2, float z)" },
{ "drawQuad", (void *)&SC_drawQuad,
"void", "(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4)" },
{ "drawTriangleArray", (void *)&SC_drawTriangleArray,
@@ -495,10 +587,19 @@ ScriptCState::SymbolTable_t ScriptCState::gSyms[] = {
// misc
{ "pfClearColor", (void *)&SC_ClearColor,
"void", "(float, float, float, float)" },
-
{ "color", (void *)&SC_color,
"void", "(float, float, float, float)" },
+ { "uploadToTexture", (void *)&SC_uploadToTexture,
+ "void", "(int, int)" },
+
+
+ { "debugF", (void *)&SC_debugF,
+ "void", "(void *, float)" },
+ { "debugI32", (void *)&SC_debugI32,
+ "void", "(void *, int)" },
+
+
{ NULL, NULL, NULL, NULL }
};
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 21f87e37..f0615f0 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -231,6 +231,9 @@ void DisplayHardware::init(uint32_t dpy)
LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
strcpy(property, "160");
}
+ } else {
+ /* for the emulator case, reset the dpi values too */
+ mDpiX = mDpiY = atoi(property);
}
mDensity = atoi(property) * (1.0f/160.0f);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index a841ab3..fbce73d 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -461,7 +461,8 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glRotatef(-90, 0, 0, 1);
}
- if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
+ if (!(mFlags & (DisplayHardware::NPOT_EXTENSION |
+ DisplayHardware::DIRECT_TEXTURE))) {
// find the smallest power-of-two that will accommodate our surface
GLuint tw = 1 << (31 - clz(width));
GLuint th = 1 << (31 - clz(height));
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 9fffbbf..ff49c87 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -177,22 +177,17 @@ status_t LayerBitmap::setSize(uint32_t w, uint32_t h)
sp<Buffer> LayerBitmap::allocate()
{
Mutex::Autolock _l(mLock);
- sp<Buffer> buffer(mBuffer);
- const uint32_t w = mWidth;
- const uint32_t h = mHeight;
- if (buffer!=0 && (w != buffer->getWidth() || h != buffer->getHeight())) {
- surface_info_t* info = mInfo;
- buffer = new Buffer(w, h, mFormat, mFlags);
- status_t err = buffer->initCheck();
- if (LIKELY(err == NO_ERROR)) {
- info->flags = surface_info_t::eBufferDirty;
- info->status = NO_ERROR;
- } else {
- memset(info, 0, sizeof(surface_info_t));
- info->status = NO_MEMORY;
- }
- mBuffer = buffer;
+ surface_info_t* info = mInfo;
+ sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
+ status_t err = buffer->initCheck();
+ if (LIKELY(err == NO_ERROR)) {
+ info->flags = surface_info_t::eBufferDirty;
+ info->status = NO_ERROR;
+ } else {
+ memset(info, 0, sizeof(surface_info_t));
+ info->status = NO_MEMORY;
}
+ mBuffer = buffer;
return buffer;
}
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 7a7574f..102899c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -650,6 +650,7 @@ void SurfaceFlinger::handleTransactionLocked(
if (currentLayers.indexOf( layer ) < 0) {
// this layer is not visible anymore
ditchedLayers.add(layer);
+ mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
}
}
}
@@ -685,17 +686,15 @@ void SurfaceFlinger::computeVisibleRegions(
layer->validateVisibility(planeTransform);
// start with the whole surface at its current location
- const Layer::State& s = layer->drawingState();
- const Rect bounds(layer->visibleBounds());
+ const Layer::State& s(layer->drawingState());
// handle hidden surfaces by setting the visible region to empty
Region opaqueRegion;
Region visibleRegion;
Region coveredRegion;
- if (UNLIKELY((s.flags & ISurfaceComposer::eLayerHidden) || !s.alpha)) {
- visibleRegion.clear();
- } else {
+ if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
const bool translucent = layer->needsBlending();
+ const Rect bounds(layer->visibleBounds());
visibleRegion.set(bounds);
coveredRegion = visibleRegion;
@@ -742,12 +741,16 @@ void SurfaceFlinger::computeVisibleRegions(
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
- // If a secure layer is partially visible, lock down the screen!
+ // If a secure layer is partially visible, lock-down the screen!
if (layer->isSecure() && !visibleRegion.isEmpty()) {
secureFrameBuffer = true;
}
}
+ // invalidate the areas where a layer was removed
+ dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
+ mDirtyRegionRemovedLayer.clear();
+
mSecureFrameBuffer = secureFrameBuffer;
opaqueRegion = aboveOpaqueLayers;
}
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index e8687a7..2569a0f 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -334,6 +334,7 @@ private:
// Can only accessed from the main thread, these members
// don't need synchronization
Region mDirtyRegion;
+ Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
wp<Client> mLastScheduledBroadcast;
diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp
index 92a9a86..4add8f9 100644
--- a/libs/ui/BufferMapper.cpp
+++ b/libs/ui/BufferMapper.cpp
@@ -65,7 +65,7 @@ status_t BufferMapper::lock(buffer_handle_t handle,
{
status_t err = mAllocMod->lock(mAllocMod, handle, usage,
bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr);
- LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+ LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));
return err;
}
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 8c8fd6b..8b7ea21 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -124,6 +124,7 @@ FramebufferNativeWindow::FramebufferNativeWindow()
android_native_window_t::dequeueBuffer = dequeueBuffer;
android_native_window_t::lockBuffer = lockBuffer;
android_native_window_t::queueBuffer = queueBuffer;
+ android_native_window_t::query = query;
}
FramebufferNativeWindow::~FramebufferNativeWindow() {
@@ -198,6 +199,23 @@ int FramebufferNativeWindow::queueBuffer(android_native_window_t* window,
return res;
}
+int FramebufferNativeWindow::query(android_native_window_t* window,
+ int what, int* value)
+{
+ FramebufferNativeWindow* self = getSelf(window);
+ Mutex::Autolock _l(self->mutex);
+ framebuffer_device_t* fb = self->fbDev;
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ *value = fb->width;
+ return NO_ERROR;
+ case NATIVE_WINDOW_HEIGHT:
+ *value = fb->height;
+ return NO_ERROR;
+ }
+ return BAD_VALUE;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 4854d6a..3aa8950 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -59,6 +59,18 @@ status_t Overlay::queueBuffer(overlay_buffer_t buffer)
return mOverlayData->queueBuffer(mOverlayData, buffer);
}
+status_t Overlay::resizeInput(uint32_t width, uint32_t height)
+{
+ if (mStatus != NO_ERROR) return mStatus;
+ return mOverlayData->resizeInput(mOverlayData, width, height);
+}
+
+status_t Overlay::setParameter(int param, int value)
+{
+ if (mStatus != NO_ERROR) return mStatus;
+ return mOverlayData->setParameter(mOverlayData, param, value);
+}
+
status_t Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
if (mStatus != NO_ERROR) return mStatus;
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index aef47fd..04ab64c 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -180,7 +180,7 @@ SurfaceControl::SurfaceControl(
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
: mClient(client), mSurface(surface),
mToken(data.token), mIdentity(data.identity),
- mFormat(format), mFlags(flags)
+ mWidth(w), mHeight(h), mFormat(format), mFlags(flags)
{
}
@@ -338,6 +338,8 @@ status_t SurfaceControl::writeSurfaceToParcel(
uint32_t format = 0;
SurfaceID token = -1;
uint32_t identity = 0;
+ uint32_t width = 0;
+ uint32_t height = 0;
sp<SurfaceComposerClient> client;
sp<ISurface> sur;
if (SurfaceControl::isValid(control)) {
@@ -345,6 +347,8 @@ status_t SurfaceControl::writeSurfaceToParcel(
identity = control->mIdentity;
client = control->mClient;
sur = control->mSurface;
+ width = control->mWidth;
+ height = control->mHeight;
format = control->mFormat;
flags = control->mFlags;
}
@@ -352,6 +356,8 @@ status_t SurfaceControl::writeSurfaceToParcel(
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
parcel->writeInt32(token);
parcel->writeInt32(identity);
+ parcel->writeInt32(width);
+ parcel->writeInt32(height);
parcel->writeInt32(format);
parcel->writeInt32(flags);
return NO_ERROR;
@@ -373,6 +379,7 @@ sp<Surface> SurfaceControl::getSurface() const
Surface::Surface(const sp<SurfaceControl>& surface)
: mClient(surface->mClient), mSurface(surface->mSurface),
mToken(surface->mToken), mIdentity(surface->mIdentity),
+ mWidth(surface->mWidth), mHeight(surface->mHeight),
mFormat(surface->mFormat), mFlags(surface->mFlags),
mBufferMapper(BufferMapper::get())
{
@@ -386,6 +393,8 @@ Surface::Surface(const Parcel& parcel)
mSurface = interface_cast<ISurface>(parcel.readStrongBinder());
mToken = parcel.readInt32();
mIdentity = parcel.readInt32();
+ mWidth = parcel.readInt32();
+ mHeight = parcel.readInt32();
mFormat = parcel.readInt32();
mFlags = parcel.readInt32();
@@ -401,6 +410,7 @@ void Surface::init()
android_native_window_t::dequeueBuffer = dequeueBuffer;
android_native_window_t::lockBuffer = lockBuffer;
android_native_window_t::queueBuffer = queueBuffer;
+ android_native_window_t::query = query;
mSwapRectangle.makeInvalid();
DisplayInfo dinfo;
SurfaceComposerClient::getDisplayInfo(0, &dinfo);
@@ -492,6 +502,13 @@ int Surface::queueBuffer(android_native_window_t* window,
return self->queueBuffer(buffer);
}
+int Surface::query(android_native_window_t* window,
+ int what, int* value)
+{
+ Surface* self = getSelf(window);
+ return self->query(what, value);
+}
+
// ----------------------------------------------------------------------------
status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
@@ -499,6 +516,9 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
*buffer = SurfaceBuffer::getSelf(out);
+ // reset the width/height with the what we get from the buffer
+ mWidth = uint32_t(out->width);
+ mHeight = uint32_t(out->height);
return err;
}
@@ -586,6 +606,19 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
return NO_ERROR;
}
+int Surface::query(int what, int* value)
+{
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ *value = int(mWidth);
+ return NO_ERROR;
+ case NATIVE_WINDOW_HEIGHT:
+ *value = int(mHeight);
+ return NO_ERROR;
+ }
+ return BAD_VALUE;
+}
+
// ----------------------------------------------------------------------------
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index be04777..0cef35a 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -193,9 +193,11 @@ BackupDataReader::Status()
if ((actual) != (expected)) { \
if ((actual) == 0) { \
m_status = EIO; \
+ m_done = true; \
} else { \
m_status = errno; \
} \
+ LOGD("CHECK_SIZE failed with at line %d m_status='%s'", __LINE__, strerror(m_status)); \
return m_status; \
} \
} while(0)
@@ -203,6 +205,7 @@ BackupDataReader::Status()
do { \
status_t err = skip_padding(); \
if (err != NO_ERROR) { \
+ LOGD("SKIP_PADDING FAILED at line %d", __LINE__); \
m_status = err; \
return err; \
} \
@@ -218,10 +221,19 @@ BackupDataReader::ReadNextHeader(bool* done, int* type)
int amt;
- // No error checking here, in case we're at the end of the stream. Just let read() fail.
- skip_padding();
+ amt = skip_padding();
+ if (amt == EIO) {
+ *done = m_done = true;
+ return NO_ERROR;
+ }
+ else if (amt != NO_ERROR) {
+ return amt;
+ }
amt = read(m_fd, &m_header, sizeof(m_header));
*done = m_done = (amt == 0);
+ if (*done) {
+ return NO_ERROR;
+ }
CHECK_SIZE(amt, sizeof(m_header));
m_pos += sizeof(m_header);
if (type) {
@@ -327,6 +339,10 @@ BackupDataReader::ReadEntityData(void* data, size_t size)
m_status = errno;
return -1;
}
+ if (amt == 0) {
+ m_status = EIO;
+ m_done = true;
+ }
m_pos += amt;
return amt;
}
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 4dca8bd..0831f4a 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -1486,7 +1486,7 @@ ssize_t ResTable::Theme::getAttribute(uint32_t resID, Res_value* outValue,
ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue,
ssize_t blockIndex, uint32_t* outLastRef,
- uint32_t* inoutTypeSpecFlags) const
+ uint32_t* inoutTypeSpecFlags, ResTable_config* inoutConfig) const
{
//printf("Resolving type=0x%x\n", inOutValue->dataType);
if (inOutValue->dataType == Res_value::TYPE_ATTRIBUTE) {
@@ -1498,7 +1498,8 @@ ssize_t ResTable::Theme::resolveAttributeReference(Res_value* inOutValue,
return blockIndex;
}
}
- return mTable.resolveReference(inOutValue, blockIndex, outLastRef);
+ return mTable.resolveReference(inOutValue, blockIndex, outLastRef,
+ inoutTypeSpecFlags, inoutConfig);
}
void ResTable::Theme::dumpToLog() const
@@ -1891,7 +1892,8 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
}
ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
- uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags) const
+ uint32_t* outLastRef, uint32_t* inoutTypeSpecFlags,
+ ResTable_config* outConfig) const
{
int count=0;
while (blockIndex >= 0 && value->dataType == value->TYPE_REFERENCE
@@ -1899,7 +1901,8 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
if (outLastRef) *outLastRef = value->data;
uint32_t lastRef = value->data;
uint32_t newFlags = 0;
- const ssize_t newIndex = getResource(value->data, value, true, &newFlags);
+ const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
+ outConfig);
//LOGI("Resolving reference d=%p: newIndex=%d, t=0x%02x, d=%p\n",
// (void*)lastRef, (int)newIndex, (int)value->dataType, (void*)value->data);
//printf("Getting reference 0x%08x: newIndex=%d\n", value->data, newIndex);
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 9e1a72c..aaac192 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -197,6 +197,10 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
// properties loaded from PROPERTIES_FILE
private Properties mProperties;
private String mNtpServer;
+ private String mSuplServerHost;
+ private int mSuplServerPort;
+ private String mC2KServerHost;
+ private int mC2KServerPort;
private final Context mContext;
private final ILocationManager mLocationManager;
@@ -348,23 +352,21 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
stream.close();
mNtpServer = mProperties.getProperty("NTP_SERVER", null);
- String host = mProperties.getProperty("SUPL_HOST");
+ mSuplServerHost = mProperties.getProperty("SUPL_HOST");
String portString = mProperties.getProperty("SUPL_PORT");
- if (host != null && portString != null) {
+ if (mSuplServerHost != null && portString != null) {
try {
- int port = Integer.parseInt(portString);
- native_set_agps_server(AGPS_TYPE_SUPL, host, port);
+ mSuplServerPort = Integer.parseInt(portString);
} catch (NumberFormatException e) {
Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
}
}
- host = mProperties.getProperty("C2K_HOST");
+ mC2KServerHost = mProperties.getProperty("C2K_HOST");
portString = mProperties.getProperty("C2K_PORT");
- if (host != null && portString != null) {
+ if (mC2KServerHost != null && portString != null) {
try {
- int port = Integer.parseInt(portString);
- native_set_agps_server(AGPS_TYPE_C2K, host, port);
+ mC2KServerPort = Integer.parseInt(portString);
} catch (NumberFormatException e) {
Log.e(TAG, "unable to parse C2K_PORT: " + portString);
}
@@ -494,6 +496,13 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
mEnabled = native_init();
if (mEnabled) {
+ if (mSuplServerHost != null) {
+ native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
+ }
+ if (mC2KServerHost != null) {
+ native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
+ }
+
// run event listener thread while we are enabled
mEventThread = new GpsEventThread();
mEventThread.start();
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 040d4bc..60fc0e0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -649,10 +649,11 @@ public class AudioManager {
* <var>false</var> to turn it off
*/
public void setSpeakerphoneOn(boolean on){
- if (on) {
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER);
- } else {
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+ IAudioService service = getService();
+ try {
+ service.setSpeakerphoneOn(on);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setSpeakerphoneOn", e);
}
}
@@ -662,9 +663,11 @@ public class AudioManager {
* @return true if speakerphone is on, false if it's off
*/
public boolean isSpeakerphoneOn() {
- if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_SPEAKER) {
- return true;
- } else {
+ IAudioService service = getService();
+ try {
+ return service.isSpeakerphoneOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in isSpeakerphoneOn", e);
return false;
}
}
@@ -676,10 +679,11 @@ public class AudioManager {
* <var>false</var> to not use bluetooth SCO for communications
*/
public void setBluetoothScoOn(boolean on){
- if (on) {
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO);
- } else {
- AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+ IAudioService service = getService();
+ try {
+ service.setBluetoothScoOn(on);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in setBluetoothScoOn", e);
}
}
@@ -690,9 +694,11 @@ public class AudioManager {
* false if otherwise
*/
public boolean isBluetoothScoOn() {
- if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) {
- return true;
- } else {
+ IAudioService service = getService();
+ try {
+ return service.isBluetoothScoOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in isBluetoothScoOn", e);
return false;
}
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 30640c3..1f9e3af 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -47,7 +47,10 @@ import com.android.internal.telephony.ITelephony;
import java.io.IOException;
import java.util.ArrayList;
-
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
/**
* The implementation of the volume manager service.
@@ -210,6 +213,12 @@ public class AudioService extends IAudioService.Stub {
private int mHeadsetState;
+ // Devices currently connected
+ private HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>();
+
+ // Forced device usage for communications
+ private int mForcedUseForComm;
+
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -220,7 +229,9 @@ public class AudioService extends IAudioService.Stub {
mContentResolver = context.getContentResolver();
mVolumePanel = new VolumePanel(context, this);
mSettingsObserver = new SettingsObserver();
-
+ mMode = AudioSystem.MODE_NORMAL;
+ mHeadsetState = 0;
+ mForcedUseForComm = AudioSystem.FORCE_NONE;
createAudioSystemThread();
readPersistedSettings();
createStreamStates();
@@ -721,6 +732,46 @@ public class AudioService extends IAudioService.Stub {
setRingerModeInt(getRingerMode(), false);
}
+ /** @see AudioManager#setSpeakerphoneOn() */
+ public void setSpeakerphoneOn(boolean on){
+ if (on) {
+ AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER);
+ mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
+ } else {
+ AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+ mForcedUseForComm = AudioSystem.FORCE_NONE;
+ }
+ }
+
+ /** @see AudioManager#isSpeakerphoneOn() */
+ public boolean isSpeakerphoneOn() {
+ if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /** @see AudioManager#setBluetoothScoOn() */
+ public void setBluetoothScoOn(boolean on){
+ if (on) {
+ AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO);
+ mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
+ } else {
+ AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE);
+ mForcedUseForComm = AudioSystem.FORCE_NONE;
+ }
+ }
+
+ /** @see AudioManager#isBluetoothScoOn() */
+ public boolean isBluetoothScoOn() {
+ if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
///////////////////////////////////////////////////////////////////////////
// Internal methods
///////////////////////////////////////////////////////////////////////////
@@ -1188,16 +1239,33 @@ public class AudioService extends IAudioService.Stub {
Log.e(TAG, "Media server died.");
// Force creation of new IAudioflinger interface
mMediaServerOk = false;
- AudioSystem.getMode();
+ AudioSystem.isMusicActive();
break;
case MSG_MEDIA_SERVER_STARTED:
Log.e(TAG, "Media server started.");
+ // Restore device connection states
+ Set set = mConnectedDevices.entrySet();
+ Iterator i = set.iterator();
+ while(i.hasNext()){
+ Map.Entry device = (Map.Entry)i.next();
+ AudioSystem.setDeviceConnectionState(((Integer)device.getKey()).intValue(),
+ AudioSystem.DEVICE_STATE_AVAILABLE,
+ (String)device.getValue());
+ }
+
+ // Restore call state
+ AudioSystem.setPhoneState(mMode);
+
+ // Restore forced usage for communcations
+ AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
+
// Restore stream volumes
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
int index;
VolumeStreamState streamState = mStreamStates[streamType];
+ AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10);
if (streamState.muteCount() == 0) {
index = streamState.mIndex;
} else {
@@ -1205,7 +1273,10 @@ public class AudioService extends IAudioService.Stub {
}
setStreamVolumeIndex(streamType, index);
}
- setRingerMode(mRingerMode);
+
+ // Restore ringer mode
+ setRingerModeInt(getRingerMode(), false);
+
mMediaServerOk = true;
break;
@@ -1276,10 +1347,12 @@ public class AudioService extends IAudioService.Stub {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
address);
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
} else if (state == BluetoothA2dp.STATE_CONNECTED){
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE,
address);
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), address);
}
} else if (action.equals(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothIntent.HEADSET_AUDIO_STATE,
@@ -1289,10 +1362,12 @@ public class AudioService extends IAudioService.Stub {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
address);
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
} else if (state == BluetoothHeadset.AUDIO_STATE_CONNECTED) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
AudioSystem.DEVICE_STATE_AVAILABLE,
address);
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO), address);
}
} else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", 0);
@@ -1301,55 +1376,65 @@ public class AudioService extends IAudioService.Stub {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
"");
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
} else if ((state & BIT_HEADSET) != 0 &&
(mHeadsetState & BIT_HEADSET) == 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), "");
}
if ((state & BIT_HEADSET_NO_MIC) == 0 &&
(mHeadsetState & BIT_HEADSET_NO_MIC) != 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
"");
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
} else if ((state & BIT_HEADSET_NO_MIC) != 0 &&
(mHeadsetState & BIT_HEADSET_NO_MIC) == 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), "");
}
if ((state & BIT_TTY) == 0 &&
(mHeadsetState & BIT_TTY) != 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
"");
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_TTY);
} else if ((state & BIT_TTY) != 0 &&
(mHeadsetState & BIT_TTY) == 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_TTY,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_TTY), "");
}
if ((state & BIT_FM_HEADSET) == 0 &&
(mHeadsetState & BIT_FM_HEADSET) != 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
"");
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_FM_HEADPHONE);
} else if ((state & BIT_FM_HEADSET) != 0 &&
(mHeadsetState & BIT_FM_HEADSET) == 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_HEADPHONE,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_FM_HEADPHONE), "");
}
if ((state & BIT_FM_SPEAKER) == 0 &&
(mHeadsetState & BIT_FM_SPEAKER) != 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
"");
+ mConnectedDevices.remove(AudioSystem.DEVICE_OUT_FM_SPEAKER);
} else if ((state & BIT_FM_SPEAKER) != 0 &&
(mHeadsetState & BIT_FM_SPEAKER) == 0) {
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER,
AudioSystem.DEVICE_STATE_AVAILABLE,
"");
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_FM_SPEAKER), "");
}
mHeadsetState = state;
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index bb4252b..d3d2d29 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -60,4 +60,12 @@ interface IAudioService {
oneway void unloadSoundEffects();
oneway void reloadAudioSettings();
+
+ void setSpeakerphoneOn(boolean on);
+
+ boolean isSpeakerphoneOn();
+
+ void setBluetoothScoOn(boolean on);
+
+ boolean isBluetoothScoOn();
}
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 2263605..1570db4 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -183,6 +183,7 @@ public class JetPlayer
*/
public void release() {
native_release();
+ singletonRef = null;
}
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 44026e4..8481410 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -605,21 +605,6 @@ public class RingtoneManager {
Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
}
- // Ringtone doesn't exist, use the fallback ringtone.
- try {
- AssetFileDescriptor afd = context.getResources().openRawResourceFd(
- com.android.internal.R.raw.fallbackring);
- if (afd != null) {
- Ringtone r = new Ringtone(context);
- r.open(afd);
- afd.close();
- return r;
- }
- } catch (Exception ex) {
- }
-
- // we should never get here
- Log.e(TAG, "unable to find a usable ringtone");
return null;
}
@@ -638,8 +623,8 @@ public class RingtoneManager {
public static Uri getActualDefaultRingtoneUri(Context context, int type) {
String setting = getSettingForType(type);
if (setting == null) return null;
- final String uriString = Settings.System.getString(context.getContentResolver(), setting);
- return uriString != null ? Uri.parse(uriString) : getValidRingtoneUri(context);
+ final String uriString = Settings.System.getString(context.getContentResolver(), setting);
+ return uriString != null ? Uri.parse(uriString) : null;
}
/**
@@ -655,7 +640,8 @@ public class RingtoneManager {
public static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri) {
String setting = getSettingForType(type);
if (setting == null) return;
- Settings.System.putString(context.getContentResolver(), setting, ringtoneUri.toString());
+ Settings.System.putString(context.getContentResolver(), setting,
+ ringtoneUri != null ? ringtoneUri.toString() : null);
}
private static String getSettingForType(int type) {
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 0273a5a..304f521 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -276,7 +276,7 @@ static void
android_media_MediaRecorder_setVideoFrameRate(JNIEnv *env, jobject thiz, jint rate)
{
LOGV("setVideoFrameRate(%d)", rate);
- if (rate <= 0 || rate > MEDIA_RECORDER_MAX_FRAME_RATE) {
+ if (rate <= 0) {
jniThrowException(env, "java/lang/IllegalArgumentException", "invalid frame rate");
return;
}
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 0d07abe..b17e31b 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -93,7 +93,7 @@ SoundPool::~SoundPool()
void SoundPool::addToRestartList(SoundChannel* channel)
{
- Mutex::Autolock lock(&mLock);
+ Mutex::Autolock lock(&mRestartLock);
mRestart.push_back(channel);
mCondition.signal();
}
@@ -106,9 +106,9 @@ int SoundPool::beginThread(void* arg)
int SoundPool::run()
{
- mLock.lock();
+ mRestartLock.lock();
while (!mQuit) {
- mCondition.wait(mLock);
+ mCondition.wait(mRestartLock);
LOGV("awake");
if (mQuit) break;
@@ -125,19 +125,19 @@ int SoundPool::run()
mRestart.clear();
mCondition.signal();
- mLock.unlock();
+ mRestartLock.unlock();
LOGV("goodbye");
return 0;
}
void SoundPool::quit()
{
- mLock.lock();
+ mRestartLock.lock();
mQuit = true;
mCondition.signal();
- mCondition.wait(mLock);
+ mCondition.wait(mRestartLock);
LOGV("return from quit");
- mLock.unlock();
+ mRestartLock.unlock();
}
bool SoundPool::startThreads()
@@ -484,11 +484,8 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV
// if not idle, this voice is being stolen
if (mState != IDLE) {
LOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
- stop_l();
mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-#ifdef USE_SHARED_MEM_BUFFER
- mSoundPool->done(this);
-#endif
+ stop();
return;
}
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 7802781..ab86e90 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -204,6 +204,7 @@ private:
jobject mSoundPoolRef;
Mutex mLock;
+ Mutex mRestartLock;
Condition mCondition;
SoundPoolThread* mDecodeThread;
SoundChannel* mChannelPool;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 1d960c5..95d61cd 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -59,6 +59,8 @@
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
+//#undef USE_STAGEFRIGHT
+
#if USE_STAGEFRIGHT
#include "StagefrightPlayer.h"
#endif
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 5944d9c..5be9224 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -26,6 +26,7 @@ LOCAL_SRC_FILES:= \
SurfaceRenderer.cpp \
TimeSource.cpp \
TimedEventQueue.cpp \
+ TIHardwareRenderer.cpp \
Utils.cpp \
AudioPlayer.cpp \
ESDS.cpp \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 17c72b9..d547556 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -87,7 +87,10 @@ void AudioPlayer::start() {
} else {
mAudioTrack = new AudioTrack(
AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
- numChannels, 8192, 0, &AudioCallback, this, 0);
+ (numChannels == 2)
+ ? AudioSystem::CHANNEL_OUT_STEREO
+ : AudioSystem::CHANNEL_OUT_MONO,
+ 8192, 0, &AudioCallback, this, 0);
assert(mAudioTrack->initCheck() == OK);
@@ -217,8 +220,10 @@ void AudioPlayer::fillBuffer(void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
mPositionTimeMediaUs = (int64_t)units * 1000000 / scale;
+
mPositionTimeRealUs =
- ((mNumFramesPlayed + size_done / 4) * 1000000) / mSampleRate; // XXX
+ ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+ / mSampleRate;
}
if (mInputBuffer->range_length() == 0) {
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 6b47a38..01cb2d9 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -73,8 +73,6 @@ static bool get_mp3_frame_size(
if (bitrate_index == 0 || bitrate_index == 0x0f) {
// Disallow "free" bitrate.
-
- LOGE("We disallow 'free' bitrate for now.");
return false;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index caaec06..4c883c6 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -73,6 +73,8 @@ private:
bool mNeedsNALFraming;
+ uint8_t *mSrcBuffer;
+
MPEG4Source(const MPEG4Source &);
MPEG4Source &operator=(const MPEG4Source &);
};
@@ -743,7 +745,8 @@ MPEG4Source::MPEG4Source(
mBuffer(NULL),
mBufferOffset(0),
mBufferSizeRemaining(0),
- mNeedsNALFraming(false) {
+ mNeedsNALFraming(false),
+ mSrcBuffer(NULL) {
const char *mime;
bool success = mFormat->findCString(kKeyMIMEType, &mime);
assert(success);
@@ -777,8 +780,13 @@ status_t MPEG4Source::start(MetaData *params) {
status_t err = mSampleTable->getMaxSampleSize(&max_size);
assert(err == OK);
- // Add padding for de-framing of AVC content just in case.
- mGroup->add_buffer(new MediaBuffer(max_size + 2));
+ // Assume that a given buffer only contains at most 10 fragments,
+ // each fragment originally prefixed with a 2 byte length will
+ // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
+ // and thus will grow by 2 bytes per fragment.
+ mGroup->add_buffer(new MediaBuffer(max_size + 10 * 2));
+
+ mSrcBuffer = new uint8_t[max_size];
mStarted = true;
@@ -793,6 +801,9 @@ status_t MPEG4Source::stop() {
mBuffer = NULL;
}
+ delete[] mSrcBuffer;
+ mSrcBuffer = NULL;
+
delete mGroup;
mGroup = NULL;
@@ -832,33 +843,31 @@ status_t MPEG4Source::read(
// fall through
}
- if (mBuffer == NULL) {
- off_t offset;
- size_t size;
- status_t err = mSampleTable->getSampleOffsetAndSize(
- mCurrentSampleIndex, &offset, &size);
+ off_t offset;
+ size_t size;
+ status_t err = mSampleTable->getSampleOffsetAndSize(
+ mCurrentSampleIndex, &offset, &size);
- if (err != OK) {
- return err;
- }
+ if (err != OK) {
+ return err;
+ }
- uint32_t dts;
- err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
+ uint32_t dts;
+ err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
- if (err != OK) {
- return err;
- }
-
- err = mGroup->acquire_buffer(&mBuffer);
- if (err != OK) {
- assert(mBuffer == NULL);
- return err;
- }
+ if (err != OK) {
+ return err;
+ }
- assert(mBuffer->size() + 2 >= size);
+ err = mGroup->acquire_buffer(&mBuffer);
+ if (err != OK) {
+ assert(mBuffer == NULL);
+ return err;
+ }
+ if (!mIsAVC || !mNeedsNALFraming) {
ssize_t num_bytes_read =
- mDataSource->read_at(offset, (uint8_t *)mBuffer->data() + 2, size);
+ mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
@@ -867,50 +876,62 @@ status_t MPEG4Source::read(
return err;
}
- mBuffer->set_range(2, size);
+ mBuffer->set_range(0, size);
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
-
++mCurrentSampleIndex;
- mBufferOffset = 2;
- mBufferSizeRemaining = size;
- }
-
- if (!mIsAVC) {
*out = mBuffer;
mBuffer = NULL;
return OK;
}
- uint8_t *data = (uint8_t *)mBuffer->data() + mBufferOffset;
- assert(mBufferSizeRemaining >= 2);
+ ssize_t num_bytes_read =
+ mDataSource->read_at(offset, mSrcBuffer, size);
- size_t nal_length = (data[0] << 8) | data[1];
- assert(mBufferSizeRemaining >= 2 + nal_length);
-
- if (mNeedsNALFraming) {
- // Insert marker.
- data[-2] = data[-1] = data[0] = 0;
- data[1] = 1;
+ if (num_bytes_read < (ssize_t)size) {
+ mBuffer->release();
+ mBuffer = NULL;
- mBuffer->set_range(mBufferOffset - 2, nal_length + 4);
- } else {
- mBuffer->set_range(mBufferOffset + 2, nal_length);
+ return err;
}
- mBufferOffset += nal_length + 2;
- mBufferSizeRemaining -= nal_length + 2;
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+ while (srcOffset < size) {
+ assert(srcOffset + 1 < size);
+ size_t nalLength =
+ (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
+ assert(srcOffset + 1 + nalLength < size);
+ srcOffset += 2;
+
+ if (nalLength == 0) {
+ continue;
+ }
- if (mBufferSizeRemaining > 0) {
- *out = mBuffer->clone();
- } else {
- *out = mBuffer;
- mBuffer = NULL;
+ assert(dstOffset + 4 <= mBuffer->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
}
+ mBuffer->set_range(0, dstOffset);
+ mBuffer->meta_data()->clear();
+ mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
+ mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
+ ++mCurrentSampleIndex;
+
+ *out = mBuffer;
+ mBuffer = NULL;
+
return OK;
}
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index 78fcdee..04c9a11 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -40,6 +40,7 @@
#include <media/stagefright/SoftwareRenderer.h>
#include <media/stagefright/SurfaceRenderer.h>
#include <media/stagefright/TimeSource.h>
+#include <media/stagefright/TIHardwareRenderer.h>
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
@@ -311,6 +312,9 @@ void MediaPlayerImpl::videoEntry() {
{
Mutex::Autolock autoLock(mLock);
mVideoPosition = pts_us;
+
+ LOGV("now_video = %.2f secs (%lld ms)",
+ pts_us / 1E6, (pts_us + 500) / 1000);
}
if (seeking && mAudioPlayer != NULL) {
@@ -344,6 +348,7 @@ void MediaPlayerImpl::displayOrDiscardFrame(
if (mAudioPlayer != NULL
&& mAudioPlayer->getMediaTimeMapping(&realtime_us, &mediatime_us)) {
mTimeSourceDeltaUs = realtime_us - mediatime_us;
+ LOGV("mTimeSourceDeltaUs = %.2f secs", mTimeSourceDeltaUs / 1E6);
}
int64_t now_us = mTimeSource->getRealTimeUs();
@@ -436,6 +441,7 @@ void MediaPlayerImpl::init() {
}
void MediaPlayerImpl::setAudioSource(MediaSource *source) {
+ LOGI("setAudioSource");
mAudioSource = source;
sp<MetaData> meta = source->getFormat();
@@ -646,17 +652,28 @@ void MediaPlayerImpl::populateISurface() {
success = success && meta->findInt32(kKeyHeight, &decodedHeight);
assert(success);
+ static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
if (mSurface.get() != NULL) {
+ LOGW("Using SurfaceRenderer.");
mRenderer =
new SurfaceRenderer(
mSurface, mVideoWidth, mVideoHeight,
decodedWidth, decodedHeight);
- } else if (format == OMX_COLOR_FormatYUV420Planar
- && !strncasecmp(component, "OMX.qcom.video.decoder.", 23)) {
+ } else if (format == OMX_QCOM_COLOR_FormatYVU420SemiPlanar
+ && !strncmp(component, "OMX.qcom.video.decoder.", 23)) {
+ LOGW("Using QComHardwareRenderer.");
mRenderer =
new QComHardwareRenderer(
mISurface, mVideoWidth, mVideoHeight,
decodedWidth, decodedHeight);
+ } else if (format == OMX_COLOR_FormatCbYCrY
+ && !strcmp(component, "OMX.TI.Video.Decoder")) {
+ LOGW("Using TIHardwareRenderer.");
+ mRenderer =
+ new TIHardwareRenderer(
+ mISurface, mVideoWidth, mVideoHeight,
+ decodedWidth, decodedHeight);
} else {
LOGW("Using software renderer.");
mRenderer = new SoftwareRenderer(
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index c059a9d..5e44999 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -20,6 +20,7 @@
#undef NDEBUG
#include <assert.h>
+#include <ctype.h>
#include <OMX_Component.h>
@@ -54,14 +55,20 @@ struct CodecInfo {
};
static const CodecInfo kDecoderInfo[] = {
+ { "audio/mpeg", "OMX.TI.MP3.decode" },
{ "audio/mpeg", "OMX.PV.mp3dec" },
+ { "audio/3gpp", "OMX.TI.AMR.decode" },
{ "audio/3gpp", "OMX.PV.amrdec" },
+ { "audio/mp4a-latm", "OMX.TI.AAC.decode" },
{ "audio/mp4a-latm", "OMX.PV.aacdec" },
{ "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" },
+ { "video/mp4v-es", "OMX.TI.Video.Decoder" },
{ "video/mp4v-es", "OMX.PV.mpeg4dec" },
{ "video/3gpp", "OMX.qcom.video.decoder.h263" },
+ { "video/3gpp", "OMX.TI.Video.Decoder" },
{ "video/3gpp", "OMX.PV.h263dec" },
{ "video/avc", "OMX.qcom.video.decoder.avc" },
+ { "video/avc", "OMX.TI.Video.Decoder" },
{ "video/avc", "OMX.PV.avcdec" },
};
@@ -92,7 +99,9 @@ static const char *GetCodec(const CodecInfo *info, size_t numInfos,
}
// static
-OMXDecoder *OMXDecoder::Create(OMXClient *client, const sp<MetaData> &meta) {
+OMXDecoder *OMXDecoder::Create(
+ OMXClient *client, const sp<MetaData> &meta,
+ bool createEncoder) {
const char *mime;
bool success = meta->findCString(kKeyMIMEType, &mime);
assert(success);
@@ -102,9 +111,15 @@ OMXDecoder *OMXDecoder::Create(OMXClient *client, const sp<MetaData> &meta) {
const char *codec = NULL;
IOMX::node_id node = 0;
for (int index = 0;; ++index) {
- codec = GetCodec(
- kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
- mime, index);
+ if (createEncoder) {
+ codec = GetCodec(
+ kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
+ mime, index);
+ } else {
+ codec = GetCodec(
+ kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
+ mime, index);
+ }
if (!codec) {
return NULL;
@@ -118,7 +133,33 @@ OMXDecoder *OMXDecoder::Create(OMXClient *client, const sp<MetaData> &meta) {
}
}
- OMXDecoder *decoder = new OMXDecoder(client, node, mime, codec);
+ uint32_t quirks = 0;
+ if (!strcmp(codec, "OMX.PV.avcdec")) {
+ quirks |= kWantsRawNALFrames;
+ }
+ if (!strcmp(codec, "OMX.TI.AAC.decode")
+ || !strcmp(codec, "OMX.TI.MP3.decode")) {
+ quirks |= kDoesntReturnBuffersOnDisable;
+ }
+ if (!strcmp(codec, "OMX.TI.AAC.decode")) {
+ quirks |= kDoesntFlushOnExecutingToIdle;
+ quirks |= kDoesntProperlyFlushAllPortsAtOnce;
+ }
+ if (!strncmp(codec, "OMX.qcom.video.encoder.", 23)) {
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ }
+ if (!strncmp(codec, "OMX.qcom.video.decoder.", 23)) {
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ }
+ if (!strncmp(codec, "OMX.qcom.video.", 15)) {
+ quirks |= kRequiresLoadedToIdleAfterAllocation;
+ }
+ if (!strcmp(codec, "OMX.TI.AAC.decode")
+ || !strcmp(codec, "OMX.TI.MP3.decode")) {
+ quirks |= kMeasuresTimeInMilliseconds;
+ }
+
+ OMXDecoder *decoder = new OMXDecoder(client, node, mime, codec, quirks);
uint32_t type;
const void *data;
@@ -169,52 +210,22 @@ OMXDecoder *OMXDecoder::Create(OMXClient *client, const sp<MetaData> &meta) {
return decoder;
}
-// static
-OMXDecoder *OMXDecoder::CreateEncoder(
- OMXClient *client, const sp<MetaData> &meta) {
- const char *mime;
- bool success = meta->findCString(kKeyMIMEType, &mime);
- assert(success);
-
- sp<IOMX> omx = client->interface();
-
- const char *codec = NULL;
- IOMX::node_id node = 0;
- for (int index = 0;; ++index) {
- codec = GetCodec(
- kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
- mime, index);
-
- if (!codec) {
- return NULL;
- }
-
- LOGI("Attempting to allocate OMX node '%s'", codec);
-
- status_t err = omx->allocate_node(codec, &node);
- if (err == OK) {
- break;
- }
- }
-
- OMXDecoder *encoder = new OMXDecoder(client, node, mime, codec);
-
- return encoder;
-}
-
OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node,
- const char *mime, const char *codec)
+ const char *mime, const char *codec,
+ uint32_t quirks)
: mClient(client),
mOMX(mClient->interface()),
mNode(node),
mComponentName(strdup(codec)),
mIsMP3(!strcasecmp(mime, "audio/mpeg")),
+ mIsAVC(!strcasecmp(mime, "video/avc")),
+ mQuirks(quirks),
mSource(NULL),
mCodecSpecificDataIterator(mCodecSpecificData.begin()),
mState(OMX_StateLoaded),
mPortStatusMask(kPortStatusActive << 2 | kPortStatusActive),
mShutdownInitiated(false),
- mDealer(new MemoryDealer(3 * 1024 * 1024)),
+ mDealer(new MemoryDealer(5 * 1024 * 1024)),
mSeeking(false),
mStarted(false),
mErrorCondition(OK),
@@ -261,7 +272,7 @@ status_t OMXDecoder::start(MetaData *) {
// mDealer->dump("Decoder Dealer");
sp<MetaData> params = new MetaData;
- if (!strcmp(mComponentName, "OMX.qcom.video.decoder.avc")) {
+ if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
params->setInt32(kKeyNeedsNALFraming, true);
}
@@ -297,7 +308,7 @@ status_t OMXDecoder::stop() {
}
int attempt = 1;
- while (mState != OMX_StateLoaded && attempt < 10) {
+ while (mState != OMX_StateLoaded && attempt < 20) {
usleep(100000);
++attempt;
@@ -366,7 +377,11 @@ status_t OMXDecoder::read(
mOutputBuffers.erase(mOutputBuffers.begin());
}
- status_t err = mOMX->send_command(mNode, OMX_CommandFlush, -1);
+ // XXX One of TI's decoders appears to ignore a flush if it doesn't
+ // currently hold on to any buffers on the port in question and
+ // never sends the completion event... FIXME
+
+ status_t err = mOMX->send_command(mNode, OMX_CommandFlush, OMX_ALL);
assert(err == OK);
// Once flushing is completed buffers will again be scheduled to be
@@ -472,9 +487,121 @@ void OMXDecoder::setAACFormat() {
assert(err == NO_ERROR);
}
-void OMXDecoder::setVideoOutputFormat(OMX_U32 width, OMX_U32 height) {
+status_t OMXDecoder::setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat) {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ format.nSize = sizeof(format);
+ format.nVersion.s.nVersionMajor = 1;
+ format.nVersion.s.nVersionMinor = 1;
+ format.nPortIndex = portIndex;
+ format.nIndex = 0;
+ bool found = false;
+
+ OMX_U32 index = 0;
+ for (;;) {
+ format.nIndex = index;
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+
+ // The following assertion is violated by TI's video decoder.
+ // assert(format.nIndex == index);
+
+ if (format.eCompressionFormat == compressionFormat
+ && format.eColorFormat == colorFormat) {
+ found = true;
+ break;
+ }
+
+ ++index;
+ }
+
+ if (!found) {
+ return UNKNOWN_ERROR;
+ }
+
+ status_t err = mOMX->set_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ return err;
+}
+
+#if 1
+void OMXDecoder::setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height) {
LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
+#if 1
+ // Enabling this code appears to be the right thing(tm), but,...
+ // the TI decoder then loses the ability to output YUV420 and only outputs
+ // YCbYCr (16bit)
+ if (!strcasecmp("video/avc", mime)) {
+ OMX_PARAM_COMPONENTROLETYPE role;
+ role.nSize = sizeof(role);
+ role.nVersion.s.nVersionMajor = 1;
+ role.nVersion.s.nVersionMinor = 1;
+ strncpy((char *)role.cRole, "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE - 1);
+ role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = mOMX->set_parameter(
+ mNode, OMX_IndexParamStandardComponentRole,
+ &role, sizeof(role));
+ assert(err == OK);
+ }
+#endif
+
+ OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
+ if (!strcasecmp("video/avc", mime)) {
+ compressionFormat = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp("video/mp4v-es", mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp("video/3gpp", mime)) {
+ compressionFormat = OMX_VIDEO_CodingH263;
+ } else {
+ assert(!"Should not be here. Not a supported video mime type.");
+ }
+
+ setVideoPortFormatType(
+ kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
+
+#if 1
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ format.nSize = sizeof(format);
+ format.nVersion.s.nVersionMajor = 1;
+ format.nVersion.s.nVersionMinor = 1;
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ assert(err == OK);
+
+ assert(format.eCompressionFormat == OMX_VIDEO_CodingUnused);
+
+ static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+ assert(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ assert(err == OK);
+ }
+#endif
+
OMX_PARAM_PORTDEFINITIONTYPE def;
OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
@@ -502,7 +629,7 @@ void OMXDecoder::setVideoOutputFormat(OMX_U32 width, OMX_U32 height) {
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
- // video_def.eCompressionFormat = OMX_VIDEO_CodingAVC;
+
video_def->eColorFormat = OMX_COLOR_FormatUnused;
err = mOMX->set_parameter(
@@ -522,21 +649,189 @@ void OMXDecoder::setVideoOutputFormat(OMX_U32 width, OMX_U32 height) {
assert(def.eDomain == OMX_PortDomainVideo);
+#if 0
def.nBufferSize =
(((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
+#endif
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
- video_def->nStride = width;
- // video_def->nSliceHeight = height;
- video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
-// video_def->eColorFormat = OMX_COLOR_FormatYUV420Planar;
err = mOMX->set_parameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
assert(err == NO_ERROR);
}
+#else
+static void hexdump(const void *_data, size_t size) {
+ char line[256];
+ char tmp[16];
+
+ const uint8_t *data = (const uint8_t *)_data;
+ size_t offset = 0;
+ while (offset < size) {
+ sprintf(line, "0x%04x ", offset);
+
+ size_t n = size - offset;
+ if (n > 16) {
+ n = 16;
+ }
+
+ for (size_t i = 0; i < 16; ++i) {
+ if (i == 8) {
+ strcat(line, " ");
+ }
+
+ if (offset + i < size) {
+ sprintf(tmp, "%02x ", data[offset + i]);
+ strcat(line, tmp);
+ } else {
+ strcat(line, " ");
+ }
+ }
+
+ strcat(line, " ");
+
+ for (size_t i = 0; i < n; ++i) {
+ if (isprint(data[offset + i])) {
+ sprintf(tmp, "%c", data[offset + i]);
+ strcat(line, tmp);
+ } else {
+ strcat(line, ".");
+ }
+ }
+
+ LOGI(line);
+
+ offset += 16;
+ }
+}
+
+static void DumpPortDefinitionType(const void *_param) {
+ OMX_PARAM_PORTDEFINITIONTYPE *param = (OMX_PARAM_PORTDEFINITIONTYPE *)_param;
+
+ LOGI("nPortIndex=%ld eDir=%s nBufferCountActual=%ld nBufferCountMin=%ld nBufferSize=%ld", param->nPortIndex, param->eDir == OMX_DirInput ? "input" : "output",
+ param->nBufferCountActual, param->nBufferCountMin, param->nBufferSize);
+
+ if (param->eDomain == OMX_PortDomainVideo) {
+ OMX_VIDEO_PORTDEFINITIONTYPE *video = &param->format.video;
+ LOGI("nFrameWidth=%ld nFrameHeight=%ld nStride=%ld nSliceHeight=%ld nBitrate=%ld xFramerate=%ld eCompressionFormat=%d eColorFormat=%d",
+ video->nFrameWidth, video->nFrameHeight, video->nStride, video->nSliceHeight, video->nBitrate, video->xFramerate, video->eCompressionFormat, video->eColorFormat);
+ } else {
+ hexdump(param, param->nSize);
+ }
+}
+
+void OMXDecoder::setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height) {
+ LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
+
+#if 0
+ // Enabling this code appears to be the right thing(tm), but,...
+ // the decoder then loses the ability to output YUV420 and only outputs
+ // YCbYCr (16bit)
+ {
+ OMX_PARAM_COMPONENTROLETYPE role;
+ role.nSize = sizeof(role);
+ role.nVersion.s.nVersionMajor = 1;
+ role.nVersion.s.nVersionMinor = 1;
+ strncpy((char *)role.cRole, "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE - 1);
+ role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = mOMX->set_parameter(
+ mNode, OMX_IndexParamStandardComponentRole,
+ &role, sizeof(role));
+ assert(err == OK);
+ }
+#endif
+
+ setVideoPortFormatType(
+ kPortIndexInput, OMX_VIDEO_CodingAVC, OMX_COLOR_FormatUnused);
+
+#if 1
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ format.nSize = sizeof(format);
+ format.nVersion.s.nVersionMajor = 1;
+ format.nVersion.s.nVersionMinor = 1;
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ assert(err == OK);
+
+ LOGI("XXX MyOMX_GetParameter OMX_IndexParamVideoPortFormat");
+ hexdump(&format, format.nSize);
+
+ assert(format.eCompressionFormat == OMX_VIDEO_CodingUnused);
+ assert(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatCbYCrY);
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ assert(err == OK);
+ }
+#endif
+
+ OMX_PORT_PARAM_TYPE ptype;
+ ptype.nSize = sizeof(ptype);
+ ptype.nVersion.s.nVersionMajor = 1;
+ ptype.nVersion.s.nVersionMinor = 1;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoInit, &ptype, sizeof(ptype));
+ assert(err == OK);
+
+ LOGI("XXX MyOMX_GetParameter OMX_IndexParamVideoInit");
+ hexdump(&ptype, ptype.nSize);
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexInput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ assert(err == OK);
+
+ LOGI("XXX MyOMX_GetParameter OMX_IndexParamPortDefinition");
+ DumpPortDefinitionType(&def);
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ assert(err == OK);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ assert(err == OK);
+
+ LOGI("XXX MyOMX_GetParameter OMX_IndexParamPortDefinition");
+ DumpPortDefinitionType(&def);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ assert(err == OK);
+}
+
+#endif
+
void OMXDecoder::setup() {
const sp<MetaData> &meta = mSource->getFormat();
@@ -554,7 +849,7 @@ void OMXDecoder::setup() {
success = success && meta->findInt32(kKeyHeight, &height);
assert(success);
- setVideoOutputFormat(width, height);
+ setVideoOutputFormat(mime, width, height);
}
// dumpPortDefinition(0);
@@ -644,10 +939,7 @@ void OMXDecoder::setup() {
}
void OMXDecoder::onStart() {
- bool needs_qcom_hack =
- !strncmp(mComponentName, "OMX.qcom.video.", 15);
-
- if (!needs_qcom_hack) {
+ if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
status_t err =
mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
assert(err == NO_ERROR);
@@ -656,7 +948,7 @@ void OMXDecoder::onStart() {
allocateBuffers(kPortIndexInput);
allocateBuffers(kPortIndexOutput);
- if (needs_qcom_hack) {
+ if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
// XXX this should happen before AllocateBuffers, but qcom's
// h264 vdec disagrees.
status_t err =
@@ -691,13 +983,17 @@ void OMXDecoder::allocateBuffers(OMX_U32 port_index) {
for (OMX_U32 i = 0; i < num_buffers; ++i) {
sp<IMemory> mem = mDealer->allocate(buffer_size);
+ if (mem.get() == NULL) {
+ LOGE("[%s] allocating IMemory of size %ld FAILED.",
+ mComponentName, buffer_size);
+ }
assert(mem.get() != NULL);
IOMX::buffer_id buffer;
status_t err;
if (port_index == kPortIndexInput
- && !strncmp(mComponentName, "OMX.qcom.video.encoder.", 23)) {
+ && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
// qcom's H.263 encoder appears to want to allocate its own input
// buffers.
err = mOMX->allocate_buffer_with_backup(mNode, port_index, mem, &buffer);
@@ -706,7 +1002,7 @@ void OMXDecoder::allocateBuffers(OMX_U32 port_index) {
mComponentName, err);
}
} else if (port_index == kPortIndexOutput
- && !strncmp(mComponentName, "OMX.qcom.video.decoder.", 23)) {
+ && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
#if 1
err = mOMX->allocate_buffer_with_backup(mNode, port_index, mem, &buffer);
#else
@@ -817,18 +1113,59 @@ void OMXDecoder::onEventCmdComplete(OMX_COMMANDTYPE type, OMX_U32 data) {
case OMX_CommandFlush: {
OMX_U32 port_index = data;
LOGV("Port %ld flush complete.", port_index);
- assert(getPortStatus(port_index) == kPortStatusFlushing);
- setPortStatus(port_index, kPortStatusActive);
- BufferList *buffers = &mBuffers.editItemAt(port_index);
- while (!buffers->empty()) {
- IOMX::buffer_id buffer = *buffers->begin();
- buffers->erase(buffers->begin());
-
- if (port_index == kPortIndexInput) {
- postEmptyBufferDone(buffer);
- } else {
- postInitialFillBuffer(buffer);
+ PortStatus status = getPortStatus(port_index);
+
+ assert(status == kPortStatusFlushing
+ || status == kPortStatusFlushingToDisabled
+ || status == kPortStatusFlushingToShutdown);
+
+ switch (status) {
+ case kPortStatusFlushing:
+ {
+ // This happens when we're flushing before a seek.
+ setPortStatus(port_index, kPortStatusActive);
+ BufferList *buffers = &mBuffers.editItemAt(port_index);
+ while (!buffers->empty()) {
+ IOMX::buffer_id buffer = *buffers->begin();
+ buffers->erase(buffers->begin());
+
+ if (port_index == kPortIndexInput) {
+ postEmptyBufferDone(buffer);
+ } else {
+ postInitialFillBuffer(buffer);
+ }
+ }
+ break;
+ }
+
+ case kPortStatusFlushingToDisabled:
+ {
+ // Port settings have changed and the (buggy) OMX component
+ // does not properly return buffers on disabling, we need to
+ // do a flush first and _then_ disable the port in question.
+
+ setPortStatus(port_index, kPortStatusDisabled);
+ status_t err = mOMX->send_command(
+ mNode, OMX_CommandPortDisable, port_index);
+ assert(err == OK);
+
+ freePortBuffers(port_index);
+ break;
+ }
+
+ default:
+ {
+ assert(status == kPortStatusFlushingToShutdown);
+
+ setPortStatus(port_index, kPortStatusShutdown);
+ if (getPortStatus(kPortIndexInput) == kPortStatusShutdown
+ && getPortStatus(kPortIndexOutput) == kPortStatusShutdown) {
+ status_t err = mOMX->send_command(
+ mNode, OMX_CommandStateSet, OMX_StateIdle);
+ assert(err == OK);
+ }
+ break;
}
}
break;
@@ -841,10 +1178,22 @@ void OMXDecoder::onEventCmdComplete(OMX_COMMANDTYPE type, OMX_U32 data) {
void OMXDecoder::onEventPortSettingsChanged(OMX_U32 port_index) {
assert(getPortStatus(port_index) == kPortStatusActive);
- setPortStatus(port_index, kPortStatusDisabled);
- status_t err =
- mOMX->send_command(mNode, OMX_CommandPortDisable, port_index);
+ status_t err;
+
+ if (mQuirks & kDoesntReturnBuffersOnDisable) {
+ // Decoder does not properly return our buffers when disabled...
+ // Need to flush port instead and _then_ disable.
+
+ setPortStatus(port_index, kPortStatusFlushingToDisabled);
+
+ err = mOMX->send_command(mNode, OMX_CommandFlush, port_index);
+ } else {
+ setPortStatus(port_index, kPortStatusDisabled);
+
+ err = mOMX->send_command(mNode, OMX_CommandPortDisable, port_index);
+ }
+
assert(err == NO_ERROR);
}
@@ -894,19 +1243,8 @@ void OMXDecoder::onStateChanged(OMX_STATETYPE to) {
mClient->send_command(mNode, OMX_CommandStateSet, OMX_StateLoaded);
assert(err == NO_ERROR);
- BufferList *ibuffers = &mBuffers.editItemAt(kPortIndexInput);
- for (BufferList::iterator it = ibuffers->begin();
- it != ibuffers->end(); ++it) {
- freeInputBuffer(*it);
- }
- ibuffers->clear();
-
- BufferList *obuffers = &mBuffers.editItemAt(kPortIndexOutput);
- for (BufferList::iterator it = obuffers->begin();
- it != obuffers->end(); ++it) {
- freeOutputBuffer(*it);
- }
- obuffers->clear();
+ freePortBuffers(kPortIndexInput);
+ freePortBuffers(kPortIndexOutput);
}
}
@@ -925,26 +1263,41 @@ void OMXDecoder::initiateShutdown() {
mShutdownInitiated = true;
- status_t err =
- mClient->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
- assert(err == NO_ERROR);
+ status_t err;
+ if (mQuirks & kDoesntFlushOnExecutingToIdle) {
+ if (mQuirks & kDoesntProperlyFlushAllPortsAtOnce) {
+ err = mOMX->send_command(mNode, OMX_CommandFlush, kPortIndexInput);
+ assert(err == OK);
- setPortStatus(kPortIndexInput, kPortStatusShutdown);
- setPortStatus(kPortIndexOutput, kPortStatusShutdown);
+ err = mOMX->send_command(mNode, OMX_CommandFlush, kPortIndexOutput);
+ } else {
+ err = mOMX->send_command(mNode, OMX_CommandFlush, OMX_ALL);
+ }
+
+ setPortStatus(kPortIndexInput, kPortStatusFlushingToShutdown);
+ setPortStatus(kPortIndexOutput, kPortStatusFlushingToShutdown);
+ } else {
+ err = mClient->send_command(
+ mNode, OMX_CommandStateSet, OMX_StateIdle);
+
+ setPortStatus(kPortIndexInput, kPortStatusShutdown);
+ setPortStatus(kPortIndexOutput, kPortStatusShutdown);
+ }
+ assert(err == OK);
}
void OMXDecoder::setPortStatus(OMX_U32 port_index, PortStatus status) {
- int shift = 2 * port_index;
+ int shift = 3 * port_index;
- mPortStatusMask &= ~(3 << shift);
+ mPortStatusMask &= ~(7 << shift);
mPortStatusMask |= status << shift;
}
OMXDecoder::PortStatus OMXDecoder::getPortStatus(
OMX_U32 port_index) const {
- int shift = 2 * port_index;
+ int shift = 3 * port_index;
- return static_cast<PortStatus>((mPortStatusMask >> shift) & 3);
+ return static_cast<PortStatus>((mPortStatusMask >> shift) & 7);
}
void OMXDecoder::onEmptyBufferDone(IOMX::buffer_id buffer) {
@@ -964,6 +1317,8 @@ void OMXDecoder::onEmptyBufferDone(IOMX::buffer_id buffer) {
break;
case kPortStatusFlushing:
+ case kPortStatusFlushingToDisabled:
+ case kPortStatusFlushingToShutdown:
LOGV("We're currently flushing, enqueue INPUT buffer %p.", buffer);
mBuffers.editItemAt(kPortIndexInput).push_back(buffer);
err = NO_ERROR;
@@ -980,7 +1335,9 @@ void OMXDecoder::onEmptyBufferDone(IOMX::buffer_id buffer) {
void OMXDecoder::onFillBufferDone(const omx_message &msg) {
IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
- LOGV("[%s] onFillBufferDone (%p)", mComponentName, buffer);
+ LOGV("[%s] on%sFillBufferDone (%p, size:%ld)", mComponentName,
+ msg.type == omx_message::INITIAL_FILL_BUFFER ? "Initial" : "",
+ buffer, msg.u.extended_buffer_data.range_length);
status_t err;
switch (getPortStatus(kPortIndexOutput)) {
@@ -995,6 +1352,8 @@ void OMXDecoder::onFillBufferDone(const omx_message &msg) {
break;
case kPortStatusFlushing:
+ case kPortStatusFlushingToDisabled:
+ case kPortStatusFlushingToShutdown:
LOGV("We're currently flushing, enqueue OUTPUT buffer %p.", buffer);
mBuffers.editItemAt(kPortIndexOutput).push_back(buffer);
err = NO_ERROR;
@@ -1035,7 +1394,7 @@ void OMXDecoder::onRealEmptyBufferDone(IOMX::buffer_id buffer) {
size_t range_length = 0;
- if (!strcmp(mComponentName, "OMX.qcom.video.decoder.avc")) {
+ if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
assert((*mCodecSpecificDataIterator).size + 4 <= mem->size());
memcpy(mem->pointer(), kNALStartCode, 4);
@@ -1142,15 +1501,18 @@ void OMXDecoder::onRealEmptyBufferDone(IOMX::buffer_id buffer) {
OMX_TICKS timestamp = 0;
if (success) {
- // XXX units should be microseconds but PV treats them as milliseconds.
- timestamp = ((OMX_S64)units * 1000) / scale;
+ if (mQuirks & kMeasuresTimeInMilliseconds) {
+ timestamp = ((OMX_S64)units * 1000) / scale;
+ } else {
+ timestamp = ((OMX_S64)units * 1000000) / scale;
+ }
}
input_buffer->release();
input_buffer = NULL;
- LOGV("[%s] Calling EmptyBuffer on buffer %p",
- mComponentName, buffer);
+ LOGV("[%s] Calling EmptyBuffer on buffer %p size:%d flags:0x%08lx",
+ mComponentName, buffer, src_length, flags);
status_t err2 = mClient->emptyBuffer(
mNode, buffer, 0, src_length, flags, timestamp);
@@ -1169,8 +1531,16 @@ void OMXDecoder::onRealFillBufferDone(const omx_message &msg) {
media_buffer->meta_data()->clear();
- media_buffer->meta_data()->setInt32(
- kKeyTimeUnits, msg.u.extended_buffer_data.timestamp);
+ if (mQuirks & kMeasuresTimeInMilliseconds) {
+ media_buffer->meta_data()->setInt32(
+ kKeyTimeUnits,
+ msg.u.extended_buffer_data.timestamp);
+ } else {
+ media_buffer->meta_data()->setInt32(
+ kKeyTimeUnits,
+ (msg.u.extended_buffer_data.timestamp + 500) / 1000);
+ }
+
media_buffer->meta_data()->setInt32(kKeyTimeScale, 1000);
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
@@ -1198,7 +1568,9 @@ void OMXDecoder::signalBufferReturned(MediaBuffer *_buffer) {
PortStatus outputStatus = getPortStatus(kPortIndexOutput);
if (outputStatus == kPortStatusShutdown
- || outputStatus == kPortStatusFlushing) {
+ || outputStatus == kPortStatusFlushing
+ || outputStatus == kPortStatusFlushingToDisabled
+ || outputStatus == kPortStatusFlushingToShutdown) {
mBuffers.editItemAt(kPortIndexOutput).push_back(buffer);
} else {
LOGV("[%s] Calling FillBuffer on buffer %p.", mComponentName, buffer);
@@ -1326,4 +1698,18 @@ void OMXDecoder::postInitialFillBuffer(IOMX::buffer_id buffer) {
postMessage(msg);
}
+void OMXDecoder::freePortBuffers(OMX_U32 port_index) {
+ BufferList *buffers = &mBuffers.editItemAt(port_index);
+ while (!buffers->empty()) {
+ IOMX::buffer_id buffer = *buffers->begin();
+ buffers->erase(buffers->begin());
+
+ if (port_index == kPortIndexInput) {
+ freeInputBuffer(buffer);
+ } else {
+ freeOutputBuffer(buffer);
+ }
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/TIHardwareRenderer.cpp b/media/libstagefright/TIHardwareRenderer.cpp
new file mode 100644
index 0000000..ba42ef4
--- /dev/null
+++ b/media/libstagefright/TIHardwareRenderer.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "TIHardwareRenderer"
+#include <utils/Log.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+#include <media/stagefright/TIHardwareRenderer.h>
+#include <ui/ISurface.h>
+#include <ui/Overlay.h>
+
+namespace android {
+
+////////////////////////////////////////////////////////////////////////////////
+
+TIHardwareRenderer::TIHardwareRenderer(
+ const sp<ISurface> &surface,
+ size_t displayWidth, size_t displayHeight,
+ size_t decodedWidth, size_t decodedHeight)
+ : mISurface(surface),
+ mDisplayWidth(displayWidth),
+ mDisplayHeight(displayHeight),
+ mDecodedWidth(decodedWidth),
+ mDecodedHeight(decodedHeight),
+ mFrameSize((mDecodedWidth * mDecodedHeight * 3) / 2) {
+ assert(mISurface.get() != NULL);
+ assert(mDecodedWidth > 0);
+ assert(mDecodedHeight > 0);
+
+ sp<OverlayRef> ref = mISurface->createOverlay(
+ mDisplayWidth, mDisplayHeight, OVERLAY_FORMAT_CbYCrY_422_I);
+
+ if (ref.get() == NULL) {
+ LOGE("Unable to create the overlay!");
+ return;
+ }
+
+ mOverlay = new Overlay(ref);
+
+ for (size_t i = 0; i < mOverlay->getBufferCount(); ++i) {
+ mOverlayAddresses.push(mOverlay->getBufferAddress((void *)i));
+ }
+ mIndex = mOverlayAddresses.size() - 1;
+}
+
+TIHardwareRenderer::~TIHardwareRenderer() {
+ if (mOverlay.get() != NULL) {
+ mOverlay->destroy();
+ mOverlay.clear();
+
+ // XXX apparently destroying an overlay is an asynchronous process...
+ sleep(1);
+ }
+}
+
+void TIHardwareRenderer::render(
+ const void *data, size_t size, void *platformPrivate) {
+ // assert(size == mFrameSize);
+
+ if (mOverlay.get() == NULL) {
+ return;
+ }
+
+#if 0
+ overlay_buffer_t buffer;
+ if (mOverlay->dequeueBuffer(&buffer) == OK) {
+ void *addr = mOverlay->getBufferAddress(buffer);
+
+ memcpy(addr, data, size);
+
+ mOverlay->queueBuffer(buffer);
+ }
+#else
+ memcpy(mOverlayAddresses[mIndex], data, size);
+ mOverlay->queueBuffer((void *)mIndex);
+
+ if (mIndex-- == 0) {
+ mIndex = mOverlayAddresses.size() - 1;
+ }
+#endif
+}
+
+} // namespace android
+
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 7afcae7..b0e54d8 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -216,8 +216,8 @@ struct egl_window_surface_v2_t : public egl_surface_t
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
virtual void connect();
virtual void disconnect();
- virtual EGLint getWidth() const { return buffer->width; }
- virtual EGLint getHeight() const { return buffer->height; }
+ virtual EGLint getWidth() const { return width; }
+ virtual EGLint getHeight() const { return height; }
virtual EGLint getHorizontalResolution() const;
virtual EGLint getVerticalResolution() const;
virtual EGLint getRefreshRate() const;
@@ -365,14 +365,32 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
// keep a reference on the window
nativeWindow->common.incRef(&nativeWindow->common);
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width);
+ nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height);
+}
+egl_window_surface_v2_t::~egl_window_surface_v2_t() {
+ if (buffer) {
+ buffer->common.decRef(&buffer->common);
+ }
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ }
+ nativeWindow->common.decRef(&nativeWindow->common);
+ if (blitengine) {
+ copybit_close(blitengine);
+ }
+}
+
+void egl_window_surface_v2_t::connect()
+{
// dequeue a buffer
nativeWindow->dequeueBuffer(nativeWindow, &buffer);
// allocate a corresponding depth-buffer
width = buffer->width;
height = buffer->height;
- if (depthFormat) {
+ if (depth.format) {
depth.width = width;
depth.height = height;
depth.stride = depth.width; // use the width here
@@ -385,23 +403,7 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy,
// keep a reference on the buffer
buffer->common.incRef(&buffer->common);
-}
-egl_window_surface_v2_t::~egl_window_surface_v2_t() {
- if (buffer) {
- buffer->common.decRef(&buffer->common);
- }
- if (previousBuffer) {
- previousBuffer->common.decRef(&previousBuffer->common);
- }
- nativeWindow->common.decRef(&nativeWindow->common);
- if (blitengine) {
- copybit_close(blitengine);
- }
-}
-
-void egl_window_surface_v2_t::connect()
-{
// Lock the buffer
nativeWindow->lockBuffer(nativeWindow, buffer);
// pin the buffer down
@@ -420,6 +422,16 @@ void egl_window_surface_v2_t::disconnect()
bits = NULL;
unlock(buffer);
}
+ // enqueue the last frame
+ nativeWindow->queueBuffer(nativeWindow, buffer);
+ if (buffer) {
+ buffer->common.decRef(&buffer->common);
+ buffer = 0;
+ }
+ if (previousBuffer) {
+ previousBuffer->common.decRef(&previousBuffer->common);
+ previousBuffer = 0;
+ }
}
status_t egl_window_surface_v2_t::lock(
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 7f3f114..445e681 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -149,7 +149,7 @@ void* Loader::open(EGLNativeDisplayType display, int impl, gl_hooks_t* hooks)
hnd = new driver_t(dso);
} else {
// Always load EGL first
- snprintf(path, PATH_MAX, "lib%s_%s.so", "EGL", tag);
+ snprintf(path, PATH_MAX, format, "EGL", tag);
dso = load_driver(path, hooks, EGL);
if (dso) {
hnd = new driver_t(dso);
diff --git a/packages/SettingsProvider/res/values-cs/defaults.xml b/packages/SettingsProvider/res/values-cs/defaults.xml
deleted file mode 100644
index a7c01b3..0000000
--- a/packages/SettingsProvider/res/values-cs/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"mobil,bluetooth,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml
index dc75a92..2b089d9 100644
--- a/packages/SettingsProvider/res/values-cs/strings.xml
+++ b/packages/SettingsProvider/res/values-cs/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Paměť pro nastavení"</string>
+ <string name="app_label" msgid="4567566098528588863">"Paměť pro nastavení"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-de/defaults.xml b/packages/SettingsProvider/res/values-de/defaults.xml
deleted file mode 100644
index f85d3f0..0000000
--- a/packages/SettingsProvider/res/values-de/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"Mobilfunk, Bluetooth, WLAN"</string>
- <string name="def_location_providers_allowed">"GPS"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml
index 50c8a14..a293522 100644
--- a/packages/SettingsProvider/res/values-de/strings.xml
+++ b/packages/SettingsProvider/res/values-de/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Einstellungsspeicher"</string>
+ <string name="app_label" msgid="4567566098528588863">"Einstellungsspeicher"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-es/defaults.xml b/packages/SettingsProvider/res/values-es/defaults.xml
deleted file mode 100644
index a64805a..0000000
--- a/packages/SettingsProvider/res/values-es/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"móvil,bluetooth,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml
index d30d195..de3958b 100644
--- a/packages/SettingsProvider/res/values-es/strings.xml
+++ b/packages/SettingsProvider/res/values-es/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Almacenamiento de configuración"</string>
+ <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml
index 686ec8b..7a1386a 100644
--- a/packages/SettingsProvider/res/values-fr/strings.xml
+++ b/packages/SettingsProvider/res/values-fr/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Stockage des paramètres"</string>
+ <string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-it/defaults.xml b/packages/SettingsProvider/res/values-it/defaults.xml
deleted file mode 100644
index 19c0896..0000000
--- a/packages/SettingsProvider/res/values-it/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"cellulare,bluetooth,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index 29e462f..f88a654 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Archiviazione impostazioni"</string>
+ <string name="app_label" msgid="4567566098528588863">"Archiviazione impostazioni"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-nl/defaults.xml b/packages/SettingsProvider/res/values-nl/defaults.xml
deleted file mode 100644
index 625235a..0000000
--- a/packages/SettingsProvider/res/values-nl/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"mobiel,bluetooth,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml
index b37b535..7a0e416 100644
--- a/packages/SettingsProvider/res/values-nl/strings.xml
+++ b/packages/SettingsProvider/res/values-nl/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Opslagruimte voor instellingen"</string>
+ <string name="app_label" msgid="4567566098528588863">"Opslagruimte voor instellingen"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-pl/defaults.xml b/packages/SettingsProvider/res/values-pl/defaults.xml
deleted file mode 100644
index b60832e..0000000
--- a/packages/SettingsProvider/res/values-pl/defaults.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"komórka,bluetooth,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml
index 4ab1e91..ccff82e3 100644
--- a/packages/SettingsProvider/res/values-pl/strings.xml
+++ b/packages/SettingsProvider/res/values-pl/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"Pamięć ustawień"</string>
+ <string name="app_label" msgid="4567566098528588863">"Pamięć ustawień"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
index b24144a..0700a76 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
@@ -15,5 +15,5 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label">"設定儲存空間"</string>
+ <string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
</resources>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index af02741..6b20445 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -21,7 +21,8 @@
<integer name="def_screen_off_timeout">60000</integer>
<bool name="def_airplane_mode_on">false</bool>
<!-- Comma-separated list of bluetooth, wifi, and cell. -->
- <string name="def_airplane_mode_radios">cell,bluetooth,wifi</string>
+ <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string>
+ <string name="airplane_mode_toggleable_radios" translatable="false">wifi</string>
<bool name="def_auto_time">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
@@ -35,7 +36,7 @@
Network location is off by default because it requires
user opt-in via Setup Wizard or Settings.
-->
- <string name="def_location_providers_allowed">gps</string>
+ <string name="def_location_providers_allowed" translatable="false">gps</string>
<bool name="assisted_gps_enabled">true</bool>
<!-- 0 == mobile, 1 == wifi. -->
<integer name="def_network_preference">1</integer>
@@ -44,5 +45,5 @@
<bool name="def_networks_available_notification_on">true</bool>
<bool name="def_backup_enabled">false</bool>
- <string name="def_backup_transport"></string>
+ <string name="def_backup_transport" translatable="false"></string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index f00fd39..835c683 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -64,7 +64,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "SettingsProvider";
private static final String DATABASE_NAME = "settings.db";
- private static final int DATABASE_VERSION = 37;
+ private static final int DATABASE_VERSION = 38;
private Context mContext;
@@ -435,6 +435,21 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 36;
}
+ if (upgradeVersion == 37) {
+ db.beginTransaction();
+ try {
+ SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ + " VALUES(?,?);");
+ loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+ R.string.airplane_mode_toggleable_radios);
+ stmt.close();
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ upgradeVersion = 38;
+ }
+
if (upgradeVersion != currentVersion) {
Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
+ ", must wipe the settings provider");
@@ -662,6 +677,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
R.string.def_airplane_mode_radios);
+ loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+ R.string.airplane_mode_toggleable_radios);
+
loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
R.bool.def_auto_time); // Sync time to NITZ
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1451682..9877342 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -24,9 +24,11 @@ import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
+import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
@@ -397,12 +399,8 @@ public class SettingsProvider extends ContentProvider {
// Get the current value for the default sound
Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType);
- if (soundUri == null) {
- // Fallback on any valid ringtone Uri
- soundUri = RingtoneManager.getValidRingtoneUri(context);
- }
- if (soundUri != null) {
+ if (soundUri != null) {
// Only proxy the openFile call to drm or media providers
String authority = soundUri.getAuthority();
boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY);
@@ -426,4 +424,64 @@ public class SettingsProvider extends ContentProvider {
return super.openFile(uri, mode);
}
+
+ @Override
+ public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
+
+ /*
+ * When a client attempts to openFile the default ringtone or
+ * notification setting Uri, we will proxy the call to the current
+ * default ringtone's Uri (if it is in the DRM or media provider).
+ */
+ int ringtoneType = RingtoneManager.getDefaultType(uri);
+ // Above call returns -1 if the Uri doesn't match a default type
+ if (ringtoneType != -1) {
+ Context context = getContext();
+
+ // Get the current value for the default sound
+ Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType);
+
+ if (soundUri != null) {
+ // Only proxy the openFile call to drm or media providers
+ String authority = soundUri.getAuthority();
+ boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY);
+ if (isDrmAuthority || authority.equals(MediaStore.AUTHORITY)) {
+
+ if (isDrmAuthority) {
+ try {
+ // Check DRM access permission here, since once we
+ // do the below call the DRM will be checking our
+ // permission, not our caller's permission
+ DrmStore.enforceAccessDrmPermission(context);
+ } catch (SecurityException e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+ }
+
+ ParcelFileDescriptor pfd = null;
+ try {
+ pfd = context.getContentResolver().openFileDescriptor(soundUri, mode);
+ return new AssetFileDescriptor(pfd, 0, -1);
+ } catch (FileNotFoundException ex) {
+ // fall through and open the fallback ringtone below
+ }
+ }
+
+ try {
+ return super.openAssetFile(soundUri, mode);
+ } catch (FileNotFoundException ex) {
+ // Since a non-null Uri was specified, but couldn't be opened,
+ // fall back to the built-in ringtone.
+ return context.getResources().openRawResourceFd(
+ com.android.internal.R.raw.fallbackring);
+ }
+ }
+ // no need to fall through and have openFile() try again, since we
+ // already know that will fail.
+ throw new FileNotFoundException(); // or return null ?
+ }
+
+ // Note that this will end up calling openFile() above.
+ return super.openAssetFile(uri, mode);
+ }
}
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 6832862..1b99d32 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -194,7 +194,7 @@ public class TtsService extends Service implements OnCompletionListener {
private boolean isDefaultEnforced() {
return (android.provider.Settings.Secure.getInt(mResolver,
android.provider.Settings.Secure.TTS_USE_DEFAULTS,
- TextToSpeech.Engine.FALLBACK_TTS_USE_DEFAULTS)
+ TextToSpeech.Engine.USE_DEFAULTS)
== 1 );
}
@@ -202,7 +202,7 @@ public class TtsService extends Service implements OnCompletionListener {
private int getDefaultRate() {
return android.provider.Settings.Secure.getInt(mResolver,
android.provider.Settings.Secure.TTS_DEFAULT_RATE,
- TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_RATE);
+ TextToSpeech.Engine.DEFAULT_RATE);
}
@@ -346,7 +346,7 @@ public class TtsService extends Service implements OnCompletionListener {
*/
private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) {
Log.v("TtsService", "TTS service received " + text);
- if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) {
+ if (queueMode == TextToSpeech.QUEUE_FLUSH) {
stop(callingApp);
} else if (queueMode == 2) {
stopAll(callingApp);
@@ -355,7 +355,7 @@ public class TtsService extends Service implements OnCompletionListener {
if (!mIsSpeaking) {
processSpeechQueue();
}
- return TextToSpeech.TTS_SUCCESS;
+ return TextToSpeech.SUCCESS;
}
/**
@@ -372,7 +372,7 @@ public class TtsService extends Service implements OnCompletionListener {
*/
private int playEarcon(String callingApp, String earcon, int queueMode,
ArrayList<String> params) {
- if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) {
+ if (queueMode == TextToSpeech.QUEUE_FLUSH) {
stop(callingApp);
} else if (queueMode == 2) {
stopAll(callingApp);
@@ -381,14 +381,14 @@ public class TtsService extends Service implements OnCompletionListener {
if (!mIsSpeaking) {
processSpeechQueue();
}
- return TextToSpeech.TTS_SUCCESS;
+ return TextToSpeech.SUCCESS;
}
/**
* Stops all speech output and removes any utterances still in the queue for the calling app.
*/
private int stop(String callingApp) {
- int result = TextToSpeech.TTS_ERROR;
+ int result = TextToSpeech.ERROR;
boolean speechQueueAvailable = false;
try{
speechQueueAvailable =
@@ -414,7 +414,7 @@ public class TtsService extends Service implements OnCompletionListener {
mIsSpeaking = false;
mCurrentSpeechItem = null;
} else {
- result = TextToSpeech.TTS_SUCCESS;
+ result = TextToSpeech.SUCCESS;
}
Log.i("TtsService", "Stopped");
}
@@ -437,7 +437,7 @@ public class TtsService extends Service implements OnCompletionListener {
* Stops all speech output and removes any utterances still in the queue globally.
*/
private int stopAll(String callingApp) {
- int result = TextToSpeech.TTS_ERROR;
+ int result = TextToSpeech.ERROR;
boolean speechQueueAvailable = false;
try{
speechQueueAvailable =
@@ -463,7 +463,7 @@ public class TtsService extends Service implements OnCompletionListener {
mIsSpeaking = false;
mCurrentSpeechItem = null;
} else {
- result = TextToSpeech.TTS_SUCCESS;
+ result = TextToSpeech.SUCCESS;
}
Log.i("TtsService", "Stopped all");
}
@@ -487,7 +487,7 @@ public class TtsService extends Service implements OnCompletionListener {
if (params != null){
for (int i = 0; i < params.size() - 1; i = i + 2){
String param = params.get(i);
- if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){
utteranceId = params.get(i+1);
}
}
@@ -500,14 +500,14 @@ public class TtsService extends Service implements OnCompletionListener {
private int playSilence(String callingApp, long duration, int queueMode,
ArrayList<String> params) {
- if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) {
+ if (queueMode == TextToSpeech.QUEUE_FLUSH) {
stop(callingApp);
}
mSpeechQueue.add(new SpeechItem(callingApp, duration, params));
if (!mIsSpeaking) {
processSpeechQueue();
}
- return TextToSpeech.TTS_SUCCESS;
+ return TextToSpeech.SUCCESS;
}
private void silence(final SpeechItem speechItem) {
@@ -517,7 +517,7 @@ public class TtsService extends Service implements OnCompletionListener {
if (speechItem.mParams != null){
for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
String param = speechItem.mParams.get(i);
- if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){
utteranceId = speechItem.mParams.get(i+1);
}
}
@@ -562,17 +562,17 @@ public class TtsService extends Service implements OnCompletionListener {
for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
String param = speechItem.mParams.get(i);
if (param != null) {
- if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) {
+ if (param.equals(TextToSpeech.Engine.KEY_PARAM_RATE)) {
speechRate = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_LANGUAGE)){
language = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_COUNTRY)){
country = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_VARIANT)){
variant = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){
utteranceId = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM)) {
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_STREAM)) {
try {
streamType
= Integer.parseInt(speechItem.mParams.get(i + 1));
@@ -638,15 +638,15 @@ public class TtsService extends Service implements OnCompletionListener {
for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
String param = speechItem.mParams.get(i);
if (param != null) {
- if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) {
+ if (param.equals(TextToSpeech.Engine.KEY_PARAM_RATE)) {
speechRate = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_LANGUAGE)){
language = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_COUNTRY)){
country = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_VARIANT)){
variant = speechItem.mParams.get(i+1);
- } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){
utteranceId = speechItem.mParams.get(i+1);
}
}
@@ -698,7 +698,7 @@ public class TtsService extends Service implements OnCompletionListener {
}
private void broadcastTtsQueueProcessingCompleted(){
- Intent i = new Intent(Intent.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
+ Intent i = new Intent(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
sendBroadcast(i);
}
@@ -843,7 +843,7 @@ public class TtsService extends Service implements OnCompletionListener {
}
for (int i = 0; i < paramList.size() - 1; i = i + 2) {
String param = paramList.get(i);
- if ((param != null) && (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM))) {
+ if ((param != null) && (param.equals(TextToSpeech.Engine.KEY_PARAM_STREAM))) {
try {
streamType = Integer.parseInt(paramList.get(i + 1));
} catch (NumberFormatException e) {
@@ -910,18 +910,18 @@ public class TtsService extends Service implements OnCompletionListener {
if (cb != null) {
mCallbacks.register(cb);
mCallbacksMap.put(packageName, cb);
- return TextToSpeech.TTS_SUCCESS;
+ return TextToSpeech.SUCCESS;
}
- return TextToSpeech.TTS_ERROR;
+ return TextToSpeech.ERROR;
}
public int unregisterCallback(String packageName, ITtsCallback cb) {
if (cb != null) {
mCallbacksMap.remove(packageName);
mCallbacks.unregister(cb);
- return TextToSpeech.TTS_SUCCESS;
+ return TextToSpeech.SUCCESS;
}
- return TextToSpeech.TTS_ERROR;
+ return TextToSpeech.ERROR;
}
/**
diff --git a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
index b749821..289ee45 100644
--- a/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
+++ b/packages/VpnServices/src/com/android/server/vpn/DaemonProxy.java
@@ -25,6 +25,7 @@ import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Serializable;
/**
* Proxy to start, stop and interact with a VPN daemon.
@@ -33,7 +34,10 @@ import java.io.OutputStream;
* connection with the daemon, to both send commands to the daemon and receive
* response and connecting error code from the daemon.
*/
-class DaemonProxy {
+class DaemonProxy implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private static final boolean DBG = true;
+
private static final int WAITING_TIME = 15; // sec
private static final String SVC_STATE_CMD_PREFIX = "init.svc.";
@@ -45,8 +49,8 @@ class DaemonProxy {
private static final int END_OF_ARGUMENTS = 255;
private String mName;
- private LocalSocket mControlSocket;
private String mTag;
+ private transient LocalSocket mControlSocket;
/**
* Creates a proxy of the specified daemon.
@@ -63,14 +67,8 @@ class DaemonProxy {
void start() throws IOException {
String svc = mName;
- Log.d(mTag, "----- Stop the daemon just in case: " + mName);
- SystemProperties.set(SVC_STOP_CMD, mName);
- if (!blockUntil(SVC_STATE_STOPPED, 5)) {
- throw new IOException("cannot start service anew: " + svc
- + ", it is still running");
- }
- Log.d(mTag, "+++++ Start: " + svc);
+ Log.i(mTag, "Start VPN daemon: " + svc);
SystemProperties.set(SVC_START_CMD, svc);
if (!blockUntil(SVC_STATE_RUNNING, WAITING_TIME)) {
@@ -103,7 +101,7 @@ class DaemonProxy {
try {
mControlSocket.close();
} catch (IOException e) {
- Log.e(mTag, "close control socket", e);
+ Log.w(mTag, "close control socket", e);
} finally {
mControlSocket = null;
}
@@ -111,10 +109,10 @@ class DaemonProxy {
void stop() {
String svc = mName;
- Log.d(mTag, "----- Stop: " + svc);
+ Log.i(mTag, "Stop VPN daemon: " + svc);
SystemProperties.set(SVC_STOP_CMD, svc);
boolean success = blockUntil(SVC_STATE_STOPPED, 5);
- Log.d(mTag, "stopping " + svc + ", success? " + success);
+ if (DBG) Log.d(mTag, "stopping " + svc + ", success? " + success);
}
boolean isStopped() {
@@ -129,7 +127,7 @@ class DaemonProxy {
if (!blocking && in.available() == 0) return 0;
int data = in.read();
- Log.d(mTag, "got data from control socket: " + data);
+ Log.i(mTag, "got data from control socket: " + data);
return data;
}
@@ -146,7 +144,7 @@ class DaemonProxy {
s.connect(a);
return s;
} catch (IOException e) {
- Log.d(mTag, "service not yet listen()ing; try again");
+ if (DBG) Log.d(mTag, "service not yet listen()ing; try again");
excp = e;
sleep(500);
}
@@ -173,8 +171,10 @@ class DaemonProxy {
int n = waitTime * 1000 / sleepTime;
for (int i = 0; i < n; i++) {
if (expectedState.equals(SystemProperties.get(cmd))) {
- Log.d(mTag, mName + " is " + expectedState + " after "
- + (i * sleepTime) + " msec");
+ if (DBG) {
+ Log.d(mTag, mName + " is " + expectedState + " after "
+ + (i * sleepTime) + " msec");
+ }
break;
}
sleep(sleepTime);
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
index 8efd7c4..7910f4a 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecPskService.java
@@ -45,4 +45,10 @@ class L2tpIpsecPskService extends VpnService<L2tpIpsecPskProfile> {
(p.isSecretEnabled() ? p.getSecretString() : null),
username, password);
}
+
+ @Override
+ protected void stopPreviouslyRunDaemons() {
+ stopDaemon(IPSEC);
+ stopDaemon(MtpdHelper.MTPD);
+ }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
index 56694b6..13b4952 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpIpsecService.java
@@ -46,6 +46,12 @@ class L2tpIpsecService extends VpnService<L2tpIpsecProfile> {
username, password);
}
+ @Override
+ protected void stopPreviouslyRunDaemons() {
+ stopDaemon(IPSEC);
+ stopDaemon(MtpdHelper.MTPD);
+ }
+
private String getCaCertPath() {
return CertTool.getInstance().getCaCertificate(
getProfile().getCaCertificate());
diff --git a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
index 9273f35..d658a36 100644
--- a/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/L2tpService.java
@@ -35,4 +35,9 @@ class L2tpService extends VpnService<L2tpProfile> {
(p.isSecretEnabled() ? p.getSecretString() : null),
username, password);
}
+
+ @Override
+ protected void stopPreviouslyRunDaemons() {
+ stopDaemon(MtpdHelper.MTPD);
+ }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
index 805a5b5..9078d9b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
+++ b/packages/VpnServices/src/com/android/server/vpn/MtpdHelper.java
@@ -24,26 +24,33 @@ import java.util.Arrays;
* A helper class for sending commands to the MTP daemon (mtpd).
*/
class MtpdHelper {
- private static final String MTPD = "mtpd";
+ static final String MTPD = "mtpd";
private static final String VPN_LINKNAME = "vpn";
private static final String PPP_ARGS_SEPARATOR = "";
static void sendCommand(VpnService<?> vpnService, String protocol,
String serverIp, String port, String secret, String username,
String password) throws IOException {
+ sendCommand(vpnService, protocol, serverIp, port, secret, username,
+ password, false);
+ }
+
+ static void sendCommand(VpnService<?> vpnService, String protocol,
+ String serverIp, String port, String secret, String username,
+ String password, boolean encryption) throws IOException {
ArrayList<String> args = new ArrayList<String>();
args.addAll(Arrays.asList(protocol, serverIp, port));
if (secret != null) args.add(secret);
args.add(PPP_ARGS_SEPARATOR);
- addPppArguments(vpnService, args, serverIp, username, password);
+ addPppArguments(args, serverIp, username, password, encryption);
DaemonProxy mtpd = vpnService.startDaemon(MTPD);
mtpd.sendCommand(args.toArray(new String[args.size()]));
}
- private static void addPppArguments(VpnService<?> vpnService,
- ArrayList<String> args, String serverIp, String username,
- String password) throws IOException {
+ private static void addPppArguments(ArrayList<String> args, String serverIp,
+ String username, String password, boolean encryption)
+ throws IOException {
args.addAll(Arrays.asList(
"linkname", VPN_LINKNAME,
"name", username,
@@ -52,6 +59,9 @@ class MtpdHelper {
"idle", "1800",
"mtu", "1400",
"mru", "1400"));
+ if (encryption) {
+ args.add("+mppe");
+ }
}
private MtpdHelper() {
diff --git a/packages/VpnServices/src/com/android/server/vpn/PptpService.java b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
index 01362a5..d903d1b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/PptpService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/PptpService.java
@@ -26,11 +26,17 @@ import java.io.IOException;
class PptpService extends VpnService<PptpProfile> {
static final String PPTP_DAEMON = "pptp";
static final String PPTP_PORT = "1723";
+
@Override
protected void connect(String serverIp, String username, String password)
throws IOException {
+ PptpProfile p = getProfile();
MtpdHelper.sendCommand(this, PPTP_DAEMON, serverIp, PPTP_PORT, null,
- username, password);
+ username, password, p.isEncryptionEnabled());
}
+ @Override
+ protected void stopPreviouslyRunDaemons() {
+ stopDaemon(MtpdHelper.MTPD);
+ }
}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 60a07d5..b107c7d 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -28,7 +28,11 @@ import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
+import java.io.Serializable;
+import java.net.DatagramSocket;
+import java.net.Socket;
import java.net.InetAddress;
+import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
@@ -36,7 +40,9 @@ import java.util.List;
/**
* The service base class for managing a type of VPN connection.
*/
-abstract class VpnService<E extends VpnProfile> {
+abstract class VpnService<E extends VpnProfile> implements Serializable {
+ protected static final long serialVersionUID = 1L;
+ private static final boolean DBG = true;
private static final int NOTIFICATION_ID = 1;
private static final String DNS1 = "net.dns1";
@@ -50,12 +56,16 @@ abstract class VpnService<E extends VpnProfile> {
private static final String REMOTE_IP = "net.ipremote";
private static final String DNS_DOMAIN_SUFFICES = "net.dns.search";
+ private static final int CHALLENGE_ERROR_CODE = 5;
+ private static final int REMOTE_HUNG_UP_ERROR_CODE = 7;
private static final int AUTH_ERROR_CODE = 51;
private final String TAG = VpnService.class.getSimpleName();
+ // FIXME: profile is only needed in connecting phase, so we can just save
+ // the profile name and service class name for recovery
E mProfile;
- VpnServiceBinder mContext;
+ transient VpnServiceBinder mContext;
private VpnState mState = VpnState.IDLE;
private Throwable mError;
@@ -63,9 +73,9 @@ abstract class VpnService<E extends VpnProfile> {
// connection settings
private String mOriginalDns1;
private String mOriginalDns2;
- private String mVpnDns1 = "";
- private String mVpnDns2 = "";
private String mOriginalDomainSuffices;
+ private String mLocalIp;
+ private String mLocalIf;
private long mStartTime; // VPN connection start time
@@ -73,7 +83,7 @@ abstract class VpnService<E extends VpnProfile> {
private DaemonHelper mDaemonHelper = new DaemonHelper();
// for helping showing, updating notification
- private NotificationHelper mNotification = new NotificationHelper();
+ private transient NotificationHelper mNotification;
/**
* Establishes a VPN connection with the specified username and password.
@@ -81,6 +91,8 @@ abstract class VpnService<E extends VpnProfile> {
protected abstract void connect(String serverIp, String username,
String password) throws IOException;
+ protected abstract void stopPreviouslyRunDaemons();
+
/**
* Starts a VPN daemon.
*/
@@ -90,6 +102,13 @@ abstract class VpnService<E extends VpnProfile> {
}
/**
+ * Stops a VPN daemon.
+ */
+ protected void stopDaemon(String daemonName) {
+ new DaemonProxy(daemonName).stop();
+ }
+
+ /**
* Returns the VPN profile associated with the connection.
*/
protected E getProfile() {
@@ -104,8 +123,22 @@ abstract class VpnService<E extends VpnProfile> {
}
void setContext(VpnServiceBinder context, E profile) {
- mContext = context;
mProfile = profile;
+ recover(context);
+ }
+
+ void recover(VpnServiceBinder context) {
+ mContext = context;
+ mNotification = new NotificationHelper();
+
+ if (VpnState.CONNECTED.equals(mState)) {
+ Log.i("VpnService", " recovered: " + mProfile.getName());
+ new Thread(new Runnable() {
+ public void run() {
+ enterConnectivityLoop();
+ }
+ }).start();
+ }
}
VpnState getState() {
@@ -117,14 +150,14 @@ abstract class VpnService<E extends VpnProfile> {
mState = VpnState.CONNECTING;
broadcastConnectivity(VpnState.CONNECTING);
+ stopPreviouslyRunDaemons();
String serverIp = getIp(getProfile().getServerName());
-
+ saveLocalIpAndInterface(serverIp);
onBeforeConnect();
connect(serverIp, username, password);
waitUntilConnectedOrTimedout();
return true;
} catch (Throwable e) {
- Log.e(TAG, "onConnect()", e);
onError(e);
return false;
}
@@ -132,7 +165,7 @@ abstract class VpnService<E extends VpnProfile> {
synchronized void onDisconnect() {
try {
- Log.d(TAG, " disconnecting VPN...");
+ Log.i(TAG, "disconnecting VPN...");
mState = VpnState.DISCONNECTING;
broadcastConnectivity(VpnState.DISCONNECTING);
mNotification.showDisconnect();
@@ -152,6 +185,7 @@ abstract class VpnService<E extends VpnProfile> {
Log.w(TAG, " multiple errors occur, record the last one: "
+ error);
}
+ Log.e(TAG, "onError()", error);
mError = error;
onDisconnect();
}
@@ -161,16 +195,18 @@ abstract class VpnService<E extends VpnProfile> {
}
- private void onBeforeConnect() {
+ private void onBeforeConnect() throws IOException {
mNotification.disableNotification();
- SystemProperties.set(VPN_DNS1, "-");
- SystemProperties.set(VPN_DNS2, "-");
+ SystemProperties.set(VPN_DNS1, "");
+ SystemProperties.set(VPN_DNS2, "");
SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
- Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_STATUS));
+ if (DBG) {
+ Log.d(TAG, " VPN UP: " + SystemProperties.get(VPN_STATUS));
+ }
}
- private void waitUntilConnectedOrTimedout() {
+ private void waitUntilConnectedOrTimedout() throws IOException {
sleep(2000); // 2 seconds
for (int i = 0; i < 60; i++) {
if (mState != VpnState.CONNECTING) {
@@ -187,39 +223,49 @@ abstract class VpnService<E extends VpnProfile> {
synchronized (VpnService.this) {
if (mState == VpnState.CONNECTING) {
- Log.d(TAG, " connecting timed out !!");
onError(new IOException("Connecting timed out"));
}
}
}
- private synchronized void onConnected() {
- Log.d(TAG, "onConnected()");
+ private synchronized void onConnected() throws IOException {
+ if (DBG) Log.d(TAG, "onConnected()");
mDaemonHelper.closeSockets();
- saveVpnDnsProperties();
+ saveOriginalDns();
saveAndSetDomainSuffices();
mState = VpnState.CONNECTED;
+ mStartTime = System.currentTimeMillis();
+
+ // set DNS after saving the states in case the process gets killed
+ // before states are saved
+ saveSelf();
+ setVpnDns();
broadcastConnectivity(VpnState.CONNECTED);
enterConnectivityLoop();
}
+ private void saveSelf() throws IOException {
+ mContext.saveStates();
+ }
+
private synchronized void onFinalCleanUp() {
- Log.d(TAG, "onFinalCleanUp()");
+ if (DBG) Log.d(TAG, "onFinalCleanUp()");
if (mState == VpnState.IDLE) return;
// keep the notification when error occurs
if (!anyError()) mNotification.disableNotification();
- restoreOriginalDnsProperties();
+ restoreOriginalDns();
restoreOriginalDomainSuffices();
mState = VpnState.IDLE;
broadcastConnectivity(VpnState.IDLE);
// stop the service itself
+ mContext.removeStates();
mContext.stopSelf();
}
@@ -227,46 +273,38 @@ abstract class VpnService<E extends VpnProfile> {
return (mError != null);
}
- private void restoreOriginalDnsProperties() {
+ private void restoreOriginalDns() {
// restore only if they are not overridden
- if (mVpnDns1.equals(SystemProperties.get(DNS1))) {
- Log.d(TAG, String.format("restore original dns prop: %s --> %s",
+ String vpnDns1 = SystemProperties.get(VPN_DNS1);
+ if (vpnDns1.equals(SystemProperties.get(DNS1))) {
+ Log.i(TAG, String.format("restore original dns prop: %s --> %s",
SystemProperties.get(DNS1), mOriginalDns1));
- Log.d(TAG, String.format("restore original dns prop: %s --> %s",
+ Log.i(TAG, String.format("restore original dns prop: %s --> %s",
SystemProperties.get(DNS2), mOriginalDns2));
SystemProperties.set(DNS1, mOriginalDns1);
SystemProperties.set(DNS2, mOriginalDns2);
}
}
- private void saveVpnDnsProperties() {
- mOriginalDns1 = mOriginalDns2 = "";
- for (int i = 0; i < 5; i++) {
- mVpnDns1 = SystemProperties.get(VPN_DNS1);
- mVpnDns2 = SystemProperties.get(VPN_DNS2);
- if (mOriginalDns1.equals(mVpnDns1)) {
- Log.d(TAG, "wait for vpn dns to settle in..." + i);
- sleep(200);
- } else {
- mOriginalDns1 = SystemProperties.get(DNS1);
- mOriginalDns2 = SystemProperties.get(DNS2);
- SystemProperties.set(DNS1, mVpnDns1);
- SystemProperties.set(DNS2, mVpnDns2);
- Log.d(TAG, String.format("save original dns prop: %s, %s",
- mOriginalDns1, mOriginalDns2));
- Log.d(TAG, String.format("set vpn dns prop: %s, %s",
- mVpnDns1, mVpnDns2));
- return;
- }
- }
- Log.d(TAG, "saveVpnDnsProperties(): DNS not updated??");
- mOriginalDns1 = mVpnDns1 = SystemProperties.get(DNS1);
- mOriginalDns2 = mVpnDns2 = SystemProperties.get(DNS2);
+ private void saveOriginalDns() {
+ mOriginalDns1 = SystemProperties.get(DNS1);
+ mOriginalDns2 = SystemProperties.get(DNS2);
+ Log.i(TAG, String.format("save original dns prop: %s, %s",
+ mOriginalDns1, mOriginalDns2));
+ }
+
+ private void setVpnDns() {
+ String vpnDns1 = SystemProperties.get(VPN_DNS1);
+ String vpnDns2 = SystemProperties.get(VPN_DNS2);
+ SystemProperties.set(DNS1, vpnDns1);
+ SystemProperties.set(DNS2, vpnDns2);
+ Log.i(TAG, String.format("set vpn dns prop: %s, %s",
+ vpnDns1, vpnDns2));
}
private void saveAndSetDomainSuffices() {
mOriginalDomainSuffices = SystemProperties.get(DNS_DOMAIN_SUFFICES);
- Log.d(TAG, "save original dns search: " + mOriginalDomainSuffices);
+ Log.i(TAG, "save original suffices: " + mOriginalDomainSuffices);
String list = mProfile.getDomainSuffices();
if (!TextUtils.isEmpty(list)) {
SystemProperties.set(DNS_DOMAIN_SUFFICES, list);
@@ -274,7 +312,7 @@ abstract class VpnService<E extends VpnProfile> {
}
private void restoreOriginalDomainSuffices() {
- Log.d(TAG, "restore original dns search --> " + mOriginalDomainSuffices);
+ Log.i(TAG, "restore original suffices --> " + mOriginalDomainSuffices);
SystemProperties.set(DNS_DOMAIN_SUFFICES, mOriginalDomainSuffices);
}
@@ -298,46 +336,73 @@ abstract class VpnService<E extends VpnProfile> {
}
private void enterConnectivityLoop() {
- mStartTime = System.currentTimeMillis();
-
- Log.d(TAG, " +++++ connectivity monitor running");
+ Log.i(TAG, "VPN connectivity monitor running");
try {
for (;;) {
synchronized (VpnService.this) {
- if (mState != VpnState.CONNECTED) break;
+ if (mState != VpnState.CONNECTED || !checkConnectivity()) {
+ break;
+ }
mNotification.update();
- checkConnectivity();
+ checkDns();
VpnService.this.wait(1000); // 1 second
}
}
} catch (InterruptedException e) {
- Log.e(TAG, "connectivity monitor", e);
+ onError(e);
}
- Log.d(TAG, " ----- connectivity monitor stopped");
+ Log.i(TAG, "VPN connectivity monitor stopped");
}
- private void checkConnectivity() {
- if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
- onDisconnect();
+ private void saveLocalIpAndInterface(String serverIp) throws IOException {
+ DatagramSocket s = new DatagramSocket();
+ int port = 80; // arbitrary
+ s.connect(InetAddress.getByName(serverIp), port);
+ InetAddress localIp = s.getLocalAddress();
+ mLocalIp = localIp.getHostAddress();
+ NetworkInterface localIf = NetworkInterface.getByInetAddress(localIp);
+ mLocalIf = (localIf == null) ? null : localIf.getName();
+ if (TextUtils.isEmpty(mLocalIf)) {
+ throw new IOException("Local interface is empty!");
+ }
+ if (DBG) {
+ Log.d(TAG, " Local IP: " + mLocalIp + ", if: " + mLocalIf);
}
}
- private boolean isLocalIpChanged() {
- // TODO
- if (!isDnsIntact()) {
- Log.w(TAG, " local IP changed");
- return true;
- } else {
+ // returns false if vpn connectivity is broken
+ private boolean checkConnectivity() {
+ if (mDaemonHelper.anyDaemonStopped() || isLocalIpChanged()) {
+ onDisconnect();
return false;
+ } else {
+ return true;
}
}
- private boolean isDnsIntact() {
+ private void checkDns() {
String dns1 = SystemProperties.get(DNS1);
- if (!mVpnDns1.equals(dns1)) {
- Log.w(TAG, " dns being overridden by: " + dns1);
- return false;
- } else {
+ String vpnDns1 = SystemProperties.get(VPN_DNS1);
+ if (!dns1.equals(vpnDns1) && dns1.equals(mOriginalDns1)) {
+ // dhcp expires?
+ setVpnDns();
+ }
+ }
+
+ private boolean isLocalIpChanged() {
+ try {
+ InetAddress localIp = InetAddress.getByName(mLocalIp);
+ NetworkInterface localIf =
+ NetworkInterface.getByInetAddress(localIp);
+ if (localIf == null || !mLocalIf.equals(localIf.getName())) {
+ Log.w(TAG, " local If changed from " + mLocalIf
+ + " to " + localIf);
+ return true;
+ } else {
+ return false;
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "isLocalIpChanged()", e);
return true;
}
}
@@ -349,7 +414,7 @@ abstract class VpnService<E extends VpnProfile> {
}
}
- private class DaemonHelper {
+ private class DaemonHelper implements Serializable {
private List<DaemonProxy> mDaemonList =
new ArrayList<DaemonProxy>();
@@ -376,7 +441,7 @@ abstract class VpnService<E extends VpnProfile> {
synchronized boolean anyDaemonStopped() {
for (DaemonProxy s : mDaemonList) {
if (s.isStopped()) {
- Log.w(TAG, " daemon gone: " + s.getName());
+ Log.w(TAG, " VPN daemon gone: " + s.getName());
return true;
}
}
@@ -401,6 +466,14 @@ abstract class VpnService<E extends VpnProfile> {
onError(VpnManager.VPN_ERROR_AUTH);
return true;
+ case CHALLENGE_ERROR_CODE:
+ onError(VpnManager.VPN_ERROR_CHALLENGE);
+ return true;
+
+ case REMOTE_HUNG_UP_ERROR_CODE:
+ onError(VpnManager.VPN_ERROR_REMOTE_HUNG_UP);
+ return true;
+
default:
onError(VpnManager.VPN_ERROR_CONNECTION_FAILED);
return true;
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index 513a2c9..4892a7b 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -27,23 +27,31 @@ import android.net.vpn.VpnManager;
import android.net.vpn.VpnProfile;
import android.net.vpn.VpnState;
import android.os.IBinder;
+import android.util.Log;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
/**
* The service class for managing a VPN connection. It implements the
* {@link IVpnService} binder interface.
*/
public class VpnServiceBinder extends Service {
- private final String TAG = VpnServiceBinder.class.getSimpleName();
+ private static final String TAG = VpnServiceBinder.class.getSimpleName();
+ private static final boolean DBG = true;
+
+ private static final String STATES_FILE_PATH = "/data/misc/vpn/.states";
// The actual implementation is delegated to the VpnService class.
private VpnService<? extends VpnProfile> mService;
private final IBinder mBinder = new IVpnService.Stub() {
public boolean connect(VpnProfile p, String username, String password) {
- android.util.Log.d("VpnServiceBinder", "becoming foreground");
- setForeground(true);
return VpnServiceBinder.this.connect(p, username, password);
}
@@ -57,6 +65,13 @@ public class VpnServiceBinder extends Service {
};
@Override
+ public void onCreate() {
+ super.onCreate();
+ checkSavedStates();
+ }
+
+
+ @Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@@ -66,14 +81,30 @@ public class VpnServiceBinder extends Service {
return mBinder;
}
+ void saveStates() throws IOException {
+ if (DBG) Log.d("VpnServiceBinder", " saving states");
+ ObjectOutputStream oos =
+ new ObjectOutputStream(new FileOutputStream(STATES_FILE_PATH));
+ oos.writeObject(mService);
+ oos.close();
+ }
+
+ void removeStates() {
+ try {
+ new File(STATES_FILE_PATH).delete();
+ } catch (Throwable e) {
+ if (DBG) Log.d("VpnServiceBinder", " remove states: " + e);
+ }
+ }
+
private synchronized boolean connect(final VpnProfile p,
final String username, final String password) {
if (mService != null) return false;
+ final VpnService s = mService = createService(p);
new Thread(new Runnable() {
public void run() {
- mService = createService(p);
- mService.onConnect(username, password);
+ s.onConnect(username, password);
}
}).start();
return true;
@@ -81,12 +112,11 @@ public class VpnServiceBinder extends Service {
private synchronized void disconnect() {
if (mService == null) return;
+ final VpnService s = mService;
new Thread(new Runnable() {
public void run() {
- mService.onDisconnect();
- android.util.Log.d("VpnServiceBinder", "becoming background");
- setForeground(false);
+ s.onDisconnect();
}
}).start();
}
@@ -100,6 +130,21 @@ public class VpnServiceBinder extends Service {
}
}
+ private void checkSavedStates() {
+ try {
+ ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
+ STATES_FILE_PATH));
+ mService = (VpnService<? extends VpnProfile>) ois.readObject();
+ mService.recover(this);
+ ois.close();
+ } catch (FileNotFoundException e) {
+ // do nothing
+ } catch (Throwable e) {
+ Log.i("VpnServiceBinder", "recovery error, remove states: " + e);
+ removeStates();
+ }
+ }
+
private VpnService<? extends VpnProfile> createService(VpnProfile p) {
switch (p.getType()) {
case L2TP:
diff --git a/preloaded-classes b/preloaded-classes
index 3858883..6eb3cf2 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -845,16 +845,18 @@ java.util.GregorianCalendar
java.util.HashMap
java.util.HashMap$1
java.util.HashMap$2
-java.util.HashMap$2$1
+java.util.HashMap$AbstractMapIterator
java.util.HashMap$Entry
+java.util.HashMap$EntryIterator
java.util.HashMap$HashMapEntrySet
-java.util.HashMap$HashMapEntrySet$1
+java.util.HashMap$KeyIterator
+java.util.HashMap$ValueIterator
java.util.HashSet
java.util.Hashtable
-java.util.Hashtable$4
-java.util.Hashtable$4$1
+java.util.Hashtable$6
+java.util.Hashtable$6$1
java.util.Hashtable$Entry
-java.util.Hashtable$HashEnumerator
+java.util.Hashtable$HashEnumIterator
java.util.Hashtable$HashIterator
java.util.IdentityHashMap
java.util.LinkedHashMap
@@ -869,7 +871,7 @@ java.util.ResourceBundle
java.util.SimpleTimeZone
java.util.TimeZone
java.util.TreeMap
-java.util.TreeMap$Entry
+java.util.TreeMap$MapEntry
java.util.TreeSet
java.util.Vector
java.util.WeakHashMap
@@ -952,14 +954,11 @@ org.apache.harmony.luni.internal.net.www.protocol.https.Handler
org.apache.harmony.luni.internal.net.www.protocol.jar.Handler
org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection
org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$1
-org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$CacheEntry
org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$JarURLConnectionInputStream
-org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnection$LRUComparator
org.apache.harmony.luni.internal.util.TimezoneGetter
org.apache.harmony.luni.internal.util.ZoneInfo
org.apache.harmony.luni.internal.util.ZoneInfoDB
org.apache.harmony.luni.net.PlainSocketImpl
-org.apache.harmony.luni.net.PlainSocketImpl2
org.apache.harmony.luni.platform.PlatformAddress
org.apache.harmony.luni.util.TwoKeyHashMap
org.apache.harmony.nio.internal.FileChannelImpl$RepositioningLock
@@ -1176,4 +1175,3 @@ org.xml.sax.helpers.NewInstance
org.xmlpull.v1.XmlPullParserFactory
org.xmlpull.v1.sax2.Driver
sun.misc.Unsafe
-
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 63c9eaa..55007ba 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -323,15 +323,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*/
private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
boolean isDefault) {
- for (int i = 0, count = mServices.size(); i < count; i++) {
- Service service = mServices.get(i);
+ try {
+ for (int i = 0, count = mServices.size(); i < count; i++) {
+ Service service = mServices.get(i);
- if (service.mIsDefault == isDefault) {
- if (canDispathEventLocked(service, event, mHandledFeedbackTypes)) {
- mHandledFeedbackTypes |= service.mFeedbackType;
- notifyAccessibilityServiceDelayedLocked(service, event);
+ if (service.mIsDefault == isDefault) {
+ if (canDispathEventLocked(service, event, mHandledFeedbackTypes)) {
+ mHandledFeedbackTypes |= service.mFeedbackType;
+ notifyAccessibilityServiceDelayedLocked(service, event);
+ }
}
}
+ } catch (IndexOutOfBoundsException oobe) {
+ // An out of bounds exception can happen if services are going away
+ // as the for loop is running. If that happens, just bail because
+ // there are no more services to notify.
+ return;
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 4643115..67f3816 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -46,6 +46,8 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
@@ -91,6 +93,20 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int MSG_RUN_RESTORE = 3;
private static final int MSG_RUN_CLEAR = 4;
+ // Event tags -- see system/core/logcat/event-log-tags
+ private static final int BACKUP_DATA_CHANGED_EVENT = 2820;
+ private static final int BACKUP_START_EVENT = 2821;
+ private static final int BACKUP_TRANSPORT_FAILURE_EVENT = 2822;
+ private static final int BACKUP_AGENT_FAILURE_EVENT = 2823;
+ private static final int BACKUP_PACKAGE_EVENT = 2824;
+ private static final int BACKUP_SUCCESS_EVENT = 2825;
+
+ private static final int RESTORE_START_EVENT = 2830;
+ private static final int RESTORE_TRANSPORT_FAILURE_EVENT = 2831;
+ private static final int RESTORE_AGENT_FAILURE_EVENT = 2832;
+ private static final int RESTORE_PACKAGE_EVENT = 2833;
+ private static final int RESTORE_SUCCESS_EVENT = 2834;
+
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -787,7 +803,7 @@ class BackupManagerService extends IBackupManager.Stub {
class ClearDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(String packageName, boolean succeeded)
- throws android.os.RemoteException {
+ throws RemoteException {
synchronized(mClearDataLock) {
mClearingData = false;
mClearDataLock.notifyAll();
@@ -820,43 +836,49 @@ class BackupManagerService extends IBackupManager.Stub {
@Override
public void run() {
+ long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
// Backups run at background priority
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- // The package manager doesn't have a proper <application> etc, but since
- // it's running here in the system process we can just set up its agent
- // directly and use a synthetic BackupRequest. We always run this pass
- // because it's cheap and this way we guarantee that we don't get out of
- // step even if we're selecting among various transports at run time.
- PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
- mPackageManager, allAgentPackages());
- BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false);
- pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL;
- processOneBackup(pmRequest,
- IBackupAgent.Stub.asInterface(pmAgent.onBind()),
- mTransport);
-
- // Now run all the backups in our queue
- doQueuedBackups(mTransport);
-
- // Finally, tear down the transport
try {
- if (!mTransport.finishBackup()) {
- // STOPSHIP TODO: handle errors
- Log.e(TAG, "Backup failure in finishBackup()");
+ EventLog.writeEvent(BACKUP_START_EVENT, mTransport.transportDirName());
+
+ // The package manager doesn't have a proper <application> etc, but since
+ // it's running here in the system process we can just set up its agent
+ // directly and use a synthetic BackupRequest. We always run this pass
+ // because it's cheap and this way we guarantee that we don't get out of
+ // step even if we're selecting among various transports at run time.
+ PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
+ mPackageManager, allAgentPackages());
+ BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false);
+ pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL;
+ processOneBackup(pmRequest,
+ IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
+
+ // Now run all the backups in our queue
+ int count = mQueue.size();
+ doQueuedBackups(mTransport);
+
+ // Finally, tear down the transport
+ if (mTransport.finishBackup()) {
+ int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
+ EventLog.writeEvent(BACKUP_SUCCESS_EVENT, count, millis);
+ } else {
+ EventLog.writeEvent(BACKUP_TRANSPORT_FAILURE_EVENT, "");
+ Log.e(TAG, "Transport error in finishBackup()");
}
- } catch (RemoteException e) {
- Log.e(TAG, "Error in finishBackup()", e);
- }
- if (!mJournal.delete()) {
- Log.e(TAG, "Unable to remove backup journal file " + mJournal.getAbsolutePath());
+ if (!mJournal.delete()) {
+ Log.e(TAG, "Unable to remove backup journal file " + mJournal);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error in backup thread", e);
+ } finally {
+ // Only once we're entirely finished do we release the wakelock
+ mWakelock.release();
}
-
- // Only once we're entirely finished do we release the wakelock
- mWakelock.release();
}
private void doQueuedBackups(IBackupTransport transport) {
@@ -882,19 +904,27 @@ class BackupManagerService extends IBackupManager.Stub {
Log.v(TAG, "bind/backup threw");
e.printStackTrace();
}
-
}
}
void processOneBackup(BackupRequest request, IBackupAgent agent, IBackupTransport transport) {
final String packageName = request.appInfo.packageName;
- Log.d(TAG, "processOneBackup doBackup() on " + packageName);
+ if (DEBUG) Log.d(TAG, "processOneBackup doBackup() on " + packageName);
+ // !!! TODO: get the state file dir from the transport
+ File savedStateName = new File(mStateDir, packageName);
+ File backupDataName = new File(mDataDir, packageName + ".data");
+ File newStateName = new File(mStateDir, packageName + ".new");
+
+ ParcelFileDescriptor savedState = null;
+ ParcelFileDescriptor backupData = null;
+ ParcelFileDescriptor newState = null;
+
+ PackageInfo packInfo;
try {
// Look up the package info & signatures. This is first so that if it
// throws an exception, there's no file setup yet that would need to
// be unraveled.
- PackageInfo packInfo;
if (packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
// The metadata 'package' is synthetic
packInfo = new PackageInfo();
@@ -904,69 +934,65 @@ class BackupManagerService extends IBackupManager.Stub {
PackageManager.GET_SIGNATURES);
}
- // !!! TODO: get the state file dir from the transport
- File savedStateName = new File(mStateDir, packageName);
- File backupDataName = new File(mDataDir, packageName + ".data");
- File newStateName = new File(mStateDir, packageName + ".new");
-
// In a full backup, we pass a null ParcelFileDescriptor as
// the saved-state "file"
- ParcelFileDescriptor savedState = (request.fullBackup) ? null
- : ParcelFileDescriptor.open(savedStateName,
+ if (!request.fullBackup) {
+ savedState = ParcelFileDescriptor.open(savedStateName,
ParcelFileDescriptor.MODE_READ_ONLY |
- ParcelFileDescriptor.MODE_CREATE);
+ ParcelFileDescriptor.MODE_CREATE); // Make an empty file if necessary
+ }
- backupDataName.delete();
- ParcelFileDescriptor backupData =
- ParcelFileDescriptor.open(backupDataName,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE);
+ backupData = ParcelFileDescriptor.open(backupDataName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE);
- newStateName.delete();
- ParcelFileDescriptor newState =
- ParcelFileDescriptor.open(newStateName,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE);
+ newState = ParcelFileDescriptor.open(newStateName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE);
// Run the target's backup pass
- boolean success = false;
- try {
- agent.doBackup(savedState, backupData, newState);
- logBackupComplete(packageName);
- success = true;
- } finally {
- if (savedState != null) {
- savedState.close();
- }
- backupData.close();
- newState.close();
- }
+ agent.doBackup(savedState, backupData, newState);
+ logBackupComplete(packageName);
+ if (DEBUG) Log.v(TAG, "doBackup() success");
+ } catch (Exception e) {
+ Log.e(TAG, "Error backing up " + packageName, e);
+ EventLog.writeEvent(BACKUP_AGENT_FAILURE_EVENT, packageName, e.toString());
+ backupDataName.delete();
+ newStateName.delete();
+ return;
+ } finally {
+ try { if (savedState != null) savedState.close(); } catch (IOException e) {}
+ try { if (backupData != null) backupData.close(); } catch (IOException e) {}
+ try { if (newState != null) newState.close(); } catch (IOException e) {}
+ savedState = backupData = newState = null;
+ }
- // Now propagate the newly-backed-up data to the transport
- if (success) {
- if (DEBUG) Log.v(TAG, "doBackup() success");
- if (backupDataName.length() > 0) {
- backupData =
- ParcelFileDescriptor.open(backupDataName,
- ParcelFileDescriptor.MODE_READ_ONLY);
- if (!transport.performBackup(packInfo, backupData)) {
- // STOPSHIP TODO: handle errors
- Log.e(TAG, "Backup failure in performBackup()");
- }
- } else {
- if (DEBUG) {
- Log.i(TAG, "no backup data written; not calling transport");
- }
- }
+ // Now propagate the newly-backed-up data to the transport
+ try {
+ int size = (int) backupDataName.length();
+ if (size > 0) {
+ backupData = ParcelFileDescriptor.open(backupDataName,
+ ParcelFileDescriptor.MODE_READ_ONLY);
- // After successful transport, delete the now-stale data
- // and juggle the files so that next time we supply the agent
- // with the new state file it just created.
- backupDataName.delete();
- newStateName.renameTo(savedStateName);
+ if (!transport.performBackup(packInfo, backupData)) throw new Exception();
+ } else {
+ if (DEBUG) Log.i(TAG, "no backup data written; not calling transport");
}
+
+ // After successful transport, delete the now-stale data
+ // and juggle the files so that next time we supply the agent
+ // with the new state file it just created.
+ backupDataName.delete();
+ newStateName.renameTo(savedStateName);
+ EventLog.writeEvent(BACKUP_PACKAGE_EVENT, packageName, size);
} catch (Exception e) {
- Log.e(TAG, "Error backing up " + packageName, e);
+ Log.e(TAG, "Transport error backing up " + packageName, e);
+ EventLog.writeEvent(BACKUP_TRANSPORT_FAILURE_EVENT, packageName);
+ return;
+ } finally {
+ try { if (backupData != null) backupData.close(); } catch (IOException e) {}
}
}
}
@@ -1012,7 +1038,6 @@ class BackupManagerService extends IBackupManager.Stub {
private IBackupTransport mTransport;
private IRestoreObserver mObserver;
private long mToken;
- private RestoreSet mImage;
private File mStateDir;
class RestoreRequest {
@@ -1042,6 +1067,7 @@ class BackupManagerService extends IBackupManager.Stub {
@Override
public void run() {
+ long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Log.v(TAG, "Beginning restore process mTransport=" + mTransport
+ " mObserver=" + mObserver + " mToken=" + mToken);
/**
@@ -1049,7 +1075,7 @@ class BackupManagerService extends IBackupManager.Stub {
*
* 1. get the restore set description for our identity
* 2. for each app in the restore set:
- * 3.a. if it's restorable on this device, add it to the restore queue
+ * 2.a. if it's restorable on this device, add it to the restore queue
* 3. for each app in the restore queue:
* 3.a. clear the app data
* 3.b. get the restore data for the app from the transport
@@ -1057,25 +1083,18 @@ class BackupManagerService extends IBackupManager.Stub {
* 3.d. agent.doRestore() with the data from the server
* 3.e. unbind the agent [and kill the app?]
* 4. shut down the transport
+ *
+ * On errors, we try our best to recover and move on to the next
+ * application, but if necessary we abort the whole operation --
+ * the user is waiting, after al.
*/
int error = -1; // assume error
// build the set of apps to restore
try {
- RestoreSet[] images = mTransport.getAvailableRestoreSets();
- if (images == null) {
- // STOPSHIP TODO: Handle the failure somehow?
- Log.e(TAG, "Error getting restore sets");
- return;
- }
-
- if (images.length == 0) {
- Log.i(TAG, "No restore sets available");
- return;
- }
-
- mImage = images[0];
+ // TODO: Log this before getAvailableRestoreSets, somehow
+ EventLog.writeEvent(RESTORE_START_EVENT, mTransport.transportDirName());
// Get the list of all packages which have backup enabled.
// (Include the Package Manager metadata pseudo-package first.)
@@ -1100,22 +1119,26 @@ class BackupManagerService extends IBackupManager.Stub {
}
if (!mTransport.startRestore(mToken, restorePackages.toArray(new PackageInfo[0]))) {
- // STOPSHIP TODO: Handle the failure somehow?
Log.e(TAG, "Error starting restore operation");
+ EventLog.writeEvent(RESTORE_TRANSPORT_FAILURE_EVENT);
return;
}
String packageName = mTransport.nextRestorePackage();
if (packageName == null) {
- // STOPSHIP TODO: Handle the failure somehow?
Log.e(TAG, "Error getting first restore package");
+ EventLog.writeEvent(RESTORE_TRANSPORT_FAILURE_EVENT);
return;
} else if (packageName.equals("")) {
Log.i(TAG, "No restore data available");
+ int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
+ EventLog.writeEvent(RESTORE_SUCCESS_EVENT, 0, millis);
return;
} else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
Log.e(TAG, "Expected restore data for \"" + PACKAGE_MANAGER_SENTINEL
+ "\", found only \"" + packageName + "\"");
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, PACKAGE_MANAGER_SENTINEL,
+ "Package manager data missing");
return;
}
@@ -1128,23 +1151,25 @@ class BackupManagerService extends IBackupManager.Stub {
// signature/version verification etc, so we simply do not proceed with
// the restore operation.
if (!pmAgent.hasMetadata()) {
- Log.i(TAG, "No restore metadata available, so not restoring settings");
+ Log.e(TAG, "No restore metadata available, so not restoring settings");
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, PACKAGE_MANAGER_SENTINEL,
+ "Package manager restore metadata missing");
return;
}
int count = 0;
for (;;) {
packageName = mTransport.nextRestorePackage();
+
if (packageName == null) {
- // STOPSHIP TODO: Handle the failure somehow?
Log.e(TAG, "Error getting next restore package");
+ EventLog.writeEvent(RESTORE_TRANSPORT_FAILURE_EVENT);
return;
} else if (packageName.equals("")) {
break;
}
if (mObserver != null) {
- ++count;
try {
mObserver.onUpdate(count);
} catch (RemoteException e) {
@@ -1156,21 +1181,34 @@ class BackupManagerService extends IBackupManager.Stub {
Metadata metaInfo = pmAgent.getRestoredMetadata(packageName);
if (metaInfo == null) {
Log.e(TAG, "Missing metadata for " + packageName);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
+ "Package metadata missing");
+ continue;
+ }
+
+ PackageInfo packageInfo;
+ try {
+ int flags = PackageManager.GET_SIGNATURES;
+ packageInfo = mPackageManager.getPackageInfo(packageName, flags);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Invalid package restoring data", e);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
+ "Package missing on device");
continue;
}
- int flags = PackageManager.GET_SIGNATURES;
- PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
if (metaInfo.versionCode > packageInfo.versionCode) {
- Log.w(TAG, "Package " + packageName
- + " restore version [" + metaInfo.versionCode
- + "] is too new for installed version ["
- + packageInfo.versionCode + "]");
+ String message = "Version " + metaInfo.versionCode
+ + " > installed version " + packageInfo.versionCode;
+ Log.w(TAG, "Package " + packageName + ": " + message);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName, message);
continue;
}
if (!signaturesMatch(metaInfo.signatures, packageInfo.signatures)) {
Log.w(TAG, "Signature mismatch restoring " + packageName);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
+ "Signature mismatch");
continue;
}
@@ -1186,11 +1224,14 @@ class BackupManagerService extends IBackupManager.Stub {
IApplicationThread.BACKUP_MODE_RESTORE);
if (agent == null) {
Log.w(TAG, "Can't find backup agent for " + packageName);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName,
+ "Restore agent missing");
continue;
}
try {
processOneRestore(packageInfo, metaInfo.versionCode, agent);
+ ++count;
} finally {
// unbind even on timeout or failure, just in case
mActivityManager.unbindBackupAgent(packageInfo.applicationInfo);
@@ -1199,21 +1240,19 @@ class BackupManagerService extends IBackupManager.Stub {
// if we get this far, report success to the observer
error = 0;
- } catch (NameNotFoundException e) {
- // STOPSHIP TODO: Handle the failure somehow?
- Log.e(TAG, "Invalid paackage restoring data", e);
- } catch (RemoteException e) {
- // STOPSHIP TODO: Handle the failure somehow?
- Log.e(TAG, "Error restoring data", e);
+ int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
+ EventLog.writeEvent(RESTORE_SUCCESS_EVENT, count, millis);
+ } catch (Exception e) {
+ Log.e(TAG, "Error in restore thread", e);
} finally {
+ if (DEBUG) Log.d(TAG, "finishing restore mObserver=" + mObserver);
+
try {
mTransport.finishRestore();
} catch (RemoteException e) {
Log.e(TAG, "Error finishing restore", e);
}
- Log.d(TAG, "finishing restore mObserver=" + mObserver);
-
if (mObserver != null) {
try {
mObserver.restoreFinished(error);
@@ -1232,57 +1271,58 @@ class BackupManagerService extends IBackupManager.Stub {
// !!! TODO: actually run the restore through mTransport
final String packageName = app.packageName;
- Log.d(TAG, "processOneRestore packageName=" + packageName);
+ if (DEBUG) Log.d(TAG, "processOneRestore packageName=" + packageName);
// !!! TODO: get the dirs from the transport
File backupDataName = new File(mDataDir, packageName + ".restore");
- backupDataName.delete();
+ File newStateName = new File(mStateDir, packageName + ".new");
+ File savedStateName = new File(mStateDir, packageName);
+
+ ParcelFileDescriptor backupData = null;
+ ParcelFileDescriptor newState = null;
+
try {
- ParcelFileDescriptor backupData =
- ParcelFileDescriptor.open(backupDataName,
+ // Run the transport's restore pass
+ backupData = ParcelFileDescriptor.open(backupDataName,
ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE);
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE);
- // Run the transport's restore pass
- // Run the target's backup pass
- try {
- if (!mTransport.getRestoreData(backupData)) {
- // STOPSHIP TODO: Handle this error somehow?
- Log.e(TAG, "Error getting restore data for " + packageName);
- return;
- }
- } finally {
- backupData.close();
+ if (!mTransport.getRestoreData(backupData)) {
+ Log.e(TAG, "Error getting restore data for " + packageName);
+ EventLog.writeEvent(RESTORE_TRANSPORT_FAILURE_EVENT);
+ return;
}
// Okay, we have the data. Now have the agent do the restore.
- File newStateName = new File(mStateDir, packageName + ".new");
- ParcelFileDescriptor newState =
- ParcelFileDescriptor.open(newStateName,
- ParcelFileDescriptor.MODE_READ_WRITE |
- ParcelFileDescriptor.MODE_CREATE);
-
+ backupData.close();
backupData = ParcelFileDescriptor.open(backupDataName,
ParcelFileDescriptor.MODE_READ_ONLY);
- try {
- agent.doRestore(backupData, appVersionCode, newState);
- } finally {
- newState.close();
- backupData.close();
- }
+ newState = ParcelFileDescriptor.open(newStateName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE |
+ ParcelFileDescriptor.MODE_TRUNCATE);
+
+ agent.doRestore(backupData, appVersionCode, newState);
// if everything went okay, remember the recorded state now
- File savedStateName = new File(mStateDir, packageName);
newStateName.renameTo(savedStateName);
+ int size = (int) backupDataName.length();
+ EventLog.writeEvent(RESTORE_PACKAGE_EVENT, packageName, size);
} catch (Exception e) {
+ Log.e(TAG, "Error restoring data for " + packageName, e);
+ EventLog.writeEvent(RESTORE_AGENT_FAILURE_EVENT, packageName, e.toString());
+
// If the agent fails restore, it might have put the app's data
// into an incoherent state. For consistency we wipe its data
// again in this case before propagating the exception
- Log.e(TAG, "Error restoring data for " + packageName, e);
clearApplicationDataSynchronous(packageName);
} finally {
backupDataName.delete();
+ try { if (backupData != null) backupData.close(); } catch (IOException e) {}
+ try { if (newState != null) newState.close(); } catch (IOException e) {}
+ backupData = newState = null;
}
}
}
@@ -1328,6 +1368,7 @@ class BackupManagerService extends IBackupManager.Stub {
// Record that we need a backup pass for the caller. Since multiple callers
// may share a uid, we need to note all candidates within that uid and schedule
// a backup pass for each of them.
+ EventLog.writeEvent(BACKUP_DATA_CHANGED_EVENT, packageName);
// If the caller does not hold the BACKUP permission, it can only request a
// backup of its own data.
@@ -1625,57 +1666,66 @@ class BackupManagerService extends IBackupManager.Stub {
}
// --- Binder interface ---
- public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
+ public synchronized RestoreSet[] getAvailableRestoreSets() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"getAvailableRestoreSets");
try {
- synchronized(this) {
if (mRestoreTransport == null) {
Log.w(TAG, "Null transport getting restore sets");
- } else if (mRestoreSets == null) { // valid transport; do the one-time fetch
+ return null;
+ }
+ if (mRestoreSets == null) { // valid transport; do the one-time fetch
mRestoreSets = mRestoreTransport.getAvailableRestoreSets();
+ if (mRestoreSets == null) EventLog.writeEvent(RESTORE_TRANSPORT_FAILURE_EVENT);
}
return mRestoreSets;
- }
- } catch (RuntimeException e) {
- Log.d(TAG, "getAvailableRestoreSets exception");
- e.printStackTrace();
- throw e;
+ } catch (Exception e) {
+ Log.e(TAG, "Error in getAvailableRestoreSets", e);
+ return null;
}
}
- public int performRestore(long token, IRestoreObserver observer)
- throws android.os.RemoteException {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "performRestore");
+ public synchronized int performRestore(long token, IRestoreObserver observer) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "performRestore");
- Log.d(TAG, "performRestore token=" + token + " observer=" + observer);
+ if (DEBUG) Log.d(TAG, "performRestore token=" + token + " observer=" + observer);
- if (mRestoreSets != null) {
- for (int i = 0; i < mRestoreSets.length; i++) {
- if (token == mRestoreSets[i].token) {
- mWakelock.acquire();
- Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
- msg.obj = new RestoreParams(mRestoreTransport, observer, token);
- mBackupHandler.sendMessage(msg);
- return 0;
- }
+ if (mRestoreTransport == null || mRestoreSets == null) {
+ Log.e(TAG, "Ignoring performRestore() with no restore set");
+ return -1;
+ }
+
+ for (int i = 0; i < mRestoreSets.length; i++) {
+ if (token == mRestoreSets[i].token) {
+ mWakelock.acquire();
+ Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+ msg.obj = new RestoreParams(mRestoreTransport, observer, token);
+ mBackupHandler.sendMessage(msg);
+ return 0;
}
- } else {
- if (DEBUG) Log.v(TAG, "No current restore set, not doing restore");
}
return -1;
}
- public void endRestoreSession() throws android.os.RemoteException {
+ public synchronized void endRestoreSession() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"endRestoreSession");
- Log.d(TAG, "endRestoreSession");
+ if (DEBUG) Log.d(TAG, "endRestoreSession");
+
+ synchronized (this) {
+ try {
+ if (mRestoreTransport != null) mRestoreTransport.finishRestore();
+ } catch (Exception e) {
+ Log.e(TAG, "Error in finishRestore", e);
+ } finally {
+ mRestoreTransport = null;
+ }
+ }
- mRestoreTransport.finishRestore();
- mRestoreTransport = null;
- synchronized(BackupManagerService.this) {
+ synchronized (BackupManagerService.this) {
if (BackupManagerService.this.mActiveRestoreSession == this) {
BackupManagerService.this.mActiveRestoreSession = null;
} else {
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index a682fcb..45c1e5c 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -44,6 +44,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import com.android.internal.app.ShutdownThread;
/**
@@ -182,6 +183,11 @@ class BatteryService extends Binder {
boolean logOutlier = false;
long dischargeDuration = 0;
+
+ // shut down gracefully if our battery is critically low and we are not powered
+ if (mBatteryLevel == 0 && isPowered(0xffffffff)) {
+ ShutdownThread.shutdown(mContext, false);
+ }
mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
if (mAcOnline) {
diff --git a/services/java/com/android/server/JournaledFile.java b/services/java/com/android/server/JournaledFile.java
new file mode 100644
index 0000000..3d1f52d
--- /dev/null
+++ b/services/java/com/android/server/JournaledFile.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import java.io.File;
+import java.io.IOException;
+
+public class JournaledFile {
+ File mReal;
+ File mTemp;
+ boolean mWriting;
+
+ public JournaledFile(File real, File temp) {
+ mReal = real;
+ mTemp = temp;
+ }
+
+ /** Returns the file for you to read.
+ * @more
+ * Prefers the real file. If it doesn't exist, uses the temp one, and then copies
+ * it to the real one. If there is both a real file and a temp one, assumes that the
+ * temp one isn't fully written and deletes it.
+ */
+ public File chooseForRead() {
+ File result;
+ if (mReal.exists()) {
+ result = mReal;
+ if (mTemp.exists()) {
+ mTemp.delete();
+ }
+ } else if (mTemp.exists()) {
+ result = mTemp;
+ mTemp.renameTo(mReal);
+ } else {
+ return mReal;
+ }
+ return result;
+ }
+
+ /**
+ * Returns a file for you to write.
+ * @more
+ * If a write is already happening, throws. In other words, you must provide your
+ * own locking.
+ * <p>
+ * Call {@link #commit} to commit the changes, or {@link #rollback} to forget the changes.
+ */
+ public File chooseForWrite() {
+ if (mWriting) {
+ throw new IllegalStateException("uncommitted write already in progress");
+ }
+ if (!mReal.exists()) {
+ // If the real one doesn't exist, it's either because this is the first time
+ // or because something went wrong while copying them. In this case, we can't
+ // trust anything that's in temp. In order to have the chooseForRead code not
+ // use the temporary one until it's fully written, create an empty file
+ // for real, which will we'll shortly delete.
+ try {
+ mReal.createNewFile();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+
+ if (mTemp.exists()) {
+ mTemp.delete();
+ }
+ mWriting = true;
+ return mTemp;
+ }
+
+ /**
+ * Commit changes.
+ */
+ public void commit() {
+ if (!mWriting) {
+ throw new IllegalStateException("no file to commit");
+ }
+ mWriting = false;
+ mTemp.renameTo(mReal);
+ }
+
+ /**
+ * Roll back changes.
+ */
+ public void rollback() {
+ if (!mWriting) {
+ throw new IllegalStateException("no file to roll back");
+ }
+ mWriting = false;
+ mTemp.delete();
+ }
+}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index d6cd4ef..9e8816b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -60,7 +60,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Debug;
import android.os.HandlerThread;
import android.os.Parcel;
import android.os.RemoteException;
@@ -495,7 +494,7 @@ class PackageManagerService extends IPackageManager.Stub {
mDrmAppInstallObserver = new AppDirObserver(
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
mDrmAppInstallObserver.startWatching();
- scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode);
+ scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
@@ -1767,7 +1766,12 @@ class PackageManagerService extends IPackageManager.Stub {
int i;
for (i=0; i<files.length; i++) {
File file = new File(dir, files[i]);
- PackageParser.Package pkg = scanPackageLI(file, file, file,
+ File resFile = file;
+ // Pick up the resource path from settings for fwd locked apps
+ if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
+ resFile = null;
+ }
+ PackageParser.Package pkg = scanPackageLI(file, file, resFile,
flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
}
}
@@ -1829,6 +1833,11 @@ class PackageManagerService extends IPackageManager.Stub {
ps = mSettings.peekPackageLP(pkg.packageName);
updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
}
+ // Verify certificates first
+ if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
+ Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
+ return null;
+ }
if (updatedPkg != null) {
// An updated system app will not have the PARSE_IS_SYSTEM flag set initially
parseFlags |= PackageParser.PARSE_IS_SYSTEM;
@@ -1846,23 +1855,30 @@ class PackageManagerService extends IPackageManager.Stub {
return null;
} else {
// Delete the older apk pointed to by ps
+ // At this point, its safely assumed that package installation for
+ // apps in system partition will go through. If not there won't be a working
+ // version of the app
+ synchronized (mPackages) {
+ // Just remove the loaded entries from package lists.
+ mPackages.remove(ps.name);
+ }
deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
mSettings.enableSystemPackageLP(ps.name);
}
}
}
}
- if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
- Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
- return null;
- }
// The apk is forward locked (not public) if its code and resources
// are kept in different files.
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
scanMode |= SCAN_FORWARD_LOCKED;
}
+ File resFile = destResourceFile;
+ if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
+ resFile = getFwdLockedResource(ps.name);
+ }
// Note that we invoke the following method only if we are about to unpack an application
- return scanPackageLI(scanFile, destCodeFile, destResourceFile,
+ return scanPackageLI(scanFile, destCodeFile, resFile,
pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
}
@@ -2135,7 +2151,7 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.packageName,
pkg.applicationInfo.processName,
pkg.applicationInfo.uid);
- pkg.applicationInfo.publicSourceDir = pkgSetting.resourcePathString;
+ pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
File dataPath;
if (mPlatformPackage == pkg) {
@@ -2262,15 +2278,26 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
}
+ // We don't expect installation to fail beyond this point,
if ((scanMode&SCAN_MONITOR) != 0) {
pkg.mPath = destCodeFile.getAbsolutePath();
mAppDirs.put(pkg.mPath, pkg);
}
+ // Request the ActivityManager to kill the process(only for existing packages)
+ // so that we do not end up in a confused state while the user is still using the older
+ // version of the application while the new one gets installed.
+ IActivityManager am = ActivityManagerNative.getDefault();
+ if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
+ try {
+ am.killApplicationWithUid(pkg.applicationInfo.packageName,
+ pkg.applicationInfo.uid);
+ } catch (RemoteException e) {
+ }
+ }
synchronized (mPackages) {
- // We don't expect installation to fail beyond this point
// Add the new setting to mSettings
- mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid);
+ mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg);
int N = pkg.providers.size();
@@ -2958,7 +2985,8 @@ class PackageManagerService extends IPackageManager.Stub {
}
if ((addedPermission || replace) && !ps.permissionsFixed &&
- (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+ ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) ||
+ ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){
// This is the first that we have heard about this package, so the
// permissions we have now selected are fixed until explicitly
// changed.
@@ -3792,6 +3820,11 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
+ private File getFwdLockedResource(String pkgName) {
+ final String publicZipFileName = pkgName + ".zip";
+ return new File(mAppInstallDir, publicZipFileName);
+ }
+
private PackageInstalledInfo installPackageLI(Uri pPackageURI,
int pFlags, boolean newInstall, String installerPackageName) {
File tmpPackageFile = null;
@@ -3871,8 +3904,7 @@ class PackageManagerService extends IPackageManager.Stub {
final String destFilePath = destPackageFile.getAbsolutePath();
File destResourceFile;
if ((pFlags&PackageManager.INSTALL_FORWARD_LOCK) != 0) {
- final String publicZipFileName = pkgName + ".zip";
- destResourceFile = new File(mAppInstallDir, publicZipFileName);
+ destResourceFile = getFwdLockedResource(pkgName);
forwardLocked = true;
} else {
destResourceFile = destPackageFile;
@@ -4159,7 +4191,9 @@ class PackageManagerService extends IPackageManager.Stub {
private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo,
int flags) {
String packageName = p.packageName;
- outInfo.removedPackage = packageName;
+ if (outInfo != null) {
+ outInfo.removedPackage = packageName;
+ }
removePackageLI(p, true);
// Retrieve object to delete permissions for shared user later on
PackageSetting deletedPs;
@@ -4181,7 +4215,9 @@ class PackageManagerService extends IPackageManager.Stub {
dataDir.delete();
}
synchronized (mPackages) {
- outInfo.removedUid = mSettings.removePackageLP(packageName);
+ if (outInfo != null) {
+ outInfo.removedUid = mSettings.removePackageLP(packageName);
+ }
}
}
synchronized (mPackages) {
@@ -4256,7 +4292,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
return true;
}
-
+
private void deletePackageResourcesLI(String packageName,
String sourceDir, String publicSourceDir) {
File sourceFile = new File(sourceDir);
@@ -4286,7 +4322,9 @@ class PackageManagerService extends IPackageManager.Stub {
Log.w(TAG, "Package " + p.packageName + " has no applicationInfo.");
return false;
}
- outInfo.uid = applicationInfo.uid;
+ if (outInfo != null) {
+ outInfo.uid = applicationInfo.uid;
+ }
// Delete package data from internal structures and also remove data if flag is set
removePackageDataLI(p, outInfo, flags);
@@ -5463,7 +5501,7 @@ class PackageManagerService extends IPackageManager.Stub {
String resourcePathString;
private long timeStamp;
private String timeStampString = "0";
- final int versionCode;
+ int versionCode;
PackageSignatures signatures = new PackageSignatures();
@@ -5701,10 +5739,6 @@ class PackageManagerService extends IPackageManager.Stub {
final String name = pkg.packageName;
PackageSetting p = getPackageLP(name, sharedUser, codePath,
resourcePath, pkg.mVersionCode, pkgFlags, create, add);
-
- if (p != null) {
- p.pkg = pkg;
- }
return p;
}
@@ -5852,22 +5886,18 @@ class PackageManagerService extends IPackageManager.Stub {
if (p != null) {
if (!p.codePath.equals(codePath)) {
// Check to see if its a disabled system app
- PackageSetting ps = mDisabledSysPackages.get(name);
- if((ps != null) && ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
+ if((p != null) && ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
// This is an updated system app with versions in both system
// and data partition. Just let the most recent version
// take precedence.
- return p;
+ Log.w(TAG, "Trying to update system app code path from " +
+ p.codePathString + " to " + codePath.toString());
} else {
// Let the app continue with previous uid if code path changes.
reportSettingsProblem(Log.WARN,
"Package " + name + " codePath changed from " + p.codePath
+ " to " + codePath + "; Retaining data and using new code from " +
codePath);
- p.codePath = codePath;
- p.resourcePath = resourcePath;
- p.codePathString = codePath.toString();
- p.resourcePathString = resourcePath.toString();
}
} else if (p.sharedUser != sharedUser) {
reportSettingsProblem(Log.WARN,
@@ -5891,8 +5921,29 @@ class PackageManagerService extends IPackageManager.Stub {
if (sharedUser != null) {
p.userId = sharedUser.userId;
} else if (MULTIPLE_APPLICATION_UIDS) {
- // Assign new user id
- p.userId = newUserIdLP(p);
+ // Clone the setting here for disabled system packages
+ PackageSetting dis = mDisabledSysPackages.get(name);
+ if (dis != null) {
+ // For disabled packages a new setting is created
+ // from the existing user id. This still has to be
+ // added to list of user id's
+ // Copy signatures from previous setting
+ if (dis.signatures.mSignatures != null) {
+ p.signatures.mSignatures = dis.signatures.mSignatures.clone();
+ }
+ p.userId = dis.userId;
+ // Clone permissions
+ p.grantedPermissions = new HashSet<String>(dis.grantedPermissions);
+ p.loadedPermissions = new HashSet<String>(dis.loadedPermissions);
+ // Clone component info
+ p.disabledComponents = new HashSet<String>(dis.disabledComponents);
+ p.enabledComponents = new HashSet<String>(dis.enabledComponents);
+ // Add new setting to list of user ids
+ addUserIdLP(p.userId, p, name);
+ } else {
+ // Assign new user id
+ p.userId = newUserIdLP(p);
+ }
} else {
p.userId = FIRST_APPLICATION_UID;
}
@@ -5904,15 +5955,39 @@ class PackageManagerService extends IPackageManager.Stub {
if (add) {
// Finish adding new package by adding it and updating shared
// user preferences
- insertPackageSettingLP(p, name, sharedUser);
+ addPackageSettingLP(p, name, sharedUser);
}
}
return p;
}
-
+
+ private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg,
+ File codePath, File resourcePath) {
+ p.pkg = pkg;
+ // Update code path if needed
+ if (!codePath.toString().equalsIgnoreCase(p.codePathString)) {
+ Log.w(TAG, "Code path for pkg : " + p.pkg.packageName +
+ " changing form " + p.codePathString + " to " + codePath);
+ p.codePath = codePath;
+ p.codePathString = codePath.toString();
+ }
+ //Update resource path if needed
+ if (!resourcePath.toString().equalsIgnoreCase(p.resourcePathString)) {
+ Log.w(TAG, "Resource path for pkg : " + p.pkg.packageName +
+ " changing form " + p.resourcePathString + " to " + resourcePath);
+ p.resourcePath = resourcePath;
+ p.resourcePathString = resourcePath.toString();
+ }
+ // Update version code if needed
+ if (pkg.mVersionCode != p.versionCode) {
+ p.versionCode = pkg.mVersionCode;
+ }
+ addPackageSettingLP(p, pkg.packageName, p.sharedUser);
+ }
+
// Utility method that adds a PackageSetting to mPackages and
// completes updating the shared user attributes
- private void insertPackageSettingLP(PackageSetting p, String name,
+ private void addPackageSettingLP(PackageSetting p, String name,
SharedUserSetting sharedUser) {
mPackages.put(name, p);
if (sharedUser != null) {
@@ -6005,7 +6080,7 @@ class PackageManagerService extends IPackageManager.Stub {
}
if (mUserIds.get(index) != null) {
reportSettingsProblem(Log.ERROR,
- "Adding duplicate shared id: " + uid
+ "Adding duplicate user id: " + uid
+ " name=" + name);
return false;
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 79d78ad..a3c3436 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -29,6 +29,10 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
@@ -58,7 +62,8 @@ import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
-class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor {
+class PowerManagerService extends IPowerManager.Stub
+ implements LocalPowerManager,Watchdog.Monitor, SensorEventListener {
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
@@ -72,7 +77,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
| PowerManager.SCREEN_DIM_WAKE_LOCK
| PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- | PowerManager.FULL_WAKE_LOCK;
+ | PowerManager.FULL_WAKE_LOCK
+ | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
// time since last state: time since last event:
// The short keylight delay comes from Gservices; this is the default.
@@ -138,6 +144,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
private int[] mBroadcastQueue = new int[] { -1, -1, -1 };
private int[] mBroadcastWhy = new int[3];
private int mPartialCount = 0;
+ private int mProximityCount = 0;
private int mPowerState;
private boolean mOffBecauseOfUser;
private int mUserState;
@@ -175,6 +182,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
private IActivityManager mActivityService;
private IBatteryStats mBatteryStats;
private BatteryService mBatteryService;
+ private SensorManager mSensorManager;
+ private Sensor mProximitySensor;
private boolean mDimScreen = true;
private long mNextTimeout;
private volatile int mPokey = 0;
@@ -536,6 +545,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
wl.minState = SCREEN_DIM;
break;
case PowerManager.PARTIAL_WAKE_LOCK:
+ case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
break;
default:
// just log and bail. we're in the server, so don't
@@ -583,6 +593,11 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
}
}
Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
+ } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
+ mProximityCount++;
+ if (mProximityCount == 1) {
+ enableProximityLockLocked();
+ }
}
if (newlock) {
acquireUid = wl.uid;
@@ -639,6 +654,11 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
Power.releaseWakeLock(PARTIAL_NAME);
}
+ } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
+ mProximityCount--;
+ if (mProximityCount == 0) {
+ disableProximityLockLocked();
+ }
}
// Unlink the lock from the binder.
wl.binder.unlinkToDeath(wl, 0);
@@ -1996,4 +2016,47 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
public void monitor() {
synchronized (mLocks) { }
}
+
+ public int getSupportedWakeLockFlags() {
+ int result = PowerManager.PARTIAL_WAKE_LOCK
+ | PowerManager.FULL_WAKE_LOCK
+ | PowerManager.SCREEN_DIM_WAKE_LOCK;
+
+ // call getSensorManager() to make sure mProximitySensor is initialized
+ getSensorManager();
+ if (mProximitySensor != null) {
+ result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
+ }
+
+ return result;
+ }
+
+ private SensorManager getSensorManager() {
+ if (mSensorManager == null) {
+ mSensorManager = new SensorManager(mHandlerThread.getLooper());
+ mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ }
+ return mSensorManager;
+ }
+
+ private void enableProximityLockLocked() {
+ mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
+ }
+
+ private void disableProximityLockLocked() {
+ mSensorManager.unregisterListener(this);
+ }
+
+ public void onSensorChanged(SensorEvent event) {
+ long milliseconds = event.timestamp / 1000000;
+ if (event.values[0] == 0.0) {
+ goToSleep(milliseconds);
+ } else {
+ userActivity(milliseconds, false);
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ // ignore
+ }
}
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
new file mode 100644
index 0000000..7f0e90d
--- /dev/null
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import com.android.internal.app.ShutdownThread;
+
+public class ShutdownActivity extends Activity {
+
+ private static final String TAG = "ShutdownActivity";
+ private boolean mConfirm;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mConfirm = getIntent().getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
+ Log.i(TAG, "onCreate(): confirm=" + mConfirm);
+
+ Handler h = new Handler();
+ h.post(new Runnable() {
+ public void run() {
+ ShutdownThread.shutdown(ShutdownActivity.this, mConfirm);
+ }
+ });
+ }
+}
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
new file mode 100644
index 0000000..b681961
--- /dev/null
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.backup.AbsoluteFileBackupHelper;
+import android.backup.BackupDataInput;
+import android.backup.BackupDataInputStream;
+import android.backup.BackupDataOutput;
+import android.backup.BackupHelper;
+import android.backup.BackupHelperAgent;
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.os.ServiceManager;
+import android.os.SystemService;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Backup agent for various system-managed data
+ */
+public class SystemBackupAgent extends BackupHelperAgent {
+ private static final String TAG = "SystemBackupAgent";
+
+ private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
+ private static final String WALLPAPER_INFO = "/data/system/wallpaper_info.xml";
+
+ @Override
+ public void onCreate() {
+ addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+ new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+ throws IOException {
+ boolean success = false;
+ try {
+ super.onRestore(data, appVersionCode, newState);
+
+ WallpaperService wallpaper = (WallpaperService)ServiceManager.getService(
+ Context.WALLPAPER_SERVICE);
+ wallpaper.settingsRestored();
+ } catch (IOException ex) {
+ // If there was a failure, delete everything for the wallpaper, this is too aggresive,
+ // but this is hopefully a rare failure.
+ Log.d(TAG, "restore failed", ex);
+ (new File(WALLPAPER_IMAGE)).delete();
+ (new File(WALLPAPER_INFO)).delete();
+ }
+ }
+}
diff --git a/services/java/com/android/server/WallpaperService.java b/services/java/com/android/server/WallpaperService.java
index d921baf..67b60a6 100644
--- a/services/java/com/android/server/WallpaperService.java
+++ b/services/java/com/android/server/WallpaperService.java
@@ -24,8 +24,9 @@ import android.app.IWallpaperServiceCallback;
import android.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
import android.os.Binder;
import android.os.RemoteException;
import android.os.FileObserver;
@@ -33,30 +34,38 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.util.Config;
import android.util.Log;
+import android.util.Xml;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import com.android.internal.util.FastXmlSerializer;
class WallpaperService extends IWallpaperService.Stub {
- private static final String TAG = WallpaperService.class.getSimpleName();
+ private static final String TAG = "WallpaperService";
+
+ private Object mLock = new Object();
private static final File WALLPAPER_DIR = new File(
"/data/data/com.android.settings/files");
private static final String WALLPAPER = "wallpaper";
private static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER);
- private static final String PREFERENCES = "wallpaper-hints";
-
- private static final String HINT_WIDTH = "hintWidth";
- private static final String HINT_HEIGHT = "hintHeight";
-
/**
* List of callbacks registered they should each be notified
* when the wallpaper is changed.
*/
private final RemoteCallbackList<IWallpaperServiceCallback> mCallbacks
= new RemoteCallbackList<IWallpaperServiceCallback>();
-
+
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
* that the wallpaper has changed. The CREATE is triggered when there is no
@@ -64,16 +73,23 @@ class WallpaperService extends IWallpaperService.Stub {
* everytime the wallpaper is changed.
*/
private final FileObserver mWallpaperObserver = new FileObserver(
- WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE) {
+ WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE | DELETE | DELETE_SELF) {
@Override
public void onEvent(int event, String path) {
if (path == null) {
return;
}
+ synchronized (mLock) {
+ // changing the wallpaper means we'll need to back up the new one
+ long origId = Binder.clearCallingIdentity();
+ BackupManager bm = new BackupManager(mContext);
+ bm.dataChanged();
+ Binder.restoreCallingIdentity(origId);
- File changedFile = new File(WALLPAPER_DIR, path);
- if (WALLPAPER_FILE.equals(changedFile)) {
- notifyCallbacks();
+ File changedFile = new File(WALLPAPER_DIR, path);
+ if (WALLPAPER_FILE.equals(changedFile)) {
+ notifyCallbacksLocked();
+ }
}
}
};
@@ -82,17 +98,14 @@ class WallpaperService extends IWallpaperService.Stub {
private int mWidth = -1;
private int mHeight = -1;
+ private String mName = "";
public WallpaperService(Context context) {
if (Config.LOGD) Log.d(TAG, "WallpaperService startup");
mContext = context;
- createFilesDir();
+ WALLPAPER_DIR.mkdirs();
+ loadSettingsLocked();
mWallpaperObserver.startWatching();
-
- SharedPreferences preferences = mContext.getSharedPreferences(PREFERENCES,
- Context.MODE_PRIVATE);
- mWidth = preferences.getInt(HINT_WIDTH, -1);
- mHeight = preferences.getInt(HINT_HEIGHT, -1);
}
@Override
@@ -102,9 +115,11 @@ class WallpaperService extends IWallpaperService.Stub {
}
public void clearWallpaper() {
- File f = WALLPAPER_FILE;
- if (f.exists()) {
- f.delete();
+ synchronized (mLock) {
+ File f = WALLPAPER_FILE;
+ if (f.exists()) {
+ f.delete();
+ }
}
}
@@ -115,70 +130,62 @@ class WallpaperService extends IWallpaperService.Stub {
throw new IllegalArgumentException("width and height must be > 0");
}
- if (width != mWidth || height != mHeight) {
- mWidth = width;
- mHeight = height;
-
- SharedPreferences preferences = mContext.getSharedPreferences(PREFERENCES,
- Context.MODE_PRIVATE);
-
- final SharedPreferences.Editor editor = preferences.edit();
- editor.putInt(HINT_WIDTH, width);
- editor.putInt(HINT_HEIGHT, height);
- editor.commit();
+ synchronized (mLock) {
+ if (width != mWidth || height != mHeight) {
+ mWidth = width;
+ mHeight = height;
+ saveSettingsLocked();
+ }
}
}
public int getWidthHint() throws RemoteException {
- return mWidth;
+ synchronized (mLock) {
+ return mWidth;
+ }
}
public int getHeightHint() throws RemoteException {
- return mHeight;
+ synchronized (mLock) {
+ return mHeight;
+ }
}
public ParcelFileDescriptor getWallpaper(IWallpaperServiceCallback cb) {
- try {
- mCallbacks.register(cb);
- File f = WALLPAPER_FILE;
- if (!f.exists()) {
- return null;
+ synchronized (mLock) {
+ try {
+ mCallbacks.register(cb);
+ File f = WALLPAPER_FILE;
+ if (!f.exists()) {
+ return null;
+ }
+ return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ /* Shouldn't happen as we check to see if the file exists */
+ if (Config.LOGD) Log.d(TAG, "Error getting wallpaper", e);
}
- return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
- } catch (FileNotFoundException e) {
-
- /* Shouldn't happen as we check to see if the file exists */
- if (Config.LOGD) Log.d(TAG, "Error getting wallpaper", e);
+ return null;
}
- return null;
}
- public ParcelFileDescriptor setWallpaper() {
+ public ParcelFileDescriptor setWallpaper(String name) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
- try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
- MODE_CREATE|MODE_READ_WRITE);
-
- // changing the wallpaper means we'll need to back up the new one
- long origId = Binder.clearCallingIdentity();
- BackupManager bm = new BackupManager(mContext);
- bm.dataChanged();
- Binder.restoreCallingIdentity(origId);
-
- return fd;
- } catch (FileNotFoundException e) {
- if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
- }
- return null;
- }
-
- private void createFilesDir() {
- if (!WALLPAPER_DIR.exists()) {
- WALLPAPER_DIR.mkdirs();
+ synchronized (mLock) {
+ if (name == null) name = "";
+ mName = name;
+ saveSettingsLocked();
+ try {
+ ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
+ MODE_CREATE|MODE_READ_WRITE);
+ return fd;
+ } catch (FileNotFoundException e) {
+ if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
+ }
+ return null;
}
}
- private void notifyCallbacks() {
+ private void notifyCallbacksLocked() {
final int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; i++) {
try {
@@ -195,9 +202,185 @@ class WallpaperService extends IWallpaperService.Stub {
}
private void checkPermission(String permission) {
- if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) {
+ if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
+ ", must have permission " + permission);
}
}
+
+ private static JournaledFile makeJournaledFile() {
+ final String base = "/data/system/wallpaper_info.xml";
+ return new JournaledFile(new File(base), new File(base + ".tmp"));
+ }
+
+ private void saveSettingsLocked() {
+ JournaledFile journal = makeJournaledFile();
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(journal.chooseForWrite(), false);
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, "utf-8");
+ out.startDocument(null, true);
+
+ out.startTag(null, "wp");
+ out.attribute(null, "width", Integer.toString(mWidth));
+ out.attribute(null, "height", Integer.toString(mHeight));
+ out.attribute(null, "name", mName);
+ out.endTag(null, "wp");
+
+ out.endDocument();
+ stream.close();
+ journal.commit();
+ } catch (IOException e) {
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException ex) {
+ // Ignore
+ }
+ journal.rollback();
+ }
+ }
+
+ private void loadSettingsLocked() {
+ JournaledFile journal = makeJournaledFile();
+ FileInputStream stream = null;
+ File file = journal.chooseForRead();
+ boolean success = false;
+ try {
+ stream = new FileInputStream(file);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, null);
+
+ int type;
+ int providerIndex = 0;
+ do {
+ type = parser.next();
+ if (type == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ if ("wp".equals(tag)) {
+ mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
+ mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
+ mName = parser.getAttributeValue(null, "name");
+ }
+ }
+ } while (type != XmlPullParser.END_DOCUMENT);
+ success = true;
+ } catch (NullPointerException e) {
+ Log.w(TAG, "failed parsing " + file + " " + e);
+ } catch (NumberFormatException e) {
+ Log.w(TAG, "failed parsing " + file + " " + e);
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "failed parsing " + file + " " + e);
+ } catch (IOException e) {
+ Log.w(TAG, "failed parsing " + file + " " + e);
+ } catch (IndexOutOfBoundsException e) {
+ Log.w(TAG, "failed parsing " + file + " " + e);
+ }
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+
+ if (!success) {
+ mWidth = -1;
+ mHeight = -1;
+ mName = "";
+ }
+ }
+
+ void settingsRestored() {
+ boolean success = false;
+ synchronized (mLock) {
+ loadSettingsLocked();
+ // If there's a wallpaper name, we use that. If that can't be loaded, then we
+ // use the default.
+ if ("".equals(mName)) {
+ success = true;
+ } else {
+ success = restoreNamedResourceLocked();
+ }
+ }
+
+ if (!success) {
+ Log.e(TAG, "Failed to restore wallpaper: '" + mName + "'");
+ mName = "";
+ WALLPAPER_FILE.delete();
+ }
+ saveSettingsLocked();
+ }
+
+ boolean restoreNamedResourceLocked() {
+ if (mName.length() > 4 && "res:".equals(mName.substring(0, 4))) {
+ String resName = mName.substring(4);
+
+ String pkg = null;
+ int colon = resName.indexOf(':');
+ if (colon > 0) {
+ pkg = resName.substring(0, colon);
+ }
+
+ String ident = null;
+ int slash = resName.lastIndexOf('/');
+ if (slash > 0) {
+ ident = resName.substring(slash+1);
+ }
+
+ String type = null;
+ if (colon > 0 && slash > 0 && (slash-colon) > 1) {
+ type = resName.substring(colon+1, slash);
+ }
+
+ if (pkg != null && ident != null && type != null) {
+ int resId = -1;
+ InputStream res = null;
+ FileOutputStream fos = null;
+ try {
+ Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
+ Resources r = c.getResources();
+ resId = r.getIdentifier(resName, null, null);
+ if (resId == 0) {
+ Log.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
+ + " ident=" + ident);
+ return false;
+ }
+
+ res = r.openRawResource(resId);
+ fos = new FileOutputStream(WALLPAPER_FILE);
+
+ byte[] buffer = new byte[32768];
+ int amt;
+ while ((amt=res.read(buffer)) > 0) {
+ fos.write(buffer, 0, amt);
+ }
+ // mWallpaperObserver will notice the close and send the change broadcast
+
+ Log.d(TAG, "Restored wallpaper: " + resName);
+ return true;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Package name " + pkg + " not found");
+ } catch (Resources.NotFoundException e) {
+ Log.e(TAG, "Resource not found: " + resId);
+ } catch (IOException e) {
+ Log.e(TAG, "IOException while restoring wallpaper ", e);
+ } finally {
+ if (res != null) {
+ try {
+ res.close();
+ } catch (IOException ex) {}
+ }
+ if (fos != null) {
+ try {
+ fos.close();
+ } catch (IOException ex) {}
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index f25c221..d4e57d2 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -93,6 +93,9 @@ public class WifiService extends IWifiManager.Stub {
private boolean mDeviceIdle;
private int mPluggedType;
+ // true if the user enabled Wifi while in airplane mode
+ private boolean mAirplaneModeOverwridden;
+
private final LockList mLocks = new LockList();
// some wifi lock statistics
private int mFullLocksAcquired;
@@ -219,6 +222,8 @@ public class WifiService extends IWifiManager.Stub {
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ // clear our flag indicating the user has overwridden airplane mode
+ mAirplaneModeOverwridden = false;
updateWifiState();
}
},
@@ -292,6 +297,8 @@ public class WifiService extends IWifiManager.Stub {
synchronized (mWifiHandler) {
sWakeLock.acquire();
mLastEnableUid = Binder.getCallingUid();
+ // set a flag if the user is enabling Wifi while in airplane mode
+ mAirplaneModeOverwridden = (enable && isAirplaneModeOn() && isAirplaneToggleable());
sendEnableMessage(enable, true, Binder.getCallingUid());
}
@@ -312,7 +319,7 @@ public class WifiService extends IWifiManager.Stub {
if (mWifiState == eventualWifiState) {
return true;
}
- if (enable && isAirplaneModeOn()) {
+ if (enable && isAirplaneModeOn() && !mAirplaneModeOverwridden) {
return false;
}
@@ -1495,7 +1502,7 @@ public class WifiService extends IWifiManager.Stub {
private void updateWifiState() {
boolean wifiEnabled = getPersistedWifiEnabled();
- boolean airplaneMode = isAirplaneModeOn();
+ boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden;
boolean lockHeld = mLocks.hasLocks();
int strongestLockMode;
boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
@@ -1559,6 +1566,13 @@ public class WifiService extends IWifiManager.Stub {
|| airplaneModeRadios.contains(Settings.System.RADIO_WIFI);
}
+ private boolean isAirplaneToggleable() {
+ String toggleableRadios = Settings.System.getString(mContext.getContentResolver(),
+ Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+ return toggleableRadios != null
+ && toggleableRadios.contains(Settings.System.RADIO_WIFI);
+ }
+
/**
* Returns true if Wi-Fi is sensitive to airplane mode, and airplane mode is
* currently on.
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 78ca831..edba5b6 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -8231,7 +8231,9 @@ public class WindowManagerService extends IWindowManager.Stub
// This has changed the visibility of windows, so perform
// a new layout to get them all up-to-date.
mLayoutNeeded = true;
- moveInputMethodWindowsIfNeededLocked(true);
+ if (!moveInputMethodWindowsIfNeededLocked(true)) {
+ assignLayersLocked();
+ }
performLayoutLockedInner();
updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8a4b8f9..552d5be 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4742,6 +4742,57 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
Binder.restoreCallingIdentity(callingId);
}
}
+
+ /*
+ * The pkg name and uid have to be specified.
+ * @see android.app.IActivityManager#killApplicationWithUid(java.lang.String, int)
+ */
+ public void killApplicationWithUid(String pkg, int uid) {
+ if (pkg == null) {
+ return;
+ }
+ // Make sure the uid is valid.
+ if (uid < 0) {
+ Log.w(TAG, "Invalid uid specified for pkg : " + pkg);
+ return;
+ }
+ int callerUid = Binder.getCallingUid();
+ // Only the system server can kill an application
+ if (callerUid == Process.SYSTEM_UID) {
+ uninstallPackageLocked(pkg, uid, false);
+ } else {
+ throw new SecurityException(callerUid + " cannot kill pkg: " +
+ pkg);
+ }
+ }
+
+ public void closeSystemDialogs(String reason) {
+ Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ if (reason != null) {
+ intent.putExtra("reason", reason);
+ }
+
+ final int uid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ synchronized (this) {
+ int i = mWatchers.beginBroadcast();
+ while (i > 0) {
+ i--;
+ IActivityWatcher w = mWatchers.getBroadcastItem(i);
+ if (w != null) {
+ try {
+ w.closingSystemDialogs(reason);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mWatchers.finishBroadcast();
+
+ broadcastIntentLocked(null, null, intent, null,
+ null, 0, null, null, null, false, false, -1, uid);
+ }
+ Binder.restoreCallingIdentity(origId);
+ }
private void restartPackageLocked(final String packageName, int uid) {
uninstallPackageLocked(packageName, uid, false);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 33e793b..5aed396 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -926,17 +926,16 @@ public class StatusBarPolicy {
// Use Evdo icon
evdoIconList = this.sSignalImages_evdo;
- int evdoEcio = mSignalStrength.getEvdoEcio();
+ int evdoDbm = mSignalStrength.getEvdoDbm();
int evdoSnr = mSignalStrength.getEvdoSnr();
- int levelEvdoEcio = 0;
+ int levelEvdoDbm = 0;
int levelEvdoSnr = 0;
- // Ec/Io are in dB*10
- if (evdoEcio >= -650) levelEvdoEcio = 4;
- else if (evdoEcio >= -750) levelEvdoEcio = 3;
- else if (evdoEcio >= -900) levelEvdoEcio = 2;
- else if (evdoEcio >= -1050) levelEvdoEcio = 1;
- else levelEvdoEcio = 0;
+ if (evdoDbm >= -65) levelEvdoDbm = 4;
+ else if (evdoDbm >= -75) levelEvdoDbm = 3;
+ else if (evdoDbm >= -90) levelEvdoDbm = 2;
+ else if (evdoDbm >= -105) levelEvdoDbm = 1;
+ else levelEvdoDbm = 0;
if (evdoSnr > 7) levelEvdoSnr = 4;
else if (evdoSnr > 5) levelEvdoSnr = 3;
@@ -944,7 +943,7 @@ public class StatusBarPolicy {
else if (evdoSnr > 1) levelEvdoSnr = 1;
else levelEvdoSnr = 0;
- evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
+ evdoIconLevel = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
mPhoneEvdoData.iconId = evdoIconList[evdoIconLevel];
mService.updateIcon(mPhoneEvdoIcon, mPhoneEvdoData, null);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 890f930..82539fb 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -40,7 +40,6 @@ import java.util.List;
/**
* Manages SMS operations such as sending data, text, and pdu SMS messages.
* Get this object by calling the static method SmsManager.getDefault().
- * @hide
*/
public final class SmsManager {
private static SmsManager sInstance;
@@ -202,6 +201,8 @@ public final class SmsManager {
/**
* Send a raw SMS PDU.
+ * A PDU is a protocol data unit. It contains the message and the
+ * associated meta information.
*
* @param smsc the SMSC to send the message through, or NULL for the
* default SMSC
@@ -219,8 +220,6 @@ public final class SmsManager {
* @param deliveryIntent if not NULL this <code>PendingIntent</code> is
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
- *
- * @hide
*/
private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
@@ -252,6 +251,8 @@ public final class SmsManager {
/**
* Copy a raw SMS PDU to the ICC.
+ * ICC (Integrated Circuit Card) is the card of the device.
+ * For example, this can be the SIM or USIM for GSM.
*
* @param smsc the SMSC for this message, or NULL for the default SMSC
* @param pdu the raw PDU to store
@@ -278,6 +279,8 @@ public final class SmsManager {
/**
* Delete the specified message from the ICC.
+ * ICC (Integrated Circuit Card) is the card of the device.
+ * For example, this can be the SIM or USIM for GSM.
*
* @param messageIndex is the record index of the message on ICC
* @return true for success
@@ -304,6 +307,8 @@ public final class SmsManager {
/**
* Update the specified message on the ICC.
+ * ICC (Integrated Circuit Card) is the card of the device.
+ * For example, this can be the SIM or USIM for GSM.
*
* @param messageIndex record index of message to update
* @param newStatus new message status (STATUS_ON_ICC_READ,
@@ -331,6 +336,8 @@ public final class SmsManager {
/**
* Retrieves all messages currently stored on ICC.
+ * ICC (Integrated Circuit Card) is the card of the device.
+ * For example, this can be the SIM or USIM for GSM.
*
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects
*
@@ -359,12 +366,12 @@ public final class SmsManager {
* <code>getAllMessagesFromIcc</code>
* @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
*/
- private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
+ private ArrayList<SmsMessage> createMessageListFromRawRecords(List<SmsRawData> records) {
ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
if (records != null) {
int count = records.size();
for (int i = 0; i < count; i++) {
- SmsRawData data = (SmsRawData)records.get(i);
+ SmsRawData data = records.get(i);
// List contains all records, including "free" records (null)
if (data != null) {
SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 775b034..0617dad 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -28,13 +28,13 @@ import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
import java.lang.Math;
import java.util.ArrayList;
+import java.util.Arrays;
import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
/**
* A Short Message Service message.
- * @hide
*/
public class SmsMessage {
private static final boolean LOCAL_DEBUG = true;
@@ -49,18 +49,6 @@ public class SmsMessage {
UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
}
- /**
- * TODO(cleanup): given that we now have more than one possible
- * 7bit encoding, this result starts to look rather vague and
- * maybe confusing... If this is just an indication of code unit
- * size, maybe that is no problem. Otherwise, should we try to
- * create an aggregate collection of GSM and CDMA encodings? CDMA
- * contains a superset of the encodings we use (it does not
- * support 8-bit GSM, but we also do not use that encoding
- * currently)... We could get rid of these and directly reference
- * the CDMA encoding definitions...
- */
-
/** User data text encoding code unit size */
public static final int ENCODING_UNKNOWN = 0;
public static final int ENCODING_7BIT = 1;
@@ -71,24 +59,9 @@ public class SmsMessage {
public static final int MAX_USER_DATA_BYTES = 140;
/**
- * TODO(cleanup): It would be more flexible and less fragile to
- * rewrite this (meaning get rid of the following constant) such
- * that an actual UDH is taken into consideration (meaning its
- * length is measured), allowing for messages that actually
- * contain other UDH fields... Hence it is actually a shame to
- * extend the API with this constant. If necessary, maybe define
- * the size of such a header and let the math for calculating
- * max_octets/septets be done elsewhere. And, while I am griping,
- * if we use the word septet, we should use the word octet in
- * corresponding places, not byte...
- */
-
- /**
* The maximum number of payload bytes per message if a user data header
* is present. This assumes the header only contains the
* CONCATENATED_8_BIT_REFERENCE element.
- *
- * @hide pending API Council approval to extend the public API
*/
public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
@@ -103,17 +76,26 @@ public class SmsMessage {
public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
/** Contains actual SmsMessage. Only public for debugging and for framework layer.
- * {@hide}
- */
+ *
+ * @hide
+ */
public SmsMessageBase mWrappedSmsMessage;
- public static class SubmitPdu extends SubmitPduBase {
+ public static class SubmitPdu {
- //Constructor
- public SubmitPdu() {
+ public byte[] encodedScAddress; // Null if not applicable.
+ public byte[] encodedMessage;
+
+ public String toString() {
+ return "SubmitPdu: encodedScAddress = "
+ + Arrays.toString(encodedScAddress)
+ + ", encodedMessage = "
+ + Arrays.toString(encodedMessage);
}
- /* {@hide} */
+ /**
+ * @hide
+ */
protected SubmitPdu(SubmitPduBase spb) {
this.encodedMessage = spb.encodedMessage;
this.encodedScAddress = spb.encodedScAddress;
@@ -121,7 +103,11 @@ public class SmsMessage {
}
- // Constructor
+ /**
+ * Constructor
+ *
+ * @hide
+ */
public SmsMessage() {
this(getSmsFacility());
}
@@ -278,8 +264,8 @@ public class SmsMessage {
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
int activePhone = TelephonyManager.getDefault().getPhoneType();
TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
- com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly) :
- com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly) :
+ com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
int ret[] = new int[4];
ret[0] = ted.msgCount;
ret[1] = ted.codeUnitCount;
@@ -295,12 +281,14 @@ public class SmsMessage {
* @param text text, must not be null.
* @return an <code>ArrayList</code> of strings that, in order,
* comprise the original msg text
+ *
+ * @hide
*/
public static ArrayList<String> fragmentText(String text) {
int activePhone = TelephonyManager.getDefault().getPhoneType();
TextEncodingDetails ted = (PHONE_TYPE_CDMA == activePhone) ?
- com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false) :
- com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false);
+ com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) :
+ com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
// TODO(cleanup): The code here could be rolled into the logic
// below cleanly if these MAX_* constants were defined more
@@ -321,11 +309,8 @@ public class SmsMessage {
while (pos < textLen) {
int nextPos = 0; // Counts code units.
if (ted.codeUnitSize == ENCODING_7BIT) {
- if (PHONE_TYPE_CDMA == activePhone) {
- nextPos = pos + Math.min(limit, textLen - pos);
- } else {
- nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit);
- }
+ // For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
+ nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit);
} else { // Assume unicode.
nextPos = pos + Math.min(limit / 2, textLen - pos);
}
@@ -346,10 +331,11 @@ public class SmsMessage {
* current encoding.
*
* @param messageBody the message to encode
- * @param use7bitOnly if true, characters that are not part of the GSM
- * alphabet are counted as a single space char. If false, a
- * messageBody containing non-GSM alphabet characters is calculated
- * for 16-bit encoding.
+ * @param use7bitOnly if true, characters that are not part of the radio
+ * specific (GSM / CDMA) alphabet encoding are converted to as a
+ * single space characters. If false, a messageBody containing
+ * non-GSM or non-CDMA alphabet characters are encoded using
+ * 16-bit encoding.
* @return an int[4] with int[0] being the number of SMS's required, int[1]
* the number of code units used, and int[2] is the number of code
* units remaining until the next message. int[3] is the encoding
@@ -691,6 +677,8 @@ public class SmsMessage {
/** This method returns the reference to a specific
* SmsMessage object, which is used for accessing its static methods.
* @return Specific SmsMessage.
+ *
+ * @hide
*/
private static final SmsMessageBase getSmsFacility(){
int activePhone = TelephonyManager.getDefault().getPhoneType();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ba5c6e7..ed9af66 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -256,7 +256,7 @@ public class TelephonyManager {
* No phone module
*
*/
- public static final int PHONE_TYPE_NONE = 0;
+ public static final int PHONE_TYPE_NONE = RILConstants.NO_PHONE;
/**
* GSM phone
diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java
index cdd707e..241c485 100644
--- a/telephony/java/android/telephony/gsm/SmsManager.java
+++ b/telephony/java/android/telephony/gsm/SmsManager.java
@@ -43,6 +43,7 @@ import java.util.ArrayList;
return sInstance;
}
+ @Deprecated
private SmsManager() {
mSmsMgrProxy = android.telephony.SmsManager.getDefault();
}
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index ebdac4e..6ebd8d6 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -1225,8 +1225,10 @@ public interface CommandsInterface {
* Request the device MDN / H_SID / H_NID / MIN.
* "response" is const char **
* [0] is MDN if CDMA subscription is available
- * [1] is H_SID (Home SID) in hexadecimal if CDMA subscription is available
- * [2] is H_NID (Home NID) in hexadecimal if CDMA subscription is available
+ * [1] is a comma separated list of H_SID (Home SID) in decimal format
+ * if CDMA subscription is available
+ * [2] is a comma separated list of H_NID (Home NID) in decimal format
+ * if CDMA subscription is available
* [3] is MIN (10 digits, MIN2+MIN1) if CDMA subscription is available
*/
public void getCDMASubscription(Message response);
@@ -1298,11 +1300,13 @@ public interface CommandsInterface {
* the username for APN, or NULL
* @param password
* the password for APN, or NULL
+ * @param authType
+ * the PAP / CHAP auth type. Values is one of SETUP_DATA_AUTH_*
* @param result
* Callback message
*/
public void setupDataCall(String radioTechnology, String profile, String apn,
- String user, String password, Message result);
+ String user, String password, String authType, Message result);
/**
* Deactivate packet data connection
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 52f6526..50bf218 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -1237,10 +1237,17 @@ public final class RIL extends BaseCommands implements CommandsInterface {
*/
public void
setupDefaultPDP(String apn, String user, String password, Message result) {
- String radioTechnology = "1"; //0 for CDMA, 1 for GSM/UMTS
+ int radioTechnology;
+ int authType;
String profile = ""; //profile number, NULL for GSM/UMTS
- setupDataCall(radioTechnology, profile, apn, user,
- password, result);
+
+ radioTechnology = RILConstants.SETUP_DATA_TECH_GSM;
+ //TODO(): Add to the APN database, AuthType is set to CHAP/PAP
+ authType = (user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP
+ : RILConstants.SETUP_DATA_AUTH_NONE;
+
+ setupDataCall(Integer.toString(radioTechnology), profile, apn, user,
+ password, Integer.toString(authType), result);
}
@@ -1259,7 +1266,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
*/
public void
setupDataCall(String radioTechnology, String profile, String apn,
- String user, String password, Message result) {
+ String user, String password, String authType, Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
@@ -1270,15 +1277,12 @@ public final class RIL extends BaseCommands implements CommandsInterface {
rr.mp.writeString(apn);
rr.mp.writeString(user);
rr.mp.writeString(password);
- //TODO(): Add to the APN database, AuthType is set to CHAP/PAP
- // 0 => Neither PAP nor CHAP will be performed, 3 => PAP / CHAP will be performed.
- if (user != null)
- rr.mp.writeString("3");
- else
- rr.mp.writeString("0");
-
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
- + apn);
+ rr.mp.writeString(authType);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ + requestToString(rr.mRequest) + " " + radioTechnology + " "
+ + profile + " " + apn + " " + user + " "
+ + password + " " + authType);
send(rr);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 7834018..90a82f9 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -68,8 +68,9 @@ public interface RILConstants {
int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
int CDMA_CELL_BROADCAST_SMS_ENABLED = 0;
- int CDMA_PHONE = 0;
+ int NO_PHONE = 0;
int GSM_PHONE = 1;
+ int CDMA_PHONE = 2;
int CDM_TTY_MODE_DISABLED = 0;
int CDM_TTY_MODE_ENABLED = 1;
@@ -78,6 +79,14 @@ public interface RILConstants {
int CDM_TTY_HCO_MODE = 2;
int CDM_TTY_VCO_MODE = 3;
+ /* Setup a packet data connection. See ril.h RIL_REQUEST_SETUP_DATA_CALL */
+ int SETUP_DATA_TECH_CDMA = 0;
+ int SETUP_DATA_TECH_GSM = 1;
+ int SETUP_DATA_AUTH_NONE = 0;
+ int SETUP_DATA_AUTH_PAP = 1;
+ int SETUP_DATA_AUTH_CHAP = 2;
+ int SETUP_DATA_AUTH_PAP_CHAP = 3;
+
/*
cat include/telephony/ril.h | \
egrep '^#define' | \
@@ -85,14 +94,6 @@ cat include/telephony/ril.h | \
>>java/android/com.android.internal.telephony/gsm/RILConstants.java
*/
-
- int RIL_SIM_ABSENT = 0;
- int RIL_SIM_NOT_READY = 1;
- int RIL_SIM_READY = 2;
- int RIL_SIM_PIN = 3;
- int RIL_SIM_PUK = 4;
- int RIL_SIM_NETWORK_PERSONALIZATION = 5;
-
/**
* No restriction at all including voice/SMS/USSD/SS/AV64
* and packet data.
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 8e76cd2..46b39a5 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -77,7 +77,6 @@ public abstract class ServiceStateTracker extends Handler {
// waiting period before recheck gprs and voice registration
public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
- public static final int MAX_NUM_DATA_STATE_READS = 15;
public static final int DATA_STATE_POLL_SLEEP_MS = 100;
//*****GSM events
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 9c78b98..6177c8a 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -118,6 +118,7 @@ public abstract class SmsMessageBase {
public int codeUnitSize;
}
+ // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
public static abstract class SubmitPduBase {
public byte[] encodedScAddress; // Null if not applicable.
public byte[] encodedMessage;
@@ -371,16 +372,10 @@ public abstract class SmsMessageBase {
* -or-
* 2. [x@y][ ]/[body]
*/
- String[] parts = messageBody.split("( /)|( )", 3);
- if (parts.length < 2 || parts[0].indexOf('@') == -1) return;
+ String[] parts = messageBody.split("( /)|( )", 2);
+ if (parts.length < 1 || parts[0].indexOf('@') == -1) return;
emailFrom = parts[0];
- if (parts.length == 3) {
- pseudoSubject = parts[1];
- emailBody = parts[2];
- } else {
- pseudoSubject = null;
- emailBody = parts[1];
- }
+ emailBody = parts[1];
isEmail = true;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index aec7aee..0d46777 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -777,6 +777,9 @@ public class CDMAPhone extends PhoneBase {
Intent intent = new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS);
ActivityManagerNative.broadcastStickyIntent(intent, null);
return false;
+ } else if ((mCT.state == Phone.State.OFFHOOK) && mCT.isInEmergencyCall()) {
+ // Do not allow data call to be enabled when emergency call is going on
+ return false;
} else {
return mDataConnection.setDataEnabled(true);
}
@@ -1057,6 +1060,7 @@ public class CDMAPhone extends PhoneBase {
onComplete.sendToTarget();
}
}
+ break;
default:{
throw new RuntimeException("unexpected event not handled");
@@ -1334,25 +1338,26 @@ public class CDMAPhone extends PhoneBase {
return isOtaSpNum;
}
- /**
- * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
- * OTASP dial string.
- *
- * @param dialStr the number to look up.
- * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
- */
+ /**
+ * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
+ * OTASP dial string.
+ *
+ * @param dialStr the number to look up.
+ * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
+ */
@Override
- public boolean isOtaSpNumber(String dialStr){
- boolean isOtaSpNum = false;
- if (dialStr != null) {
- isOtaSpNum = isIs683OtaSpDialStr(dialStr);
- if(isOtaSpNum == false){
- isOtaSpNum = isCarrierOtaSpNum(dialStr);
- }
- }
- if (DBG) Log.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
- return isOtaSpNum;
- }
+ public boolean isOtaSpNumber(String dialStr){
+ boolean isOtaSpNum = false;
+ String dialableStr = PhoneNumberUtils.extractNetworkPortion(dialStr);
+ if (dialableStr != null) {
+ isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
+ if (isOtaSpNum == false) {
+ isOtaSpNum = isCarrierOtaSpNum(dialableStr);
+ }
+ }
+ if (DBG) Log.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
+ return isOtaSpNum;
+ }
@Override
public int getCdmaEriIconIndex() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index cc456c5..84d6b3d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -80,6 +80,7 @@ public final class CdmaCallTracker extends CallTracker {
int pendingCallClirMode;
Phone.State state = Phone.State.IDLE;
+ private boolean mIsInEmergencyCall = false;
// boolean needsPoll;
@@ -210,6 +211,9 @@ public final class CdmaCallTracker extends CallTracker {
// Always unmute when initiating a new call
setMute(false);
+ // Check data call
+ disableDataCallInEmergencyCall(dialString);
+
String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
if(inEcm.equals("false")) {
cm.dial(pendingMO.address, clirMode, obtainCompleteMessage());
@@ -236,6 +240,9 @@ public final class CdmaCallTracker extends CallTracker {
private Connection
dialThreeWay (String dialString) {
if (!foregroundCall.isIdle()) {
+ // Check data call
+ disableDataCallInEmergencyCall(dialString);
+
// Attach the new connection to foregroundCall
pendingMO = new CdmaConnection(phone.getContext(),
dialString, this, foregroundCall);
@@ -529,6 +536,9 @@ public final class CdmaCallTracker extends CallTracker {
}
}
foregroundCall.setGeneric(false);
+
+ mIsInEmergencyCall = false;
+
// Dropped connections are removed from the CallTracker
// list but kept in the Call list
connections[i] = null;
@@ -668,8 +678,8 @@ public final class CdmaCallTracker extends CallTracker {
// the hangup reason is user ignoring or timing out. So conn.onDisconnect()
// is not called here. Instead, conn.onLocalDisconnect() is called.
conn.onLocalDisconnect();
- phone.notifyPreciseCallStateChanged();
updatePhoneState();
+ phone.notifyPreciseCallStateChanged();
return;
} else {
try {
@@ -957,6 +967,7 @@ public final class CdmaCallTracker extends CallTracker {
if (ar.exception == null) {
// Assume 3 way call is connected
pendingMO.onConnectedInOrOut();
+ pendingMO = null;
}
break;
@@ -966,6 +977,26 @@ public final class CdmaCallTracker extends CallTracker {
}
}
+ /**
+ * Disable data call when emergency call is connected
+ */
+ private void disableDataCallInEmergencyCall(String dialString) {
+ if (PhoneNumberUtils.isEmergencyNumber(dialString)) {
+ phone.disableDataConnectivity();
+ mIsInEmergencyCall = true;
+ }
+ }
+
+ /**
+ * Check if current call is in emergency call
+ *
+ * @return true if it is in emergency call
+ * false if it is not in emergency call
+ */
+ boolean isInEmergencyCall() {
+ return mIsInEmergencyCall;
+ }
+
protected void log(String msg) {
Log.d(LOG_TAG, "[CdmaCallTracker] " + msg);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index fef6d3c..4588f36 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -143,9 +143,10 @@ public class CdmaDataConnection extends DataConnection {
lastFailTime = -1;
lastFailCause = FailCause.NONE;
receivedDisconnectReq = false;
- phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE),
+ phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), null, null,
- null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+ null, Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
+ obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
}
private void tearDownData(Message msg) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index c4db609..3ab1f77 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -88,7 +88,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
int teleService = sms.getTeleService();
boolean handled = false;
- if (sms.getUserData() == null) {
+ if ((sms.getUserData() == null) && (SmsEnvelope.TELESERVICE_MWI != teleService)) {
if (Config.LOGD) {
Log.d(TAG, "Received SMS without user data");
}
@@ -99,10 +99,11 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
return Intents.RESULT_SMS_HANDLED;
}
- if (SmsEnvelope.TELESERVICE_WAP == teleService){
+ if (SmsEnvelope.TELESERVICE_WAP == teleService) {
return processCdmaWapPdu(sms.getUserData(), sms.messageRef,
sms.getOriginatingAddress());
- } else if (SmsEnvelope.TELESERVICE_VMN == teleService) {
+ } else if ((SmsEnvelope.TELESERVICE_VMN == teleService) ||
+ (SmsEnvelope.TELESERVICE_MWI == teleService)) {
// handling Voicemail
int voicemailCount = sms.getNumOfVoicemails();
Log.d(TAG, "Voicemail count=" + voicemailCount);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index d5da666..53f0274 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -121,8 +121,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
private int curSpnRule = 0;
private String mMdn;
- private int mHomeSystemId;
- private int mHomeNetworkId;
+ private int mHomeSystemId[] = null;
+ private int mHomeNetworkId[] = null;
private String mMin;
private String mPrlVersion;
@@ -398,15 +398,31 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
String cdmaSubscription[] = (String[])ar.result;
if (cdmaSubscription != null && cdmaSubscription.length >= 5) {
mMdn = cdmaSubscription[0];
- // TODO: Only grabbing the first SID/NID for now.
if (cdmaSubscription[1] != null) {
String[] sid = cdmaSubscription[1].split(",");
- mHomeSystemId = sid.length > 0 ? Integer.parseInt(sid[0], 16) : 0;
+ mHomeSystemId = new int[sid.length];
+ for (int i = 0; i < sid.length; i++) {
+ try {
+ mHomeSystemId[i] = Integer.parseInt(sid[i]);
+ } catch (NumberFormatException ex) {
+ Log.e(LOG_TAG, "error parsing system id: ", ex);
+ }
+ }
}
+ Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION SID=" + cdmaSubscription[1] );
+
if (cdmaSubscription[2] != null) {
String[] nid = cdmaSubscription[2].split(",");
- mHomeNetworkId = nid.length > 0 ? Integer.parseInt(nid[0], 16) : 0;
+ mHomeNetworkId = new int[nid.length];
+ for (int i = 0; i < nid.length; i++) {
+ try {
+ mHomeNetworkId[i] = Integer.parseInt(nid[i]);
+ } catch (NumberFormatException ex) {
+ Log.e(LOG_TAG, "error parsing network id: ", ex);
+ }
+ }
}
+ Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION NID=" + cdmaSubscription[2] );
mMin = cdmaSubscription[3];
mPrlVersion = cdmaSubscription[4];
Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION MDN=" + mMdn);
@@ -504,9 +520,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
dcTracker.sendMessage(msg);
- // Poll data state up to 15 times, with a 100ms delay
- // totaling 1.5 sec. Normal data disable action will finish in 100ms.
- for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+ // Poll data state up to 50 times, with a 100ms delay
+ // totaling 5 sec.
+ // TODO: change the 5 seconds wait from blocking to non-blocking.
+ for (int i = 0; i < 50; i++) {
DataConnectionTracker.State currentState = dcTracker.getState();
if (currentState != DataConnectionTracker.State.CONNECTED
&& currentState != DataConnectionTracker.State.DISCONNECTING) {
@@ -703,7 +720,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (pollingContext[0] == 0) {
boolean namMatch = false;
- if ((mHomeSystemId != 0) && (mHomeSystemId == newSS.getSystemId()) ) {
+ if (!isSidsAllZeros() && isHomeSid(newSS.getSystemId())) {
namMatch = true;
}
@@ -715,33 +732,43 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
// Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
- // TODO(Teleca): Validate this is correct.
- if (mIsInPrl) {
- if (namMatch && (mRoamingIndicator <= 2)) {
- // System is acquired, prl match, nam match and mRoamingIndicator <= 2
- newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
- } else {
- // System is acquired, prl match, no nam match or mRoamingIndicator > 2
- newSS.setCdmaRoamingIndicator(mRoamingIndicator);
- }
- } else {
- if (mRegistrationState == 5) {
- // System is acquired but prl not loaded or no prl match
+ newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+ boolean isPrlLoaded = true;
+ if (TextUtils.isEmpty(mPrlVersion)) {
+ isPrlLoaded = false;
+ }
+ if (!isPrlLoaded) {
+ newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
+ } else if (!isSidsAllZeros()) {
+ if (!namMatch && !mIsInPrl) {
+ // Use default
+ newSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator);
+ } else if (namMatch && !mIsInPrl) {
newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
+ } else if (!namMatch && mIsInPrl) {
+ // Use the one from PRL/ERI
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
} else {
- // Use the default indicator
+ // It means namMatch && mIsInPrl
+ if ((mRoamingIndicator <= 2)) {
+ newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
+ } else {
+ // Use the one from PRL/ERI
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+ }
}
}
- newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
// NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
// depending on the mRoamingIndicator.
if (DBG) {
log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
- + ". mCdmaRoaming = " + mCdmaRoaming + ", namMatch = " + namMatch
- + ", mIsInPrl = " + mIsInPrl + ", mRoamingIndicator = " + mRoamingIndicator
+ + ". mCdmaRoaming = " + mCdmaRoaming + ", isPrlLoaded = " + isPrlLoaded
+ + ". namMatch = " + namMatch + " , mIsInPrl = " + mIsInPrl
+ + ", mRoamingIndicator = " + mRoamingIndicator
+ ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
}
pollStateDone();
@@ -1073,7 +1100,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
/**
* send signal-strength-changed notification if changed
- * Called both for solicited and unsolicited signal stength updates
+ * Called both for solicited and unsolicited signal strength updates
*/
private void
onSignalStrengthResult(AsyncResult ar) {
@@ -1086,15 +1113,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
int[] ints = (int[])ar.result;
int offset = 2;
- int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -1;
- int cdmaEcio = (ints[offset+1] > 0) ? -ints[offset+1] : -1;
+ int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -120;
+ int cdmaEcio = (ints[offset+1] > 0) ? -ints[offset+1] : -160;
int evdoRssi = -1;
int evdoEcio = -1;
int evdoSnr = -1;
if ((networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
|| (networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
- evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -1;
+ evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -120;
evdoEcio = (ints[offset+3] > 0) ? -ints[offset+3] : -1;
evdoSnr = ((ints[offset+4] > 0) && (ints[offset+4] <= 8)) ? ints[offset+4] : -1;
}
@@ -1449,6 +1476,31 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
+ private boolean isSidsAllZeros() {
+ if (mHomeSystemId != null) {
+ for (int i=0; i < mHomeSystemId.length; i++) {
+ if (mHomeSystemId[i] != 0) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check whether a specified system ID that matches one of the home system IDs.
+ */
+ private boolean isHomeSid(int sid) {
+ if (mHomeSystemId != null) {
+ for (int i=0; i < mHomeSystemId.length; i++) {
+ if (sid == mHomeSystemId[i]) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* @return true if phone is camping on a technology
* that could support voice and data simultaneously.
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 30adc52..9c04305 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -527,6 +527,19 @@ public class SmsMessage extends SmsMessageBase {
* Parses a SMS message from its BearerData stream. (mobile-terminated only)
*/
protected void parseSms() {
+ // Message Waiting Info Record defined in 3GPP2 C.S-0005, 3.7.5.6
+ // It contains only an 8-bit number with the number of messages waiting
+ if (mEnvelope.teleService == SmsEnvelope.TELESERVICE_MWI) {
+ mBearerData = new BearerData();
+ if (mEnvelope.bearerData != null) {
+ mBearerData.numberOfMessages = 0x000000FF & mEnvelope.bearerData[0];
+ }
+ if (Config.DEBUG) {
+ Log.d(LOG_TAG, "parseSms: get MWI " +
+ Integer.toString(mBearerData.numberOfMessages));
+ }
+ return;
+ }
mBearerData = BearerData.decode(mEnvelope.bearerData);
messageRef = mBearerData.messageId;
if (mBearerData.userData != null) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 13cea99..c71003b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -798,23 +798,34 @@ public final class BearerData {
return null;
}
- private static void decodeMessageId(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeMessageId(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 3) {
- throw new CodingException("MESSAGE_IDENTIFIER subparam size incorrect");
- }
- bData.messageType = inStream.read(4);
- bData.messageId = inStream.read(8) << 8;
- bData.messageId |= inStream.read(8);
- bData.hasUserDataHeader = (inStream.read(1) == 1);
- inStream.skip(3);
+ final int EXPECTED_PARAM_SIZE = 3 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.messageType = inStream.read(4);
+ bData.messageId = inStream.read(8) << 8;
+ bData.messageId |= inStream.read(8);
+ bData.hasUserDataHeader = (inStream.read(1) == 1);
+ inStream.skip(3);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeUserData(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeUserData(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException
{
- int paramBytes = inStream.read(8);
+ int paramBits = inStream.read(8) * 8;
bData.userData = new UserData();
bData.userData.msgEncoding = inStream.read(5);
bData.userData.msgEncodingSet = true;
@@ -827,8 +838,9 @@ public final class BearerData {
}
bData.userData.numFields = inStream.read(8);
consumedBits += 8;
- int dataBits = (paramBytes * 8) - consumedBits;
+ int dataBits = paramBits - consumedBits;
bData.userData.payload = inStream.readByteArray(dataBits);
+ return true;
}
private static String decodeUtf16(byte[] data, int offset, int numFields)
@@ -1081,36 +1093,68 @@ public final class BearerData {
}
}
- private static void decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- int paramBytes = inStream.read(8);
- if (paramBytes != 1) {
- throw new CodingException("REPLY_OPTION subparam size incorrect");
- }
- bData.userAckReq = (inStream.read(1) == 1);
- bData.deliveryAckReq = (inStream.read(1) == 1);
- bData.readAckReq = (inStream.read(1) == 1);
- bData.reportReq = (inStream.read(1) == 1);
- inStream.skip(4);
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.userAckReq = (inStream.read(1) == 1);
+ bData.deliveryAckReq = (inStream.read(1) == 1);
+ bData.readAckReq = (inStream.read(1) == 1);
+ bData.reportReq = (inStream.read(1) == 1);
+ inStream.skip(4);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "REPLY_OPTION decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("NUMBER_OF_MESSAGES subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.numberOfMessages = inStream.read(8);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.numberOfMessages = inStream.read(8);
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeDepositIndex(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeDepositIndex(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 2) {
- throw new CodingException("MESSAGE_DEPOSIT_INDEX subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 2 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.depositIndex = (inStream.read(8) << 8) | inStream.read(8);
}
- bData.depositIndex = (inStream.read(8) << 8) | inStream.read(8);
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
@@ -1144,10 +1188,10 @@ public final class BearerData {
}
}
- private static void decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- int paramBytes = inStream.read(8);
+ int paramBits = inStream.read(8) * 8;
CdmaSmsAddress addr = new CdmaSmsAddress();
addr.digitMode = inStream.read(1);
byte fieldBits = 4;
@@ -1160,140 +1204,274 @@ public final class BearerData {
}
addr.numberOfDigits = inStream.read(8);
consumedBits += 8;
- int remainingBits = (paramBytes * 8) - consumedBits;
+ int remainingBits = paramBits - consumedBits;
int dataBits = addr.numberOfDigits * fieldBits;
int paddingBits = remainingBits - dataBits;
if (remainingBits < dataBits) {
throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" +
- "remainingBits " + remainingBits + ", dataBits " +
- dataBits + ", paddingBits " + paddingBits + ")");
+ "remainingBits + " + remainingBits + ", dataBits + " +
+ dataBits + ", paddingBits + " + paddingBits + ")");
}
addr.origBytes = inStream.readByteArray(dataBits);
inStream.skip(paddingBits);
decodeSmsAddress(addr);
bData.callbackNumber = addr;
+ return true;
}
- private static void decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("MESSAGE_STATUS subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.errorClass = inStream.read(2);
+ bData.messageStatus = inStream.read(6);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "MESSAGE_STATUS decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.errorClass = inStream.read(2);
- bData.messageStatus = inStream.read(6);
- bData.messageStatusSet = true;
+ inStream.skip(paramBits);
+ bData.messageStatusSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeMsgCenterTimeStamp(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeMsgCenterTimeStamp(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 6) {
- throw new CodingException("MESSAGE_CENTER_TIME_STAMP subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 6 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.msgCenterTimeStamp = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
}
- bData.msgCenterTimeStamp = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeValidityAbs(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeValidityAbs(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 6) {
- throw new CodingException("VALIDITY_PERIOD_ABSOLUTE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 6 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.validityPeriodAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.validityPeriodAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeDeferredDeliveryAbs(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeDeferredDeliveryAbs(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 6) {
- throw new CodingException("DEFERRED_DELIVERY_TIME_ABSOLUTE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 6 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.deferredDeliveryTimeAbsolute = TimeStamp.fromByteArray(
+ inStream.readByteArray(6 * 8));
}
- bData.deferredDeliveryTimeAbsolute = TimeStamp.fromByteArray(inStream.readByteArray(6 * 8));
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ return decodeSuccess;
}
- private static void decodeValidityRel(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeValidityRel(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("VALIDITY_PERIOD_RELATIVE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.deferredDeliveryTimeRelative = inStream.read(8);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.deferredDeliveryTimeRelative = inStream.read(8);
- bData.deferredDeliveryTimeRelativeSet = true;
+ inStream.skip(paramBits);
+ bData.deferredDeliveryTimeRelativeSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeDeferredDeliveryRel(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeDeferredDeliveryRel(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("DEFERRED_DELIVERY_TIME_RELATIVE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.validityPeriodRelative = inStream.read(8);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.validityPeriodRelative = inStream.read(8);
- bData.validityPeriodRelativeSet = true;
+ inStream.skip(paramBits);
+ bData.validityPeriodRelativeSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodePrivacyIndicator(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("PRIVACY_INDICATOR subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.privacy = inStream.read(2);
+ inStream.skip(6);
}
- bData.privacy = inStream.read(2);
- inStream.skip(6);
- bData.privacyIndicatorSet = true;
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "PRIVACY_INDICATOR decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ bData.privacyIndicatorSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeLanguageIndicator(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("LANGUAGE_INDICATOR subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.language = inStream.read(8);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "LANGUAGE_INDICATOR decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.language = inStream.read(8);
- bData.languageIndicatorSet = true;
+ inStream.skip(paramBits);
+ bData.languageIndicatorSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeDisplayMode(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("DISPLAY_MODE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.displayMode = inStream.read(2);
+ inStream.skip(6);
}
- bData.displayMode = inStream.read(2);
- inStream.skip(6);
- bData.displayModeSet = true;
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "DISPLAY_MODE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ bData.displayModeSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodePriorityIndicator(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("PRIORITY_INDICATOR subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.priority = inStream.read(2);
+ inStream.skip(6);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "PRIORITY_INDICATOR decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.priority = inStream.read(2);
- inStream.skip(6);
- bData.priorityIndicatorSet = true;
+ inStream.skip(paramBits);
+ bData.priorityIndicatorSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeMsgDeliveryAlert(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("ALERT_ON_MESSAGE_DELIVERY subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.alert = inStream.read(2);
+ inStream.skip(6);
}
- bData.alert = inStream.read(2);
- inStream.skip(6);
- bData.alertIndicatorSet = true;
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
+ }
+ inStream.skip(paramBits);
+ bData.alertIndicatorSet = decodeSuccess;
+ return decodeSuccess;
}
- private static void decodeUserResponseCode(BearerData bData, BitwiseInputStream inStream)
+ private static boolean decodeUserResponseCode(BearerData bData, BitwiseInputStream inStream)
throws BitwiseInputStream.AccessException, CodingException
{
- if (inStream.read(8) != 1) {
- throw new CodingException("USER_REPONSE_CODE subparam size incorrect");
+ final int EXPECTED_PARAM_SIZE = 1 * 8;
+ boolean decodeSuccess = false;
+ int paramBits = inStream.read(8) * 8;
+ if (paramBits >= EXPECTED_PARAM_SIZE) {
+ paramBits -= EXPECTED_PARAM_SIZE;
+ decodeSuccess = true;
+ bData.userResponseCode = inStream.read(8);
+ }
+ if ((! decodeSuccess) || (paramBits > 0)) {
+ Log.d(LOG_TAG, "USER_REPONSE_CODE decode " +
+ (decodeSuccess ? "succeeded" : "failed") +
+ " (extra bits = " + paramBits + ")");
}
- bData.userResponseCode = inStream.read(8);
- bData.userResponseCodeSet = true;
+ inStream.skip(paramBits);
+ bData.userResponseCodeSet = decodeSuccess;
+ return decodeSuccess;
}
/**
@@ -1310,72 +1488,73 @@ public final class BearerData {
BearerData bData = new BearerData();
int foundSubparamMask = 0;
while (inStream.available() > 0) {
+ boolean decodeSuccess = false;
int subparamId = inStream.read(8);
int subparamIdBit = 1 << subparamId;
if ((foundSubparamMask & subparamIdBit) != 0) {
throw new CodingException("illegal duplicate subparameter (" +
subparamId + ")");
}
- foundSubparamMask |= subparamIdBit;
switch (subparamId) {
case SUBPARAM_MESSAGE_IDENTIFIER:
- decodeMessageId(bData, inStream);
+ decodeSuccess = decodeMessageId(bData, inStream);
break;
case SUBPARAM_USER_DATA:
- decodeUserData(bData, inStream);
+ decodeSuccess = decodeUserData(bData, inStream);
break;
case SUBPARAM_USER_REPONSE_CODE:
- decodeUserResponseCode(bData, inStream);
+ decodeSuccess = decodeUserResponseCode(bData, inStream);
break;
case SUBPARAM_REPLY_OPTION:
- decodeReplyOption(bData, inStream);
+ decodeSuccess = decodeReplyOption(bData, inStream);
break;
case SUBPARAM_NUMBER_OF_MESSAGES:
- decodeMsgCount(bData, inStream);
+ decodeSuccess = decodeMsgCount(bData, inStream);
break;
case SUBPARAM_CALLBACK_NUMBER:
- decodeCallbackNumber(bData, inStream);
+ decodeSuccess = decodeCallbackNumber(bData, inStream);
break;
case SUBPARAM_MESSAGE_STATUS:
- decodeMsgStatus(bData, inStream);
+ decodeSuccess = decodeMsgStatus(bData, inStream);
break;
case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
- decodeMsgCenterTimeStamp(bData, inStream);
+ decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream);
break;
case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE:
- decodeValidityAbs(bData, inStream);
+ decodeSuccess = decodeValidityAbs(bData, inStream);
break;
case SUBPARAM_VALIDITY_PERIOD_RELATIVE:
- decodeValidityRel(bData, inStream);
+ decodeSuccess = decodeValidityRel(bData, inStream);
break;
case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE:
- decodeDeferredDeliveryAbs(bData, inStream);
+ decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream);
break;
case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE:
- decodeDeferredDeliveryRel(bData, inStream);
+ decodeSuccess = decodeDeferredDeliveryRel(bData, inStream);
break;
case SUBPARAM_PRIVACY_INDICATOR:
- decodePrivacyIndicator(bData, inStream);
+ decodeSuccess = decodePrivacyIndicator(bData, inStream);
break;
case SUBPARAM_LANGUAGE_INDICATOR:
- decodeLanguageIndicator(bData, inStream);
+ decodeSuccess = decodeLanguageIndicator(bData, inStream);
break;
case SUBPARAM_MESSAGE_DISPLAY_MODE:
- decodeDisplayMode(bData, inStream);
+ decodeSuccess = decodeDisplayMode(bData, inStream);
break;
case SUBPARAM_PRIORITY_INDICATOR:
- decodePriorityIndicator(bData, inStream);
+ decodeSuccess = decodePriorityIndicator(bData, inStream);
break;
case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
- decodeMsgDeliveryAlert(bData, inStream);
+ decodeSuccess = decodeMsgDeliveryAlert(bData, inStream);
break;
case SUBPARAM_MESSAGE_DEPOSIT_INDEX:
- decodeDepositIndex(bData, inStream);
+ decodeSuccess = decodeDepositIndex(bData, inStream);
break;
default:
throw new CodingException("unsupported bearer data subparameter ("
+ subparamId + ")");
}
+ if (decodeSuccess) foundSubparamMask |= subparamIdBit;
}
if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
index f80e8c0..0dcacc1 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -36,6 +36,14 @@ public final class SmsEnvelope{
static public final int TELESERVICE_WAP = 0x1004;
static public final int TELESERVICE_WEMT = 0x1005;
+ /**
+ * The following are defined as extensions to the standard teleservices
+ */
+ // Voice mail notification through Message Waiting Indication in CDMA mode or Analog mode.
+ // Defined in 3GPP2 C.S-0005, 3.7.5.6, an Info Record containing an 8-bit number with the
+ // number of messages waiting, it's used by some CDMA carriers for a voice mail count.
+ static public final int TELESERVICE_MWI = 0x40000;
+
// ServiceCategories for Cell Broadcast, see 3GPP2 C.R1001 table 9.3.1-1
//static public final int SERVICECATEGORY_EMERGENCY = 0x0010;
//...
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index b3b4345..4178115 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -151,6 +151,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted
static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted
+ static final int MAX_NUM_DATA_STATE_READS = 15;
+
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 89de867..224419e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -84,9 +84,13 @@ public class PdpConnection extends DataConnection {
lastFailCause = FailCause.NONE;
receivedDisconnectReq = false;
- phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE),
+ int authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
+ RILConstants.SETUP_DATA_AUTH_NONE;
+
+ phone.mCM.setupDataCall(Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
Integer.toString(RILConstants.DATA_PROFILE_DEFAULT), apn.apn, apn.user,
- apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+ apn.password, Integer.toString(authType),
+ obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
}
private void tearDownData(Message msg) {
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index be5b842..11b3fd6 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -944,7 +944,7 @@ public final class SimulatedCommands extends BaseCommands
}
public void setupDataCall(String radioTechnology, String profile, String apn, String user,
- String password, Message result) {
+ String password, String authType, Message result) {
unimplemented(result);
}
diff --git a/test-runner/android/test/ProviderTestCase2.java b/test-runner/android/test/ProviderTestCase2.java
index ac17ebf..a923d2a 100644
--- a/test-runner/android/test/ProviderTestCase2.java
+++ b/test-runner/android/test/ProviderTestCase2.java
@@ -3,6 +3,7 @@ package android.test;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.res.Resources;
import android.test.mock.MockContext;
import android.test.mock.MockContentResolver;
import android.database.DatabaseUtils;
@@ -26,6 +27,14 @@ public abstract class ProviderTestCase2<T extends ContentProvider> extends Andro
private IsolatedContext mProviderContext;
private MockContentResolver mResolver;
+ private class MockContext2 extends MockContext {
+
+ @Override
+ public Resources getResources() {
+ return getContext().getResources();
+ }
+ }
+
public ProviderTestCase2(Class<T> providerClass, String providerAuthority) {
mProviderClass = providerClass;
mProviderAuthority = providerAuthority;
@@ -47,7 +56,7 @@ public abstract class ProviderTestCase2<T extends ContentProvider> extends Andro
mResolver = new MockContentResolver();
final String filenamePrefix = "test.";
RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
- new MockContext(), // The context that most methods are delegated to
+ new MockContext2(), // The context that most methods are delegated to
getContext(), // The context that file methods are delegated to
filenamePrefix);
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index b83a44d..9fb1e61 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -110,6 +110,7 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
@Override
public File getSharedPrefsFile(String name) {
throw new UnsupportedOperationException();
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index 90a2917..528545c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -637,6 +637,16 @@ public class CdmaSmsTest extends AndroidTestCase {
BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
assertEquals(bd4.alert, 3);
assertEquals(bd4.userData.payloadStr, "Test Alert 3");
+ String pdu5 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840E1062D3D39A900C028000";
+ BearerData bd5 = BearerData.decode(HexDump.hexStringToByteArray(pdu5));
+ assertEquals(bd5.alert, BearerData.ALERT_MEDIUM_PRIO);
+ assertEquals(bd5.userData.payloadStr, "test message delivery alert (with 8 bits)");
+ String pdu6 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
+ "69ED979794187665E5D1028EFA7A6840C1062D3D39A900C00";
+ BearerData bd6 = BearerData.decode(HexDump.hexStringToByteArray(pdu6));
+ assertEquals(bd6.userData.payloadStr, "test message delivery alert (with 0 bits)");
+ assertEquals(bd6.alertIndicatorSet, false);
}
@SmallTest
diff --git a/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java b/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java
index 7dc1314..67fcd61 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/VpnTest.java
@@ -16,10 +16,22 @@
package com.android.unit_tests;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.vpn.L2tpProfile;
import android.net.vpn.L2tpIpsecProfile;
+import android.net.vpn.L2tpIpsecPskProfile;
+import android.net.vpn.PptpProfile;
+import android.net.vpn.VpnManager;
+import android.net.vpn.VpnProfile;
+import android.net.vpn.VpnState;
import android.net.vpn.VpnType;
+import android.os.ConditionVariable;
+import android.os.Parcel;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
/**
* Unit test class to test VPN api
@@ -29,6 +41,12 @@ import android.test.suitebuilder.annotation.SmallTest;
* -w com.android.unit_tests/android.test.InstrumentationTestRunner
*/
public class VpnTest extends AndroidTestCase {
+ private static final String NAME = "a name";
+ private static final String SERVER_NAME = "a server name";
+ private static final String ID = "some id";
+ private static final String SUFFICES = "some suffices";
+ private static final String ROUTES = "some routes";
+ private static final String SAVED_NAME = "some name";
@Override
public void setUp() {
@@ -39,8 +57,102 @@ public class VpnTest extends AndroidTestCase {
}
@SmallTest
+ public void testVpnType() {
+ testVpnType(VpnType.L2TP);
+ testVpnType(VpnType.L2TP_IPSEC);
+ testVpnType(VpnType.L2TP_IPSEC_PSK);
+ testVpnType(VpnType.PPTP);
+ }
+
+ @SmallTest
+ public void testVpnProfile() {
+ VpnState state = VpnState.CONNECTING;
+ testVpnProfile(createTestProfile(state), state);
+ }
+
+ @SmallTest
public void testGetType() {
- L2tpIpsecProfile li = new L2tpIpsecProfile();
- assertTrue(VpnType.L2TP_IPSEC== li.getType());
+ assertEquals(VpnType.L2TP, new L2tpProfile().getType());
+ assertEquals(VpnType.L2TP_IPSEC, new L2tpIpsecProfile().getType());
+ assertEquals(VpnType.L2TP_IPSEC_PSK,
+ new L2tpIpsecPskProfile().getType());
+ assertEquals(VpnType.PPTP, new PptpProfile().getType());
+ }
+
+ @SmallTest
+ public void testVpnTypes() {
+ assertTrue(VpnManager.getSupportedVpnTypes().length > 0);
+ }
+
+ @SmallTest
+ public void testGetTypeFromManager() {
+ VpnManager m = new VpnManager(getContext());
+ VpnType[] types = VpnManager.getSupportedVpnTypes();
+ for (VpnType t : types) {
+ assertEquals(t, m.createVpnProfile(t).getType());
+ }
+ }
+
+ @SmallTest
+ public void testParcelable() {
+ VpnProfile p = createTestProfile(VpnState.CONNECTED);
+ Parcel parcel = Parcel.obtain();
+ p.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ // VpnState is transient and not saved in the parcel
+ testVpnProfile(VpnProfile.CREATOR.createFromParcel(parcel), null);
+ }
+
+ @SmallTest
+ public void testReceiver() {
+ final String profileName = "whatever";
+ final VpnState state = VpnState.DISCONNECTING;
+ final ConditionVariable cv = new ConditionVariable();
+ cv.close();
+ BroadcastReceiver r = new BroadcastReceiver() {
+ public void onReceive(Context c, Intent i) {
+ assertEquals(profileName,
+ i.getStringExtra(VpnManager.BROADCAST_PROFILE_NAME));
+ assertEquals(state, i.getSerializableExtra(
+ VpnManager.BROADCAST_CONNECTION_STATE));
+ cv.open();
+ }
+ };
+
+ VpnManager m = new VpnManager(getContext());
+ m.registerConnectivityReceiver(r);
+ m.broadcastConnectivity(profileName, state);
+
+ // fail it if onReceive() doesn't get executed in 5 sec
+ assertTrue(cv.block(5000));
+ }
+
+ private void testVpnType(VpnType type) {
+ assertFalse(TextUtils.isEmpty(type.getDisplayName()));
+ assertNotNull(type.getDescription());
+ assertNotNull(type.getProfileClass());
+ }
+
+ private VpnProfile createTestProfile(VpnState state) {
+ VpnProfile p = new L2tpProfile();
+ p.setName(NAME);
+ p.setServerName(SERVER_NAME);
+ p.setId(ID);
+ p.setDomainSuffices(SUFFICES);
+ p.setRouteList(ROUTES);
+ p.setSavedUsername(SAVED_NAME);
+ p.setState(state);
+ return p;
+ }
+
+ private void testVpnProfile(VpnProfile p, VpnState state) {
+ assertEquals(NAME, p.getName());
+ assertEquals(SERVER_NAME, p.getServerName());
+ assertEquals(ID, p.getId());
+ assertEquals(SUFFICES, p.getDomainSuffices());
+ assertEquals(ROUTES, p.getRouteList());
+ assertEquals(SAVED_NAME, p.getSavedUsername());
+ if (state != null) assertEquals(state, p.getState());
}
}
diff --git a/tests/CoreTests/android/core/CryptoTest.java b/tests/CoreTests/android/core/CryptoTest.java
index f00d49f..e6e50ec 100644
--- a/tests/CoreTests/android/core/CryptoTest.java
+++ b/tests/CoreTests/android/core/CryptoTest.java
@@ -22,7 +22,6 @@ import junit.framework.TestCase;
import org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigest;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;
-import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
@@ -93,16 +92,6 @@ public class CryptoTest extends TestCase {
// Assert.assertTrue("New hash should be faster", newTime < oldTime);
}
-
- /**
- * Tests the MD2 implementation.
- */
- @LargeTest
- public void testMD2() {
- Digest oldDigest = new MD2Digest();
- Digest newDigest = OpenSSLMessageDigest.getInstance("MD2");
- doTestMessageDigest(oldDigest, newDigest);
- }
/**
* Tests the MD4 implementation.
diff --git a/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png b/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png
new file mode 100644
index 0000000..4d717a8
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/reslogo240dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png b/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png
new file mode 100644
index 0000000..4d717a8
--- /dev/null
+++ b/tests/DpiTest/res/drawable-hdpi/stylogo240dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png b/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png
new file mode 100644
index 0000000..46bbd5b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/reslogo120dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png b/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png
new file mode 100644
index 0000000..46bbd5b
--- /dev/null
+++ b/tests/DpiTest/res/drawable-ldpi/stylogo120dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/reslogo160dpi.png b/tests/DpiTest/res/drawable/reslogo160dpi.png
new file mode 100644
index 0000000..c23b2ce
--- /dev/null
+++ b/tests/DpiTest/res/drawable/reslogo160dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/drawable/stylogo160dpi.png b/tests/DpiTest/res/drawable/stylogo160dpi.png
new file mode 100644
index 0000000..c23b2ce
--- /dev/null
+++ b/tests/DpiTest/res/drawable/stylogo160dpi.png
Binary files differ
diff --git a/tests/DpiTest/res/layout/image_views.xml b/tests/DpiTest/res/layout/image_views.xml
new file mode 100644
index 0000000..6a91497
--- /dev/null
+++ b/tests/DpiTest/res/layout/image_views.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/reslogo120dpi" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/reslogo160dpi" />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/reslogo240dpi" />
+
+</LinearLayout>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml b/tests/DpiTest/res/layout/styled_image_views.xml
index fdbba88..86c63bf 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/defaults.xml
+++ b/tests/DpiTest/res/layout/styled_image_views.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,10 +13,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="def_airplane_mode_radios">"手機,藍牙,wifi"</string>
- <string name="def_location_providers_allowed">"gps"</string>
- <!-- no translation found for def_backup_transport (6764822064303377157) -->
- <skip />
-</resources>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView style="@style/ImageView120dpi" />
+ <ImageView style="@style/ImageView160dpi" />
+ <ImageView style="@style/ImageView240dpi" />
+
+</LinearLayout>
diff --git a/tests/DpiTest/res/values/styles.xml b/tests/DpiTest/res/values/styles.xml
new file mode 100644
index 0000000..bb4b13c
--- /dev/null
+++ b/tests/DpiTest/res/values/styles.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <style name="ImageView120dpi">
+ <item name="android:src">@drawable/stylogo120dpi</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+ <style name="ImageView160dpi">
+ <item name="android:src">@drawable/stylogo160dpi</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+ <style name="ImageView240dpi">
+ <item name="android:src">@drawable/stylogo240dpi</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+</resources>
diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index 68220a1..ae53b76 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -28,6 +28,7 @@ import android.graphics.drawable.Drawable;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ScrollView;
+import android.view.LayoutInflater;
import android.view.View;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -71,6 +72,9 @@ public class DpiTestActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final LayoutInflater li = (LayoutInflater)getSystemService(
+ LAYOUT_INFLATER_SERVICE);
+
this.setTitle(R.string.act_title);
LinearLayout root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
@@ -96,6 +100,14 @@ public class DpiTestActivity extends Activity {
addLabelToRoot(root, "Prescaled resource drawable");
addChildToRoot(root, layout);
+ layout = (LinearLayout)li.inflate(R.layout.image_views, null);
+ addLabelToRoot(root, "Inflated layout");
+ addChildToRoot(root, layout);
+
+ layout = (LinearLayout)li.inflate(R.layout.styled_image_views, null);
+ addLabelToRoot(root, "Inflated styled layout");
+ addChildToRoot(root, layout);
+
layout = new LinearLayout(this);
addCanvasBitmap(layout, R.drawable.logo120dpi, true);
addCanvasBitmap(layout, R.drawable.logo160dpi, true);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index a03490d..2eecef8 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -16,6 +16,9 @@
package com.android.dumprendertree;
+import com.android.dumprendertree.forwarder.AdbUtils;
+import com.android.dumprendertree.forwarder.ForwardServer;
+
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
@@ -42,7 +45,7 @@ class MyTestRecorder {
private BufferedOutputStream mBufferedOutputFailedStream;
private BufferedOutputStream mBufferedOutputNoresultStream;
private BufferedOutputStream mBufferedOutputTimedoutStream;
-
+
public void passed(String layout_file) {
try {
mBufferedOutputPassedStream.write(layout_file.getBytes());
@@ -52,7 +55,7 @@ class MyTestRecorder {
e.printStackTrace();
}
}
-
+
public void failed(String layout_file) {
try {
mBufferedOutputFailedStream.write(layout_file.getBytes());
@@ -62,7 +65,7 @@ class MyTestRecorder {
e.printStackTrace();
}
}
-
+
public void noresult(String layout_file) {
try {
mBufferedOutputNoresultStream.write(layout_file.getBytes());
@@ -72,7 +75,7 @@ class MyTestRecorder {
e.printStackTrace();
}
}
-
+
public void timedout(String url) {
try {
mBufferedOutputTimedoutStream.write(url.getBytes());
@@ -82,14 +85,14 @@ class MyTestRecorder {
e.printStackTrace();
}
}
-
+
public MyTestRecorder(boolean resume) {
try {
File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt");
File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt");
File noExpectedResultFile = new File("/sdcard/layout_tests_nontext.txt");
File resultTimedoutFile = new File("/sdcard/layout_tests_timedout.txt");
-
+
mBufferedOutputPassedStream =
new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume));
mBufferedOutputFailedStream =
@@ -102,7 +105,7 @@ class MyTestRecorder {
e.printStackTrace();
}
}
-
+
public void close() {
try {
mBufferedOutputPassedStream.close();
@@ -120,7 +123,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
private static final String LOGTAG = "LayoutTests";
static final int DEFAULT_TIMEOUT_IN_MILLIS = 5000;
-
+
static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/";
static final String LAYOUT_TESTS_RESULT_DIR = "/sdcard/android/layout_tests_results/";
static final String ANDROID_EXPECTED_RESULT_DIR = "/sdcard/android/expected_results/";
@@ -139,14 +142,35 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
static final String LAYOUT_RESULTS_CRASHED_RESULT_FILE = "results/layout_tests_crashed.txt";
static final String LAYOUT_TESTS_RUNNER = "run_layout_tests.py";
+ static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
+ static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
+ static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
+ static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
+ static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
+
+
+ private ForwardServer fs8000, fs8080, fs8443;
+
private MyTestRecorder mResultRecorder;
private Vector<String> mTestList;
private boolean mRebaselineResults;
private String mTestPathPrefix;
private boolean mFinished;
-
+
public LayoutTestsAutoTest() {
super("com.android.dumprendertree", TestShellActivity.class);
+
+ int addr = -1;
+ try {
+ addr = AdbUtils.resolve("android-browser-test.mtv.corp.google.com");
+ } catch (IOException ioe) {
+ Log.e(LOGTAG, "failed to resolve server address.", ioe);
+ }
+ if(addr != -1) {
+ fs8000 = new ForwardServer(8000, addr, 8000);
+ fs8080 = new ForwardServer(8080, addr, 8080);
+ fs8443 = new ForwardServer(8443, addr, 8443);
+ }
}
// This function writes the result of the layout test to
@@ -157,7 +181,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
bundle.putBoolean(file, result);
inst.sendStatus(0, bundle);
}
-
+
private void getTestList() {
// Read test list.
try {
@@ -174,7 +198,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
Log.e(LOGTAG, "Error while reading test list : " + e.getMessage());
}
}
-
+
private void resumeTestList() {
// read out the test name it stoped last time.
try {
@@ -189,7 +213,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE);
}
}
-
+
private void clearTestStatus() {
// Delete TEST_STATUS_FILE
try {
@@ -208,13 +232,13 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
// Write actual results to result directory.
return shortName.replaceFirst(LAYOUT_TESTS_ROOT, LAYOUT_TESTS_RESULT_DIR) + "-result.txt";
}
-
+
private String getExpectedResultFile(String test) {
int pos = test.lastIndexOf('.');
if(pos == -1)
return null;
String shortName = test.substring(0, pos);
- return shortName + "-expected.txt";
+ return shortName + "-expected.txt";
}
private String getAndroidExpectedResultFile(String expectedResultFile) {
@@ -224,7 +248,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
// Wrap up
private void failedCase(String file) {
Log.w("Layout test: ", file + " failed");
- mResultRecorder.failed(file);
+ mResultRecorder.failed(file);
}
private void passedCase(String file) {
@@ -236,7 +260,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
Log.v("Layout test:", file + " no expected result");
mResultRecorder.noresult(file);
}
-
+
private void processResult(String testFile, String actualResultFile, String expectedResultFile) {
Log.v(LOGTAG, " Processing result: " + testFile);
@@ -257,13 +281,13 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
break;
}
}
-
+
if (passing) {
passedCase(testFile);
} else {
failedCase(testFile);
}
-
+
fe.close();
fr.close();
} catch (FileNotFoundException ex) {
@@ -278,7 +302,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
noresultCase(testFile);
}
}
-
+
private void runTestAndWaitUntilDone(TestShellActivity activity, String test, int timeout) {
activity.setCallback(new TestShellCallback() {
public void finished() {
@@ -287,7 +311,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
LayoutTestsAutoTest.this.notifyAll();
}
}
-
+
public void timedOut(String url) {
}
});
@@ -306,16 +330,16 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
resultFile = getAndroidExpectedResultFile(expectedResultFile);
}
-
+
mFinished = false;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(activity, TestShellActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- intent.putExtra(TestShellActivity.TEST_URL, "file://" + test);
+ intent.putExtra(TestShellActivity.TEST_URL, getTestUrl(test));
intent.putExtra(TestShellActivity.RESULT_FILE, resultFile);
intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
activity.startActivity(intent);
-
+
// Wait until done.
synchronized (this) {
while(!mFinished){
@@ -324,18 +348,18 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
} catch (InterruptedException e) { }
}
}
-
+
if (!mRebaselineResults) {
String expectedResultFile = getExpectedResultFile(test);
File f = new File(expectedResultFile);
if (!f.exists()) {
expectedResultFile = getAndroidExpectedResultFile(expectedResultFile);
}
-
+
processResult(test, resultFile, expectedResultFile);
}
- }
-
+ }
+
// Invokes running of layout tests
// and waits till it has finished running.
public void executeLayoutTests(boolean resume) {
@@ -348,28 +372,28 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
}
this.mTestList = new Vector<String>();
-
+
// Read settings
try {
this.mTestPathPrefix =
(new File(LAYOUT_TESTS_ROOT + runner.mTestPath)).getCanonicalPath();
- } catch (IOException e) {
+ } catch (IOException e) {
Log.e(LOGTAG, "Cannot find test path prefix: " + e.getMessage());
return;
}
-
+
this.mRebaselineResults = runner.mRebaseline;
-
+
int timeout = runner.mTimeoutInMillis;
if (timeout <= 0) {
timeout = DEFAULT_TIMEOUT_IN_MILLIS;
}
-
+
this.mResultRecorder = new MyTestRecorder(resume);
-
+
if (!resume)
clearTestStatus();
-
+
getTestList();
if (resume)
resumeTestList();
@@ -377,6 +401,15 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
TestShellActivity activity = (TestShellActivity) getActivity();
// Run tests.
+ int addr = -1;
+ try{
+ addr = AdbUtils.resolve("android-browser-test.mtv.corp.google.com");
+ } catch (IOException ioe) {
+ Log.w(LOGTAG, "error while resolving test host name", ioe);
+ }
+ if(addr == -1) {
+ Log.w(LOGTAG, "failed to resolve test host. http tests will fail.");
+ }
for (int i = 0; i < mTestList.size(); i++) {
String s = mTestList.elementAt(i);
FsUtils.updateTestStatus(TEST_STATUS_FILE, s);
@@ -385,10 +418,48 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
}
FsUtils.updateTestStatus(TEST_STATUS_FILE, "#DONE");
-
+ if(fs8000 != null)
+ fs8000.stop();
+ if(fs8080 != null)
+ fs8080.stop();
+ if(fs8443 != null)
+ fs8443.stop();
+
activity.finish();
}
+ private void startForwardServerIfNeeded() {
+ try {
+ if(fs8000 != null)
+ fs8000.start();
+ if(fs8080 != null)
+ fs8080.start();
+ if(fs8443 != null)
+ fs8443.start();
+ } catch (IOException ioe) {
+ Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe);
+ }
+ }
+
+ private String getTestUrl(String path) {
+ String url = null;
+ if (!path.startsWith(HTTP_TESTS_PREFIX)) {
+ url = "file://" + path;
+ } else {
+ startForwardServerIfNeeded();
+ if (path.startsWith(HTTPS_TESTS_PREFIX)) {
+ // still cut the URL after "http/tests/"
+ url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
+ } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
+ && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
+ && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
+ url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
+ } else {
+ url = "file://" + path;
+ }
+ }
+ return url;
+ }
private String getTestPath() {
LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
@@ -403,10 +474,10 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
Log.e("LayoutTestsAutoTest", "Cannot get cannonical path " + e.getMessage());
}
Log.v("LayoutTestsAutoTest", " Test path : " + test_path);
-
+
return test_path;
}
-
+
public void generateTestList() {
try {
File tests_list = new File(LAYOUT_TESTS_LIST_FILE);
@@ -431,7 +502,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
} catch (Exception e) {
e.printStackTrace();
}
-
+
executeLayoutTests(false);
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 48c1e5d..30e1d99 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -531,8 +531,14 @@ public class TestShellActivity extends Activity implements LayoutTestController
}
@Override
+ public boolean onJsTimeout() {
+ Log.v(LOGTAG, "JavaScript timeout");
+ return false;
+ }
+
+ @Override
public void onExceededDatabaseQuota(String url_str,
- String databaseIdentifier, long currentQuota,
+ String databaseIdentifier, long currentQuota, long totalUsedQuota,
WebStorage.QuotaUpdater callback) {
if (mDumpDatabaseCallbacks) {
if (mDatabaseCallbackStrings == null) {
@@ -614,6 +620,9 @@ public class TestShellActivity extends Activity implements LayoutTestController
}
WebSettings settings = webview.getSettings();
+ settings.setAppCacheEnabled(true);
+ settings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
+ settings.setAppCacheMaxSize(Long.MAX_VALUE);
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setSupportMultipleWindows(true);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
new file mode 100644
index 0000000..9a3e9c2
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
@@ -0,0 +1,112 @@
+package com.android.dumprendertree.forwarder;
+
+import android.util.Log;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+public class AdbUtils {
+
+ private static final String ADB_OK = "OKAY";
+ private static final int ADB_PORT = 5037;
+ private static final String ADB_HOST = "127.0.0.1";
+ private static final int ADB_RESPONSE_SIZE = 4;
+
+ private static final String LOGTAG = "AdbUtils";
+
+ /**
+ *
+ * Convert integer format IP into xxx.xxx.xxx.xxx format
+ *
+ * @param host IP address in integer format
+ * @return human readable format
+ */
+ public static String convert(int host) {
+ return ((host >> 24) & 0xFF) + "."
+ + ((host >> 16) & 0xFF) + "."
+ + ((host >> 8) & 0xFF) + "."
+ + (host & 0xFF);
+ }
+
+ /**
+ *
+ * Resolve DNS name into IP address
+ *
+ * @param host DNS name
+ * @return IP address in integer format
+ * @throws IOException
+ */
+ public static int resolve(String host) throws IOException {
+ Socket localSocket = new Socket(ADB_HOST, ADB_PORT);
+ DataInputStream dis = new DataInputStream(localSocket.getInputStream());
+ OutputStream os = localSocket.getOutputStream();
+ int count_read = 0;
+ byte[] buf = new byte[128];
+
+ if (localSocket == null || dis == null || os == null)
+ return -1;
+ String cmd = "dns:" + host;
+
+ if(!sendAdbCmd(dis, os, cmd))
+ return -1;
+
+ count_read = dis.readInt();
+ localSocket.close();
+ return count_read;
+ }
+
+ /**
+ *
+ * Send an ADB command using existing socket connection
+ *
+ * the streams provided must be from a socket connected to adbd already
+ *
+ * @param is input stream of the socket connection
+ * @param os output stream of the socket
+ * @param cmd the adb command to send
+ * @return if adb gave a success response
+ * @throws IOException
+ */
+ public static boolean sendAdbCmd(InputStream is, OutputStream os,
+ String cmd) throws IOException {
+ byte[] buf = new byte[ADB_RESPONSE_SIZE];
+
+ cmd = String.format("%04X", cmd.length()) + cmd;
+ os.write(cmd.getBytes());
+ int read = is.read(buf);
+ if(read != ADB_RESPONSE_SIZE || !ADB_OK.equals(new String(buf))) {
+ Log.w(LOGTAG, "adb cmd faild.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ *
+ * Get a tcp socket connection to specified IP address and port proxied by adb
+ *
+ * The proxying is transparent, e.g. if a socket is returned, then it can be written to and
+ * read from as if it is directly connected to the target
+ *
+ * @param remoteAddress IP address of the host to connect to
+ * @param remotePort port of the host to connect to
+ * @return a valid Socket instance if successful, null otherwise
+ */
+ public static Socket getForwardedSocket(int remoteAddress, int remotePort) {
+ try {
+ Socket socket = new Socket(ADB_HOST, ADB_PORT);
+ String cmd = "tcp:" + remotePort + ":" + convert(remoteAddress);
+ if(!sendAdbCmd(socket.getInputStream(), socket.getOutputStream(), cmd)) {
+ socket.close();
+ return null;
+ }
+ return socket;
+ } catch (IOException ioe) {
+ Log.w(LOGTAG, "error creating adb socket", ioe);
+ return null;
+ }
+ }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
new file mode 100644
index 0000000..74e018e
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
@@ -0,0 +1,117 @@
+package com.android.dumprendertree.forwarder;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * A port forwarding server. Listens at specified local port and forward the tcp communications to
+ * external host/port via adb networking proxy.
+ *
+ */
+public class ForwardServer {
+
+ private static final String LOGTAG = "ForwardServer";
+
+ private int remotePort;
+ private int remoteAddress;
+ private int localPort;
+ private ServerSocket serverSocket;
+ private boolean started;
+
+ private Set<Forwarder> forwarders;
+
+ public ForwardServer(int localPort, int remoteAddress, int remotePort) {
+ this.localPort = localPort;
+ this.remoteAddress = remoteAddress;
+ this.remotePort = remotePort;
+ started = false;
+ forwarders = new HashSet<Forwarder>();
+ }
+
+ public synchronized void start() throws IOException {
+ if(!started) {
+ serverSocket = new ServerSocket(localPort);
+ Thread serverThread = new Thread(new ServerRunner(serverSocket));
+ serverThread.setName(LOGTAG);
+ serverThread.start();
+ started = true;
+ }
+ }
+
+ public synchronized void stop() {
+ if(started) {
+ synchronized (forwarders) {
+ for(Forwarder forwarder : forwarders)
+ forwarder.stop();
+ forwarders.clear();
+ }
+ try {
+ serverSocket.close();
+ } catch (IOException ioe) {
+ Log.v(LOGTAG, "exception while closing", ioe);
+ } finally {
+ started = false;
+ }
+ }
+ }
+
+ public synchronized boolean isRunning() {
+ return started;
+ }
+
+ private class ServerRunner implements Runnable {
+
+ private ServerSocket socket;
+
+ public ServerRunner(ServerSocket socket) {
+ this.socket = socket;
+ }
+
+ public void run() {
+ try {
+ while (true) {
+ Socket localSocket = socket.accept();
+ Socket remoteSocket = AdbUtils.getForwardedSocket(remoteAddress, remotePort);
+ if(remoteSocket == null) {
+ try {
+ localSocket.close();
+ } catch (IOException ioe) {
+ Log.w(LOGTAG, "error while closing socket", ioe);
+ } finally {
+ Log.w(LOGTAG, "failed to start forwarding from " + localSocket);
+ }
+ } else {
+ Forwarder forwarder = new Forwarder(localSocket, remoteSocket,
+ ForwardServer.this);
+ forwarder.start();
+ }
+ }
+ } catch (IOException ioe) {
+ return;
+ }
+ }
+ }
+
+ public void register(Forwarder forwarder) {
+ synchronized (forwarders) {
+ if(!forwarders.contains(forwarder)) {
+ forwarders.add(forwarder);
+ }
+ }
+ }
+
+ public void unregister(Forwarder recyclable) {
+ synchronized (forwarders) {
+ if(forwarders.contains(recyclable)) {
+ recyclable.stop();
+ forwarders.remove(recyclable);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
new file mode 100644
index 0000000..e1e04a7
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
@@ -0,0 +1,92 @@
+package com.android.dumprendertree.forwarder;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ *
+ * Worker class for {@link ForwardServer}. A Forwarder will be created once the ForwardServer
+ * accepts an incoming connection, and it will then forward the incoming/outgoing streams to a
+ * connection already proxied by adb networking (see also {@link AdbUtils}).
+ *
+ */
+public class Forwarder {
+
+ private ForwardServer server;
+ private Socket from, to;
+
+ private static final String LOGTAG = "Forwarder";
+
+ public Forwarder (Socket from, Socket to, ForwardServer server) {
+ this.server = server;
+ this.from = from;
+ this.to = to;
+ server.register(this);
+ }
+
+ public void start() {
+ Thread outgoing = new Thread(new SocketPipe(from, to));
+ Thread incoming = new Thread(new SocketPipe(to, from));
+ outgoing.setName(LOGTAG);
+ incoming.setName(LOGTAG);
+ outgoing.start();
+ incoming.start();
+ }
+
+ public void stop() {
+ shutdown(from);
+ shutdown(to);
+ }
+
+ private void shutdown(Socket socket) {
+ try {
+ socket.shutdownInput();
+ } catch (IOException e) {
+ Log.v(LOGTAG, "Socket#shutdownInput", e);
+ }
+ try {
+ socket.shutdownOutput();
+ } catch (IOException e) {
+ Log.v(LOGTAG, "Socket#shutdownOutput", e);
+ }
+ try {
+ socket.close();
+ } catch (IOException e) {
+ Log.v(LOGTAG, "Socket#close", e);
+ }
+ }
+
+ private class SocketPipe implements Runnable {
+
+ private Socket in, out;
+
+ public SocketPipe(Socket in, Socket out) {
+ this.in = in;
+ this.out = out;
+ }
+
+ public void run() {
+ try {
+ int length;
+ InputStream is = in.getInputStream();
+ OutputStream os = out.getOutputStream();
+ byte[] buffer = new byte[4096];
+ while ((length = is.read(buffer)) > 0) {
+ os.write(buffer, 0, length);
+ }
+ } catch (IOException ioe) {
+ } finally {
+ server.unregister(Forwarder.this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SocketPipe{" + in + "=>" + out + "}";
+ }
+ }
+}
diff --git a/vpn/java/android/net/vpn/PptpProfile.java b/vpn/java/android/net/vpn/PptpProfile.java
index c68bb71..b4b7be5 100644
--- a/vpn/java/android/net/vpn/PptpProfile.java
+++ b/vpn/java/android/net/vpn/PptpProfile.java
@@ -16,15 +16,41 @@
package android.net.vpn;
+import android.os.Parcel;
+
/**
* The profile for PPTP type of VPN.
* {@hide}
*/
public class PptpProfile extends VpnProfile {
private static final long serialVersionUID = 1L;
+ private boolean mEncryption = true;
@Override
public VpnType getType() {
return VpnType.PPTP;
}
+
+ /**
+ * Enables/disables the encryption for PPTP tunnel.
+ */
+ public void setEncryptionEnabled(boolean enabled) {
+ mEncryption = enabled;
+ }
+
+ public boolean isEncryptionEnabled() {
+ return mEncryption;
+ }
+
+ @Override
+ protected void readFromParcel(Parcel in) {
+ super.readFromParcel(in);
+ mEncryption = in.readInt() > 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeInt(mEncryption ? 1 : 0);
+ }
}
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index 0bf2346..e448e5a 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -50,6 +50,10 @@ public class VpnManager {
public static final int VPN_ERROR_CONNECTION_FAILED = 2;
/** Error code to indicate the server is not known. */
public static final int VPN_ERROR_UNKNOWN_SERVER = 3;
+ /** Error code to indicate an error from challenge response. */
+ public static final int VPN_ERROR_CHALLENGE = 4;
+ /** Error code to indicate an error of remote server hanging up. */
+ public static final int VPN_ERROR_REMOTE_HUNG_UP = 5;
private static final int VPN_ERROR_NO_ERROR = 0;
public static final String PROFILES_PATH = "/data/misc/vpn/profiles";
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 2ee1945..d8a03a9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -871,7 +871,10 @@ public class WifiManager {
* Create a new MulticastLock
*
* @param tag a tag for the MulticastLock to identify it in debugging
- * messages.
+ * messages. This string is never shown to the user under
+ * normal conditions, but should be descriptive enough to
+ * identify your application and the specific MulticastLock
+ * within it, if it holds multiple MulticastLocks.
*
* @return a new, unacquired MulticastLock with the given tag.
*
@@ -887,26 +890,36 @@ public class WifiManager {
* addressed to this device. Acquring a MulticastLock will
* cause the stack to receive packets addressed to multicast
* addresses. Processing these extra packets can cause a noticable
- * battery drain and should be disabled when not needed
+ * battery drain and should be disabled when not needed.
*/
public class MulticastLock {
private String mTag;
private final IBinder mBinder;
+ private int mRefCount;
+ private boolean mRefCounted;
private boolean mHeld;
private MulticastLock(String tag) {
mTag = tag;
mBinder = new Binder();
+ mRefCount = 0;
+ mRefCounted = true;
mHeld = false;
}
/**
* Locks Wifi Multicast on until {@link #release} is called.
*
- * The first call to {@code acquire} will lock the Multicast on
- * but subsequent calls will be ignored. Only one call to
- * {@link #release} will be required, regardless of the number of
- * times that {@code acquire} is called.
+ * If this MulticastLock is reference-counted each call to
+ * {@code acquire} will increment the reference count, and the
+ * wifi interface will receive multicast packets as long as the
+ * reference count is above zero.
+ *
+ * If this MulticastLock is not reference-counted, the first call to
+ * {@code acquire} will turn on the multicast packets, but subsequent
+ * calls will be ignored. Only one call to {@link #release} will
+ * be required, regardless of the number of times that {@code acquire}
+ * is called.
*
* Note that other applications may also lock Wifi Multicast on.
* Only they can relinquish their lock.
@@ -916,7 +929,7 @@ public class WifiManager {
*/
public void acquire() {
synchronized (mBinder) {
- if (!mHeld) {
+ if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) {
try {
mService.acquireMulticastLock(mBinder, mTag);
synchronized (WifiManager.this) {
@@ -927,9 +940,9 @@ public class WifiManager {
}
mActiveLockCount++;
}
- mHeld = true;
} catch (RemoteException ignore) {
}
+ mHeld = true;
}
}
}
@@ -938,6 +951,18 @@ public class WifiManager {
* Unlocks Wifi Multicast, restoring the filter of packets
* not addressed specifically to this device and saving power.
*
+ * If this MulticastLock is reference-counted, each call to
+ * {@code release} will decrement the reference count, and the
+ * multicast packets will only stop being received when the reference
+ * count reaches zero. If the reference count goes below zero (that
+ * is, if {@code release} is called a greater number of times than
+ * {@link #acquire}), an exception is thrown.
+ *
+ * If this MulticastLock is not reference-counted, the first call to
+ * {@code release} (after the radio was multicast locked using
+ * {@linke #acquire}) will unlock the multicast, and subsequent calls
+ * will be ignored.
+ *
* Note that if any other Wifi Multicast Locks are still outstanding
* this {@code release} call will not have an immediate effect. Only
* when all applications have released all their Multicast Locks will
@@ -948,20 +973,43 @@ public class WifiManager {
*/
public void release() {
synchronized (mBinder) {
- if (mHeld) {
+ if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
try {
mService.releaseMulticastLock();
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- mHeld = false;
} catch (RemoteException ignore) {
}
+ mHeld = false;
+ }
+ if (mRefCount < 0) {
+ throw new RuntimeException("MulticastLock under-locked "
+ + mTag);
}
}
}
/**
+ * Controls whether this is a reference-counted or non-reference-
+ * counted MulticastLock.
+ *
+ * Reference-counted MulticastLocks keep track of the number of calls
+ * to {@link #acquire} and {@link #release}, and only stop the
+ * reception of multicast packets when every call to {@link #acquire}
+ * has been balanced with a call to {@link #release}. Non-reference-
+ * counted MulticastLocks allow the reception of multicast packets
+ * whenever {@link #acquire} is called and stop accepting multicast
+ * packets whenever {@link #release} is called.
+ *
+ * @param refCounted true if this MulticastLock should keep a reference
+ * count
+ */
+ public void setReferenceCounted(boolean refCounted) {
+ mRefCounted = refCounted;
+ }
+
+ /**
* Checks whether this MulticastLock is currently held.
*
* @return true if this MulticastLock is held, false otherwise
@@ -973,17 +1021,23 @@ public class WifiManager {
}
public String toString() {
- String s1, s2;
+ String s1, s2, s3;
synchronized (mBinder) {
s1 = Integer.toHexString(System.identityHashCode(this));
s2 = mHeld ? "held; " : "";
- return "MulticastLock{ " + s1 + "; " + s2 + " }";
+ if (mRefCounted) {
+ s3 = "refcounted: refcount = " + mRefCount;
+ } else {
+ s3 = "not refcounted";
+ }
+ return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }";
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
+ setReferenceCounted(false);
release();
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 12abce5..083cda3 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1467,6 +1467,7 @@ public class WifiStateTracker extends NetworkStateTracker {
public synchronized boolean restart() {
if (mRunState == RUN_STATE_STOPPED) {
mRunState = RUN_STATE_STARTING;
+ resetInterface(true);
return WifiNative.startDriverCommand();
} else if (mRunState == RUN_STATE_STOPPING) {
mRunState = RUN_STATE_STARTING;