summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml973
-rw-r--r--cmds/stagefright/record.cpp60
-rw-r--r--core/java/android/app/Activity.java95
-rw-r--r--core/java/android/app/ActivityThread.java74
-rw-r--r--core/java/android/app/ApplicationThreadNative.java26
-rw-r--r--core/java/android/app/Fragment.java117
-rw-r--r--core/java/android/app/FragmentBreadCrumbs.java22
-rw-r--r--core/java/android/app/FragmentManager.java152
-rw-r--r--core/java/android/app/IApplicationThread.java5
-rw-r--r--core/java/android/app/backup/package.html6
-rw-r--r--core/java/android/content/CursorLoader.java13
-rw-r--r--core/java/android/database/sqlite/DatabaseConnectionPool.java11
-rw-r--r--core/java/android/database/sqlite/SQLiteClosable.java7
-rw-r--r--core/java/android/hardware/Camera.java25
-rw-r--r--core/java/android/net/DownloadManager.java23
-rw-r--r--core/java/android/net/LinkCapabilities.aidl3
-rw-r--r--core/java/android/net/LinkCapabilities.java2
-rw-r--r--core/java/android/net/LinkProperties.aidl3
-rw-r--r--core/java/android/net/LinkProperties.java2
-rw-r--r--core/java/android/net/LinkSocket.java15
-rw-r--r--core/java/android/net/LinkSocketNotifier.java2
-rw-r--r--core/java/android/net/LocalSocket.java7
-rw-r--r--core/java/android/net/ProxyProperties.java2
-rw-r--r--core/java/android/os/BatteryStats.java25
-rw-r--r--core/java/android/os/MessageQueue.java125
-rw-r--r--core/java/android/os/RecoverySystem.java15
-rw-r--r--core/java/android/provider/Downloads.java15
-rw-r--r--core/java/android/provider/Mtp.java10
-rw-r--r--core/java/android/provider/Settings.java16
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java2
-rw-r--r--core/java/android/util/Base64InputStream.java2
-rw-r--r--core/java/android/view/LayoutInflater.java102
-rw-r--r--core/java/android/view/View.java57
-rw-r--r--core/java/android/view/ViewGroup.java100
-rw-r--r--core/java/android/view/ViewParent.java7
-rw-r--r--core/java/android/view/ViewRoot.java18
-rw-r--r--core/java/android/webkit/WebSettings.java5
-rw-r--r--core/java/android/webkit/WebView.java2
-rw-r--r--core/java/android/webkit/WebViewCore.java4
-rw-r--r--core/java/android/webkit/ZoomManager.java14
-rw-r--r--core/java/android/widget/PopupWindow.java1
-rw-r--r--core/java/android/widget/RemoteViews.java140
-rw-r--r--core/java/android/widget/TextView.java524
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java80
-rw-r--r--core/jni/android/graphics/Shader.cpp146
-rw-r--r--core/res/res/drawable-mdpi/overscroll_edge.pngbin0 -> 2180 bytes
-rw-r--r--core/res/res/drawable-mdpi/overscroll_glow.pngbin0 -> 30390 bytes
-rw-r--r--core/res/res/layout/simple_list_item_2.xml2
-rw-r--r--core/res/res/layout/simple_list_item_activated_1.xml25
-rw-r--r--core/res/res/layout/simple_list_item_activated_2.xml43
-rwxr-xr-xcore/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/public.xml11
-rw-r--r--core/res/res/values/styles.xml11
-rw-r--r--core/res/res/values/themes.xml1
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/net/DownloadManagerBaseTest.java31
-rw-r--r--core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java264
-rw-r--r--core/tests/coretests/src/android/util/Base64Test.java11
-rw-r--r--core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java2
-rw-r--r--core/tests/hosttests/src/android/net/DownloadManagerHostTests.java27
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java57
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java2
-rw-r--r--data/fonts/MTLc3m.ttfbin0 -> 1922744 bytes
-rw-r--r--data/fonts/MTLmr3m.ttfbin0 -> 2868496 bytes
-rw-r--r--graphics/java/android/graphics/RadialGradient.java13
-rw-r--r--graphics/java/android/graphics/Shader.java3
-rw-r--r--graphics/java/android/graphics/SweepGradient.java13
-rw-r--r--graphics/java/android/renderscript/BaseObj.java3
-rw-r--r--graphics/java/android/renderscript/RenderScript.java4
-rw-r--r--graphics/java/android/renderscript/Script.java4
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp10
-rw-r--r--include/camera/CameraParameters.h14
-rw-r--r--include/media/stagefright/foundation/ADebug.h49
-rw-r--r--include/utils/Looper.h1
-rw-r--r--libs/camera/CameraParameters.cpp2
-rw-r--r--libs/hwui/GradientCache.cpp2
-rw-r--r--libs/hwui/GradientCache.h4
-rw-r--r--libs/hwui/Matrix.cpp6
-rw-r--r--libs/hwui/Matrix.h2
-rw-r--r--libs/hwui/ProgramCache.cpp73
-rw-r--r--libs/hwui/ProgramCache.h30
-rw-r--r--libs/hwui/SkiaShader.cpp99
-rw-r--r--libs/hwui/SkiaShader.h38
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java26
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/primitives.rs44
-rw-r--r--libs/rs/java/tests/src/com/android/rs/test/shared.rsh10
-rw-r--r--libs/rs/rs.spec6
-rw-r--r--libs/rs/rsScript.cpp6
-rw-r--r--libs/utils/Looper.cpp29
-rw-r--r--location/java/android/location/Geocoder.java8
-rw-r--r--location/java/android/location/GeocoderParams.java2
-rw-r--r--location/java/android/location/ILocationManager.aidl2
-rw-r--r--location/java/android/location/provider/GeocodeProvider.java2
-rw-r--r--location/java/android/location/provider/LocationProvider.java2
-rw-r--r--media/java/android/media/AudioEffect.java68
-rw-r--r--media/java/android/media/MtpClient.java16
-rw-r--r--media/java/android/media/MtpCursor.java8
-rwxr-xr-xmedia/java/android/media/Visualizer.java13
-rwxr-xr-xmedia/java/android/media/videoeditor/Transition.java6
-rw-r--r--media/java/android/media/videoeditor/TransitionEndCurtainClosing.java7
-rwxr-xr-xmedia/java/android/media/videoeditor/TransitionEndFadeToBlack.java8
-rwxr-xr-xmedia/java/android/media/videoeditor/TransitionStartCurtainOpening.java8
-rw-r--r--media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java8
-rw-r--r--media/java/android/media/videoeditor/VideoEditorTestImpl.java278
-rw-r--r--media/jni/android_media_MtpClient.cpp20
-rw-r--r--media/jni/android_media_MtpCursor.cpp4
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp22
-rw-r--r--media/libstagefright/NuCachedSource2.cpp28
-rw-r--r--media/libstagefright/OMXCodec.cpp2
-rw-r--r--media/libstagefright/ThreadedSource.cpp4
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp69
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp96
-rw-r--r--media/libstagefright/foundation/ADebug.cpp76
-rw-r--r--media/libstagefright/foundation/ALooperRoster.cpp13
-rw-r--r--media/libstagefright/foundation/Android.mk1
-rw-r--r--media/libstagefright/foundation/hexdump.cpp6
-rw-r--r--media/libstagefright/include/AACDecoder.h2
-rw-r--r--media/libstagefright/include/AVCDecoder.h2
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp192
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp2
-rw-r--r--media/libstagefright/rtsp/AAMRAssembler.cpp16
-rw-r--r--media/libstagefright/rtsp/AAVCAssembler.cpp61
-rw-r--r--media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp16
-rw-r--r--media/libstagefright/rtsp/APacketSource.cpp15
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp21
-rw-r--r--media/libstagefright/rtsp/ARTPSession.cpp24
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp103
-rw-r--r--media/libstagefright/rtsp/ARTPSource.h1
-rw-r--r--media/libstagefright/rtsp/ARTPWriter.cpp26
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp28
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp13
-rw-r--r--media/libstagefright/rtsp/MyHandler.h70
-rw-r--r--media/libstagefright/rtsp/UDPPusher.cpp12
-rw-r--r--media/libstagefright/rtsp/rtp_test.cpp7
-rw-r--r--media/mtp/MtpCursor.cpp2
-rw-r--r--media/tests/CameraBrowser/Android.mk2
-rw-r--r--media/tests/CameraBrowser/res/layout/object_info.xml10
-rw-r--r--media/tests/CameraBrowser/res/values/strings.xml1
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java18
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java11
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java29
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java21
-rw-r--r--opengl/libs/EGL/Loader.cpp28
-rw-r--r--opengl/libs/EGL/Loader.h2
-rw-r--r--opengl/tests/testLatency/Android.mk20
-rw-r--r--opengl/tests/testLatency/AndroidManifest.xml37
-rw-r--r--opengl/tests/testLatency/res/values/strings.xml29
-rw-r--r--opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java47
-rw-r--r--opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java267
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml27
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java17
-rw-r--r--services/java/com/android/server/ConnectivityService.java43
-rw-r--r--services/java/com/android/server/InputManager.java20
-rw-r--r--services/java/com/android/server/LocationManagerService.java2
-rw-r--r--services/java/com/android/server/PackageManagerService.java20
-rw-r--r--services/java/com/android/server/WindowManagerService.java5
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java222
-rw-r--r--services/java/com/android/server/am/ActivityStack.java38
-rwxr-xr-xservices/java/com/android/server/location/ComprehensiveCountryDetector.java10
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java9
-rw-r--r--services/java/com/android/server/sip/SipService.java6
-rw-r--r--services/jni/com_android_server_InputManager.cpp45
-rw-r--r--services/surfaceflinger/Layer.cpp3
-rw-r--r--telephony/java/com/android/internal/telephony/CallManager.java133
-rw-r--r--telephony/java/com/android/internal/telephony/Phone.java4
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java33
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java35
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhone.java30
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhoneBase.java2
-rwxr-xr-xtests/DumpRenderTree2/assets/run_apache2.py7
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java2
-rw-r--r--tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java38
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml11
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java114
-rw-r--r--tools/layoutlib/bridge/src/android/view/BridgeInflater.java4
-rw-r--r--tools/layoutlib/create/README.txt200
-rwxr-xr-xtools/obbtool/mkobb.sh260
182 files changed, 4860 insertions, 2503 deletions
diff --git a/api/current.xml b/api/current.xml
index 374e26f..c43ebac 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6268,17 +6268,6 @@
visibility="public"
>
</field>
-<field name="kraken_resource_pad57"
- type="int"
- transient="false"
- volatile="false"
- value="16843464"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="kraken_resource_pad6"
type="int"
transient="false"
@@ -10129,6 +10118,17 @@
visibility="public"
>
</field>
+<field name="textSelectHandleWindowStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843464"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textSize"
type="int"
transient="false"
@@ -15869,6 +15869,28 @@
visibility="public"
>
</field>
+<field name="simple_list_item_activated_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367075"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="simple_list_item_activated_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367076"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="simple_list_item_checked"
type="int"
transient="false"
@@ -22618,7 +22640,7 @@
</implements>
<implements name="android.view.KeyEvent.Callback">
</implements>
-<implements name="android.view.LayoutInflater.Factory">
+<implements name="android.view.LayoutInflater.Factory2">
</implements>
<implements name="android.view.View.OnCreateContextMenuListener">
</implements>
@@ -22751,6 +22773,23 @@
<parameter name="ev" type="android.view.MotionEvent">
</parameter>
</method>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="false"
@@ -23456,6 +23495,25 @@
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
</method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
<method name="onDestroy"
return="void"
abstract="false"
@@ -28720,6 +28778,25 @@
visibility="public"
>
</constructor>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="equals"
return="boolean"
abstract="false"
@@ -28908,6 +28985,17 @@
visibility="public"
>
</method>
+<method name="isInLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isResumed"
return="boolean"
abstract="false"
@@ -29514,6 +29602,25 @@
visibility="public"
>
</method>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="true"
@@ -46477,6 +46584,21 @@
<parameter name="cursor" type="android.database.Cursor">
</parameter>
</method>
+<method name="registerContentObserver"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cursor" type="android.database.Cursor">
+</parameter>
+<parameter name="observer" type="android.database.ContentObserver">
+</parameter>
+</method>
<method name="setProjection"
return="void"
abstract="false"
@@ -87108,11 +87230,11 @@
visibility="public"
>
</field>
-<field name="FOCUS_MODE_CONTINUOUS"
+<field name="FOCUS_MODE_CONTINUOUS_VIDEO"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;continuous&quot;"
+ value="&quot;continuous-video&quot;"
static="true"
final="true"
deprecated="not deprecated"
@@ -92719,8 +92841,8 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
-<method name="isImplemented"
- return="java.lang.Boolean"
+<method name="isPresent"
+ return="boolean"
abstract="false"
native="false"
synchronized="false"
@@ -92731,75 +92853,6 @@
>
</method>
</class>
-<class name="GeocoderParams"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.Parcelable">
-</implements>
-<method name="describeContents"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getClientPackage"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getLocale"
- return="java.util.Locale"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="writeToParcel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="parcel" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="GpsSatellite"
extends="java.lang.Object"
abstract="false"
@@ -94391,396 +94444,6 @@
</field>
</class>
</package>
-<package name="android.location.provider"
->
-<class name="GeocodeProvider"
- extends="java.lang.Object"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="GeocodeProvider"
- type="android.location.provider.GeocodeProvider"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetFromLocation"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="latitude" type="double">
-</parameter>
-<parameter name="longitude" type="double">
-</parameter>
-<parameter name="maxResults" type="int">
-</parameter>
-<parameter name="params" type="android.location.GeocoderParams">
-</parameter>
-<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
-</parameter>
-</method>
-<method name="onGetFromLocationName"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="locationName" type="java.lang.String">
-</parameter>
-<parameter name="lowerLeftLatitude" type="double">
-</parameter>
-<parameter name="lowerLeftLongitude" type="double">
-</parameter>
-<parameter name="upperRightLatitude" type="double">
-</parameter>
-<parameter name="upperRightLongitude" type="double">
-</parameter>
-<parameter name="maxResults" type="int">
-</parameter>
-<parameter name="params" type="android.location.GeocoderParams">
-</parameter>
-<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
-</parameter>
-</method>
-</class>
-<class name="LocationProvider"
- extends="java.lang.Object"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="LocationProvider"
- type="android.location.provider.LocationProvider"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onAddListener"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uid" type="int">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onDisable"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onEnable"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onEnableLocationTracking"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="enable" type="boolean">
-</parameter>
-</method>
-<method name="onGetAccuracy"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetInternalState"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetPowerRequirement"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetStatus"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="onGetStatusUpdateTime"
- return="long"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onHasMonetaryCost"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onMeetsCriteria"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="criteria" type="android.location.Criteria">
-</parameter>
-</method>
-<method name="onRemoveListener"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uid" type="int">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onRequiresCell"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onRequiresNetwork"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onRequiresSatellite"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSendExtraCommand"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="command" type="java.lang.String">
-</parameter>
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="onSetMinTime"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="minTime" type="long">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onSupportsAltitude"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSupportsBearing"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSupportsSpeed"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onUpdateLocation"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="location" type="android.location.Location">
-</parameter>
-</method>
-<method name="onUpdateNetworkState"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="state" type="int">
-</parameter>
-<parameter name="info" type="android.net.NetworkInfo">
-</parameter>
-</method>
-<method name="reportLocation"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="location" type="android.location.Location">
-</parameter>
-</method>
-</class>
-</package>
<package name="android.media"
>
<class name="AsyncPlayer"
@@ -95370,6 +95033,39 @@
<parameter name="value" type="short">
</parameter>
</method>
+<field name="ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ALREADY_EXISTS"
type="int"
transient="false"
@@ -95381,6 +95077,50 @@
visibility="public"
>
</field>
+<field name="CONTENT_TYPE_GAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MOVIE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MUSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_VOICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EFFECT_AUXILIARY"
type="java.lang.String"
transient="false"
@@ -95529,6 +95269,39 @@
visibility="public"
>
</field>
+<field name="EXTRA_AUDIO_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.AUDIO_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CONTENT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.CONTENT_TYPE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_PACKAGE_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.PACKAGE_NAME&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="NATIVE_EVENT_CONTROL_STATUS"
type="int"
transient="false"
@@ -106737,6 +106510,17 @@
visibility="public"
>
</field>
+<field name="ERROR_FILE_ALREADY_EXISTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1009"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ERROR_FILE_ERROR"
type="int"
transient="false"
@@ -107011,6 +106795,19 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setShowRunningNotification"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="show" type="boolean">
+</parameter>
+</method>
<method name="setTitle"
return="android.net.DownloadManager.Request"
abstract="false"
@@ -157486,6 +157283,17 @@
visibility="public"
>
</field>
+<field name="AUTO_TIME_ZONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;auto_time_zone&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="BLUETOOTH_DISCOVERABILITY"
type="java.lang.String"
transient="false"
@@ -178798,19 +178606,6 @@
<parameter name="event" type="android.view.MotionEvent">
</parameter>
</method>
-<method name="setCursorController"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursorController" type="android.widget.TextView.CursorController">
-</parameter>
-</method>
</class>
<class name="BaseKeyListener"
extends="android.text.method.MetaKeyKeyListener"
@@ -193506,6 +193301,17 @@
visibility="public"
>
</method>
+<method name="getFactory2"
+ return="android.view.LayoutInflater.Factory2"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFilter"
return="android.view.LayoutInflater.Filter"
abstract="false"
@@ -193598,6 +193404,25 @@
<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
</exception>
</method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
+</exception>
+</method>
<method name="setFactory"
return="void"
abstract="false"
@@ -193611,6 +193436,19 @@
<parameter name="factory" type="android.view.LayoutInflater.Factory">
</parameter>
</method>
+<method name="setFactory2"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factory" type="android.view.LayoutInflater.Factory2">
+</parameter>
+</method>
<method name="setFilter"
return="void"
abstract="false"
@@ -193650,6 +193488,35 @@
</parameter>
</method>
</interface>
+<interface name="LayoutInflater.Factory2"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.LayoutInflater.Factory">
+</implements>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
+</interface>
<interface name="LayoutInflater.Filter"
abstract="true"
static="true"
@@ -233604,6 +233471,21 @@
<parameter name="extras" type="android.os.Bundle">
</parameter>
</method>
+<method name="setOnClickFillInIntent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="fillInIntent" type="android.content.Intent">
+</parameter>
+</method>
<method name="setOnClickPendingIntent"
return="void"
abstract="false"
@@ -239565,121 +239447,6 @@
>
</method>
</class>
-<interface name="TextView.CursorController"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="draw"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="canvas" type="android.graphics.Canvas">
-</parameter>
-</method>
-<method name="getOffsetX"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getOffsetY"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="hide"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isShowing"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="show"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="updatePosition"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="x" type="int">
-</parameter>
-<parameter name="y" type="int">
-</parameter>
-</method>
-<field name="FADE_OUT_DURATION"
- type="int"
- transient="false"
- volatile="false"
- value="400"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</interface>
<interface name="TextView.OnEditorActionListener"
abstract="true"
static="true"
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index c424281..b718299 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -36,24 +36,30 @@ static const int32_t kFramerate = 24; // fps
static const int32_t kIFramesIntervalSec = 1;
static const int32_t kVideoBitRate = 512 * 1024;
static const int32_t kAudioBitRate = 12200;
-static const int32_t kColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
static const int64_t kDurationUs = 10000000LL; // 10 seconds
#if 1
class DummySource : public MediaSource {
public:
- DummySource(int width, int height)
+ DummySource(int width, int height, int colorFormat)
: mWidth(width),
mHeight(height),
+ mColorFormat(colorFormat),
mSize((width * height * 3) / 2) {
mGroup.add_buffer(new MediaBuffer(mSize));
+
+ // Check the color format to make sure
+ // that the buffer size mSize it set correctly above.
+ CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+ colorFormat == OMX_COLOR_FormatYUV420Planar);
}
virtual sp<MetaData> getFormat() {
sp<MetaData> meta = new MetaData;
meta->setInt32(kKeyWidth, mWidth);
meta->setInt32(kKeyHeight, mHeight);
+ meta->setInt32(kKeyColorFormat, mColorFormat);
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
return meta;
@@ -100,6 +106,7 @@ protected:
private:
MediaBufferGroup mGroup;
int mWidth, mHeight;
+ int mColorFormat;
size_t mSize;
int64_t mNumFramesOutput;;
@@ -139,20 +146,47 @@ sp<MediaSource> createSource(const char *filename) {
return source;
}
+enum {
+ kYUV420SP = 0,
+ kYUV420P = 1,
+};
+
+// returns -1 if mapping of the given color is unsuccessful
+// returns an omx color enum value otherwise
+static int translateColorToOmxEnumValue(int color) {
+ switch (color) {
+ case kYUV420SP:
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ case kYUV420P:
+ return OMX_COLOR_FormatYUV420Planar;
+ default:
+ fprintf(stderr, "Unsupported color: %d\n", color);
+ return -1;
+ }
+}
+
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
DataSource::RegisterDefaultSniffers();
#if 1
- if (argc != 2) {
- fprintf(stderr, "usage: %s filename\n", argv[0]);
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]);
+ fprintf(stderr, " <input_color_format>: 0 (YUV420SP) or 1 (YUV420P)\n");
return 1;
}
+ int colorFormat = translateColorToOmxEnumValue(atoi(argv[2]));
+ if (colorFormat == -1) {
+ fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
+ return 1;
+ }
OMXClient client;
CHECK_EQ(client.connect(), OK);
+ status_t err = OK;
+
#if 0
sp<MediaSource> source = createSource(argv[1]);
@@ -173,7 +207,7 @@ int main(int argc, char **argv) {
#else
int width = 720;
int height = 480;
- sp<MediaSource> decoder = new DummySource(width, height);
+ sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
#endif
sp<MetaData> enc_meta = new MetaData;
@@ -187,7 +221,7 @@ int main(int argc, char **argv) {
enc_meta->setInt32(kKeyStride, width);
enc_meta->setInt32(kKeySliceHeight, height);
enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
- enc_meta->setInt32(kKeyColorFormat, kColorFormat);
+ enc_meta->setInt32(kKeyColorFormat, colorFormat);
sp<MediaSource> encoder =
OMXCodec::Create(
@@ -197,14 +231,14 @@ int main(int argc, char **argv) {
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
writer->addSource(encoder);
writer->setMaxFileDuration(kDurationUs);
- writer->start();
+ CHECK_EQ(OK, writer->start());
while (!writer->reachedEOS()) {
fprintf(stderr, ".");
usleep(100000);
}
- writer->stop();
+ err = writer->stop();
#else
- encoder->start();
+ CHECK_EQ(OK, encoder->start());
MediaBuffer *buffer;
while (encoder->read(&buffer) == OK) {
@@ -222,7 +256,7 @@ int main(int argc, char **argv) {
buffer = NULL;
}
- encoder->stop();
+ err = encoder->stop();
#endif
printf("$\n");
@@ -247,12 +281,16 @@ int main(int argc, char **argv) {
buffer = NULL;
}
- source->stop();
+ err = source->stop();
delete source;
source = NULL;
#endif
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ fprintf(stderr, "record failed: %d\n", err);
+ return 1;
+ }
return 0;
}
#else
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2e8d682..ee49d97 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,6 +74,8 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
import android.widget.FrameLayout;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -605,7 +607,7 @@ import java.util.HashMap;
* or finished.
*/
public class Activity extends ContextThemeWrapper
- implements LayoutInflater.Factory,
+ implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks {
private static final String TAG = "Activity";
@@ -1488,7 +1490,9 @@ public class Activity extends ContextThemeWrapper
* <li> The function will be called between {@link #onStop} and
* {@link #onDestroy}.
* <li> A new instance of the activity will <em>always</em> be immediately
- * created after this one's {@link #onDestroy()} is called.
+ * created after this one's {@link #onDestroy()} is called. In particular,
+ * <em>no</em> messages will be dispatched during this time (when the returned
+ * object does not have an activity to be associated with).
* <li> The object you return here will <em>always</em> be available from
* the {@link #getLastNonConfigurationInstance()} method of the following
* activity instance as described there.
@@ -1501,6 +1505,15 @@ public class Activity extends ContextThemeWrapper
* may change based on the configuration, including any data loaded from
* resources such as strings, layouts, or drawables.
*
+ * <p>The guarantee of no message handling during the switch to the next
+ * activity simplifies use with active objects. For example if your retained
+ * state is an {@link android.os.AsyncTask} you are guaranteed that its
+ * call back functions (like {@link android.os.AsyncTask#onPostExecute}) will
+ * not be called from the call here until you execute the next instance's
+ * {@link #onCreate(Bundle)}. (Note however that there is of course no such
+ * guarantee for {@link android.os.AsyncTask#doInBackground} since that is
+ * running in a separate thread.)
+ *
* @return Return any Object holding the desired state to propagate to the
* next activity instance.
*/
@@ -4019,15 +4032,30 @@ public class Activity extends ContextThemeWrapper
* Standard implementation of
* {@link android.view.LayoutInflater.Factory#onCreateView} used when
* inflating with the LayoutInflater returned by {@link #getSystemService}.
+ * This implementation does nothing and is for
+ * pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB} apps. Newer apps
+ * should use {@link #onCreateView(View, String, Context, AttributeSet)}.
+ *
+ * @see android.view.LayoutInflater#createView
+ * @see android.view.Window#getLayoutInflater
+ */
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ return null;
+ }
+
+ /**
+ * Standard implementation of
+ * {@link android.view.LayoutInflater.Factory2#onCreateView(View, String, Context, AttributeSet)}
+ * used when inflating with the LayoutInflater returned by {@link #getSystemService}.
* This implementation handles <fragment> tags to embed fragments inside
* of the activity.
*
* @see android.view.LayoutInflater#createView
* @see android.view.Window#getLayoutInflater
*/
- public View onCreateView(String name, Context context, AttributeSet attrs) {
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
if (!"fragment".equals(name)) {
- return null;
+ return onCreateView(name, context, attrs);
}
String fname = attrs.getAttributeValue(null, "class");
@@ -4036,42 +4064,70 @@ public class Activity extends ContextThemeWrapper
if (fname == null) {
fname = a.getString(com.android.internal.R.styleable.Fragment_name);
}
- int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, 0);
+ int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
a.recycle();
- if (id == 0) {
+ int containerId = parent != null ? parent.getId() : 0;
+ if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
throw new IllegalArgumentException(attrs.getPositionDescription()
- + ": Must specify unique android:id for " + fname);
+ + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
}
-
+
// If we restored from a previous state, we may already have
// instantiated this fragment from the state and should use
// that instance instead of making a new one.
- Fragment fragment = mFragments.findFragmentById(id);
+ Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
+ if (fragment == null && tag != null) {
+ fragment = mFragments.findFragmentByTag(tag);
+ }
+ if (fragment == null && containerId != View.NO_ID) {
+ fragment = mFragments.findFragmentById(containerId);
+ }
+
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
+ Integer.toHexString(id) + " fname=" + fname
+ " existing=" + fragment);
if (fragment == null) {
fragment = Fragment.instantiate(this, fname);
fragment.mFromLayout = true;
- fragment.mFragmentId = id;
+ fragment.mFragmentId = id != 0 ? id : containerId;
+ fragment.mContainerId = containerId;
fragment.mTag = tag;
+ fragment.mInLayout = true;
fragment.mImmediateActivity = this;
fragment.mFragmentManager = mFragments;
+ fragment.onInflate(attrs, fragment.mSavedFragmentState);
+ mFragments.addFragment(fragment, true);
+
+ } else if (fragment.mInLayout) {
+ // A fragment already exists and it is not one we restored from
+ // previous state.
+ throw new IllegalArgumentException(attrs.getPositionDescription()
+ + ": Duplicate id 0x" + Integer.toHexString(id)
+ + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+ + " with another fragment for " + fname);
+ } else {
+ // This fragment was retained from a previous instance; get it
+ // going now.
+ fragment.mInLayout = true;
+ fragment.mImmediateActivity = this;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
if (!fragment.mRetaining) {
fragment.onInflate(attrs, fragment.mSavedFragmentState);
}
- mFragments.addFragment(fragment, true);
+ mFragments.moveToState(fragment);
}
+
if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname
+ " did not create a view.");
}
- fragment.mView.setId(id);
+ if (id != 0) {
+ fragment.mView.setId(id);
+ }
if (fragment.mView.getTag() == null) {
fragment.mView.setTag(tag);
}
@@ -4079,6 +4135,19 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Print the Activity's state into the given stream. This gets invoked if
+ * you run "adb shell dumpsys activity <youractivityname>".
+ *
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be
+ * closed for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mFragments.dump("", fd, writer, args);
+ }
+
+ /**
* Bit indicating that this activity is "immersive" and should not be
* interrupted by notifications if possible.
*
@@ -4166,7 +4235,7 @@ public class Activity extends ContextThemeWrapper
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
- mWindow.getLayoutInflater().setFactory(this);
+ mWindow.getLayoutInflater().setFactory2(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c0e2987..3f74904 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -335,9 +335,9 @@ public final class ActivityThread {
}
}
- private static final class DumpServiceInfo {
+ private static final class DumpComponentInfo {
FileDescriptor fd;
- IBinder service;
+ IBinder token;
String[] args;
boolean dumped;
}
@@ -370,7 +370,8 @@ public final class ActivityThread {
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d";
private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
- private static final String DB_INFO_FORMAT = " %4d %6d %8d %14s %s";
+ private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
+ private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
@@ -591,9 +592,9 @@ public final class ActivityThread {
}
public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
- DumpServiceInfo data = new DumpServiceInfo();
+ DumpComponentInfo data = new DumpComponentInfo();
data.fd = fd;
- data.service = servicetoken;
+ data.token = servicetoken;
data.args = args;
data.dumped = false;
queueOrSendMessage(H.DUMP_SERVICE, data);
@@ -663,6 +664,25 @@ public final class ActivityThread {
public void scheduleCrash(String msg) {
queueOrSendMessage(H.SCHEDULE_CRASH, msg);
}
+
+ public void dumpActivity(FileDescriptor fd, IBinder activitytoken, String[] args) {
+ DumpComponentInfo data = new DumpComponentInfo();
+ data.fd = fd;
+ data.token = activitytoken;
+ data.args = args;
+ data.dumped = false;
+ queueOrSendMessage(H.DUMP_ACTIVITY, data);
+ synchronized (data) {
+ while (!data.dumped) {
+ try {
+ data.wait();
+ } catch (InterruptedException e) {
+ // no need to do anything here, we will keep waiting until
+ // dumped is set
+ }
+ }
+ }
+ }
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -820,20 +840,23 @@ public final class ActivityThread {
// SQLite mem info
pw.println(" ");
pw.println(" SQL");
- printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:",
stats.memoryUsed / 1024);
- printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
- "largestMemAlloc:", stats.largestMemAlloc / 1024);
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:",
+ stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
pw.println(" ");
int N = stats.dbStats.size();
if (N > 0) {
pw.println(" DATABASES");
- printRow(pw, " %4s %6s %8s %14s %s", "pgsz", "dbsz", "lkaside", "cache",
- "Dbname");
+ printRow(pw, " %8s %8s %14s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
+ "Dbname");
for (int i = 0; i < N; i++) {
DbStats dbStats = stats.dbStats.get(i);
- printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
- dbStats.lookaside, dbStats.cache, dbStats.dbName);
+ printRow(pw, DB_INFO_FORMAT,
+ (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
+ (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
+ (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
+ dbStats.cache, dbStats.dbName);
}
}
@@ -888,6 +911,7 @@ public final class ActivityThread {
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
public static final int DUMP_HEAP = 135;
+ public static final int DUMP_ACTIVITY = 136;
String codeToString(int code) {
if (localLOGV) {
switch (code) {
@@ -927,6 +951,7 @@ public final class ActivityThread {
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
case DUMP_HEAP: return "DUMP_HEAP";
+ case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
}
}
return "(unknown)";
@@ -1021,7 +1046,7 @@ public final class ActivityThread {
scheduleGcIdler();
break;
case DUMP_SERVICE:
- handleDumpService((DumpServiceInfo)msg.obj);
+ handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
handleLowMemory();
@@ -1055,6 +1080,9 @@ public final class ActivityThread {
case DUMP_HEAP:
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
break;
+ case DUMP_ACTIVITY:
+ handleDumpActivity((DumpComponentInfo)msg.obj);
+ break;
}
}
@@ -2020,9 +2048,9 @@ public final class ActivityThread {
}
}
- private void handleDumpService(DumpServiceInfo info) {
+ private void handleDumpService(DumpComponentInfo info) {
try {
- Service s = mServices.get(info.service);
+ Service s = mServices.get(info.token);
if (s != null) {
PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
s.dump(info.fd, pw, info.args);
@@ -2036,6 +2064,22 @@ public final class ActivityThread {
}
}
+ private void handleDumpActivity(DumpComponentInfo info) {
+ try {
+ ActivityClientRecord r = mActivities.get(info.token);
+ if (r != null && r.activity != null) {
+ PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
+ r.activity.dump(info.fd, pw, info.args);
+ pw.close();
+ }
+ } finally {
+ synchronized (info) {
+ info.dumped = true;
+ info.notifyAll();
+ }
+ }
+ }
+
private final void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index dc2145f..95689fc 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -414,6 +414,21 @@ public abstract class ApplicationThreadNative extends Binder
dumpHeap(managed, path, fd);
return true;
}
+
+ case DUMP_ACTIVITY_TRANSACTION: {
+ data.enforceInterface(IApplicationThread.descriptor);
+ ParcelFileDescriptor fd = data.readFileDescriptor();
+ final IBinder activity = data.readStrongBinder();
+ final String[] args = data.readStringArray();
+ if (fd != null) {
+ dumpActivity(fd.getFileDescriptor(), activity, args);
+ try {
+ fd.close();
+ } catch (IOException e) {
+ }
+ }
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -857,5 +872,16 @@ class ApplicationThreadProxy implements IApplicationThread {
IBinder.FLAG_ONEWAY);
data.recycle();
}
+
+ public void dumpActivity(FileDescriptor fd, IBinder token, String[] args)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeFileDescriptor(fd);
+ data.writeStrongBinder(token);
+ data.writeStringArray(args);
+ mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
+ data.recycle();
+ }
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 1cbed79..12bf7e5 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -38,6 +38,8 @@ import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.HashMap;
final class FragmentState implements Parcelable {
@@ -207,7 +209,7 @@ final class FragmentState implements Parcelable {
*
* <p>An activity's layout XML can include <code>&lt;fragment&gt;</code> tags
* to embed fragment instances inside of the layout. For example, here is
- * a simply layout that embeds one fragment:</p>
+ * a simple layout that embeds one fragment:</p>
*
* {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
*
@@ -251,6 +253,33 @@ final class FragmentState implements Parcelable {
* details activity will finish of it finds itself running in a configuration
* where the details can be shown inline.
*
+ * <p>When a configuration change causes the activity hosting these fragments
+ * to restart, its new instance may use a different layout that doesn't
+ * include the same fragments as the previous layout. In this case all of
+ * the previous fragments will still be instantiated and running in the new
+ * instance; however, any that are no longer associated with a &lt;fragment&gt;
+ * tag in the view hierarchy will not have their content view created and will
+ * return false from {@link #isInLayout}.
+ *
+ * <p>The attributes of the &lt;fragment&gt; tag are used to control the
+ * LayoutParams provider when attaching the fragment's view to the parent
+ * container. They can alse be parsed by the fragment in {@link #onInflate}
+ * as parameters.
+ *
+ * <p>The fragment being instantiated must have some kind of unique identifier
+ * so that it can be re-associated with a previous instance if the parent
+ * activity needs to be destroyed and recreated. This can be provided these
+ * ways:
+ *
+ * <ul>
+ * <li>If nothing is explicitly supplied, the view ID of the container will
+ * be used.
+ * <li><code>android:tag</code> can be used in &lt;fragment&gt; to provide
+ * a specific tag name for the fragment.
+ * <li><code>android:id</code> can be used in &lt;fragment&gt; to provide
+ * a specific identifier for the fragment.
+ * </ul>
+ *
* <a name="BackStack"></a>
* <h3>Back Stack</h3>
*
@@ -316,6 +345,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
+ // Set to true when the view has actually been inflated in its layout.
+ boolean mInLayout;
+
// Number of active back stack entries this fragment is in.
int mBackStackNesting;
@@ -585,7 +617,7 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
/**
* Return the FragmentManager for interacting with fragments associated
* with this fragment's activity. Note that this will be non-null slightly
- * before {@link #getActivity()}, in the time from when the fragment is
+ * before {@link #getActivity()}, during the time from when the fragment is
* placed in a {@link FragmentTransaction} until it is committed and
* attached to its activity.
*/
@@ -601,6 +633,17 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
}
/**
+ * Return true if the layout is included as part of an activity view
+ * hierarchy via the &lt;fragment&gt; tag. This will always be true when
+ * fragments are created through the &lt;fragment&gt; tag, <em>except</em>
+ * in the case where an old fragment is restored from a previous state and
+ * it does not appear in the layout of the current state.
+ */
+ final public boolean isInLayout() {
+ return mInLayout;
+ }
+
+ /**
* Return true if the fragment is in the resumed state. This is true
* for the duration of {@link #onResume()} and {@link #onPause()} as well.
*/
@@ -1075,6 +1118,76 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
return false;
}
+ /**
+ * Print the Fragments's state into the given stream.
+ *
+ * @param prefix Text to print at the front of each line.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be
+ * closed for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.print(prefix); writer.print("mFragmentId="); writer.print(mFragmentId);
+ writer.print(" mContainerId="); writer.print(mContainerId);
+ writer.print(" mTag="); writer.println(mTag);
+ writer.print(prefix); writer.print("mState="); writer.print(mState);
+ writer.print(" mIndex="); writer.print(mIndex);
+ writer.print(" mWho="); writer.print(mWho);
+ writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
+ writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
+ writer.print(" mResumed="); writer.print(mResumed);
+ writer.print(" mFromLayout="); writer.print(mFromLayout);
+ writer.print(" mInLayout="); writer.println(mInLayout);
+ writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
+ writer.print(" mRetainInstance="); writer.print(mRetainInstance);
+ writer.print(" mRetaining="); writer.print(mRetaining);
+ writer.print(" mHasMenu="); writer.println(mHasMenu);
+ if (mFragmentManager != null) {
+ writer.print(prefix); writer.print("mFragmentManager=");
+ writer.println(mFragmentManager);
+ }
+ if (mImmediateActivity != null) {
+ writer.print(prefix); writer.print("mImmediateActivity=");
+ writer.println(mImmediateActivity);
+ }
+ if (mActivity != null) {
+ writer.print(prefix); writer.print("mActivity=");
+ writer.println(mActivity);
+ }
+ if (mArguments != null) {
+ writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
+ }
+ if (mSavedFragmentState != null) {
+ writer.print(prefix); writer.print("mSavedFragmentState=");
+ writer.println(mSavedFragmentState);
+ }
+ if (mSavedViewState != null) {
+ writer.print(prefix); writer.print("mSavedViewState=");
+ writer.println(mSavedViewState);
+ }
+ if (mTarget != null) {
+ writer.print(prefix); writer.print("mTarget="); writer.print(mTarget);
+ writer.print(" mTargetRequestCode=");
+ writer.println(mTargetRequestCode);
+ }
+ if (mNextAnim != 0) {
+ writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim);
+ }
+ if (mContainer != null) {
+ writer.print(prefix); writer.print("mContainer="); writer.println(mContainer);
+ }
+ if (mView != null) {
+ writer.print(prefix); writer.print("mView="); writer.println(mView);
+ }
+ if (mLoaderManager != null) {
+ writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager);
+ writer.print(" mStarted="); writer.print(mStarted);
+ writer.print(" mCheckedForLoaderManager=");
+ writer.println(mCheckedForLoaderManager);
+ }
+ }
+
void performStop() {
onStop();
if (mStarted) {
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index 0d39d0b..22e0747 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -16,6 +16,7 @@
package android.app;
+import android.app.FragmentManager.BackStackEntry;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -139,14 +140,14 @@ public class FragmentBreadCrumbs extends ViewGroup
FragmentManager fm = mActivity.getFragmentManager();
int numEntries = fm.countBackStackEntries();
int numViews = mContainer.getChildCount();
- for (int i=mTopEntry != null ? -1 : 0; i<numEntries; i++) {
- FragmentManager.BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
- int viewI = mTopEntry != null ? i+1 : i;
+ for (int i = mTopEntry != null ? -1 : 0; i < numEntries; i++) {
+ BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
+ int viewI = mTopEntry != null ? i + 1 : i;
if (viewI < numViews) {
View v = mContainer.getChildAt(viewI);
Object tag = v.getTag();
if (tag != bse) {
- for (int j=viewI; j<numViews; j++) {
+ for (int j = viewI; j < numViews; j++) {
mContainer.removeViewAt(viewI);
}
numViews = viewI;
@@ -163,13 +164,24 @@ public class FragmentBreadCrumbs extends ViewGroup
text.setCompoundDrawables(null, null, null, null);
}
mContainer.addView(item);
+ item.setOnClickListener(mOnClickListener);
}
}
- int viewI = mTopEntry != null ? numEntries+1 : numEntries;
+ int viewI = mTopEntry != null ? numEntries + 1 : numEntries;
numViews = mContainer.getChildCount();
while (numViews > viewI) {
mContainer.removeViewAt(numViews-1);
numViews--;
}
}
+
+ private OnClickListener mOnClickListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (v.getTag() instanceof BackStackEntry) {
+ BackStackEntry bse = (BackStackEntry) v.getTag();
+ mActivity.getFragmentManager().popBackStack(bse.getId(),
+ bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0);
+ }
+ }
+ };
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9f95824..da7ba6f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -32,6 +32,8 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
@@ -190,6 +192,16 @@ public interface FragmentManager {
* the given reference.
*/
public Fragment getFragment(Bundle bundle, String key);
+
+ /**
+ * Print the FragmentManager's state into the given stream.
+ *
+ * @param prefix Text to print at the front of each line.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer A PrintWriter to which the dump is to be set.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
}
final class FragmentManagerState implements Parcelable {
@@ -270,18 +282,23 @@ final class FragmentManagerImpl implements FragmentManager {
execPendingActions();
}
};
+
+ @Override
public FragmentTransaction openTransaction() {
return new BackStackRecord(this);
}
+ @Override
public boolean popBackStack() {
return popBackStackState(mActivity.mHandler, null, -1, 0);
}
+ @Override
public boolean popBackStack(String name, int flags) {
return popBackStackState(mActivity.mHandler, name, -1, flags);
}
+ @Override
public boolean popBackStack(int id, int flags) {
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
@@ -289,14 +306,17 @@ final class FragmentManagerImpl implements FragmentManager {
return popBackStackState(mActivity.mHandler, null, id, flags);
}
+ @Override
public int countBackStackEntries() {
return mBackStack != null ? mBackStack.size() : 0;
}
+ @Override
public BackStackEntry getBackStackEntry(int index) {
return mBackStack.get(index);
}
+ @Override
public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
if (mBackStackChangeListeners == null) {
mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
@@ -304,12 +324,14 @@ final class FragmentManagerImpl implements FragmentManager {
mBackStackChangeListeners.add(listener);
}
+ @Override
public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
if (mBackStackChangeListeners != null) {
mBackStackChangeListeners.remove(listener);
}
}
+ @Override
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
throw new IllegalStateException("Fragment " + fragment
@@ -318,6 +340,7 @@ final class FragmentManagerImpl implements FragmentManager {
bundle.putInt(key, fragment.mIndex);
}
+ @Override
public Fragment getFragment(Bundle bundle, String key) {
int index = bundle.getInt(key, -1);
if (index == -1) {
@@ -335,6 +358,51 @@ final class FragmentManagerImpl implements FragmentManager {
return f;
}
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (mActive == null || mActive.size() <= 0) {
+ return;
+ }
+
+ writer.print(prefix); writer.println("Active Fragments:");
+
+ String innerPrefix = prefix + " ";
+
+ int N = mActive.size();
+ for (int i=0; i<N; i++) {
+ Fragment f = mActive.get(i);
+ if (f != null) {
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(f.toString());
+ f.dump(innerPrefix, fd, writer, args);
+ }
+ }
+
+ if (mAdded != null) {
+ N = mAdded.size();
+ if (N > 0) {
+ writer.print(prefix); writer.println("Added Fragments:");
+ for (int i=0; i<N; i++) {
+ Fragment f = mAdded.get(i);
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(f.toString());
+ }
+ }
+ }
+
+ if (mBackStack != null) {
+ N = mBackStack.size();
+ if (N > 0) {
+ writer.print(prefix); writer.println("Back Stack:");
+ for (int i=0; i<N; i++) {
+ BackStackRecord bs = mBackStack.get(i);
+ writer.print(prefix); writer.print(" #"); writer.print(i);
+ writer.print(": "); writer.println(bs.toString());
+ }
+ }
+ }
+ }
+
Animator loadAnimator(Fragment fragment, int transit, boolean enter,
int transitionStyle) {
Animator animObj = fragment.onCreateAnimator(transit, enter,
@@ -436,7 +504,7 @@ final class FragmentManagerImpl implements FragmentManager {
if (f.mContainerId != 0) {
container = (ViewGroup)mActivity.findViewById(f.mContainerId);
if (container == null) {
- throw new IllegalArgumentException("New view found for id 0x"
+ throw new IllegalArgumentException("No view found for id 0x"
+ Integer.toHexString(f.mContainerId)
+ " for fragment " + f);
}
@@ -519,7 +587,7 @@ final class FragmentManagerImpl implements FragmentManager {
if (f.mView != null) {
// Need to save the current view state if not
// done already.
- if (!mActivity.isFinishing() && f.mSavedFragmentState == null) {
+ if (!mActivity.isFinishing() && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
@@ -581,6 +649,10 @@ final class FragmentManagerImpl implements FragmentManager {
f.mState = newState;
}
+ void moveToState(Fragment f) {
+ moveToState(f, mCurState, 0, 0);
+ }
+
void moveToState(int newState, boolean always) {
moveToState(newState, 0, 0, always);
}
@@ -655,7 +727,7 @@ final class FragmentManagerImpl implements FragmentManager {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
- moveToState(fragment, mCurState, 0, 0);
+ moveToState(fragment);
}
}
@@ -1010,37 +1082,42 @@ final class FragmentManagerImpl implements FragmentManager {
FragmentState fs = new FragmentState(f);
active[i] = fs;
- if (mStateBundle == null) {
- mStateBundle = new Bundle();
- }
- f.onSaveInstanceState(mStateBundle);
- if (!mStateBundle.isEmpty()) {
- fs.mSavedFragmentState = mStateBundle;
- mStateBundle = null;
- }
-
- if (f.mView != null) {
- saveFragmentViewState(f);
- if (f.mSavedViewState != null) {
+ if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
+ if (mStateBundle == null) {
+ mStateBundle = new Bundle();
+ }
+ f.onSaveInstanceState(mStateBundle);
+ if (!mStateBundle.isEmpty()) {
+ fs.mSavedFragmentState = mStateBundle;
+ mStateBundle = null;
+ }
+
+ if (f.mView != null) {
+ saveFragmentViewState(f);
+ if (f.mSavedViewState != null) {
+ if (fs.mSavedFragmentState == null) {
+ fs.mSavedFragmentState = new Bundle();
+ }
+ fs.mSavedFragmentState.putSparseParcelableArray(
+ FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+ }
+ }
+
+ if (f.mTarget != null) {
if (fs.mSavedFragmentState == null) {
fs.mSavedFragmentState = new Bundle();
}
- fs.mSavedFragmentState.putSparseParcelableArray(
- FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+ putFragment(fs.mSavedFragmentState,
+ FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
+ if (f.mTargetRequestCode != 0) {
+ fs.mSavedFragmentState.putInt(
+ FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
+ f.mTargetRequestCode);
+ }
}
- }
- if (f.mTarget != null) {
- if (fs.mSavedFragmentState == null) {
- fs.mSavedFragmentState = new Bundle();
- }
- putFragment(fs.mSavedFragmentState,
- FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
- if (f.mTargetRequestCode != 0) {
- fs.mSavedFragmentState.putInt(
- FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
- f.mTargetRequestCode);
- }
+ } else {
+ fs.mSavedFragmentState = f.mSavedFragmentState;
}
if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
@@ -1057,13 +1134,15 @@ final class FragmentManagerImpl implements FragmentManager {
BackStackState[] backStack = null;
// Build list of currently added fragments.
- N = mAdded.size();
- if (N > 0) {
- added = new int[N];
- for (int i=0; i<N; i++) {
- added[i] = mAdded.get(i).mIndex;
- if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
- + ": " + mAdded.get(i));
+ if (mAdded != null) {
+ N = mAdded.size();
+ if (N > 0) {
+ added = new int[N];
+ for (int i=0; i<N; i++) {
+ added[i] = mAdded.get(i).mIndex;
+ if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+ + ": " + mAdded.get(i));
+ }
}
}
@@ -1104,6 +1183,7 @@ final class FragmentManagerImpl implements FragmentManager {
fs.mInstance = f;
f.mSavedViewState = null;
f.mBackStackNesting = 0;
+ f.mInLayout = false;
f.mAdded = false;
if (fs.mSavedFragmentState != null) {
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 039bcb9..1f8a7c58 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -105,7 +105,9 @@ public interface IApplicationThread extends IInterface {
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
void scheduleCrash(String msg) throws RemoteException;
-
+ void dumpActivity(FileDescriptor fd, IBinder servicetoken, String[] args)
+ throws RemoteException;
+
String descriptor = "android.app.IApplicationThread";
int SCHEDULE_PAUSE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
@@ -143,4 +145,5 @@ public interface IApplicationThread extends IInterface {
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
+ int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
}
diff --git a/core/java/android/app/backup/package.html b/core/java/android/app/backup/package.html
index ae29994..e140349 100644
--- a/core/java/android/app/backup/package.html
+++ b/core/java/android/app/backup/package.html
@@ -3,6 +3,9 @@
<p>Contains the backup and restore functionality available to
applications. If a user wipes the data on their device or upgrades to a new Android-powered
device, all applications that have enabled backup will restore the user's previous data.</p>
+
+<p>For a detailed guide to using the backup APIs, see the <a
+href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p>
{@more}
<p>All backup and restore operations are controlled by the {@link
@@ -22,8 +25,5 @@ employing backup helpers such as {@link android.app.backup.SharedPreferencesBack
<li>Restore the data saved to remote storage</li>
</ul>
-<p>For a detailed guide to using the backup APIs, see the <a
-href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p>
-
</BODY>
</HTML>
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index 42599ed..7776874 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -16,6 +16,7 @@
package android.content;
+import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@@ -37,14 +38,22 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> {
public Cursor loadInBackground() {
Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
mSelectionArgs, mSortOrder);
- // Ensure the cursor window is filled
if (cursor != null) {
+ // Ensure the cursor window is filled
cursor.getCount();
- cursor.registerContentObserver(mObserver);
+ registerContentObserver(cursor, mObserver);
}
return cursor;
}
+ /**
+ * Registers an observer to get notifications from the content provider
+ * when the cursor needs to be refreshed.
+ */
+ public void registerContentObserver(Cursor cursor, ContentObserver observer) {
+ cursor.registerContentObserver(mObserver);
+ }
+
/* Runs on the UI thread */
@Override
public void deliverResult(Cursor cursor) {
diff --git a/core/java/android/database/sqlite/DatabaseConnectionPool.java b/core/java/android/database/sqlite/DatabaseConnectionPool.java
index 54b0605..4f5c4e6 100644
--- a/core/java/android/database/sqlite/DatabaseConnectionPool.java
+++ b/core/java/android/database/sqlite/DatabaseConnectionPool.java
@@ -16,6 +16,7 @@
package android.database.sqlite;
+import android.content.res.Resources;
import android.os.SystemClock;
import android.util.Log;
@@ -31,13 +32,9 @@ import java.util.Random;
private static final String TAG = "DatabaseConnectionPool";
- /** The default connection pool size. It is set based on the amount of memory the device has.
- * TODO: set this with 'a system call' which returns the amount of memory the device has
- */
- private static final int DEFAULT_CONNECTION_POOL_SIZE = 1;
-
- /** the pool size set for this {@link SQLiteDatabase} */
- private volatile int mMaxPoolSize = DEFAULT_CONNECTION_POOL_SIZE;
+ /** The default connection pool size. */
+ private volatile int mMaxPoolSize =
+ Resources.getSystem().getInteger(com.android.internal.R.integer.db_connection_pool_size);
/** The connection pool objects are stored in this member.
* TODO: revisit this data struct as the number of pooled connections increase beyond
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index a5e612b..96e6f22 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -23,12 +23,13 @@ import android.database.CursorWindow;
*/
public abstract class SQLiteClosable {
private int mReferenceCount = 1;
+ private Object mLock = new Object(); // STOPSHIP remove this line
protected abstract void onAllReferencesReleased();
protected void onAllReferencesReleasedFromContainer() {}
public void acquireReference() {
- synchronized(this) {
+ synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
checkRefCount();
if (mReferenceCount <= 0) {
throw new IllegalStateException(
@@ -39,7 +40,7 @@ public abstract class SQLiteClosable {
}
public void releaseReference() {
- synchronized(this) {
+ synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
checkRefCount();
mReferenceCount--;
if (mReferenceCount == 0) {
@@ -49,7 +50,7 @@ public abstract class SQLiteClosable {
}
public void releaseReferenceFromContainer() {
- synchronized(this) {
+ synchronized(mLock) { // STOPSHIP change 'mLock' to 'this'
checkRefCount();
mReferenceCount--;
if (mReferenceCount == 0) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 26600f3..0d8228c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1182,14 +1182,17 @@ public class Camera {
public static final String FOCUS_MODE_EDOF = "edof";
/**
- * Continuous auto focus mode. The camera continuously tries to focus.
- * This is ideal for shooting video or shooting photo of moving object.
- * Auto focus starts when the parameter is set. Applications should not
- * call {@link #autoFocus(AutoFocusCallback)} in this mode. To stop
- * continuous focus, applications should change the focus mode to other
- * modes.
- */
- public static final String FOCUS_MODE_CONTINUOUS = "continuous";
+ * Continuous auto focus mode intended for video recording. The camera
+ * continuously tries to focus. This is ideal for shooting video.
+ * Applications still can call {@link
+ * #takePicture(Camera.ShutterCallback, Camera.PictureCallback,
+ * Camera.PictureCallback)} in this mode but the subject may not be in
+ * focus. Auto focus starts when the parameter is set. Applications
+ * should not call {@link #autoFocus(AutoFocusCallback)} in this mode.
+ * To stop continuous focus, applications should change the focus mode
+ * to other modes.
+ */
+ public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";
// Indices for focus distance array.
/**
@@ -2023,7 +2026,7 @@ public class Camera {
* @see #FOCUS_MODE_MACRO
* @see #FOCUS_MODE_FIXED
* @see #FOCUS_MODE_EDOF
- * @see #FOCUS_MODE_CONTINUOUS
+ * @see #FOCUS_MODE_CONTINUOUS_VIDEO
*/
public String getFocusMode() {
return get(KEY_FOCUS_MODE);
@@ -2225,8 +2228,8 @@ public class Camera {
* #autoFocus(AutoFocusCallback)}, {@link #cancelAutoFocus}, or {@link
* #startPreview()}. Applications can call {@link #getParameters()}
* and this method anytime to get the latest focus distances. If the
- * focus mode is FOCUS_MODE_CONTINUOUS, focus distances may change from
- * time to time.
+ * focus mode is FOCUS_MODE_CONTINUOUS_VIDEO, focus distances may change
+ * from time to time.
*
* This method is intended to estimate the distance between the camera
* and the subject. After autofocus, the subject distance may be within
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index 00c1aac..fc5ebb3 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -25,7 +25,6 @@ import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.Downloads;
-import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -195,6 +194,12 @@ public class DownloadManager {
public final static int ERROR_CANNOT_RESUME = 1008;
/**
+ * Value of {@link #COLUMN_ERROR_CODE} when the requested destination file already exists (the
+ * download manager will not overwrite an existing file).
+ */
+ public final static int ERROR_FILE_ALREADY_EXISTS = 1009;
+
+ /**
* Broadcast intent action sent by the download manager when a download completes.
*/
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
@@ -235,10 +240,11 @@ public class DownloadManager {
Downloads.COLUMN_URI,
Downloads.COLUMN_MIME_TYPE,
Downloads.COLUMN_TOTAL_BYTES,
- Downloads._DATA,
Downloads.COLUMN_STATUS,
Downloads.COLUMN_CURRENT_BYTES,
Downloads.COLUMN_LAST_MODIFICATION,
+ Downloads.COLUMN_DESTINATION,
+ Downloads.Impl.COLUMN_FILE_NAME_HINT,
};
private static final Set<String> LONG_COLUMNS = new HashSet<String>(
@@ -359,7 +365,6 @@ public class DownloadManager {
*
* @param show whether the download manager should show a notification for this download.
* @return this object
- * @hide
*/
public Request setShowRunningNotification(boolean show) {
mShowNotification = show;
@@ -820,15 +825,10 @@ public class DownloadManager {
}
private String getLocalUri() {
- String localUri = getUnderlyingString(Downloads.Impl._DATA);
- if (localUri == null) {
- return null;
- }
-
long destinationType = getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
if (destinationType == Downloads.Impl.DESTINATION_FILE_URI) {
- // return file URI for external download
- return Uri.fromFile(new File(localUri)).toString();
+ // return client-provided file URI for external download
+ return getUnderlyingString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
}
// return content URI for cache download
@@ -894,6 +894,9 @@ public class DownloadManager {
case Downloads.Impl.STATUS_CANNOT_RESUME:
return ERROR_CANNOT_RESUME;
+ case Downloads.Impl.STATUS_FILE_ALREADY_EXISTS_ERROR:
+ return ERROR_FILE_ALREADY_EXISTS;
+
default:
return ERROR_UNKNOWN;
}
diff --git a/core/java/android/net/LinkCapabilities.aidl b/core/java/android/net/LinkCapabilities.aidl
index 5f47baf..df72599 100644
--- a/core/java/android/net/LinkCapabilities.aidl
+++ b/core/java/android/net/LinkCapabilities.aidl
@@ -1,7 +1,6 @@
/*
**
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** Copyright (C) 2010 The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java
index d10a759..eb9166f 100644
--- a/core/java/android/net/LinkCapabilities.java
+++ b/core/java/android/net/LinkCapabilities.java
@@ -146,7 +146,7 @@ public class LinkCapabilities implements Parcelable {
// code these to match
/** Default Role */
- public static final String DEFAULT = "0";
+ public static final String DEFAULT = "default";
/** Bulk down load */
public static final String BULK_DOWNLOAD = "bulk.download";
/** Bulk upload */
diff --git a/core/java/android/net/LinkProperties.aidl b/core/java/android/net/LinkProperties.aidl
index 73c7988..9cd06d5 100644
--- a/core/java/android/net/LinkProperties.aidl
+++ b/core/java/android/net/LinkProperties.aidl
@@ -1,7 +1,6 @@
/*
**
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** Copyright (C) 2010 The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 24aebfc..f411eac 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/core/java/android/net/LinkSocket.java b/core/java/android/net/LinkSocket.java
index d416ed0..5aa6451 100644
--- a/core/java/android/net/LinkSocket.java
+++ b/core/java/android/net/LinkSocket.java
@@ -197,6 +197,17 @@ public class LinkSocket extends Socket {
/**
* Connect a duplicate socket socket to the same remote host address and port
+ * as the original with a timeout parameter.
+ * @param timeout the timeout value in milliseconds or 0 for infinite timeout
+ * @throws IOException if the socket is already connected or an error occurs
+ * while connecting
+ */
+ public void connect(int timeout) throws IOException {
+ if (DBG) log("connect(timeout) EX");
+ }
+
+ /**
+ * Connect a duplicate socket socket to the same remote host address and port
* as the original.
* @throws IOException if the socket is already connected or an error occurs
* while connecting
@@ -237,9 +248,9 @@ public class LinkSocket extends Socket {
*/
@Override
@Deprecated
- public void bind(SocketAddress localAddr) throws IOException {
+ public void bind(SocketAddress localAddr) throws UnsupportedOperationException {
if (DBG) log("bind(localAddr) EX throws IOException");
- throw new IOException("bind is deprecated for LinkSocket");
+ throw new UnsupportedOperationException("bind is deprecated for LinkSocket");
}
/**
diff --git a/core/java/android/net/LinkSocketNotifier.java b/core/java/android/net/LinkSocketNotifier.java
index 183c767..28e2834 100644
--- a/core/java/android/net/LinkSocketNotifier.java
+++ b/core/java/android/net/LinkSocketNotifier.java
@@ -84,5 +84,5 @@ public interface LinkSocketNotifier {
* Get notified of every capability change
* check for LinkSockets on that Link that are interested in that Capability - call them
*/
- public void onCapabilityChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
+ public void onCapabilitiesChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
}
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 4039a69..3ee8a80 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -70,8 +70,11 @@ public class LocalSocket {
if (!implCreated) {
synchronized (this) {
if (!implCreated) {
- implCreated = true;
- impl.create(true);
+ try {
+ impl.create(true);
+ } finally {
+ implCreated = true;
+ }
}
}
}
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index fb59fed..140b71f 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1e88c56..ba8014f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -397,7 +397,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
- public final class HistoryItem implements Parcelable {
+ public final static class HistoryItem implements Parcelable {
public HistoryItem next;
public long time;
@@ -482,6 +482,18 @@ public abstract class BatteryStats implements Parcelable {
dest.writeInt(states);
}
+ public void setTo(HistoryItem o) {
+ time = o.time;
+ cmd = o.cmd;
+ batteryLevel = o.batteryLevel;
+ batteryStatus = o.batteryStatus;
+ batteryHealth = o.batteryHealth;
+ batteryPlugType = o.batteryPlugType;
+ batteryTemperature = o.batteryTemperature;
+ batteryVoltage = o.batteryVoltage;
+ states = o.states;
+ }
+
public void setTo(long time, byte cmd, HistoryItem o) {
this.time = time;
this.cmd = cmd;
@@ -526,6 +538,10 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ public abstract boolean startIteratingHistoryLocked();
+
+ public abstract boolean getNextHistoryLocked(HistoryItem out);
+
/**
* Return the current history of battery state changes.
*/
@@ -1688,8 +1704,8 @@ public abstract class BatteryStats implements Parcelable {
*/
@SuppressWarnings("unused")
public void dumpLocked(PrintWriter pw) {
- HistoryItem rec = getHistory();
- if (rec != null) {
+ final HistoryItem rec = new HistoryItem();
+ if (startIteratingHistoryLocked()) {
pw.println("Battery History:");
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
int oldState = 0;
@@ -1698,7 +1714,7 @@ public abstract class BatteryStats implements Parcelable {
int oldPlug = -1;
int oldTemp = -1;
int oldVolt = -1;
- while (rec != null) {
+ while (getNextHistoryLocked(rec)) {
pw.print(" ");
TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" ");
@@ -1803,7 +1819,6 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
oldState = rec.states;
- rec = rec.next;
}
pw.println("");
}
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index e89f7c2..be5b685 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -33,6 +33,7 @@ import java.util.ArrayList;
public class MessageQueue {
Message mMessages;
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
+ private IdleHandler[] mPendingIdleHandlers;
private boolean mQuiting = false;
boolean mQuitAllowed = true;
@@ -105,91 +106,75 @@ public class MessageQueue {
}
final Message next() {
- boolean tryIdle = true;
- // when we start out, we'll just touch the input pipes and then go from there
- int timeToNextEventMillis = 0;
+ int pendingIdleHandlerCount = -1; // -1 only during first iteration
+ int nextPollTimeoutMillis = 0;
- while (true) {
- long now;
- Object[] idlers = null;
-
- boolean dispatched = nativePollOnce(timeToNextEventMillis);
+ for (;;) {
+ if (nextPollTimeoutMillis != 0) {
+ Binder.flushPendingCommands();
+ }
+ nativePollOnce(nextPollTimeoutMillis);
- // Try to retrieve the next message, returning if found.
synchronized (this) {
- now = SystemClock.uptimeMillis();
- Message msg = pullNextLocked(now);
+ // Try to retrieve the next message. Return if found.
+ final long now = SystemClock.uptimeMillis();
+ final Message msg = mMessages;
if (msg != null) {
- msg.markInUse();
- return msg;
+ final long when = msg.when;
+ if (now >= when) {
+ mMessages = msg.next;
+ if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
+ msg.markInUse();
+ return msg;
+ } else {
+ nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
+ }
+ } else {
+ nextPollTimeoutMillis = -1;
+ }
+
+ // If first time, then get the number of idlers to run.
+ if (pendingIdleHandlerCount < 0) {
+ pendingIdleHandlerCount = mIdleHandlers.size();
}
-
- if (tryIdle && mIdleHandlers.size() > 0) {
- idlers = mIdleHandlers.toArray();
+ if (pendingIdleHandlerCount == 0) {
+ // No idle handlers to run. Loop and wait some more.
+ continue;
}
- }
-
- // There was no message so we are going to wait... but first,
- // if there are any idle handlers let them know.
- boolean didIdle = false;
- if (idlers != null) {
- for (Object idler : idlers) {
- boolean keep = false;
- try {
- didIdle = true;
- keep = ((IdleHandler)idler).queueIdle();
- } catch (Throwable t) {
- Log.wtf("MessageQueue", "IdleHandler threw exception", t);
- }
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler);
- }
- }
+ if (mPendingIdleHandlers == null) {
+ mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
- }
-
- // While calling an idle handler, a new message could have been
- // delivered... so go back and look again for a pending message.
- if (didIdle) {
- tryIdle = false;
- continue;
+ mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
- synchronized (this) {
- // No messages, nobody to tell about it... time to wait!
- if (mMessages != null) {
- long longTimeToNextEventMillis = mMessages.when - now;
-
- if (longTimeToNextEventMillis > 0) {
- Binder.flushPendingCommands();
- timeToNextEventMillis = (int) Math.min(longTimeToNextEventMillis,
- Integer.MAX_VALUE);
- } else {
- timeToNextEventMillis = 0;
+ // Run the idle handlers.
+ // We only ever reach this code block during the first iteration.
+ for (int i = 0; i < pendingIdleHandlerCount; i++) {
+ final IdleHandler idler = mPendingIdleHandlers[i];
+ mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+ boolean keep = false;
+ try {
+ keep = idler.queueIdle();
+ } catch (Throwable t) {
+ Log.wtf("MessageQueue", "IdleHandler threw exception", t);
+ }
+
+ if (!keep) {
+ synchronized (this) {
+ mIdleHandlers.remove(idler);
}
- } else {
- Binder.flushPendingCommands();
- timeToNextEventMillis = -1;
}
}
- // loop to the while(true) and do the appropriate nativeWait(when)
- }
- }
- final Message pullNextLocked(long now) {
- Message msg = mMessages;
- if (msg != null) {
- if (now >= msg.when) {
- mMessages = msg.next;
- if (Config.LOGV) Log.v(
- "MessageQueue", "Returning message: " + msg);
- return msg;
- }
- }
+ // Reset the idle handler count to 0 so we do not run them again.
+ pendingIdleHandlerCount = 0;
- return null;
+ // While calling an idle handler, a new message could have been delivered
+ // so go back and look again for a pending message without waiting.
+ nextPollTimeoutMillis = 0;
+ }
}
final boolean enqueueMessage(Message msg, long when) {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5fea6fe..e56e257 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -307,8 +307,10 @@ public class RecoverySystem {
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
- * @param packageFile the update package to install. Currently
- * must be on the /cache or /data partitions.
+ * @param packageFile the update package to install. Must be on
+ * a partition mountable by recovery. (The set of partitions
+ * known to recovery may vary from device to device. Generally,
+ * /cache and /data are safe.)
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
@@ -316,15 +318,6 @@ public class RecoverySystem {
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
-
- if (filename.startsWith("/cache/")) {
- filename = "CACHE:" + filename.substring(7);
- } else if (filename.startsWith("/data/")) {
- filename = "DATA:" + filename.substring(6);
- } else {
- throw new IllegalArgumentException(
- "Must start with /cache or /data: " + filename);
- }
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
String arg = "--update_package=" + filename;
bootCommand(context, arg);
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 74c7372..1e358c9 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -895,6 +895,14 @@ public final class Downloads {
*/
public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui";
+ /**
+ * If true, the user has confirmed that this download can proceed over the mobile network
+ * even though it exceeds the recommended maximum size.
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT =
+ "bypass_recommended_size_limit";
+
/*
* Lists the destinations that an application can specify for a download.
*/
@@ -1077,7 +1085,12 @@ public final class Downloads {
/**
* The lowest-valued error status that is not an actual HTTP status code.
*/
- public static final int MIN_ARTIFICIAL_ERROR_STATUS = 489;
+ public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488;
+
+ /**
+ * The requested destination file already exists.
+ */
+ public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
/**
* Some possibly transient error occurred, but we can't resume the download.
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index e25dbad..de161e7 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -75,7 +75,7 @@ public final class Mtp
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage");
}
- public static Uri getContentUri(int deviceID, int storageID) {
+ public static Uri getContentUri(int deviceID, long storageID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage/" + storageID);
}
@@ -97,17 +97,17 @@ public final class Mtp
*/
public static final class Object implements BaseColumns {
- public static Uri getContentUri(int deviceID, int objectID) {
+ public static Uri getContentUri(int deviceID, long objectID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/object/" + objectID);
}
- public static Uri getContentUriForObjectChildren(int deviceID, int objectID) {
+ public static Uri getContentUriForObjectChildren(int deviceID, long objectID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/object/" + objectID + "/child");
}
- public static Uri getContentUriForStorageChildren(int deviceID, int storageID) {
+ public static Uri getContentUriForStorageChildren(int deviceID, long storageID) {
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
+ "/storage/" + storageID + "/child");
}
@@ -147,7 +147,7 @@ public final class Mtp
* or any of the valid MTP object formats as defined in the MTP specification.
* <P>Type: INTEGER</P>
*/
- public static final String THUMB_FORMAT = "format";
+ public static final String THUMB_FORMAT = "thumb_format";
/**
* The size of the object's thumbnail in bytes.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5b4aedb..51dc6ae 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1494,6 +1494,12 @@ public final class Settings {
public static final String AUTO_TIME = "auto_time";
/**
+ * Value to specify if the user prefers the time zone
+ * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+ */
+ public static final String AUTO_TIME_ZONE = "auto_time_zone";
+
+ /**
* Display times as 12 or 24 hours
* 12
* 24
@@ -1775,6 +1781,7 @@ public final class Settings {
TEXT_AUTO_PUNCTUATE,
TEXT_SHOW_PASSWORD,
AUTO_TIME,
+ AUTO_TIME_ZONE,
TIME_12_24,
DATE_FORMAT,
ACCELEROMETER_ROTATION,
@@ -3530,6 +3537,15 @@ public final class Settings {
"download_manager_max_bytes_over_mobile";
/**
+ * The recommended maximum size, in bytes, of a download that the download manager should
+ * transfer over a non-wifi connection. Over this size, the use will be warned, but will
+ * have the option to start the download over the mobile connection anyway.
+ * @hide
+ */
+ public static final String DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE =
+ "download_manager_recommended_max_bytes_over_mobile";
+
+ /**
* ms during which to consume extra events related to Inet connection condition
* after a transtion to fully-connected
* @hide
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 0408673..733b535 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -314,6 +314,8 @@ public class ArrowKeyMovementMethod implements MovementMethod {
* {@link MotionEvent#ACTION_CANCEL} event), the controller is reset to null.
*
* @param cursorController A cursor controller implementation
+ *
+ * @hide
*/
public void setCursorController(CursorController cursorController) {
mCursorController = cursorController;
diff --git a/core/java/android/util/Base64InputStream.java b/core/java/android/util/Base64InputStream.java
index da3911d..e9dac24 100644
--- a/core/java/android/util/Base64InputStream.java
+++ b/core/java/android/util/Base64InputStream.java
@@ -112,7 +112,7 @@ public class Base64InputStream extends FilterInputStream {
if (outputStart >= outputEnd) {
return -1;
} else {
- return coder.output[outputStart++];
+ return coder.output[outputStart++] & 0xff;
}
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 458274f..d24af52 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -67,6 +67,7 @@ public abstract class LayoutInflater {
// these are optional, set by the caller
private boolean mFactorySet;
private Factory mFactory;
+ private Factory2 mFactory2;
private Filter mFilter;
private final Object[] mConstructorArgs = new Object[2];
@@ -122,12 +123,33 @@ public abstract class LayoutInflater {
public View onCreateView(String name, Context context, AttributeSet attrs);
}
- private static class FactoryMerger implements Factory {
+ public interface Factory2 extends Factory {
+ /**
+ * Version of {@link #onCreateView(String, Context, AttributeSet)}
+ * that also supplies the parent that the view created view will be
+ * placed in.
+ *
+ * @param parent The parent that the created view will be placed
+ * in; <em>note that this may be null</em>.
+ * @param name Tag name to be inflated.
+ * @param context The context the view is being created in.
+ * @param attrs Inflation attributes as specified in XML file.
+ *
+ * @return View Newly created view. Return null for the default
+ * behavior.
+ */
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
+ }
+
+ private static class FactoryMerger implements Factory2 {
private final Factory mF1, mF2;
+ private final Factory2 mF12, mF22;
- FactoryMerger(Factory f1, Factory f2) {
+ FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
mF1 = f1;
mF2 = f2;
+ mF12 = f12;
+ mF22 = f22;
}
public View onCreateView(String name, Context context, AttributeSet attrs) {
@@ -135,6 +157,14 @@ public abstract class LayoutInflater {
if (v != null) return v;
return mF2.onCreateView(name, context, attrs);
}
+
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
+ : mF1.onCreateView(name, context, attrs);
+ if (v != null) return v;
+ return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
+ : mF2.onCreateView(name, context, attrs);
+ }
}
/**
@@ -162,6 +192,7 @@ public abstract class LayoutInflater {
protected LayoutInflater(LayoutInflater original, Context newContext) {
mContext = newContext;
mFactory = original.mFactory;
+ mFactory2 = original.mFactory2;
mFilter = original.mFilter;
}
@@ -200,7 +231,7 @@ public abstract class LayoutInflater {
}
/**
- * Return the current factory (or null). This is called on each element
+ * Return the current {@link Factory} (or null). This is called on each element
* name. If the factory returns a View, add that to the hierarchy. If it
* returns null, proceed to call onCreateView(name).
*/
@@ -209,6 +240,17 @@ public abstract class LayoutInflater {
}
/**
+ * Return the current {@link Factory2}. Returns null if no factory is set
+ * or the set factory does not implement the {@link Factory2} interface.
+ * This is called on each element
+ * name. If the factory returns a View, add that to the hierarchy. If it
+ * returns null, proceed to call onCreateView(name).
+ */
+ public final Factory2 getFactory2() {
+ return mFactory2;
+ }
+
+ /**
* Attach a custom Factory interface for creating views while using
* this LayoutInflater. This must not be null, and can only be set once;
* after setting, you can not change the factory. This is
@@ -234,7 +276,26 @@ public abstract class LayoutInflater {
if (mFactory == null) {
mFactory = factory;
} else {
- mFactory = new FactoryMerger(factory, mFactory);
+ mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
+ }
+ }
+
+ /**
+ * Like {@link #setFactory}, but allows you to set a {@link Factory2}
+ * interface.
+ */
+ public void setFactory2(Factory2 factory) {
+ if (mFactorySet) {
+ throw new IllegalStateException("A factory has already been set on this LayoutInflater");
+ }
+ if (factory == null) {
+ throw new NullPointerException("Given factory can not be null");
+ }
+ mFactorySet = true;
+ if (mFactory == null) {
+ mFactory = mFactory2 = factory;
+ } else {
+ mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
}
}
@@ -384,7 +445,7 @@ public abstract class LayoutInflater {
rInflate(parser, root, attrs, false);
} else {
// Temp is the root view that was found in the xml
- View temp = createViewFromTag(name, attrs);
+ View temp = createViewFromTag(root, name, attrs);
ViewGroup.LayoutParams params = null;
@@ -557,10 +618,27 @@ public abstract class LayoutInflater {
return createView(name, "android.view.", attrs);
}
+ /**
+ * Version of {@link #onCreateView(String, AttributeSet)} that also
+ * takes the future parent of the view being constructure. The default
+ * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
+ *
+ * @param parent The future parent of the returned view. <em>Note that
+ * this may be null.</em>
+ * @param name The fully qualified class name of the View to be create.
+ * @param attrs An AttributeSet of attributes to apply to the View.
+ *
+ * @return View The View created.
+ */
+ protected View onCreateView(View parent, String name, AttributeSet attrs)
+ throws ClassNotFoundException {
+ return onCreateView(name, attrs);
+ }
+
/*
* default visibility so the BridgeInflater can override it.
*/
- View createViewFromTag(String name, AttributeSet attrs) {
+ View createViewFromTag(View parent, String name, AttributeSet attrs) {
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
}
@@ -568,12 +646,14 @@ public abstract class LayoutInflater {
if (DEBUG) System.out.println("******** Creating view: " + name);
try {
- View view = (mFactory == null) ? null : mFactory.onCreateView(name,
- mContext, attrs);
+ View view;
+ if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
+ else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
+ else view = null;
if (view == null) {
if (-1 == name.indexOf('.')) {
- view = onCreateView(name, attrs);
+ view = onCreateView(parent, name, attrs);
} else {
view = createView(name, null, attrs);
}
@@ -628,7 +708,7 @@ public abstract class LayoutInflater {
} else if (TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
} else {
- final View view = createViewFromTag(name, attrs);
+ final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
@@ -689,7 +769,7 @@ public abstract class LayoutInflater {
// Inflate all children.
rInflate(childParser, parent, childAttrs, false);
} else {
- final View view = createViewFromTag(childName, childAttrs);
+ final View view = createViewFromTag(parent, childName, childAttrs);
final ViewGroup group = (ViewGroup) parent;
// We try to load the layout params set in the <include /> tag. If
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97d58d2..3d5aff7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1613,12 +1613,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
/**
- * Indicates that this view has a visible/touchable overlay.
- * @hide
- */
- static final int HAS_OVERLAY = 0x10000000;
-
- /**
* Indicates that pivotX or pivotY were explicitly set and we should not assume the center
* for transform operations
*
@@ -3040,57 +3034,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
resetPressedState();
}
- /**
- * Enable or disable drawing overlays after a full drawing pass. This enables a view to
- * draw on a topmost overlay layer after normal drawing completes and get right of first
- * refusal for touch events in the window.
- *
- * <em>Warning:</em> Views that use this feature should take care to disable/enable overlay
- * appropriately when they are attached/detached from their window. All overlays should be
- * disabled when detached.
- *
- * @param enabled true if overlay drawing should be enabled for this view, false otherwise
- *
- * @see #onDrawOverlay(Canvas)
- *
- * @hide
- */
- protected void setOverlayEnabled(boolean enabled) {
- final boolean oldValue = (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
- mPrivateFlags = (mPrivateFlags & ~HAS_OVERLAY) | (enabled ? HAS_OVERLAY : 0);
- if (enabled != oldValue) {
- final ViewParent parent = getParent();
- if (parent != null) {
- try {
- parent.childOverlayStateChanged(this);
- } catch (AbstractMethodError e) {
- Log.e(VIEW_LOG_TAG, "Could not propagate hasOverlay state", e);
- }
- }
- }
- }
-
- /**
- * @return true if this View has an overlay enabled.
- *
- * @see #setOverlayEnabled(boolean)
- * @see #onDrawOverlay(Canvas)
- *
- * @hide
- */
- public boolean isOverlayEnabled() {
- return (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
- }
-
- /**
- * Override this method to draw on an overlay layer above all other views in the window
- * after the standard drawing pass is complete. This allows a view to draw outside its
- * normal boundaries.
- * @hide
- */
- public void onDrawOverlay(Canvas canvas) {
- }
-
private void resetPressedState() {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3db4857..2b92e87 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -245,11 +245,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
/**
- * When set, at least one child of this ViewGroup will return true from hasOverlay.
- */
- private static final int FLAG_CHILD_HAS_OVERLAY = 0x100000;
-
- /**
* When set, this ViewGroup will split MotionEvents to multiple child Views when appropriate.
*/
private static final int FLAG_SPLIT_MOTION_EVENTS = 0x200000;
@@ -910,33 +905,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View[] children = mChildren;
final int count = mChildrenCount;
- // Check for children with overlays first. They don't rely on hit rects to determine
- // if they can accept a new touch event.
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
- for (int i = count - 1; i >= 0; i--) {
- final View child = children[i];
- // Don't let children respond to events as an overlay during an animation.
- if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
- && child.getAnimation() == null
- && child.isOverlayEnabled()) {
- // offset the event to the view's coordinate system
- final float xc = scrolledXFloat - child.mLeft;
- final float yc = scrolledYFloat - child.mTop;
- ev.setLocation(xc, yc);
- child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
- if (child.dispatchTouchEvent(ev)) {
- // Event handled, we have a target now.
- mMotionTarget = child;
- return true;
- }
- // The event didn't get handled, try the next view.
- // Don't reset the event's location, it's not
- // necessary here.
- }
- }
- }
-
- // Now check views normally.
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
@@ -2774,8 +2742,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (clearChildFocus != null) {
clearChildFocus(clearChildFocus);
}
-
- mGroupFlags &= ~FLAG_CHILD_HAS_OVERLAY;
}
/**
@@ -3024,8 +2990,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int left = mLeft;
final int top = mTop;
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY ||
- dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+ if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
(mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
@@ -4013,69 +3978,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
/**
- * Called when a child's overlay state changes between enabled/disabled.
- * @param child Child view whose state has changed or null
- * @hide
- */
- public void childOverlayStateChanged(View child) {
- boolean childHasOverlay = false;
- if (child != null) {
- childHasOverlay = child.isOverlayEnabled();
- } else {
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- if (childHasOverlay |= getChildAt(i).isOverlayEnabled()) {
- break;
- }
- }
- }
-
- final boolean hasChildWithOverlay = childHasOverlay ||
- (mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY;
-
- final boolean oldValue = isOverlayEnabled();
- mGroupFlags = (mGroupFlags & ~FLAG_CHILD_HAS_OVERLAY) |
- (hasChildWithOverlay ? FLAG_CHILD_HAS_OVERLAY : 0);
- if (isOverlayEnabled() != oldValue) {
- final ViewParent parent = getParent();
- if (parent != null) {
- try {
- parent.childOverlayStateChanged(this);
- } catch (AbstractMethodError e) {
- Log.e("ViewGroup", "Could not propagate hasOverlay state", e);
- }
- }
- }
- }
-
- /**
- * @hide
- */
- public boolean isOverlayEnabled() {
- return super.isOverlayEnabled() ||
- ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY);
- }
-
- /**
- * @hide
- */
- @Override
- public void onDrawOverlay(Canvas canvas) {
- if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- if (child.isOverlayEnabled()) {
- canvas.translate(child.mLeft - child.mScrollX, child.mTop - child.mScrollY);
- child.onDrawOverlay(canvas);
- canvas.translate(-(child.mLeft - child.mScrollX),
- -(child.mTop - child.mScrollY));
- }
- }
- }
- }
-
- /**
* LayoutParams are used by views to tell their parents how they want to be
* laid out. See
* {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d2907da..d7d4c3f 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -222,11 +222,4 @@ public interface ViewParent {
*/
public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
boolean immediate);
-
- /**
- * Called when a child view's overlay state changes between enabled/disabled.
- * @param child Child view whose state changed or null.
- * @hide
- */
- public void childOverlayStateChanged(View child);
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index cb9f84d..e71b5b6 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -206,8 +206,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
AudioManager mAudioManager;
private final int mDensity;
-
- private boolean mHasOverlay;
public static IWindowSession getWindowSession(Looper mainLooper) {
synchronized (mStaticInit) {
@@ -1359,9 +1357,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
canvas.setScreenDensity(scalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
- if (mHasOverlay) {
- mView.onDrawOverlay(canvas);
- }
} finally {
mAttachInfo.mIgnoreDirtyState = false;
}
@@ -2744,19 +2739,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
return scrollToRectOrFocus(rectangle, immediate);
}
- /**
- * @hide
- */
- public void childOverlayStateChanged(View child) {
- final boolean oldState = mHasOverlay;
- mHasOverlay = child.isOverlayEnabled();
- // Invalidate the whole thing when we change overlay states just in case
- // something left chunks of data drawn someplace it shouldn't have.
- if (mHasOverlay != oldState) {
- child.invalidate();
- }
- }
-
class TakenSurfaceHolder extends BaseSurfaceHolder {
@Override
public boolean onAllowLockCanvas() {
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 122c268..63fc008 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -19,6 +19,7 @@ package android.webkit;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
@@ -326,7 +327,9 @@ public class WebSettings {
// Detect tablet device for fixed viewport mode.
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
final int landscapeWidth = Math.max(metrics.widthPixels, metrics.heightPixels);
- mUseFixedViewport = (metrics.density == 1.0f && landscapeWidth >= 800);
+ final int minTabletWidth = context.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.min_xlarge_screen_width);
+ mUseFixedViewport = (metrics.density == 1.0f && landscapeWidth >= minTabletWidth);
mMaxFixedViewportWidth = (int) (landscapeWidth * 1.25);
if (sLockForLocaleSettings == null) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c62894c..127eae2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1941,7 +1941,7 @@ public class WebView extends AbsoluteLayout
public void clearView() {
mContentWidth = 0;
mContentHeight = 0;
- nativeSetBaseLayer(0);
+ if (mNativeClass != 0) nativeSetBaseLayer(0);
mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index acea163..bb43690 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1829,9 +1829,11 @@ final class WebViewCore {
draw.mViewState = mInitialViewState;
if (mViewportWidth == -1 && mSettings.getUseFixedViewport() &&
mSettings.getUseWideViewPort()) {
+ final int fixedViewportMargin = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.fixed_viewport_margin);
// Use website's initial preferred width as the fixed viewport width.
mViewportWidth = Math.min(mSettings.getMaxFixedViewportWidth(),
- draw.mMinPrefWidth);
+ draw.mMinPrefWidth + 2 * fixedViewportMargin);
draw.mViewState.mViewportWidth = mViewportWidth;
}
mInitialViewState = null;
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 0d704a0..2096fc4 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -58,9 +58,9 @@ class ZoomManager {
/*
* For large screen devices, the defaultScale usually set to 1.0 and
* equal to the overview scale, to differentiate the zoom level for double tapping,
- * a minimum reading level scale is used.
+ * a default reading level scale is used.
*/
- private static final float MIN_READING_LEVEL_SCALE = 1.5f;
+ private static final float DEFAULT_READING_LEVEL_SCALE = 1.5f;
/*
* The scale factors that determine the upper and lower bounds for the
@@ -258,7 +258,15 @@ class ZoomManager {
}
public final float getReadingLevelScale() {
- return Math.max(mDefaultScale, MIN_READING_LEVEL_SCALE);
+ // The reading scale is at least 0.5f apart from the overview scale.
+ final float MIN_SCALE_DIFF = 0.5f;
+ final float zoomOverviewScale = getZoomOverviewScale();
+ if (zoomOverviewScale > DEFAULT_READING_LEVEL_SCALE) {
+ return Math.min(DEFAULT_READING_LEVEL_SCALE,
+ zoomOverviewScale - MIN_SCALE_DIFF);
+ }
+ return Math.max(zoomOverviewScale + MIN_SCALE_DIFF,
+ DEFAULT_READING_LEVEL_SCALE);
}
public final float getInvDefaultScale() {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 4a3e2a9..71f4f03 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -176,6 +176,7 @@ public class PopupWindow {
attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
+ mAnimationStyle = a.getResourceId(R.styleable.PopupWindow_windowAnimationStyle, -1);
// If this is a StateListDrawable, try to find and store the drawable to be
// used when the drop-down is placed above its anchor view, and the one to be
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5645101..945ffeb 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -156,6 +156,93 @@ public class RemoteViews implements Parcelable, Filter {
}
}
+ private class SetOnClickFillInIntent extends Action {
+ public SetOnClickFillInIntent(int id, Intent fillInIntent) {
+ this.viewId = id;
+ this.fillInIntent = fillInIntent;
+ }
+
+ public SetOnClickFillInIntent(Parcel parcel) {
+ viewId = parcel.readInt();
+ fillInIntent = Intent.CREATOR.createFromParcel(parcel);
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(TAG);
+ dest.writeInt(viewId);
+ fillInIntent.writeToParcel(dest, 0 /* no flags */);
+ }
+
+ @Override
+ public void apply(View root) {
+ final View target = root.findViewById(viewId);
+
+ if (!mIsWidgetCollectionChild) {
+ Log.e("RemoteViews", "The method setOnClickFillInIntent is available " +
+ "only from RemoteViewsFactory (ie. on collection items).");
+ return;
+ }
+
+ if (target != null && fillInIntent != null) {
+ OnClickListener listener = new OnClickListener() {
+ public void onClick(View v) {
+ // Insure that this view is a child of an AdapterView
+ View parent = (View) v.getParent();
+ while (!(parent instanceof AdapterView<?>)
+ && !(parent instanceof AppWidgetHostView)) {
+ parent = (View) parent.getParent();
+ }
+
+ if (parent instanceof AppWidgetHostView) {
+ // Somehow they've managed to get this far without having
+ // and AdapterView as a parent.
+ Log.e("RemoteViews", "Collection item doesn't have AdapterView parent");
+ return;
+ }
+
+ // Insure that a template pending intent has been set on an ancestor
+ if (!(parent.getTag() instanceof PendingIntent)) {
+ Log.e("RemoteViews", "Attempting setOnClickFillInIntent without" +
+ " calling setPendingIntentTemplate on parent.");
+ return;
+ }
+
+ PendingIntent pendingIntent = (PendingIntent) parent.getTag();
+
+ final float appScale = v.getContext().getResources()
+ .getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+
+ final Rect rect = new Rect();
+ rect.left = (int) (pos[0] * appScale + 0.5f);
+ rect.top = (int) (pos[1] * appScale + 0.5f);
+ rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f);
+ rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f);
+
+ fillInIntent.setSourceBounds(rect);
+ try {
+ // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+ v.getContext().startIntentSender(
+ pendingIntent.getIntentSender(), fillInIntent,
+ Intent.FLAG_ACTIVITY_NEW_TASK,
+ Intent.FLAG_ACTIVITY_NEW_TASK, 0);
+ } catch (IntentSender.SendIntentException e) {
+ android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
+ }
+ }
+
+ };
+ target.setOnClickListener(listener);
+ }
+ }
+
+ int viewId;
+ Intent fillInIntent;
+
+ public final static int TAG = 9;
+ }
+
private class SetOnClickExtras extends Action {
public SetOnClickExtras(int id, Bundle extras) {
this.viewId = id;
@@ -273,7 +360,7 @@ public class RemoteViews implements Parcelable, Filter {
target.setTag(pendingIntentTemplate);
} else {
Log.e("RemoteViews", "Cannot setPendingIntentTemplate on a view which is not" +
- "an AdapterView.");
+ "an AdapterView (id: " + viewId + ")");
return;
}
}
@@ -313,7 +400,8 @@ public class RemoteViews implements Parcelable, Filter {
// If the view is an AdapterView, setting a PendingIntent on click doesn't make much
// sense, do they mean to set a PendingIntent template for the AdapterView's children?
if (mIsWidgetCollectionChild) {
- Log.e("RemoteViews", "Cannot setOnClickPendingIntent for collection item.");
+ Log.e("RemoteViews", "Cannot setOnClickPendingIntent for collection item " +
+ "(id: " + viewId + ")");
// TODO: return; We'll let this slide until apps are up to date.
}
@@ -824,6 +912,9 @@ public class RemoteViews implements Parcelable, Filter {
case SetPendingIntentTemplate.TAG:
mActions.add(new SetPendingIntentTemplate(parcel));
break;
+ case SetOnClickFillInIntent.TAG:
+ mActions.add(new SetOnClickFillInIntent(parcel));
+ break;
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -1020,6 +1111,11 @@ public class RemoteViews implements Parcelable, Filter {
* {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)}
* to launch the provided {@link PendingIntent}.
*
+ * When setting the on-click action of items within collections (eg. {@link ListView},
+ * {@link StackView} etc.), this method will not work. Instead, use {@link
+ * RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with
+ * RemoteViews#setOnClickFillInIntent(int, Intent).
+ *
* @param viewId The id of the view that will trigger the {@link PendingIntent} when clicked
* @param pendingIntent The {@link PendingIntent} to send when user clicks
*/
@@ -1028,10 +1124,11 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * When using collections (eg. ListView, StackView etc.) in widgets, it is very costly
- * to set PendingIntents on the individual items, and is hence not permitted. Instead
- * a single PendingIntent template can be set on the collection, and individual items can
- * differentiate their click behavior using {@link RemoteViews#setOnClickExtras(int, Bundle)}.
+ * When using collections (eg. {@link ListView}, {@link StackView} etc.) in widgets, it is very
+ * costly to set PendingIntents on the individual items, and is hence not permitted. Instead
+ * this method should be used to set a single PendingIntent template on the collection, and
+ * individual items can differentiate their on-click behavior using
+ * {@link RemoteViews#setOnClickFillInIntent(int, Intent)}.
*
* @param viewId The id of the collection who's children will use this PendingIntent template
* when clicked
@@ -1043,13 +1140,9 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * When using collections (eg. ListView, StackView etc.) in widgets, it is very costly
- * to set PendingIntents on the individual items, and is hence not permitted. Instead
- * a single PendingIntent template can be set on the collection, see {@link
- * RemoteViews#setPendingIntentTemplate(int, PendingIntent)}, and the items click
- * behaviour can be distinguished by setting extras.
+ * Being deprecated. See {@link RemoteViews#setOnClickFillInIntent(int, Intent)}.
*
- * @param viewId The id of the
+ * @param viewId
* @param extras
*/
public void setOnClickExtras(int viewId, Bundle extras) {
@@ -1057,6 +1150,29 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * When using collections (eg. {@link ListView}, {@link StackView} etc.) in widgets, it is very
+ * costly to set PendingIntents on the individual items, and is hence not permitted. Instead
+ * a single PendingIntent template can be set on the collection, see {@link
+ * RemoteViews#setPendingIntentTemplate(int, PendingIntent)}, and the individual on-click
+ * action of a given item can be distinguished by setting a fillInIntent on that item. The
+ * fillInIntent is then combined with the PendingIntent template in order to determine the final
+ * intent which will be executed when the item is clicked. This works as follows: any fields
+ * which are left blank in the PendingIntent template, but are provided by the fillInIntent
+ * will be overwritten, and the resulting PendingIntent will be used.
+ *
+ *
+ * of the PendingIntent template will then be filled in with the associated fields that are
+ * set in fillInIntent. See {@link Intent#fillIn(Intent, int)} for more details.
+ *
+ * @param viewId The id of the view on which to set the fillInIntent
+ * @param fillInIntent The intent which will be combined with the parent's PendingIntent
+ * in order to determine the on-click behavior of the view specified by viewId
+ */
+ public void setOnClickFillInIntent(int viewId, Intent fillInIntent) {
+ addAction(new SetOnClickFillInIntent(viewId, fillInIntent));
+ }
+
+ /**
* @hide
* Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
* {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e5ddfc..d49b4d7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -96,7 +96,6 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewRoot;
@@ -199,6 +198,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private static final int PRIORITY = 100;
private int mCurrentAlpha = 255;
+
+ private final int[] mTempCoords = new int[2];
+
private ColorStateList mTextColor;
private int mCurTextColor;
private ColorStateList mHintTextColor;
@@ -3779,8 +3781,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
showError();
mShowErrorAfterAttach = false;
}
-
- updateOverlay();
}
@Override
@@ -3798,8 +3798,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mError != null) {
hideError();
}
-
- setOverlayEnabled(false);
}
@Override
@@ -4169,19 +4167,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
canvas.restore();
}
- /**
- * @hide
- */
- @Override
- public void onDrawOverlay(Canvas canvas) {
- if (mInsertionPointCursorController != null) {
- mInsertionPointCursorController.draw(canvas);
- }
- if (mSelectionModifierCursorController != null) {
- mSelectionModifierCursorController.draw(canvas);
- }
- }
-
@Override
public void getFocusedRect(Rect r) {
if (mLayout == null) {
@@ -6768,31 +6753,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
- // Check to see if we're testing for our anchor overlay.
- boolean handled = false;
- final float x = event.getX();
- final float y = event.getY();
- if (x < 0 || x >= mRight - mLeft || y < 0 || y >= mBottom - mTop) {
- if (mInsertionPointCursorController != null) {
- handled |= mInsertionPointCursorController.onTouchEvent(event);
- }
- if (mSelectionModifierCursorController != null) {
- handled |= mSelectionModifierCursorController.onTouchEvent(event);
- }
-
- if (!handled) {
- return false;
- }
+ if (mInsertionPointCursorController != null) {
+ mInsertionPointCursorController.onTouchEvent(event);
+ }
+ if (mSelectionModifierCursorController != null) {
+ mSelectionModifierCursorController.onTouchEvent(event);
}
// Reset this state; it will be re-set if super.onTouchEvent
// causes focus to move to the view.
mTouchFocusSelected = false;
mScrolled = false;
-
- if (handled) {
- return true;
- }
}
final boolean superResult = super.onTouchEvent(event);
@@ -6808,7 +6779,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
-
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.onTouchEvent(event);
}
@@ -6822,11 +6792,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int oldSelStart = getSelectionStart();
int oldSelEnd = getSelectionEnd();
+ final int oldScrollX = mScrollX;
+ final int oldScrollY = mScrollY;
+
if (mMovement != null) {
handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
}
if (isTextEditable()) {
+ if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
+ // Hide insertion anchor while scrolling. Leave selection.
+ hideInsertionPointCursorController();
+ if (mSelectionModifierCursorController != null &&
+ mSelectionModifierCursorController.isShowing()) {
+ mSelectionModifierCursorController.updatePosition();
+ }
+ }
if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -7705,22 +7686,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- private void updateOverlay() {
- boolean enableOverlay = false;
- if (mSelectionModifierCursorController != null) {
- enableOverlay |= mSelectionModifierCursorController.isShowing();
- }
- if (mInsertionPointCursorController != null) {
- enableOverlay |= mInsertionPointCursorController.isShowing();
- }
- setOverlayEnabled(enableOverlay);
- }
-
/**
* A CursorController instance can be used to control a cursor in the text.
*
* It can be passed to an {@link ArrowKeyMovementMethod} which can intercepts events
* and send them to this object instead of the cursor.
+ *
+ * @hide
*/
public interface CursorController {
/* Cursor fade-out animation duration, in milliseconds. */
@@ -7748,6 +7720,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
public void updatePosition(int x, int y);
+ public void updatePosition();
+
/**
* The controller and the cursor's positions can be link by a fixed offset,
* computed when the controller is touched, and then maintained as it moves
@@ -7766,154 +7740,192 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @param event The touch event
*/
public boolean onTouchEvent(MotionEvent event);
-
- /**
- * Draws a visual representation of the controller on the canvas.
- *
- * Called at the end of {@link #draw(Canvas)}, in the content coordinates system.
- * @param canvas The Canvas used by this TextView.
- */
- public void draw(Canvas canvas);
}
- private class Handle {
- Drawable mDrawable;
- // Vertical extension of the touch region
- int mTopExtension, mBottomExtension;
- // Position of the virtual finger position on screen
- int mHotSpotVerticalPosition;
+ private class HandleView extends View {
+ private boolean mPositionOnTop = false;
+ private Drawable mDrawable;
+ private PopupWindow mContainer;
+ private int mPositionX;
+ private int mPositionY;
+ private CursorController mController;
+ private boolean mIsDragging;
- Handle(Drawable drawable) {
- mDrawable = drawable;
+ public HandleView(CursorController controller, Drawable handle) {
+ super(TextView.this.mContext);
+ mController = controller;
+ mDrawable = handle;
+ mContainer = new PopupWindow(TextView.this.mContext, null,
+ com.android.internal.R.attr.textSelectHandleWindowStyle);
}
- void positionAtCursor(final int offset, boolean bottom) {
- final int drawableWidth = mDrawable.getIntrinsicWidth();
- final int drawableHeight = mDrawable.getIntrinsicHeight();
- final int line = mLayout.getLineForOffset(offset);
- final int lineTop = mLayout.getLineTop(line);
- final int lineBottom = mLayout.getLineBottom(line);
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(mDrawable.getIntrinsicWidth(),
+ mDrawable.getIntrinsicHeight());
+ }
- mHotSpotVerticalPosition = lineTop;
+ public void show() {
+ if (!isPositionInBounds()) {
+ hide();
+ return;
+ }
+ mContainer.setContentView(this);
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+ mContainer.showAtLocation(TextView.this, 0, coords[0], coords[1]);
+ }
- final Rect bounds = sCursorControllerTempRect;
- bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0)
- + mScrollX;
- bounds.top = (bottom ? lineBottom : lineTop) + mScrollY;
+ public void hide() {
+ mIsDragging = false;
+ mContainer.dismiss();
+ }
- mTopExtension = bottom ? 0 : drawableHeight / 2;
- mBottomExtension = 0; //drawableHeight / 4;
+ public boolean isShowing() {
+ return mContainer.isShowing();
+ }
+
+ private boolean isPositionInBounds() {
+ final int extendedPaddingTop = getExtendedPaddingTop();
+ final int extendedPaddingBottom = getExtendedPaddingBottom();
+ final int compoundPaddingLeft = getCompoundPaddingLeft();
+ final int compoundPaddingRight = getCompoundPaddingRight();
+
+ final TextView hostView = TextView.this;
+ final int right = hostView.mRight;
+ final int left = hostView.mLeft;
+ final int bottom = hostView.mBottom;
+ final int top = hostView.mTop;
+
+ final int clipLeft = left + compoundPaddingLeft;
+ final int clipTop = top + extendedPaddingTop;
+ final int clipRight = right - compoundPaddingRight;
+ final int clipBottom = bottom - extendedPaddingBottom;
+
+ final int handleWidth = mDrawable.getIntrinsicWidth();
+ return mPositionX >= clipLeft - handleWidth * 0.75f &&
+ mPositionX <= clipRight + handleWidth * 0.25f &&
+ mPositionY >= clipTop && mPositionY <= clipBottom;
+ }
+
+ private void moveTo(int x, int y) {
+ mPositionX = x - TextView.this.mScrollX;
+ mPositionY = y - TextView.this.mScrollY;
+ if (isPositionInBounds()) {
+ if (mContainer.isShowing()){
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+ mContainer.update(coords[0], coords[1], mRight - mLeft, mBottom - mTop);
+ } else {
+ show();
+ }
+ } else {
+ hide();
+ }
+ }
- // Extend touch region up when editing the last line of text (or a single line) so that
- // it is easier to grab.
- if (line == mLayout.getLineCount() - 1) {
- mTopExtension = (lineBottom - lineTop) - drawableHeight / 2;
+ @Override
+ public void onDraw(Canvas c) {
+ mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+ if (mPositionOnTop) {
+ c.save();
+ c.rotate(180, (mRight - mLeft) / 2, (mBottom - mTop) / 2);
+ mDrawable.draw(c);
+ c.restore();
+ } else {
+ mDrawable.draw(c);
}
+ }
- bounds.right = bounds.left + drawableWidth;
- bounds.bottom = bounds.top + drawableHeight;
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mIsDragging = true;
+ break;
- convertFromViewportToContentCoordinates(bounds);
- invalidate();
- mDrawable.setBounds(bounds);
- invalidate();
- }
+ case MotionEvent.ACTION_MOVE:
+ final float rawX = ev.getRawX();
+ final float rawY = ev.getRawY();
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationOnScreen(coords);
+ final int x = (int) (rawX - coords[0] + 0.5f);
+ final int y = (int) (rawY - coords[1] + 0.5f);
+ mController.updatePosition(x, y);
+ break;
- boolean hasFingerOn(float x, float y) {
- // Simulate a 'fat finger' to ease grabbing of the controller.
- // Expands according to controller image size instead of using dip distance.
- // Assumes controller imager has a sensible size, proportionnal to screen density.
- final int drawableWidth = mDrawable.getIntrinsicWidth();
- final Rect fingerRect = sCursorControllerTempRect;
- fingerRect.set((int) (x - drawableWidth / 2.0),
- (int) (y - mBottomExtension),
- (int) (x + drawableWidth / 2.0),
- (int) (y + mTopExtension));
- fingerRect.offset(mScrollX, mScrollY);
- return Rect.intersects(mDrawable.getBounds(), fingerRect);
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mIsDragging = false;
+ }
+ return true;
}
- void invalidate() {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.invalidate(bounds.left, bounds.top,
- bounds.right, bounds.bottom);
+ public boolean isDragging() {
+ return mIsDragging;
}
- void postInvalidate() {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.postInvalidate(bounds.left, bounds.top,
- bounds.right, bounds.bottom);
- }
+ void positionAtCursor(final int offset, boolean bottom) {
+ final int width = mDrawable.getIntrinsicWidth();
+ final int height = mDrawable.getIntrinsicHeight();
+ final int line = mLayout.getLineForOffset(offset);
+ final int lineTop = mLayout.getLineTop(line);
+ final int lineBottom = mLayout.getLineBottom(line);
+
+ final Rect bounds = sCursorControllerTempRect;
+ bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0)
+ + TextView.this.mScrollX;
+ bounds.top = (bottom ? lineBottom : lineTop) + TextView.this.mScrollY;
- void postInvalidateDelayed(long delay) {
- final Rect bounds = mDrawable.getBounds();
- TextView.this.postInvalidateDelayed(delay, bounds.left, bounds.top,
- bounds.right, bounds.bottom);
+ bounds.right = bounds.left + width;
+ bounds.bottom = bounds.top + height;
+
+ convertFromViewportToContentCoordinates(bounds);
+ moveTo(bounds.left, bounds.top);
}
}
class InsertionPointCursorController implements CursorController {
- private static final int DELAY_BEFORE_FADE_OUT = 2100;
+ private static final int DELAY_BEFORE_FADE_OUT = 4100;
- // Whether or not the cursor control is currently visible
- private boolean mIsVisible = false;
- // Starting time of the fade timer
- private long mFadeOutTimerStart;
// The cursor controller image
- private final Handle mHandle;
- // Used to detect a tap (vs drag) on the controller
- private long mOnDownTimerStart;
+ private final HandleView mHandle;
// Offset between finger hot point on cursor controller and actual cursor
private float mOffsetX, mOffsetY;
+ private final Runnable mHider = new Runnable() {
+ public void run() {
+ hide();
+ }
+ };
+
InsertionPointCursorController() {
Resources res = mContext.getResources();
- mHandle = new Handle(res.getDrawable(mTextSelectHandleRes));
+ mHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRes));
}
public void show() {
- updateDrawablePosition();
- // Has to be done after updateDrawablePosition, so that previous position invalidate
- // in only done if necessary.
- mIsVisible = true;
- updateOverlay();
+ updatePosition();
+ mHandle.show();
+ hideDelayed(DELAY_BEFORE_FADE_OUT);
}
public void hide() {
- if (mIsVisible) {
- long time = System.currentTimeMillis();
- // Start fading out, only if not already in progress
- if (time - mFadeOutTimerStart < DELAY_BEFORE_FADE_OUT) {
- mFadeOutTimerStart = time - DELAY_BEFORE_FADE_OUT;
- mHandle.postInvalidate();
- }
- }
+ mHandle.hide();
+ TextView.this.removeCallbacks(mHider);
}
- public boolean isShowing() {
- return mIsVisible;
+ private void hideDelayed(int msec) {
+ TextView.this.removeCallbacks(mHider);
+ TextView.this.postDelayed(mHider, msec);
}
- public void draw(Canvas canvas) {
- if (mIsVisible) {
- int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
- if (time <= DELAY_BEFORE_FADE_OUT) {
- mHandle.postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time);
- } else {
- time -= DELAY_BEFORE_FADE_OUT;
- if (time <= FADE_OUT_DURATION) {
- final int alpha = (int)
- ((255.0 * (FADE_OUT_DURATION - time)) / FADE_OUT_DURATION);
- mHandle.mDrawable.setAlpha(alpha);
- mHandle.postInvalidateDelayed(30);
- } else {
- mHandle.mDrawable.setAlpha(0);
- mIsVisible = false;
- updateOverlay();
- }
- }
- mHandle.mDrawable.draw(canvas);
- }
+ public boolean isShowing() {
+ return mHandle.isShowing();
}
public void updatePosition(int x, int y) {
@@ -7922,81 +7934,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (offset != previousOffset) {
Selection.setSelection((Spannable) mText, offset);
- updateDrawablePosition();
+ updatePosition();
}
+ hideDelayed(DELAY_BEFORE_FADE_OUT);
}
- private void updateDrawablePosition() {
- if (mIsVisible) {
- // Clear previous cursor controller before bounds are updated
- mHandle.postInvalidate();
- }
-
+ public void updatePosition() {
final int offset = getSelectionStart();
if (offset < 0) {
// Should never happen, safety check.
Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
- mIsVisible = false;
- updateOverlay();
+ hide();
return;
}
mHandle.positionAtCursor(offset, true);
-
- mFadeOutTimerStart = System.currentTimeMillis();
- mHandle.mDrawable.setAlpha(255);
- }
-
- public boolean onTouchEvent(MotionEvent event) {
- if (isFocused() && isTextEditable() && mIsVisible) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN : {
- final float x = event.getX();
- final float y = event.getY();
-
- if (mHandle.hasFingerOn(x, y)) {
- show();
-
- if (mMovement instanceof ArrowKeyMovementMethod) {
- ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
- }
-
- if (mParent != null) {
- // Prevent possible scrollView parent from scrolling, so that
- // we can use auto-scrolling.
- mParent.requestDisallowInterceptTouchEvent(true);
- }
-
- final Rect bounds = mHandle.mDrawable.getBounds();
- mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = mHandle.mHotSpotVerticalPosition - y;
-
- mOffsetX += viewportToContentHorizontalOffset();
- mOffsetY += viewportToContentVerticalOffset();
-
- mOnDownTimerStart = event.getEventTime();
- return true;
- }
- return false;
- }
-
- case MotionEvent.ACTION_UP : {
- int time = (int) (event.getEventTime() - mOnDownTimerStart);
-
- if (time <= ViewConfiguration.getTapTimeout()) {
- // A tap on the controller (not a drag) will move the cursor
- int offset = getOffset((int) event.getX(), (int) event.getY());
- Selection.setSelection((Spannable) mText, offset);
-
- // Modified by cancelLongPress and prevents the cursor from changing
- mScrolled = false;
- }
- break;
- }
- }
- }
- return false;
}
public float getOffsetX() {
@@ -8006,88 +7959,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public float getOffsetY() {
return mOffsetY;
}
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ return false;
+ }
}
class SelectionModifierCursorController implements CursorController {
- // Whether or not the selection controls are currently visible
- private boolean mIsVisible = false;
- // Whether that start or the end of selection controller is dragged
- private boolean mStartIsDragged = false;
- // Starting time of the fade timer
- private long mFadeOutTimerStart;
// The cursor controller images
- private final Handle mStartHandle, mEndHandle;
+ private HandleView mStartHandle, mEndHandle;
// Offset between finger hot point on active cursor controller and actual cursor
private float mOffsetX, mOffsetY;
// The offsets of that last touch down event. Remembered to start selection there.
private int mMinTouchOffset, mMaxTouchOffset;
+ // Whether selection anchors are active
+ private boolean mIsShowing;
SelectionModifierCursorController() {
Resources res = mContext.getResources();
- mStartHandle = new Handle(res.getDrawable(mTextSelectHandleLeftRes));
- mEndHandle = new Handle(res.getDrawable(mTextSelectHandleRightRes));
+ mStartHandle = new HandleView(this, res.getDrawable(mTextSelectHandleLeftRes));
+ mEndHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRightRes));
}
public void show() {
- updateDrawablesPositions();
- // Has to be done after updateDrawablePositions, so that previous position invalidate
- // in only done if necessary.
- mIsVisible = true;
- updateOverlay();
- mFadeOutTimerStart = -1;
+ mIsShowing = true;
+ updatePosition();
+ mStartHandle.show();
+ mEndHandle.show();
hideInsertionPointCursorController();
}
public void hide() {
- if (mIsVisible && (mFadeOutTimerStart < 0)) {
- mFadeOutTimerStart = System.currentTimeMillis();
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
+ mStartHandle.hide();
+ mEndHandle.hide();
+ mIsShowing = false;
}
public boolean isShowing() {
- return mIsVisible;
+ return mIsShowing;
}
public void cancelFadeOutAnimation() {
- mIsVisible = false;
- updateOverlay();
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
-
- public void draw(Canvas canvas) {
- if (mIsVisible) {
- if (mFadeOutTimerStart >= 0) {
- int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
- if (time <= FADE_OUT_DURATION) {
- final int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
- mStartHandle.mDrawable.setAlpha(alpha);
- mEndHandle.mDrawable.setAlpha(alpha);
- mStartHandle.postInvalidateDelayed(30);
- mEndHandle.postInvalidateDelayed(30);
- } else {
- mStartHandle.mDrawable.setAlpha(0);
- mEndHandle.mDrawable.setAlpha(0);
- mIsVisible = false;
- updateOverlay();
- }
- }
- mStartHandle.mDrawable.draw(canvas);
- mEndHandle.mDrawable.draw(canvas);
- }
+ hide();
}
public void updatePosition(int x, int y) {
int selectionStart = getSelectionStart();
int selectionEnd = getSelectionEnd();
- final int previousOffset = mStartIsDragged ? selectionStart : selectionEnd;
+ final int previousOffset = mStartHandle.isDragging() ? selectionStart : selectionEnd;
int offset = getHysteresisOffset(x, y, previousOffset);
// Handle the case where start and end are swapped, making sure start <= end
- if (mStartIsDragged) {
+ if (mStartHandle.isDragging()) {
if (offset <= selectionEnd) {
if (selectionStart == offset) {
return; // no change, no need to redraw;
@@ -8096,7 +8020,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
selectionStart = selectionEnd;
selectionEnd = offset;
- mStartIsDragged = false;
+ HandleView temp = mStartHandle;
+ mStartHandle = mEndHandle;
+ mEndHandle = temp;
}
} else {
if (offset >= selectionStart) {
@@ -8107,43 +8033,35 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
selectionEnd = selectionStart;
selectionStart = offset;
- mStartIsDragged = true;
+ HandleView temp = mStartHandle;
+ mStartHandle = mEndHandle;
+ mEndHandle = temp;
}
}
Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
- updateDrawablesPositions();
+ updatePosition();
}
- private void updateDrawablesPositions() {
- if (mIsVisible) {
- // Clear previous cursor controller before bounds are updated
- mStartHandle.postInvalidate();
- mEndHandle.postInvalidate();
- }
-
+ public void updatePosition() {
final int selectionStart = getSelectionStart();
final int selectionEnd = getSelectionEnd();
if ((selectionStart < 0) || (selectionEnd < 0)) {
// Should never happen, safety check.
Log.w(LOG_TAG, "Update selection controller position called with no cursor");
- mIsVisible = false;
- updateOverlay();
+ hide();
return;
}
- boolean oneLineSelection =
- mLayout.getLineForOffset(selectionStart) == mLayout.getLineForOffset(selectionEnd);
+ boolean oneLineSelection = mLayout.getLineForOffset(selectionStart) ==
+ mLayout.getLineForOffset(selectionEnd);
mStartHandle.positionAtCursor(selectionStart, oneLineSelection);
mEndHandle.positionAtCursor(selectionEnd, true);
-
- mStartHandle.mDrawable.setAlpha(255);
- mEndHandle.mDrawable.setAlpha(255);
}
public boolean onTouchEvent(MotionEvent event) {
- if (isTextEditable()) {
+ if (isFocused() && isTextEditable()) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
final int x = (int) event.getX();
@@ -8152,34 +8070,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Remember finger down position, to be able to start selection from there
mMinTouchOffset = mMaxTouchOffset = mLastTouchOffset = getOffset(x, y);
- if (mIsVisible) {
- if (mMovement instanceof ArrowKeyMovementMethod) {
- boolean isOnStart = mStartHandle.hasFingerOn(x, y);
- boolean isOnEnd = mEndHandle.hasFingerOn(x, y);
- if (isOnStart || isOnEnd) {
- if (mParent != null) {
- // Prevent possible scrollView parent from scrolling, so
- // that we can use auto-scrolling.
- mParent.requestDisallowInterceptTouchEvent(true);
- }
-
- // In case both controllers are under finger (very small
- // selection region), arbitrarily pick end controller.
- mStartIsDragged = !isOnEnd;
- final Handle draggedHandle =
- mStartIsDragged ? mStartHandle : mEndHandle;
- final Rect bounds = draggedHandle.mDrawable.getBounds();
- mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
- mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
-
- mOffsetX += viewportToContentHorizontalOffset();
- mOffsetY += viewportToContentVerticalOffset();
-
- ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
- return true;
- }
- }
- }
break;
case MotionEvent.ACTION_POINTER_DOWN:
@@ -8230,7 +8120,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @return true iff this controller is currently used to move the selection start.
*/
public boolean isSelectionStartDragged() {
- return mIsVisible && mStartIsDragged;
+ return mStartHandle.isDragging();
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0508df6..4e61ddf 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -51,6 +51,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
/**
* All information we are collecting about things that can happen that impact
@@ -3836,6 +3837,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ private HistoryItem mHistoryIterator;
+
+ public boolean startIteratingHistoryLocked() {
+ return (mHistoryIterator = mHistory) != null;
+ }
+
+ public boolean getNextHistoryLocked(HistoryItem out) {
+ HistoryItem cur = mHistoryIterator;
+ if (cur == null) {
+ return false;
+ }
+ out.setTo(cur);
+ mHistoryIterator = cur.next;
+ return true;
+ }
+
@Override
public HistoryItem getHistory() {
return mHistory;
@@ -3962,7 +3979,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
- writeLocked();
+ writeAsyncLocked();
}
}
}
@@ -4358,11 +4375,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void shutdownLocked() {
- writeLocked();
+ writeSyncLocked();
mShuttingDown = true;
}
- public void writeLocked() {
+ Parcel mPendingWrite = null;
+ final ReentrantLock mWriteLock = new ReentrantLock();
+
+ public void writeAsyncLocked() {
+ writeLocked(false);
+ }
+
+ public void writeSyncLocked() {
+ writeLocked(true);
+ }
+
+ void writeLocked(boolean sync) {
if (mFile == null) {
Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
return;
@@ -4372,23 +4400,51 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
+ Parcel out = Parcel.obtain();
+ writeSummaryToParcel(out);
+ mLastWriteTime = SystemClock.elapsedRealtime();
+
+ if (mPendingWrite != null) {
+ mPendingWrite.recycle();
+ }
+ mPendingWrite = out;
+
+ if (sync) {
+ commitPendingDataToDisk();
+ } else {
+ Thread thr = new Thread("BatteryStats-Write") {
+ @Override
+ public void run() {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ commitPendingDataToDisk();
+ }
+ };
+ thr.start();
+ }
+ }
+
+ public void commitPendingDataToDisk() {
+ Parcel next;
+ synchronized (this) {
+ next = mPendingWrite;
+ mPendingWrite = null;
+
+ mWriteLock.lock();
+ }
+
try {
FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
- Parcel out = Parcel.obtain();
- writeSummaryToParcel(out);
- stream.write(out.marshall());
- out.recycle();
-
+ stream.write(next.marshall());
stream.flush();
stream.close();
mFile.commit();
-
- mLastWriteTime = SystemClock.elapsedRealtime();
- return;
} catch (IOException e) {
Slog.w("BatteryStats", "Error writing battery statistics", e);
+ mFile.rollback();
+ } finally {
+ next.recycle();
+ mWriteLock.unlock();
}
- mFile.rollback();
}
static byte[] readFully(FileInputStream stream) throws java.io.IOException {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 9202429..ee44747 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -226,10 +226,8 @@ static SkShader* LinearGradient_create2(JNIEnv* env, jobject o,
///////////////////////////////////////////////////////////////////////////////////////////////
-static SkShader* RadialGradient_create1(JNIEnv* env, jobject,
- float x, float y, float radius,
- jintArray colorArray, jfloatArray posArray, int tileMode)
-{
+static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius,
+ jintArray colorArray, jfloatArray posArray, int tileMode) {
SkPoint center;
center.set(SkFloatToScalar(x), SkFloatToScalar(y));
@@ -259,10 +257,8 @@ static SkShader* RadialGradient_create1(JNIEnv* env, jobject,
return shader;
}
-static SkShader* RadialGradient_create2(JNIEnv* env, jobject,
- float x, float y, float radius,
- int color0, int color1, int tileMode)
-{
+static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius,
+ int color0, int color1, int tileMode) {
SkPoint center;
center.set(SkFloatToScalar(x), SkFloatToScalar(y));
@@ -276,11 +272,65 @@ static SkShader* RadialGradient_create2(JNIEnv* env, jobject,
return s;
}
+static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+ size_t count = env->GetArrayLength(colorArray);
+ const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
+
+ jfloat* storedPositions = new jfloat[count];
+ uint32_t* storedColors = new uint32_t[count];
+ for (size_t i = 0; i < count; i++) {
+ storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+ }
+
+ if (posArray) {
+ AutoJavaFloatArray autoPos(env, posArray, count);
+ const float* posValues = autoPos.ptr();
+ for (size_t i = 0; i < count; i++) {
+ storedPositions[i] = posValues[i];
+ }
+ } else {
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+ }
+
+ SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+ storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
+static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, float radius, int color0, int color1, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+ float* storedPositions = new float[2];
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+
+ uint32_t* storedColors = new uint32_t[2];
+ storedColors[0] = static_cast<uint32_t>(color0);
+ storedColors[1] = static_cast<uint32_t>(color1);
+
+ SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+ storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
+ (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
///////////////////////////////////////////////////////////////////////////////
static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
- jintArray jcolors, jfloatArray jpositions)
-{
+ jintArray jcolors, jfloatArray jpositions) {
size_t count = env->GetArrayLength(jcolors);
const jint* colors = env->GetIntArrayElements(jcolors, NULL);
@@ -307,8 +357,7 @@ static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
}
static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
- int color0, int color1)
-{
+ int color0, int color1) {
SkColor colors[2];
colors[0] = color0;
colors[1] = color1;
@@ -318,6 +367,59 @@ static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
return s;
}
+static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, jintArray colorArray, jfloatArray posArray) {
+#ifdef USE_OPENGL_RENDERER
+ size_t count = env->GetArrayLength(colorArray);
+ const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
+
+ jfloat* storedPositions = new jfloat[count];
+ uint32_t* storedColors = new uint32_t[count];
+ for (size_t i = 0; i < count; i++) {
+ storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+ }
+
+ if (posArray) {
+ AutoJavaFloatArray autoPos(env, posArray, count);
+ const float* posValues = autoPos.ptr();
+ for (size_t i = 0; i < count; i++) {
+ storedPositions[i] = posValues[i];
+ }
+ } else {
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+ }
+
+ SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
+ shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
+static SkiaShader* SweepGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
+ float x, float y, int color0, int color1) {
+#ifdef USE_OPENGL_RENDERER
+ float* storedPositions = new float[2];
+ storedPositions[0] = 0.0f;
+ storedPositions[1] = 1.0f;
+
+ uint32_t* storedColors = new uint32_t[2];
+ storedColors[0] = static_cast<uint32_t>(color0);
+ storedColors[1] = static_cast<uint32_t>(color1);
+
+ SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
+ shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+ return skiaShader;
+#else
+ return NULL;
+#endif
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////
static SkShader* ComposeShader_create1(JNIEnv* env, jobject o,
@@ -384,20 +486,24 @@ static JNINativeMethod gLinearGradientMethods[] = {
};
static JNINativeMethod gRadialGradientMethods[] = {
- {"nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
- {"nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 }
+ { "nativeCreate1", "(FFF[I[FI)I", (void*)RadialGradient_create1 },
+ { "nativeCreate2", "(FFFIII)I", (void*)RadialGradient_create2 },
+ { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 },
+ { "nativePostCreate2", "(IFFFIII)I", (void*)RadialGradient_postCreate2 }
};
static JNINativeMethod gSweepGradientMethods[] = {
- {"nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
- {"nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 }
+ { "nativeCreate1", "(FF[I[F)I", (void*)SweepGradient_create1 },
+ { "nativeCreate2", "(FFII)I", (void*)SweepGradient_create2 },
+ { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
+ { "nativePostCreate2", "(IFFII)I", (void*)SweepGradient_postCreate2 }
};
static JNINativeMethod gComposeShaderMethods[] = {
- {"nativeCreate1", "(III)I", (void*)ComposeShader_create1 },
- {"nativeCreate2", "(III)I", (void*)ComposeShader_create2 },
- {"nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 },
- {"nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 }
+ { "nativeCreate1", "(III)I", (void*)ComposeShader_create1 },
+ { "nativeCreate2", "(III)I", (void*)ComposeShader_create2 },
+ { "nativePostCreate1", "(IIII)I", (void*)ComposeShader_postCreate1 },
+ { "nativePostCreate2", "(IIII)I", (void*)ComposeShader_postCreate2 }
};
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/res/res/drawable-mdpi/overscroll_edge.png b/core/res/res/drawable-mdpi/overscroll_edge.png
new file mode 100644
index 0000000..22f4ef8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/overscroll_glow.png b/core/res/res/drawable-mdpi/overscroll_glow.png
new file mode 100644
index 0000000..761fb74
--- /dev/null
+++ b/core/res/res/drawable-mdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 5eab54e..c87922c 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -15,8 +15,6 @@
-->
<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
- android:paddingTop="2dip"
- android:paddingBottom="2dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
new file mode 100644
index 0000000..8416df2
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+/>
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
new file mode 100644
index 0000000..2ffbf02
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
+ android:paddingTop="2dip"
+ android:paddingBottom="2dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:mode="twoLine"
+>
+
+ <TextView android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <TextView android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_alignLeft="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+
+</TwoLineListItem>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 779a33f..19b76ab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -466,6 +466,9 @@
<attr name="quickContactBadgeStyleSmallWindowMedium" format="reference" />
<!-- Default quickcontact badge style with large quickcontact window. -->
<attr name="quickContactBadgeStyleSmallWindowLarge" format="reference" />
+ <!-- Reference to a style that will be used for the window containing a text
+ selection anchor. -->
+ <attr name="textSelectHandleWindowStyle" format="reference" />
<!-- Default ListPopupWindow style. -->
<attr name="listPopupWindowStyle" format="reference" />
<!-- Default PopupMenu style. -->
@@ -2355,6 +2358,7 @@
</declare-styleable>
<declare-styleable name="PopupWindow">
<attr name="popupBackground" format="reference|color" />
+ <attr name="windowAnimationStyle" />
</declare-styleable>
<declare-styleable name="ViewAnimator">
<!-- Identifier for the animation to use when a view is shown. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ff37d05..b4e1fcb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -416,4 +416,8 @@
<!-- Enables SIP on WIFI only -->
<bool name="config_sip_wifi_only">false</bool>
+
+ <!-- Number of database connections opened and managed by framework layer
+ to handle queries on each database. -->
+ <integer name="db_connection_pool_size">1</integer>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d3aa2d4..171bb45 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -43,6 +43,10 @@
<dimen name="fastscroll_thumb_width">64dp</dimen>
<!-- Height of the fastscroll thumb -->
<dimen name="fastscroll_thumb_height">52dp</dimen>
+ <!-- Min width for a tablet device -->
+ <dimen name="min_xlarge_screen_width">800dp</dimen>
+ <!-- Fixed viewport margin for website content width change -->
+ <dimen name="fixed_viewport_margin">7dp</dimen>
<!-- Default height of a key in the password keyboard for alpha -->
<dimen name="password_keyboard_key_height_alpha">56dip</dimen>
<!-- Default height of a key in the password keyboard for numeric -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6f53677..cdeb899 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1255,6 +1255,7 @@
<public type="attr" name="textSelectHandleLeft" id="0x010102c5" />
<public type="attr" name="textSelectHandleRight" id="0x010102c6" />
<public type="attr" name="textSelectHandle" id="0x010102c7" />
+ <public type="attr" name="textSelectHandleWindowStyle" id="0x010102c8" />
<public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
@@ -1376,6 +1377,16 @@
<!-- A simple ListView item layout which can contain text and support (single or multiple) item selection. -->
<public type="layout" name="simple_selectable_list_item" />
+ <!-- A version of {@link #simple_list_item_1} that is able to change its
+ background state to indicate when it is activated (that is checked by
+ a ListView). -->
+ <public type="layout" name="simple_list_item_activated_1" />
+
+ <!-- A version of {@link #simple_list_item_2} that is able to change its
+ background state to indicate when it is activated (that is checked by
+ a ListView). -->
+ <public type="layout" name="simple_list_item_activated_2" />
+
<public type="style" name="Theme.WithActionBar" />
<public type="style" name="Widget.Spinner.DropDown" />
<public type="style" name="Widget.ActionButton" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e8343f1..c37bb66 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -881,6 +881,17 @@
<item name="android:background">@android:drawable/bottom_bar</item>
</style>
+ <!-- Style for the small popup windows that contain text selection anchors. -->
+ <style name="Widget.TextSelectHandle">
+ <item name="android:windowAnimationStyle">@android:style/Animation.TextSelectHandle</item>
+ </style>
+
+ <!-- Style for animating text selection handles. -->
+ <style name="Animation.TextSelectHandle">
+ <item name="windowEnterAnimation">@android:anim/fade_in</item>
+ <item name="windowExitAnimation">@android:anim/fade_out</item>
+ </style>
+
<style name="Widget.ActionBar">
<item name="android:background">@android:drawable/action_bar_background</item>
<item name="android:displayOptions">useLogo</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index fd39179..9425fc4 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -156,6 +156,7 @@
<item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item>
<!-- Widget styles -->
<item name="absListViewStyle">@android:style/Widget.AbsListView</item>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index e449ddb..b1e38ee 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -35,6 +35,7 @@
android:label="@string/permlab_testDenied"
android:description="@string/permdesc_testDenied" />
+ <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
index ee0f5f1..a7ec7d5 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
@@ -27,6 +27,7 @@ import android.net.NetworkInfo;
import android.net.DownloadManager.Query;
import android.net.DownloadManager.Request;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
@@ -43,9 +44,12 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeoutException;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.Vector;
import junit.framework.AssertionFailedError;
@@ -67,6 +71,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest";
protected static final int HTTP_OK = 200;
+ protected static final int HTTP_REDIRECT = 307;
protected static final int HTTP_PARTIAL_CONTENT = 206;
protected static final int HTTP_NOT_FOUND = 404;
protected static final int HTTP_SERVICE_UNAVAILABLE = 503;
@@ -119,6 +124,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver {
private volatile int mNumDownloadsCompleted = 0;
+ private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>());
/**
* {@inheritDoc}
@@ -129,6 +135,8 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
++mNumDownloadsCompleted;
Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
+ Bundle extras = intent.getExtras();
+ downloadIds.add(new Long(extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID)));
}
}
@@ -142,6 +150,18 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
public int numDownloadsCompleted() {
return mNumDownloadsCompleted;
}
+
+ /**
+ * Gets the list of download IDs.
+ * @return A Set<Long> with the ids of the completed downloads.
+ */
+ public Set<Long> getDownloadIds() {
+ synchronized(downloadIds) {
+ Set<Long> returnIds = new HashSet<Long>(downloadIds);
+ return returnIds;
+ }
+ }
+
}
public static class WiFiChangedReceiver extends BroadcastReceiver {
@@ -196,6 +216,17 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
}
/**
+ * Helper to enqueue a response from the MockWebServer with no body.
+ *
+ * @param status The HTTP status code to return for this response
+ * @return Returns the mock web server response that was queued (which can be modified)
+ */
+ protected MockResponse enqueueResponse(int status) {
+ return doEnqueueResponse(status);
+
+ }
+
+ /**
* Helper to enqueue a response from the MockWebServer.
*
* @param status The HTTP status code to return for this response
diff --git a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
index be3cbf7..a61f02d 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
+import android.net.DownloadManager;
import android.net.DownloadManager.Query;
import android.net.DownloadManager.Request;
import android.net.DownloadManagerBaseTest.DataType;
@@ -28,6 +29,7 @@ import android.net.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.StatFs;
import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -36,10 +38,13 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
+import java.util.Iterator;
import java.util.Random;
+import java.util.Set;
import junit.framework.AssertionFailedError;
@@ -51,8 +56,11 @@ import coretestutils.http.MockWebServer;
*/
public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
- private static String LOG_TAG = "android.net.DownloadManagerIntegrationTest";
- private static String PROHIBITED_DIRECTORY = "/system";
+ private final static String LOG_TAG = "android.net.DownloadManagerIntegrationTest";
+ private final static String PROHIBITED_DIRECTORY =
+ Environment.getRootDirectory().getAbsolutePath();
+ private final static String CACHE_DIR =
+ Environment.getDownloadCacheDirectory().getAbsolutePath();
protected MultipleDownloadsCompletedReceiver mReceiver = null;
/**
@@ -74,25 +82,48 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
public void tearDown() throws Exception {
super.tearDown();
setWiFiStateOn(true);
+ removeAllCurrentDownloads();
if (mReceiver != null) {
mContext.unregisterReceiver(mReceiver);
mReceiver = null;
- removeAllCurrentDownloads();
}
}
/**
* Helper that does the actual basic download verification.
*/
- protected void doBasicDownload(byte[] blobData) throws Exception {
+ protected long doBasicDownload(byte[] blobData) throws Exception {
long dlRequest = doStandardEnqueue(blobData);
// wait for the download to complete
waitForDownloadOrTimeout(dlRequest);
- verifyAndCleanupSingleFileDownload(dlRequest, blobData);
assertEquals(1, mReceiver.numDownloadsCompleted());
+ return dlRequest;
+ }
+
+ /**
+ * Verifies a particular error code was received from a download
+ *
+ * @param uri The uri to enqueue to the DownloadManager
+ * @param error The error code expected
+ * @throws an Exception if the test fails
+ */
+ @LargeTest
+ public void doErrorTest(Uri uri, int error) throws Exception {
+ Request request = new Request(uri);
+ request.setTitle(DEFAULT_FILENAME);
+
+ long dlRequest = mDownloadManager.enqueue(request);
+ waitForDownloadOrTimeout(dlRequest);
+
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE, error);
+ } finally {
+ cursor.close();
+ }
}
/**
@@ -103,7 +134,8 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
int fileSize = 500 * 1024; // 500k
byte[] blobData = generateData(fileSize, DataType.BINARY);
- doBasicDownload(blobData);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
}
/**
@@ -114,7 +146,8 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
int fileSize = 300000;
byte[] blobData = generateData(fileSize, DataType.TEXT);
- doBasicDownload(blobData);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
}
/**
@@ -348,34 +381,209 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
}
/**
- * Tests trying to download two large files (50M bytes, followed by 60M bytes)
+ * Tests downloading a file to cache when there isn't enough space in the cache to hold the
+ * entire file.
*/
@LargeTest
- public void testInsufficientSpaceSingleFiles() throws Exception {
- long fileSize1 = 50000000L;
- long fileSize2 = 60000000L;
- File largeFile1 = createFileOnSD(null, fileSize1, DataType.TEXT, null);
- File largeFile2 = createFileOnSD(null, fileSize2, DataType.TEXT, null);
+ public void testDownloadToCache_whenFull() throws Exception {
+ int DOWNLOAD_FILE_SIZE = 500000;
+
+ StatFs fs = new StatFs(CACHE_DIR);
+ Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
+ Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
+
+ int blockSize = fs.getBlockSize();
+ int availableBlocks = fs.getAvailableBlocks();
+ int availableBytes = blockSize * availableBlocks;
+ File outFile = null;
try {
- long dlRequest = doStandardEnqueue(largeFile1);
- waitForDownloadOrTimeout(dlRequest);
- ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
- verifyFileContents(pfd, largeFile1);
- verifyFileSize(pfd, largeFile1.length());
+ // fill cache to ensure we don't have enough space - take half the size of the
+ // download size, and leave that much freespace left on the cache partition
+ if (DOWNLOAD_FILE_SIZE <= availableBytes) {
+ int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2);
+
+ int writeSizeBlocks = writeSizeBytes / blockSize;
+ int remainderSizeBlocks = availableBlocks - writeSizeBlocks;
+
+ FileOutputStream fo = null;
+ try {
+ outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR));
+ Log.v(LOG_TAG, "writing " + writeSizeBlocks + " blocks to file "
+ + outFile.getAbsolutePath());
+
+ fo = new FileOutputStream(outFile);
+
+ byte[] buffer = new byte[blockSize];
+ while (fs.getAvailableBlocks() >= remainderSizeBlocks) {
+ fo.write(buffer);
+ fs.restat(CACHE_DIR);
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "error filling file: ", e);
+ throw e;
+ } finally {
+ if (fo != null) {
+ fo.close();
+ }
+ }
+ }
- dlRequest = doStandardEnqueue(largeFile2);
- waitForDownloadOrTimeout(dlRequest);
- Cursor cursor = getCursor(dlRequest);
- try {
- verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE,
- DownloadManager.ERROR_INSUFFICIENT_SPACE);
- } finally {
- cursor.close();
+ assertTrue(DOWNLOAD_FILE_SIZE > (fs.getAvailableBlocks() * blockSize));
+ byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
+
+ } finally {
+ if (outFile != null) {
+ outFile.delete();
}
+ }
+ }
+
+ /**
+ * Tests that files are not deleted when DOWNLOAD_CACHE_NON_PURGEABLE is set, even if we've
+ * run out of space.
+ */
+ @LargeTest
+ public void testDownloadCacheNonPurgeable() throws Exception {
+ int fileSize = 10000000;
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+ long dlRequest = -1;
+
+ // Fill up the cache partition until there's not enough room for another download.
+ // Note that we need to initiate a download first, then check for the available space. This
+ // is b/c there could be some files that are still left in the cache that can (and will be)
+ // cleared out, but not until DM gets a request for a download and reclaims that
+ // space first.
+ boolean spaceAvailable = true;
+ while (spaceAvailable) {
+ dlRequest = doStandardEnqueue(blobData);
+ waitForDownloadOrTimeout(dlRequest);
+
+ // Check if we've filled up the cache yet
+ StatFs fs = new StatFs(CACHE_DIR);
+ Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
+ Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
+ int availableBytes = fs.getBlockSize() * fs.getAvailableBlocks();
+ spaceAvailable = (availableBytes > fileSize) ? true : false;
+ }
+
+ // Now add one more download (should not fit in the space left over)
+ dlRequest = doStandardEnqueue(blobData);
+ waitForDownloadOrTimeout(dlRequest);
+
+ // For the last download we should have failed b/c there is not enough space left in cache
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE,
+ DownloadManager.ERROR_INSUFFICIENT_SPACE);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Tests that we get the correct download ID from the download notification.
+ */
+ @LargeTest
+ public void testGetDownloadIdOnNotification() throws Exception {
+ byte[] blobData = generateData(3000, DataType.TEXT); // file size = 3000 bytes
+
+ MockResponse response = enqueueResponse(HTTP_OK, blobData);
+ long dlRequest = doCommonStandardEnqueue();
+ waitForDownloadOrTimeout(dlRequest);
+
+ Set<Long> ids = mReceiver.getDownloadIds();
+ assertEquals(1, ids.size());
+ Iterator<Long> it = ids.iterator();
+ assertEquals("Download ID received from notification does not match initial id!",
+ dlRequest, it.next().longValue());
+ }
+
+ /**
+ * Tests the download failure error after too many redirects (>5).
+ */
+ @LargeTest
+ public void testErrorTooManyRedirects() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+
+ // force 6 redirects
+ for (int i = 0; i < 6; ++i) {
+ MockResponse response = enqueueResponse(HTTP_REDIRECT);
+ response.addHeader("Location", uri.toString());
+ }
+ doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS);
+ }
+
+ /**
+ * Tests the download failure error from an unhandled HTTP status code
+ */
+ @LargeTest
+ public void testErrorUnhandledHttpCode() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT);
+
+ doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
+ }
+
+ /**
+ * Tests the download failure error from an unhandled HTTP status code
+ */
+ @LargeTest
+ public void testErrorHttpDataError_invalidRedirect() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ MockResponse response = enqueueResponse(HTTP_REDIRECT);
+ response.addHeader("Location", "://blah.blah.blah.com");
+
+ doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR);
+ }
+
+ /**
+ * Tests that we can remove a download from the download manager.
+ */
+ @LargeTest
+ public void testRemoveDownload() throws Exception {
+ int fileSize = 100 * 1024; // 100k
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+
+ long dlRequest = doBasicDownload(blobData);
+ Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest));
+ try {
+ assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount());
+ mDownloadManager.remove(dlRequest);
+ cursor.requery();
+ assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount());
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Tests that we can set the title of a download.
+ */
+ @LargeTest
+ public void testSetTitle() throws Exception {
+ int fileSize = 50 * 1024; // 50k
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+ MockResponse response = enqueueResponse(HTTP_OK, blobData);
+
+ // An arbitrary unicode string title
+ final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" +
+ "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'";
+
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ Request request = new Request(uri);
+ request.setTitle(title);
+
+ long dlRequest = mDownloadManager.enqueue(request);
+ waitForDownloadOrTimeout(dlRequest);
+
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyString(cursor, DownloadManager.COLUMN_TITLE, title);
} finally {
- largeFile1.delete();
- largeFile2.delete();
+ cursor.close();
}
}
}
diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java
index 0f5b090..53368d4 100644
--- a/core/tests/coretests/src/android/util/Base64Test.java
+++ b/core/tests/coretests/src/android/util/Base64Test.java
@@ -16,6 +16,9 @@
package android.util;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
@@ -404,6 +407,14 @@ public class Base64Test extends TestCase {
}
}
+ /** http://b/3026478 */
+ public void testSingleByteReads() throws IOException {
+ InputStream in = new Base64InputStream(
+ new ByteArrayInputStream("/v8=".getBytes()), Base64.DEFAULT);
+ assertEquals(254, in.read());
+ assertEquals(255, in.read());
+ }
+
/**
* Tests that Base64OutputStream produces exactly the same results
* as calling Base64.encode/.decode on an in-memory array.
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
index 0f7351a..c698e99 100644
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
+++ b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
@@ -601,7 +601,7 @@ public class PackageManagerHostTestUtils extends Assert {
mTestRunErrorMessage = errorMessage;
}
- public void testRunStarted(int testCount) {
+ public void testRunStarted(String runName, int testCount) {
// ignore
}
diff --git a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
index cfabb6c..a94555c 100644
--- a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
+++ b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
@@ -46,8 +46,10 @@ public class DownloadManagerHostTests extends DeviceTestCase {
private static final String EXTERNAL_DOWNLOAD_URI_KEY = "external_download_uri";
// Note: External environment variable ANDROID_TEST_EXTERNAL_URI must be set to point to the
// external URI under which the files downloaded by the tests can be found. Note that the Uri
- // must be accessible by the device during a test run.
- private static String EXTERNAL_DOWNLOAD_URI_VALUE = null;
+ // must be accessible by the device during a test run. Correspondingly,
+ // ANDROID_TEST_EXTERNAL_LARGE_URI should point to the external URI of the folder containing
+ // large files.
+ private static String externalDownloadUriValue = null;
Hashtable<String, String> mExtraParams = null;
@@ -61,8 +63,8 @@ public class DownloadManagerHostTests extends DeviceTestCase {
// ensure apk path has been set before test is run
assertNotNull(getTestAppPath());
mPMUtils = new PackageManagerHostTestUtils(getDevice());
- EXTERNAL_DOWNLOAD_URI_VALUE = System.getenv("ANDROID_TEST_EXTERNAL_URI");
- assertNotNull(EXTERNAL_DOWNLOAD_URI_VALUE);
+ externalDownloadUriValue = System.getenv("ANDROID_TEST_EXTERNAL_URI");
+ assertNotNull(externalDownloadUriValue);
mExtraParams = getExtraParams();
}
@@ -71,7 +73,7 @@ public class DownloadManagerHostTests extends DeviceTestCase {
*/
protected Hashtable<String, String> getExtraParams() {
Hashtable<String, String> extraParams = new Hashtable<String, String>();
- extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, EXTERNAL_DOWNLOAD_URI_VALUE);
+ extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, externalDownloadUriValue);
return extraParams;
}
@@ -190,4 +192,19 @@ public class DownloadManagerHostTests extends DeviceTestCase {
DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
assertTrue(testPassed);
}
+
+ /**
+ * Spawns a device-based function to test 15 concurrent downloads of 5,000,000-byte files
+ *
+ * @throws Exception if the test failed at any point
+ */
+ public void testDownloadMultipleSimultaneously() throws Exception {
+ mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
+ File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
+
+ boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
+ FILE_DOWNLOAD_CLASS, "runDownloadMultipleSimultaneously",
+ DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
+ assertTrue(testPassed);
+ }
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
index ef81353..0293ded 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
@@ -35,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
+import java.util.HashSet;
import coretestutils.http.MockResponse;
import coretestutils.http.MockWebServer;
@@ -55,8 +56,13 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
protected static String DOWNLOAD_10MB_FILENAME = "External10mb.apk";
protected static long DOWNLOAD_10MB_FILESIZE = 10258741;
+ private static final String FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX = "file";
+ private static final String FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION = ".bin";
+ protected static long CONCURRENT_DOWNLOAD_FILESIZE = 1000000;
+
// Values to be obtained from TestRunner
private String externalDownloadUriValue = null;
+ private String externalLargeDownloadUriValue = null;
/**
* {@inheritDoc }
@@ -65,12 +71,24 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
public void setUp() throws Exception {
super.setUp();
DownloadManagerTestRunner mRunner = (DownloadManagerTestRunner)getInstrumentation();
- externalDownloadUriValue = mRunner.externalDownloadUriValue;
+ externalDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
assertNotNull(externalDownloadUriValue);
- if (!externalDownloadUriValue.endsWith("/")) {
- externalDownloadUriValue += "/";
+ externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
+ assertNotNull(externalLargeDownloadUriValue);
+ }
+
+ /**
+ * Normalizes a uri to ensure it ends with a "/"
+ *
+ * @param uri The uri to normalize (or null)
+ * @return The normalized uri, or null if null was passed in
+ */
+ public String normalizeUri(String uri) {
+ if (uri != null && !uri.endsWith("/")) {
+ uri += "/";
}
+ return uri;
}
/**
@@ -460,4 +478,37 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
downloadedFile.delete();
}
}
+
+ /**
+ * Tests 15 concurrent downloads of 1,000,000-byte files.
+ *
+ * @throws Exception if test failed
+ */
+ public void runDownloadMultipleSimultaneously() throws Exception {
+ final int TOTAL_DOWNLOADS = 15;
+ HashSet<Long> downloadIds = new HashSet<Long>(TOTAL_DOWNLOADS);
+ MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver();
+
+ // Make sure there are no pending downloads currently going on
+ removeAllCurrentDownloads();
+
+ try {
+ for (int i = 0; i < TOTAL_DOWNLOADS; ++i) {
+ long dlRequest = -1;
+ String filename = FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX + i
+ + FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION;
+ Uri remoteUri = getExternalFileUri(filename);
+ Request request = new Request(remoteUri);
+ request.setTitle(filename);
+ dlRequest = mDownloadManager.enqueue(request);
+ assertTrue(dlRequest != -1);
+ downloadIds.add(dlRequest);
+ }
+
+ waitForDownloadsOrTimeout(DEFAULT_WAIT_POLL_TIME, 15 * 60 * 2000); // wait 15 mins max
+ assertEquals(TOTAL_DOWNLOADS, receiver.numDownloadsCompleted());
+ } finally {
+ removeAllCurrentDownloads();
+ }
+ }
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
index 0f16619..27bf7e1 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
@@ -30,7 +30,7 @@ import junit.framework.TestSuite;
*
* To run the download manager tests:
*
- * adb shell am instrument -e external_download_1mb_uri <uri> external_download_500k_uri <uri> \
+ * adb shell am instrument -e external_download_uri <uri> external_large_download_uri <uri> \
* -w com.android.frameworks.downloadmanagertests/.DownloadManagerTestRunner
*/
diff --git a/data/fonts/MTLc3m.ttf b/data/fonts/MTLc3m.ttf
new file mode 100644
index 0000000..3cc5c96
--- /dev/null
+++ b/data/fonts/MTLc3m.ttf
Binary files differ
diff --git a/data/fonts/MTLmr3m.ttf b/data/fonts/MTLmr3m.ttf
new file mode 100644
index 0000000..05b9093
--- /dev/null
+++ b/data/fonts/MTLmr3m.ttf
Binary files differ
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index b4e902d..897762c 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -40,6 +40,8 @@ public class RadialGradient extends Shader {
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt);
+ native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions,
+ tile.nativeInt);
}
/** Create a shader that draws a radial gradient given the center and radius.
@@ -56,11 +58,18 @@ public class RadialGradient extends Shader {
throw new IllegalArgumentException("radius must be > 0");
}
native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
+ native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
+ tile.nativeInt);
}
private static native int nativeCreate1(float x, float y, float radius,
- int colors[], float positions[], int tileMode);
+ int colors[], float positions[], int tileMode);
private static native int nativeCreate2(float x, float y, float radius,
- int color0, int color1, int tileMode);
+ int color0, int color1, int tileMode);
+
+ private static native int nativePostCreate1(int native_shader, float x, float y, float radius,
+ int colors[], float positions[], int tileMode);
+ private static native int nativePostCreate2(int native_shader, float x, float y, float radius,
+ int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index b397662..0400b5c 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -71,7 +71,8 @@ public class Shader {
* @param localM The shader's new local matrix, or null to specify identity
*/
public void setLocalMatrix(Matrix localM) {
- nativeSetLocalMatrix(native_instance, native_shader, localM.native_instance);
+ nativeSetLocalMatrix(native_instance, native_shader,
+ localM == null ? 0 : localM.native_instance);
}
protected void finalize() throws Throwable {
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 7456993..2afdd4d 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -42,6 +42,7 @@ public class SweepGradient extends Shader {
"color and position arrays must be of equal length");
}
native_instance = nativeCreate1(cx, cy, colors, positions);
+ native_shader = nativePostCreate1(native_instance, cx, cy, colors, positions);
}
/**
@@ -54,11 +55,15 @@ public class SweepGradient extends Shader {
*/
public SweepGradient(float cx, float cy, int color0, int color1) {
native_instance = nativeCreate2(cx, cy, color0, color1);
+ native_shader = nativePostCreate2(native_instance, cx, cy, color0, color1);
}
- private static native int nativeCreate1(float x, float y,
- int colors[], float positions[]);
- private static native int nativeCreate2(float x, float y,
- int color0, int color1);
+ private static native int nativeCreate1(float x, float y, int colors[], float positions[]);
+ private static native int nativeCreate2(float x, float y, int color0, int color1);
+
+ private static native int nativePostCreate1(int native_shader, float cx, float cy,
+ int[] colors, float[] positions);
+ private static native int nativePostCreate2(int native_shader, float cx, float cy,
+ int color0, int color1);
}
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 3198e3f..715e3fb 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -32,6 +32,9 @@ class BaseObj {
}
public int getID() {
+ if (mDestroyed) {
+ throw new IllegalStateException("using a destroyed object.");
+ }
return mID;
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 1312036..159e070 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -358,6 +358,10 @@ public class RenderScript {
synchronized void nScriptSetVarF(int id, int slot, float val) {
rsnScriptSetVarF(mContext, id, slot, val);
}
+ native void rsnScriptSetVarD(int con, int id, int slot, double val);
+ synchronized void nScriptSetVarD(int id, int slot, double val) {
+ rsnScriptSetVarD(mContext, id, slot, val);
+ }
native void rsnScriptSetVarV(int con, int id, int slot, byte[] val);
synchronized void nScriptSetVarV(int id, int slot, byte[] val) {
rsnScriptSetVarV(mContext, id, slot, val);
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 19c444c..8772c4c 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -72,6 +72,10 @@ public class Script extends BaseObj {
mRS.nScriptSetVarF(mID, index, v);
}
+ public void setVar(int index, double v) {
+ mRS.nScriptSetVarD(mID, index, v);
+ }
+
public void setVar(int index, int v) {
mRS.nScriptSetVarI(mID, index, v);
}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index f386537..ee2080e 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -791,11 +791,18 @@ nScriptSetVarI(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slo
static void
nScriptSetVarF(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, float val)
{
- LOG_API("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%f)", con, (void *)script, slot, val);
+ LOG_API("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", con, (void *)script, slot, val);
rsScriptSetVarF(con, (RsScript)script, slot, val);
}
static void
+nScriptSetVarD(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, double val)
+{
+ LOG_API("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", con, (void *)script, slot, val);
+ rsScriptSetVarD(con, (RsScript)script, slot, val);
+}
+
+static void
nScriptSetVarV(JNIEnv *_env, jobject _this, RsContext con, jint script, jint slot, jbyteArray data)
{
LOG_API("nScriptSetVarV, con(%p), s(%p), slot(%i)", con, (void *)script, slot);
@@ -1281,6 +1288,7 @@ static JNINativeMethod methods[] = {
{"rsnScriptInvokeV", "(III[B)V", (void*)nScriptInvokeV },
{"rsnScriptSetVarI", "(IIII)V", (void*)nScriptSetVarI },
{"rsnScriptSetVarF", "(IIIF)V", (void*)nScriptSetVarF },
+{"rsnScriptSetVarD", "(IIID)V", (void*)nScriptSetVarD },
{"rsnScriptSetVarV", "(III[B)V", (void*)nScriptSetVarV },
{"rsnScriptCBegin", "(I)V", (void*)nScriptCBegin },
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 72d5756..705b101 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -383,12 +383,14 @@ public:
// continuously. Applications should not call
// CameraHardwareInterface.autoFocus in this mode.
static const char FOCUS_MODE_EDOF[];
- // Continuous auto focus mode. The camera continuously tries to focus. This
- // is ideal for shooting video or shooting photo of moving object. Auto
- // focus starts when the parameter is set. Applications should not call
- // CameraHardwareInterface.autoFocus in this mode. To stop continuous
- // focus, applications should change the focus mode to other modes.
- static const char FOCUS_MODE_CONTINUOUS[];
+ // Continuous auto focus mode intended for video recording. The camera
+ // continuously tries to focus. This is ideal for shooting video.
+ // Applications still can call CameraHardwareInterface.takePicture in this
+ // mode but the subject may not be in focus. Auto focus starts when the
+ // parameter is set. Applications should not call
+ // CameraHardwareInterface.autoFocus in this mode. To stop continuous focus,
+ // applications should change the focus mode to other modes.
+ static const char FOCUS_MODE_CONTINUOUS_VIDEO[];
private:
DefaultKeyedVector<String8,String8> mMap;
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 0f986a0..69021d8 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -22,45 +22,18 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
namespace android {
-enum LogType {
- VERBOSE,
- INFO,
- WARNING,
- ERROR,
- FATAL,
-};
-
-struct Logger {
- Logger(LogType type);
- virtual ~Logger();
-
- template<class T> Logger &operator<<(const T &x) {
- mMessage.append(x);
-
- return *this;
- }
-
-private:
- android::AString mMessage;
- LogType mLogType;
-
- DISALLOW_EVIL_CONSTRUCTORS(Logger);
-};
-
-const char *LeafName(const char *s);
-
-#undef LOG
-#define LOG(type) Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " "
+#define LITERAL_TO_STRING_INTERNAL(x) #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
#define CHECK(condition) \
- do { \
- if (!(condition)) { \
- LOG(FATAL) << "CHECK(" #condition ") failed."; \
- } \
- } while (false)
+ LOG_ALWAYS_FATAL_IF( \
+ !(condition), \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK(" #condition ") failed.")
#define MAKE_COMPARATOR(suffix,op) \
template<class A, class B> \
@@ -85,8 +58,10 @@ MAKE_COMPARATOR(GT,>)
do { \
AString ___res = Compare_##suffix(x, y); \
if (!___res.empty()) { \
- LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: " \
- << ___res; \
+ LOG_ALWAYS_FATAL( \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK_" #suffix "( " #x "," #y ") failed: %s", \
+ ___res.c_str()); \
} \
} while (false)
@@ -97,7 +72,7 @@ MAKE_COMPARATOR(GT,>)
#define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=)
#define CHECK_GT(x,y) CHECK_OP(x,y,GT,>)
-#define TRESPASS() LOG(FATAL) << "Should not be here."
+#define TRESPASS() LOG_ALWAYS_FATAL("Should not be here.")
} // namespace android
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 7d90866..3f00b78 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -205,6 +205,7 @@ private:
int pollInner(int timeoutMillis);
+ static void initTLSKey();
static void threadDestructor(void *st);
};
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 887b12c..af58f77 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -142,7 +142,7 @@ const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity";
const char CameraParameters::FOCUS_MODE_MACRO[] = "macro";
const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
-const char CameraParameters::FOCUS_MODE_CONTINUOUS[] = "continuous";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
CameraParameters::CameraParameters()
: mMap()
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 9957370..97f4cb4 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -116,7 +116,7 @@ void GradientCache::clear() {
mCache.clear();
}
-Texture* GradientCache::addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors,
+Texture* GradientCache::addLinearGradient(SkShader* shader, uint32_t* colors,
float* positions, int count, SkShader::TileMode tileMode) {
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1024, 1);
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 51a8c01..c829fd4 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -46,8 +46,8 @@ public:
* Adds a new linear gradient to the cache. The generated texture is
* returned.
*/
- Texture* addLinearGradient(SkShader* shader, float* bounds, uint32_t* colors,
- float* positions, int count, SkShader::TileMode tileMode);
+ Texture* addLinearGradient(SkShader* shader, uint32_t* colors, float* positions,
+ int count, SkShader::TileMode tileMode = SkShader::kClamp_TileMode);
/**
* Returns the texture associated with the specified shader.
*/
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 264ad3d..c698b5a 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -144,6 +144,12 @@ float Matrix4::getTranslateY() {
return data[kTranslateY];
}
+void Matrix4::multiply(float v) {
+ for (int i = 0; i < 16; i++) {
+ data[i] *= v;
+ }
+}
+
void Matrix4::loadTranslate(float x, float y, float z) {
loadIdentity();
data[kTranslateX] = x;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index c247a67..0608efe 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -83,6 +83,8 @@ public:
load(u);
}
+ void multiply(float v);
+
void translate(float x, float y, float z) {
Matrix4 u;
u.loadTranslate(x, y, z);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index becbc22..3e9412c 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -33,11 +33,21 @@ const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
const char* gVS_Header_Uniforms =
"uniform mat4 transform;\n";
-const char* gVS_Header_Uniforms_HasGradient =
+const char* gVS_Header_Uniforms_HasGradient[3] = {
+ // Linear
"uniform float gradientLength;\n"
"uniform vec2 gradient;\n"
"uniform vec2 gradientStart;\n"
- "uniform mat4 screenSpace;\n";
+ "uniform mat4 screenSpace;\n",
+ // Circular
+ "uniform vec2 gradientStart;\n"
+ "uniform mat4 gradientMatrix;\n"
+ "uniform mat4 screenSpace;\n",
+ // Sweep
+ "uniform vec2 gradientStart;\n"
+ "uniform mat4 gradientMatrix;\n"
+ "uniform mat4 screenSpace;\n"
+};
const char* gVS_Header_Uniforms_HasBitmap =
"uniform mat4 textureTransform;\n"
"uniform vec2 textureDimension;\n";
@@ -45,15 +55,29 @@ const char* gVS_Header_Varyings_HasTexture =
"varying vec2 outTexCoords;\n";
const char* gVS_Header_Varyings_HasBitmap =
"varying vec2 outBitmapTexCoords;\n";
-const char* gVS_Header_Varyings_HasGradient =
- "varying float index;\n";
+const char* gVS_Header_Varyings_HasGradient[3] = {
+ // Linear
+ "varying float index;\n",
+ // Circular
+ "varying vec2 circular;\n",
+ // Sweep
+ "varying vec2 sweep;\n"
+};
const char* gVS_Main =
"\nvoid main(void) {\n";
const char* gVS_Main_OutTexCoords =
" outTexCoords = texCoords;\n";
-const char* gVS_Main_OutGradientIndex =
+const char* gVS_Main_OutGradient[3] = {
+ // Linear
+ " vec4 location = screenSpace * position;\n"
+ " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n",
+ // Circular
" vec4 location = screenSpace * position;\n"
- " index = dot(location.xy - gradientStart, gradient) * gradientLength;\n";
+ " circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n",
+ // Sweep
+ " vec4 location = screenSpace * position;\n"
+ " sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n"
+};
const char* gVS_Main_OutBitmapTexCoords =
" vec4 bitmapCoords = textureTransform * position;\n"
" outBitmapTexCoords = bitmapCoords.xy * textureDimension;\n";
@@ -74,8 +98,15 @@ const char* gFS_Uniforms_Color =
"uniform vec4 color;\n";
const char* gFS_Uniforms_TextureSampler =
"uniform sampler2D sampler;\n";
-const char* gFS_Uniforms_GradientSampler =
- "uniform sampler2D gradientSampler;\n";
+const char* gFS_Uniforms_GradientSampler[3] = {
+ // Linear
+ "uniform sampler2D gradientSampler;\n",
+ // Circular
+ "uniform float gradientRadius;\n"
+ "uniform sampler2D gradientSampler;\n",
+ // Sweep
+ "uniform sampler2D gradientSampler;\n"
+};
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
const char* gFS_Uniforms_ColorOp[4] = {
@@ -99,8 +130,16 @@ const char* gFS_Main_FetchTexture =
" fragColor = color * texture2D(sampler, outTexCoords);\n";
const char* gFS_Main_FetchA8Texture =
" fragColor = color * texture2D(sampler, outTexCoords).a;\n";
-const char* gFS_Main_FetchGradient =
- " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n";
+const char* gFS_Main_FetchGradient[3] = {
+ // Linear
+ " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
+ // Circular
+ " float index = length(circular) * gradientRadius;\n"
+ " vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
+ // Sweep
+ " float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
+ " vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
+};
const char* gFS_Main_FetchBitmap =
" vec4 bitmapColor = texture2D(bitmapSampler, outBitmapTexCoords);\n";
const char* gFS_Main_FetchBitmapNpot =
@@ -217,7 +256,7 @@ Program* ProgramCache::get(const ProgramDescription& description) {
ssize_t index = mCache.indexOfKey(key);
Program* program = NULL;
if (index < 0) {
- PROGRAM_LOGD("Could not find program with key 0x%x", key);
+ description.log("Could not find program");
program = generateProgram(description, key);
mCache.add(key, program);
} else {
@@ -247,7 +286,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
// Uniforms
shader.append(gVS_Header_Uniforms);
if (description.hasGradient) {
- shader.append(gVS_Header_Uniforms_HasGradient);
+ shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Uniforms_HasBitmap);
@@ -257,7 +296,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasGradient) {
- shader.append(gVS_Header_Varyings_HasGradient);
+ shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Varyings_HasBitmap);
@@ -269,7 +308,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
shader.append(gVS_Main_OutTexCoords);
}
if (description.hasGradient) {
- shader.append(gVS_Main_OutGradientIndex);
+ shader.append(gVS_Main_OutGradient[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gVS_Main_OutBitmapTexCoords);
@@ -301,7 +340,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gVS_Header_Varyings_HasTexture);
}
if (description.hasGradient) {
- shader.append(gVS_Header_Varyings_HasGradient);
+ shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gVS_Header_Varyings_HasBitmap);
@@ -314,7 +353,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Uniforms_TextureSampler);
}
if (description.hasGradient) {
- shader.append(gFS_Uniforms_GradientSampler);
+ shader.append(gFS_Uniforms_GradientSampler[description.gradientType]);
}
if (description.hasBitmap) {
shader.append(gFS_Uniforms_BitmapSampler);
@@ -348,7 +387,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_FetchColor);
}
if (description.hasGradient) {
- shader.append(gFS_Main_FetchGradient);
+ shader.append(gFS_Main_FetchGradient[description.gradientType]);
}
if (description.hasBitmap) {
if (!description.isBitmapNpot) {
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 0a17052..4fa8011 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -44,9 +44,6 @@ namespace uirenderer {
#define PROGRAM_LOGD(...)
#endif
-/*
- * IMPORTANT: All 32 bits are used, switch to a long.
- */
#define PROGRAM_KEY_TEXTURE 0x1
#define PROGRAM_KEY_A8_TEXTURE 0x2
#define PROGRAM_KEY_BITMAP 0x4
@@ -70,14 +67,13 @@ namespace uirenderer {
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
#define PROGRAM_BITMAP_WRAPT_SHIFT 11
+#define PROGRAM_GRADIENT_TYPE_SHIFT 33
+
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
-/*
- * IMPORTANT: All 32 bits are used, switch to a long.
- */
-typedef uint32_t programid;
+typedef uint64_t programid;
///////////////////////////////////////////////////////////////////////////////
// Cache
@@ -96,9 +92,16 @@ struct ProgramDescription {
kColorBlend
};
+ enum Gradient {
+ kGradientLinear,
+ kGradientCircular,
+ kGradientSweep
+ };
+
ProgramDescription():
hasTexture(false), hasAlpha8Texture(false),
hasBitmap(false), isBitmapNpot(false), hasGradient(false),
+ gradientType(kGradientLinear),
shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false),
bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE),
colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode),
@@ -112,8 +115,12 @@ struct ProgramDescription {
// Shaders
bool hasBitmap;
bool isBitmapNpot;
+
bool hasGradient;
+ Gradient gradientType;
+
SkXfermode::Mode shadersMode;
+
bool isBitmapFirst;
GLenum bitmapWrapS;
GLenum bitmapWrapT;
@@ -152,7 +159,8 @@ struct ProgramDescription {
}
}
if (hasGradient) key |= PROGRAM_KEY_GRADIENT;
- if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
+ key |= programid(gradientType) << PROGRAM_GRADIENT_TYPE_SHIFT;
+ if (isBitmapFirst) key |= PROGRAM_KEY_BITMAP_FIRST;
if (hasBitmap && hasGradient) {
key |= (shadersMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_SHADER_SHIFT;
}
@@ -174,6 +182,12 @@ struct ProgramDescription {
if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
return key;
}
+
+ void log(const char* message) const {
+ programid k = key();
+ PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32),
+ uint32_t(k & 0xffffffff));
+ }
}; // struct ProgramDescription
/**
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 946cc4b..9e1f6c2 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -164,6 +164,7 @@ SkiaLinearGradientShader::~SkiaLinearGradientShader() {
void SkiaLinearGradientShader::describe(ProgramDescription& description,
const Extensions& extensions) {
description.hasGradient = true;
+ description.gradientType = ProgramDescription::kGradientLinear;
}
void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
@@ -173,8 +174,7 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV
Texture* texture = mGradientCache->get(mKey);
if (!texture) {
- texture = mGradientCache->addLinearGradient(mKey, mBounds, mColors, mPositions,
- mCount, mTileX);
+ texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount, mTileX);
}
Rect start(mBounds[0], mBounds[1], mBounds[2], mBounds[3]);
@@ -209,6 +209,101 @@ void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& mo
}
///////////////////////////////////////////////////////////////////////////////
+// Circular gradient shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
+ uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+ SkMatrix* matrix, bool blend):
+ SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
+ tileMode, matrix, blend),
+ mRadius(radius) {
+}
+
+void SkiaCircularGradientShader::describe(ProgramDescription& description,
+ const Extensions& extensions) {
+ description.hasGradient = true;
+ description.gradientType = ProgramDescription::kGradientCircular;
+}
+
+void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
+ const Snapshot& snapshot, GLuint* textureUnit) {
+ SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
+ glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Sweep gradient shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
+ float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
+ SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode, matrix, blend),
+ mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
+}
+
+SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
+ float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+ SkMatrix* matrix, bool blend):
+ SkiaShader(type, key, tileMode, tileMode, matrix, blend),
+ mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
+}
+
+SkiaSweepGradientShader::~SkiaSweepGradientShader() {
+ delete[] mColors;
+ delete[] mPositions;
+}
+
+void SkiaSweepGradientShader::describe(ProgramDescription& description,
+ const Extensions& extensions) {
+ description.hasGradient = true;
+ description.gradientType = ProgramDescription::kGradientSweep;
+}
+
+void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
+ const Snapshot& snapshot, GLuint* textureUnit) {
+ GLuint textureSlot = (*textureUnit)++;
+ glActiveTexture(gTextureUnitsMap[textureSlot]);
+
+ Texture* texture = mGradientCache->get(mKey);
+ if (!texture) {
+ texture = mGradientCache->addLinearGradient(mKey, mColors, mPositions, mCount);
+ }
+
+ float left = mX;
+ float top = mY;
+
+ mat4 shaderMatrix;
+ if (mMatrix) {
+ shaderMatrix.load(*mMatrix);
+ shaderMatrix.mapPoint(left, top);
+ }
+
+ mat4 copy(shaderMatrix);
+ shaderMatrix.loadInverse(copy);
+
+ snapshot.transform->mapPoint(left, top);
+
+ mat4 screenSpace(*snapshot.transform);
+ screenSpace.multiply(modelView);
+
+ // Uniforms
+ bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
+ glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+ glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
+ glUniform2f(program->getUniform("gradientStart"), left, top);
+ glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
+}
+
+void SkiaSweepGradientShader::updateTransforms(Program* program, const mat4& modelView,
+ const Snapshot& snapshot) {
+ mat4 screenSpace(*snapshot.transform);
+ screenSpace.multiply(modelView);
+ glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
+}
+
+///////////////////////////////////////////////////////////////////////////////
// Compose shader
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index cc94ae6..0023c46 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -145,6 +145,44 @@ private:
}; // struct SkiaLinearGradientShader
/**
+ * A shader that draws a sweep gradient.
+ */
+struct SkiaSweepGradientShader: public SkiaShader {
+ SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count,
+ SkShader* key, SkMatrix* matrix, bool blend);
+ ~SkiaSweepGradientShader();
+
+ virtual void describe(ProgramDescription& description, const Extensions& extensions);
+ virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+ GLuint* textureUnit);
+ void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
+
+protected:
+ SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
+ int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
+ float mX, mY;
+ uint32_t* mColors;
+ float* mPositions;
+ int mCount;
+}; // struct SkiaSweepGradientShader
+
+/**
+ * A shader that draws a circular gradient.
+ */
+struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
+ SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions,
+ int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
+ void describe(ProgramDescription& description, const Extensions& extensions);
+ void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+ GLuint* textureUnit);
+
+private:
+ float mRadius;
+}; // struct SkiaCircularGradientShader
+
+/**
* A shader that draws two shaders, composited with an xfermode.
*/
struct SkiaComposeShader: public SkiaShader {
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index 6645372..cf9c6be 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -38,33 +38,21 @@ public class RSTestCore {
return true;
}
- //private ScriptC_Fountain mScript;
+ private boolean rs_primitives_test() {
+ ScriptC_primitives s = new ScriptC_primitives(mRS, mRes, R.raw.primitives, true);
+ s.invoke_rs_primitives_test(0, 0);
+ return true;
+ }
+
public void init(RenderScriptGL rs, Resources res, int width, int height) {
mRS = rs;
mRes = res;
mRootScript = new ScriptC_test_root(mRS, mRes, R.raw.test_root, true);
+ rs_primitives_test();
fp_mad();
-
- /*
- ProgramFragment.Builder pfb = new ProgramFragment.Builder(rs);
- pfb.setVaryingColor(true);
- rs.contextBindProgramFragment(pfb.create());
-
- ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);
-
- Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
- smb.addVertexAllocation(points.getAllocation());
- smb.addIndexType(Primitive.POINT);
- Mesh sm = smb.create();
-
- mScript = new ScriptC_Fountain(mRS, mRes, R.raw.fountain, true);
- mScript.set_partMesh(sm);
- mScript.bind_point(points);
- mRS.contextBindRootScript(mScript);
- */
}
public void newTouchPosition(float x, float y, float pressure, int id) {
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
new file mode 100644
index 0000000..39bd2c4
--- /dev/null
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -0,0 +1,44 @@
+#include "shared.rsh"
+
+#pragma rs export_func(rs_primitives_test)
+
+// Testing primitive types
+#pragma rs export_var(floatTest)
+#pragma rs export_var(doubleTest)
+static float floatTest = 1.99f;
+static double doubleTest = 2.05;
+static char charTest = -8;
+static short shortTest = -16;
+static int intTest = -32;
+static uchar ucharTest = 8;
+static ushort ushortTest = 16;
+static uint uintTest = 32;
+
+static void test_primitive_types(uint32_t index) {
+ bool failed = false;
+ start();
+
+ _RS_ASSERT(floatTest == 1.99f);
+ _RS_ASSERT(doubleTest == 2.05);
+ _RS_ASSERT(charTest == -8);
+ _RS_ASSERT(shortTest == -16);
+ _RS_ASSERT(intTest == -32);
+ _RS_ASSERT(ucharTest == 8);
+ _RS_ASSERT(ushortTest == 16);
+ _RS_ASSERT(uintTest == 32);
+
+ float time = end(index);
+ if (failed) {
+ rsDebug("test_primitives FAILED ", time);
+ }
+ else {
+ rsDebug("test_primitives PASSED ", time);
+ }
+}
+
+
+void rs_primitives_test(uint32_t index, int test_num) {
+ test_primitive_types(index);
+}
+
+
diff --git a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
index 1773e47..8c3e5f4 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
+++ b/libs/rs/java/tests/src/com/android/rs/test/shared.rsh
@@ -23,3 +23,13 @@ static float end(uint32_t idx) {
return ((float)t) / 1000.f;
}
+#define _RS_ASSERT(b) \
+do { \
+ rsDebug("Checking " #b, ((int) (b))); \
+ if (!(b)) { \
+ failed = true; \
+ rsDebug(#b " FAILED", 0); \
+ } \
+\
+} while (0)
+
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index c7fb2af..31d70c7 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -338,6 +338,12 @@ ScriptSetVarF {
param float value
}
+ScriptSetVarD {
+ param RsScript s
+ param uint32_t slot
+ param double value
+ }
+
ScriptSetVarV {
param RsScript s
param uint32_t slot
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index fc22fc3..43bb09e 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -101,6 +101,12 @@ void rsi_ScriptSetVarF(Context *rsc, RsScript vs, uint32_t slot, float value)
s->setVar(slot, &value, sizeof(value));
}
+void rsi_ScriptSetVarD(Context *rsc, RsScript vs, uint32_t slot, double value)
+{
+ Script *s = static_cast<Script *>(vs);
+ s->setVar(slot, &value, sizeof(value));
+}
+
void rsi_ScriptSetVarV(Context *rsc, RsScript vs, uint32_t slot, const void *data, uint32_t len)
{
const float *fp = (const float *)data;
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index b46279e..d2dd6eb 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -24,16 +24,15 @@
namespace android {
-static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
-static pthread_key_t gTLS = 0;
-
// Hint for number of file descriptors to be associated with the epoll instance.
static const int EPOLL_SIZE_HINT = 8;
// Maximum number of file descriptors for which to retrieve poll events each iteration.
static const int EPOLL_MAX_EVENTS = 16;
+static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
+static pthread_key_t gTLSKey = 0;
+
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks),
mResponseIndex(0) {
@@ -56,6 +55,7 @@ Looper::Looper(bool allowNonCallbacks) :
errno);
struct epoll_event eventItem;
+ memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
@@ -69,6 +69,11 @@ Looper::~Looper() {
close(mEpollFd);
}
+void Looper::initTLSKey() {
+ int result = pthread_key_create(& gTLSKey, threadDestructor);
+ LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
+}
+
void Looper::threadDestructor(void *st) {
Looper* const self = static_cast<Looper*>(st);
if (self != NULL) {
@@ -83,7 +88,7 @@ void Looper::setForThread(const sp<Looper>& looper) {
looper->incStrong((void*)threadDestructor);
}
- pthread_setspecific(gTLS, looper.get());
+ pthread_setspecific(gTLSKey, looper.get());
if (old != NULL) {
old->decStrong((void*)threadDestructor);
@@ -91,17 +96,10 @@ void Looper::setForThread(const sp<Looper>& looper) {
}
sp<Looper> Looper::getForThread() {
- if (!gHaveTLS) {
- pthread_mutex_lock(&gTLSMutex);
- if (pthread_key_create(&gTLS, threadDestructor) != 0) {
- pthread_mutex_unlock(&gTLSMutex);
- return NULL;
- }
- gHaveTLS = true;
- pthread_mutex_unlock(&gTLSMutex);
- }
+ int result = pthread_once(& gTLSOnce, initTLSKey);
+ LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
- return (Looper*)pthread_getspecific(gTLS);
+ return (Looper*)pthread_getspecific(gTLSKey);
}
sp<Looper> Looper::prepare(int opts) {
@@ -331,6 +329,7 @@ int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback,
request.data = data;
struct epoll_event eventItem;
+ memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java
index 546bb9d..ac7eb8b 100644
--- a/location/java/android/location/Geocoder.java
+++ b/location/java/android/location/Geocoder.java
@@ -41,7 +41,7 @@ import java.util.List;
* The Geocoder class requires a backend service that is not included in
* the core android framework. The Geocoder query methods will return an
* empty list if there no backend service in the platform. Use the
- * isImplemented() method to determine whether a Geocoder implementation
+ * isPresent() method to determine whether a Geocoder implementation
* exists.
*/
public final class Geocoder {
@@ -56,13 +56,13 @@ public final class Geocoder {
* connectivity may still cause these methods to return null or
* empty lists.
*/
- public static Boolean isImplemented() {
+ public static boolean isPresent() {
IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
ILocationManager lm = ILocationManager.Stub.asInterface(b);
try {
- return lm.geocoderIsImplemented();
+ return lm.geocoderIsPresent();
} catch (RemoteException e) {
- Log.e(TAG, "isImplemented: got RemoteException", e);
+ Log.e(TAG, "isPresent: got RemoteException", e);
return false;
}
}
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 8b8e63b..174fe3e 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -29,6 +29,8 @@ import java.util.Locale;
* as well as the Geocoder client's package name for geocoder server
* logging. This information is kept in a separate class to allow for
* future expansion of the IGeocodeProvider interface.
+ *
+ * @hide
*/
public class GeocoderParams implements Parcelable {
private Locale mLocale;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 32d4b27..2255bf2 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -67,7 +67,7 @@ interface ILocationManager
// it need not be shared with other providers.
void reportLocation(in Location location, boolean passive);
- boolean geocoderIsImplemented();
+ boolean geocoderIsPresent();
String getFromLocation(double latitude, double longitude, int maxResults,
in GeocoderParams params, out List<Address> addrs);
String getFromLocationName(String locationName,
diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/java/android/location/provider/GeocodeProvider.java
index 9a58763..493c631 100644
--- a/location/java/android/location/provider/GeocodeProvider.java
+++ b/location/java/android/location/provider/GeocodeProvider.java
@@ -29,6 +29,8 @@ import java.util.List;
* outside of the core android platform.
* Geocode providers can be implemented as services and return the result of
* {@link GeocodeProvider#getBinder()} in its getBinder() method.
+ *
+ * @hide
*/
public abstract class GeocodeProvider {
diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java
index 95b4425..14dea14 100644
--- a/location/java/android/location/provider/LocationProvider.java
+++ b/location/java/android/location/provider/LocationProvider.java
@@ -34,6 +34,8 @@ import android.util.Log;
* outside of the core android platform.
* Location providers can be implemented as services and return the result of
* {@link LocationProvider#getBinder()} in its getBinder() method.
+ *
+ * @hide
*/
public abstract class LocationProvider {
diff --git a/media/java/android/media/AudioEffect.java b/media/java/android/media/AudioEffect.java
index ae67114..ed7601e 100644
--- a/media/java/android/media/AudioEffect.java
+++ b/media/java/android/media/AudioEffect.java
@@ -847,39 +847,40 @@ public class AudioEffect {
// -------------------------------------------------------------------------
/**
- * This intent launches an audio effect control panel UI. The goal of this intent is to enable
- * separate implementations of music/media player applications and audio effect control
- * application or services. This will allow platform vendors to offer more advanced control
- * options for standard effects or control for platform specific effects.
+ * Intent to launch an audio effect control panel UI.
+ * <p>The goal of this intent is to enable separate implementations of music/media player
+ * applications and audio effect control application or services.
+ * This will allow platform vendors to offer more advanced control options for standard effects
+ * or control for platform specific effects.
* <p>The intent carries a number of extras used by the player application to communicate
* necessary pieces of information to the control panel application.
* <p>The calling application must use the
* {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the
* control panel so that its package name is indicated and used by the control panel
* application to keep track of changes for this particular application.
- * <p>The android.media.EXTRA_AUDIO_SESSION extra will indicate an audio session to which the
+ * <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the
* audio effects should be applied. If no audio session is specified, either one of the
* follownig will happen:
- * - If an audio session was previously opened by the calling application with
+ * <p>- If an audio session was previously opened by the calling application with
* {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will
* be applied to that session.
- * - If no audio session is opened, the changes will be stored in the package specific storage
- * area and applied whenever a new audio session is opened by this application.
- * <p>The android.media.EXTRA_CONTENT_TYPE extra will help the control panel application
+ * <p>- If no audio session is opened, the changes will be stored in the package specific
+ * storage area and applied whenever a new audio session is opened by this application.
+ * <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application
* customize both the UI layout and the default audio effect settings if none are already
* stored for the calling application.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL =
"android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";
/**
- * This intent indicates to the effect control application or service that a new audio session
- * is opened and requires audio effects to be applied. This is different from
- * {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no UI should be displayed in
- * this case. Music player applications can broadcast this intent before starting playback
- * to make sure that any audio effect settings previously selected by the user are applied.
+ * Intent to signal to the effect control application or service that a new audio session
+ * is opened and requires audio effects to be applied.
+ * <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no
+ * UI should be displayed in this case. Music player applications can broadcast this intent
+ * before starting playback to make sure that any audio effect settings previously selected
+ * by the user are applied.
* <p>The effect control application receiving this intent will look for previously stored
* settings for the calling application, create all required audio effects and apply the
* effect settings to the specified audio session.
@@ -888,48 +889,50 @@ public class AudioEffect {
* <p>If no stored settings are found for the calling application, default settings for the
* content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings
* for a given content type are platform specific.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
/**
- * This intent indicates to the effect control application or service that an audio session
+ * Intent to signal to the effect control application or service that an audio session
* is closed and that effects should not be applied anymore.
- * <p>The effect control application receiving this intent will delete all effects on this
- * session and store current settings in package specific storage.
+ * <p>The effect control application receiving this intent will delete all effects on
+ * this session and store current settings in package specific storage.
* <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
* audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
* <p>It is good practice for applications to broadcast this intent when music playback stops
* and/or when exiting to free system resources consumed by audio effect engines.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
/**
- * This extra indicates the ID of the audio session the effects should be applied to.
+ * Contains the ID of the audio session the effects should be applied to.
+ * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL},
+ * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
+ * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
* <p>The extra value is of type int and is the audio session ID.
- * @see android.media.MediaPlayer#setAudioSessionId(int) for details on audio sessions.
- * {@hide} pending API council approval
+ *
+ * @see android.media.MediaPlayer#setAudioSessionId(int)
*/
public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
/**
- * This extra indicates the package name of the calling application for
- * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
+ * Contains the package name of the calling application.
+ * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
* {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
* <p>The extra value is a string containing the full package name.
- * {@hide} pending API council approval
*/
public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
/**
- * This extra indicates which type of content is played by the application. This information is
- * used by the effect control application to customize UI and default effect settings.
- * The content type is one of the following:
+ * Indicates which type of content is played by the application.
+ * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and
+ * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents.
+ * <p>This information is used by the effect control application to customize UI and select
+ * appropriate default effect settings. The content type is one of the following:
* <ul>
* <li>{@link #CONTENT_TYPE_MUSIC}</li>
* <li>{@link #CONTENT_TYPE_MOVIE}</li>
@@ -937,28 +940,23 @@ public class AudioEffect {
* <li>{@link #CONTENT_TYPE_VOICE}</li>
* </ul>
* If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}.
- * {@hide} pending API council approval
*/
public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_MUSIC = 0;
/**
- * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video of movie
- * {@hide} pending API council approval
+ * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie
*/
public static final int CONTENT_TYPE_MOVIE = 1;
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_GAME = 2;
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_VOICE = 3;
diff --git a/media/java/android/media/MtpClient.java b/media/java/android/media/MtpClient.java
index f7c0ce2..98da1f6 100644
--- a/media/java/android/media/MtpClient.java
+++ b/media/java/android/media/MtpClient.java
@@ -57,20 +57,20 @@ public class MtpClient {
native_stop();
}
- public boolean deleteObject(int deviceID, int objectID) {
+ public boolean deleteObject(int deviceID, long objectID) {
return native_delete_object(deviceID, objectID);
}
- public int getParent(int deviceID, int objectID) {
+ public long getParent(int deviceID, long objectID) {
return native_get_parent(deviceID, objectID);
}
- public int getStorageID(int deviceID, int objectID) {
+ public long getStorageID(int deviceID, long objectID) {
return native_get_storage_id(deviceID, objectID);
}
// create a file descriptor for reading the contents of an object over MTP
- public ParcelFileDescriptor openFile(int deviceID, int objectID) {
+ public ParcelFileDescriptor openFile(int deviceID, long objectID) {
return native_open_file(deviceID, objectID);
}
@@ -101,8 +101,8 @@ public class MtpClient {
private native final void native_finalize();
private native boolean native_start();
private native void native_stop();
- private native boolean native_delete_object(int deviceID, int objectID);
- private native int native_get_parent(int deviceID, int objectID);
- private native int native_get_storage_id(int deviceID, int objectID);
- private native ParcelFileDescriptor native_open_file(int deviceID, int objectID);
+ private native boolean native_delete_object(int deviceID, long objectID);
+ private native long native_get_parent(int deviceID, long objectID);
+ private native long native_get_storage_id(int deviceID, long objectID);
+ private native ParcelFileDescriptor native_open_file(int deviceID, long objectID);
}
diff --git a/media/java/android/media/MtpCursor.java b/media/java/android/media/MtpCursor.java
index d4142d8..b9dd03e 100644
--- a/media/java/android/media/MtpCursor.java
+++ b/media/java/android/media/MtpCursor.java
@@ -43,8 +43,8 @@ public final class MtpCursor extends AbstractWindowedCursor {
private int mQueryType;
private int mDeviceID;
- private int mStorageID;
- private int mQbjectID;
+ private long mStorageID;
+ private long mQbjectID;
/** The names of the columns in the projection */
private String[] mColumns;
@@ -54,7 +54,7 @@ public final class MtpCursor extends AbstractWindowedCursor {
private final MtpClient mClient;
- public MtpCursor(MtpClient client, int queryType, int deviceID, int storageID, int objectID,
+ public MtpCursor(MtpClient client, int queryType, int deviceID, long storageID, long objectID,
String[] projection) {
mClient = client;
@@ -220,7 +220,7 @@ public final class MtpCursor extends AbstractWindowedCursor {
private int mNativeContext;
private native final void native_setup(MtpClient client, int queryType,
- int deviceID, int storageID, int objectID, int[] columns);
+ int deviceID, long storageID, long objectID, int[] columns);
private native final void native_finalize();
private native void native_wait_for_event();
private native int native_fill_window(CursorWindow window, int startPos);
diff --git a/media/java/android/media/Visualizer.java b/media/java/android/media/Visualizer.java
index 453fc04..33222ff 100755
--- a/media/java/android/media/Visualizer.java
+++ b/media/java/android/media/Visualizer.java
@@ -218,13 +218,16 @@ public class Visualizer {
public int setEnabled(boolean enabled)
throws IllegalStateException {
synchronized (mStateLock) {
- if ((enabled && mState != STATE_INITIALIZED) ||
- (!enabled && mState != STATE_ENABLED)) {
+ if (mState == STATE_UNINITIALIZED) {
throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
}
- int status = native_setEnabled(enabled);
- if (status == SUCCESS) {
- mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+ int status = SUCCESS;
+ if ((enabled && (mState == STATE_INITIALIZED)) ||
+ (!enabled && (mState == STATE_ENABLED))) {
+ status = native_setEnabled(enabled);
+ if (status == SUCCESS) {
+ mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+ }
}
return status;
}
diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java
index e4bc9a4..eb71285 100755
--- a/media/java/android/media/videoeditor/Transition.java
+++ b/media/java/android/media/videoeditor/Transition.java
@@ -34,6 +34,7 @@ import java.io.File;
*/
public abstract class Transition {
// The transition behavior
+ private static final int BEHAVIOR_MIN_VALUE = 0;
/** The transition starts slowly and speed up */
public static final int BEHAVIOR_SPEED_UP = 0;
/** The transition start fast and speed down */
@@ -45,6 +46,8 @@ public abstract class Transition {
/** The transition starts slowly and ends slowly with a fast middle */
public static final int BEHAVIOR_MIDDLE_FAST = 4;
+ private static final int BEHAVIOR_MAX_VALUE = 4;
+
// The unique id of the transition
private final String mUniqueId;
@@ -84,6 +87,9 @@ public abstract class Transition {
*/
protected Transition(String transitionId, MediaItem afterMediaItem, MediaItem beforeMediaItem,
long durationMs, int behavior) {
+ if (behavior < BEHAVIOR_MIN_VALUE || behavior > BEHAVIOR_MAX_VALUE) {
+ throw new IllegalArgumentException("Invalid behavior: " + behavior);
+ }
mUniqueId = transitionId;
mAfterMediaItem = afterMediaItem;
mBeforeMediaItem = beforeMediaItem;
diff --git a/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java b/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java
index 0bf4ff2..b1c6bb5 100644
--- a/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java
+++ b/media/java/android/media/videoeditor/TransitionEndCurtainClosing.java
@@ -28,7 +28,7 @@ public class TransitionEndCurtainClosing extends Transition {
*/
@SuppressWarnings("unused")
private TransitionEndCurtainClosing() {
- this(null, null, 0);
+ this(null, null, 0, BEHAVIOR_LINEAR);
}
/**
@@ -38,10 +38,11 @@ public class TransitionEndCurtainClosing extends Transition {
* @param afterMediaItem The transition is applied to the end of this
* media item
* @param durationMs duration of the transition in milliseconds
+ * @param behavior The transition behavior
*/
public TransitionEndCurtainClosing(String transitionId, MediaItem afterMediaItem,
- long duration) {
- super(transitionId, afterMediaItem, null, duration, Transition.BEHAVIOR_LINEAR);
+ long duration, int behavior) {
+ super(transitionId, afterMediaItem, null, duration, behavior);
}
/*
diff --git a/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java b/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java
index 752532c..5f913fc 100755
--- a/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java
+++ b/media/java/android/media/videoeditor/TransitionEndFadeToBlack.java
@@ -28,7 +28,7 @@ public class TransitionEndFadeToBlack extends Transition {
*/
@SuppressWarnings("unused")
private TransitionEndFadeToBlack() {
- this(null, null, 0);
+ this(null, null, 0, BEHAVIOR_LINEAR);
}
/**
@@ -38,9 +38,11 @@ public class TransitionEndFadeToBlack extends Transition {
* @param afterMediaItem The transition is applied to the end of this
* media item
* @param durationMs duration of the transition in milliseconds
+ * @param behavior The transition behavior
*/
- public TransitionEndFadeToBlack(String transitionId, MediaItem afterMediaItem, long duration) {
- super(transitionId, afterMediaItem, null, duration, Transition.BEHAVIOR_LINEAR);
+ public TransitionEndFadeToBlack(String transitionId, MediaItem afterMediaItem, long duration,
+ int behavior) {
+ super(transitionId, afterMediaItem, null, duration, behavior);
}
/*
diff --git a/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java b/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java
index 5f03e0e..b787b32 100755
--- a/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java
+++ b/media/java/android/media/videoeditor/TransitionStartCurtainOpening.java
@@ -30,7 +30,7 @@ public class TransitionStartCurtainOpening extends Transition {
*/
@SuppressWarnings("unused")
private TransitionStartCurtainOpening() {
- this(null, null, 0);
+ this(null, null, 0, Transition.BEHAVIOR_LINEAR);
}
/**
@@ -40,11 +40,11 @@ public class TransitionStartCurtainOpening extends Transition {
* @param beforeMediaItem The transition is applied to the beginning of
* this media item
* @param durationMs The duration of the transition in milliseconds
+ * @param behavior The transition behavior
*/
public TransitionStartCurtainOpening(String transitionId, MediaItem beforeMediaItem,
- long durationMs) {
- super(transitionId, null, beforeMediaItem, durationMs,
- Transition.BEHAVIOR_LINEAR);
+ long durationMs, int behavior) {
+ super(transitionId, null, beforeMediaItem, durationMs, behavior);
}
/*
diff --git a/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java b/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java
index 08fd8bf..be993a5 100644
--- a/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java
+++ b/media/java/android/media/videoeditor/TransitionStartFadeFromBlack.java
@@ -28,7 +28,7 @@ public class TransitionStartFadeFromBlack extends Transition {
*/
@SuppressWarnings("unused")
private TransitionStartFadeFromBlack() {
- this(null, null, 0);
+ this(null, null, 0, Transition.BEHAVIOR_LINEAR);
}
/**
@@ -38,11 +38,11 @@ public class TransitionStartFadeFromBlack extends Transition {
* @param beforeMediaItem The transition is applied to the beginning of
* this media item
* @param durationMs The duration of the transition in milliseconds
+ * @param behavior The transition behavior
*/
public TransitionStartFadeFromBlack(String transitionId, MediaItem beforeMediaItem,
- long durationMs) {
- super(transitionId, null, beforeMediaItem, durationMs,
- Transition.BEHAVIOR_LINEAR);
+ long durationMs, int behavior) {
+ super(transitionId, null, beforeMediaItem, durationMs, behavior);
}
/*
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index e8cc776..14e2658 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -35,8 +35,7 @@ import android.util.Xml;
import android.view.SurfaceHolder;
/**
- * The VideoEditor implementation
- * {@hide}
+ * The VideoEditor implementation {@hide}
*/
public class VideoEditorTestImpl implements VideoEditor {
// Logging
@@ -49,6 +48,8 @@ public class VideoEditorTestImpl implements VideoEditor {
private static final String TAG_PROJECT = "project";
private static final String TAG_MEDIA_ITEMS = "media_items";
private static final String TAG_MEDIA_ITEM = "media_item";
+ private static final String TAG_BEGIN_TRANSITION = "begin_transition";
+ private static final String TAG_END_TRANSITION = "end_transition";
private static final String ATTR_ID = "id";
private static final String ATTR_FILENAME = "filename";
private static final String ATTR_AUDIO_WAVEFORM_FILENAME = "wavefoem";
@@ -59,8 +60,14 @@ public class VideoEditorTestImpl implements VideoEditor {
private static final String ATTR_BEGIN_TIME = "start_time";
private static final String ATTR_END_TIME = "end_time";
private static final String ATTR_VOLUME = "volume";
-
- private static long mDurationMs;
+ private static final String ATTR_BEHAVIOR = "behavior";
+ private static final String ATTR_DIRECTION = "direction";
+ private static final String ATTR_BLENDING = "blending";
+ private static final String ATTR_INVERT = "invert";
+ private static final String ATTR_MASK = "mask";
+
+ // Instance variables
+ private long mDurationMs;
private final String mProjectPath;
private final List<MediaItem> mMediaItems = new ArrayList<MediaItem>();
private final List<AudioTrack> mAudioTracks = new ArrayList<AudioTrack>();
@@ -74,6 +81,8 @@ public class VideoEditorTestImpl implements VideoEditor {
private class PreviewThread extends Thread {
// Instance variables
private final static long FRAME_DURATION = 33;
+
+ // Instance variables
private final PreviewProgressListener mListener;
private final int mCallbackAfterFrameCount;
private final long mFromMs, mToMs;
@@ -85,10 +94,12 @@ public class VideoEditorTestImpl implements VideoEditor {
*
* @param fromMs Start preview at this position
* @param toMs The time (relative to the timeline) at which the preview
- * will stop. Use -1 to play to the end of the timeline
- * @param callbackAfterFrameCount The listener interface should be invoked
- * after the number of frames specified by this parameter.
- * @param loop true if the preview should be looped once it reaches the end
+ * will stop. Use -1 to play to the end of the timeline
+ * @param callbackAfterFrameCount The listener interface should be
+ * invoked after the number of frames specified by this
+ * parameter.
+ * @param loop true if the preview should be looped once it reaches the
+ * end
* @param listener The listener
*/
public PreviewThread(long fromMs, long toMs, boolean loop, int callbackAfterFrameCount,
@@ -217,7 +228,15 @@ public class VideoEditorTestImpl implements VideoEditor {
throw new IllegalArgumentException("Media item already exists: " + mediaItem.getId());
}
+ // Invalidate the end transition if necessary
+ final int mediaItemsCount = mMediaItems.size();
+ if ( mediaItemsCount > 0) {
+ removeTransitionAfter(mediaItemsCount - 1);
+ }
+
+ // Add the new media item
mMediaItems.add(mediaItem);
+
computeTimelineDuration();
}
@@ -235,9 +254,8 @@ public class VideoEditorTestImpl implements VideoEditor {
if (afterMediaItemId == null) {
if (mMediaItems.size() > 0) {
- final MediaItem mi = mMediaItems.get(0);
// Invalidate the transition at the beginning of the timeline
- removeTransitionBefore(mi);
+ removeTransitionBefore(0);
}
mMediaItems.add(0, mediaItem);
computeTimelineDuration();
@@ -247,9 +265,9 @@ public class VideoEditorTestImpl implements VideoEditor {
final MediaItem mi = mMediaItems.get(i);
if (mi.getId().equals(afterMediaItemId)) {
// Invalidate the transition at this position
- removeTransitionAfter(mi);
+ removeTransitionAfter(i);
// Insert the new media item
- mMediaItems.add(i+1, mediaItem);
+ mMediaItems.add(i + 1, mediaItem);
computeTimelineDuration();
return;
}
@@ -273,9 +291,9 @@ public class VideoEditorTestImpl implements VideoEditor {
if (afterMediaItemId == null) {
if (mMediaItems.size() > 0) {
- final MediaItem mi = mMediaItems.get(0);
// Invalidate adjacent transitions at the insertion point
- removeTransitionBefore(mi);
+ removeTransitionBefore(0);
+
// Insert the media item at the new position
mMediaItems.add(0, moveMediaItem);
computeTimelineDuration();
@@ -288,9 +306,9 @@ public class VideoEditorTestImpl implements VideoEditor {
final MediaItem mi = mMediaItems.get(i);
if (mi.getId().equals(afterMediaItemId)) {
// Invalidate adjacent transitions at the insertion point
- removeTransitionAfter(mi);
+ removeTransitionAfter(i);
// Insert the media item at the new position
- mMediaItems.add(i+1, moveMediaItem);
+ mMediaItems.add(i + 1, moveMediaItem);
computeTimelineDuration();
return;
}
@@ -359,28 +377,27 @@ public class VideoEditorTestImpl implements VideoEditor {
* {@inheritDoc}
*/
public synchronized void addTransition(Transition transition) {
- // If a transition already exists at the specified position then
- // invalidate it.
- final Iterator<Transition> it = mTransitions.iterator();
- while (it.hasNext()) {
- final Transition t = it.next();
- if (t.getAfterMediaItem() == transition.getAfterMediaItem()
- || t.getBeforeMediaItem() == transition.getBeforeMediaItem()) {
- it.remove();
- t.invalidate();
- break;
- }
- }
-
mTransitions.add(transition);
- // Cross reference the transitions
+ final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
final MediaItem afterMediaItem = transition.getAfterMediaItem();
+
+ // Cross reference the transitions
if (afterMediaItem != null) {
+ // If a transition already exists at the specified position then
+ // invalidate it.
+ if (afterMediaItem.getEndTransition() != null) {
+ afterMediaItem.getEndTransition().invalidate();
+ }
afterMediaItem.setEndTransition(transition);
}
- final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
+
if (beforeMediaItem != null) {
+ // If a transition already exists at the specified position then
+ // invalidate it.
+ if (beforeMediaItem.getBeginTransition() != null) {
+ beforeMediaItem.getBeginTransition().invalidate();
+ }
beforeMediaItem.setBeginTransition(transition);
}
computeTimelineDuration();
@@ -460,7 +477,7 @@ public class VideoEditorTestImpl implements VideoEditor {
for (int i = 0; i < audioTrackCount; i++) {
AudioTrack at = mAudioTracks.get(i);
if (at.getId().equals(afterAudioTrackId)) {
- mAudioTracks.add(i+1, audioTrack);
+ mAudioTracks.add(i + 1, audioTrack);
return;
}
}
@@ -526,24 +543,67 @@ public class VideoEditorTestImpl implements VideoEditor {
serializer.startTag("", TAG_PROJECT);
serializer.attribute("", ATTR_ASPECT_RATIO, Integer.toString(mAspectRatio));
+ boolean firstMediaItem = true;
serializer.startTag("", TAG_MEDIA_ITEMS);
for (MediaItem mediaItem : mMediaItems) {
serializer.startTag("", TAG_MEDIA_ITEM);
serializer.attribute("", ATTR_ID, mediaItem.getId());
serializer.attribute("", ATTR_TYPE, mediaItem.getClass().getSimpleName());
serializer.attribute("", ATTR_FILENAME, mediaItem.getFilename());
- serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(mediaItem.getRenderingMode()));
+ serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(mediaItem
+ .getRenderingMode()));
if (mediaItem instanceof MediaVideoItem) {
final MediaVideoItem mvi = (MediaVideoItem)mediaItem;
- serializer.attribute("", ATTR_BEGIN_TIME, Long.toString(mvi.getBoundaryBeginTime()));
+ serializer
+ .attribute("", ATTR_BEGIN_TIME, Long.toString(mvi.getBoundaryBeginTime()));
serializer.attribute("", ATTR_END_TIME, Long.toString(mvi.getBoundaryEndTime()));
serializer.attribute("", ATTR_VOLUME, Integer.toString(mvi.getVolume()));
if (mvi.getAudioWaveformFilename() != null) {
- serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME, mvi.getAudioWaveformFilename());
+ serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME, mvi
+ .getAudioWaveformFilename());
}
} else if (mediaItem instanceof MediaImageItem) {
serializer.attribute("", ATTR_DURATION, Long.toString(mediaItem.getDuration()));
}
+
+ if (firstMediaItem) {
+ firstMediaItem = false;
+ final Transition beginTransition = mediaItem.getBeginTransition();
+ if (beginTransition != null) {
+ serializer.startTag("", TAG_BEGIN_TRANSITION);
+ serializer.attribute("", ATTR_ID, beginTransition.getId());
+ serializer.attribute("", ATTR_TYPE, beginTransition.getClass()
+ .getSimpleName());
+ serializer.attribute("", ATTR_DURATION, Long.toString(beginTransition
+ .getDuration()));
+ serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(beginTransition
+ .getBehavior()));
+ serializer.endTag("", TAG_BEGIN_TRANSITION);
+ }
+ }
+
+ final Transition endTransition = mediaItem.getEndTransition();
+ if (endTransition != null) {
+ serializer.startTag("", TAG_END_TRANSITION);
+ serializer.attribute("", ATTR_ID, endTransition.getId());
+ serializer.attribute("", ATTR_TYPE, endTransition.getClass().getSimpleName());
+ serializer.attribute("", ATTR_DURATION, Long.toString(endTransition
+ .getDuration()));
+ serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(endTransition
+ .getBehavior()));
+ if (endTransition instanceof TransitionSliding) {
+ serializer.attribute("", ATTR_DIRECTION, Integer
+ .toString(((TransitionSliding)endTransition).getDirection()));
+ } else if (endTransition instanceof TransitionAlpha) {
+ TransitionAlpha ta = (TransitionAlpha)endTransition;
+ serializer.attribute("", ATTR_BLENDING, Integer.toString(ta
+ .getBlendingPercent()));
+ serializer.attribute("", ATTR_INVERT, Boolean.toString(ta.isInvert()));
+ serializer.attribute("", ATTR_MASK, ta.getMaskFilename());
+ }
+ serializer.endTag("", TAG_END_TRANSITION);
+ }
+
serializer.endTag("", TAG_MEDIA_ITEM);
}
serializer.endTag("", TAG_MEDIA_ITEMS);
@@ -568,6 +628,8 @@ public class VideoEditorTestImpl implements VideoEditor {
parser.setInput(new FileInputStream(file), "UTF-8");
int eventType = parser.getEventType();
String name;
+ MediaItem currentMediaItem = null;
+ MediaItem previousMediaItem = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
@@ -579,27 +641,59 @@ public class VideoEditorTestImpl implements VideoEditor {
final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
final String type = parser.getAttributeValue("", ATTR_TYPE);
final String filename = parser.getAttributeValue("", ATTR_FILENAME);
- final int renderingMode = Integer.parseInt(parser.getAttributeValue("", ATTR_RENDERING_MODE));
- final MediaItem mediaItem;
+ final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
+ ATTR_RENDERING_MODE));
+
if (MediaImageItem.class.getSimpleName().equals(type)) {
- final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
- mediaItem = new MediaImageItem(mediaItemId, filename, durationMs,
- renderingMode);
- } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
- final String audioWaveformFilename = parser.getAttributeValue("", ATTR_AUDIO_WAVEFORM_FILENAME);
- mediaItem = new MediaVideoItem(mediaItemId, filename, renderingMode, audioWaveformFilename);
-
- final long beginTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
- final long endTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
- ((MediaVideoItem)mediaItem).setExtractBoundaries(beginTimeMs, endTimeMs);
-
- final int volumePercent = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
- ((MediaVideoItem)mediaItem).setVolume(volumePercent);
+ final long durationMs = Long.parseLong(parser.getAttributeValue("",
+ ATTR_DURATION));
+ currentMediaItem = new MediaImageItem(mediaItemId, filename,
+ durationMs, renderingMode);
+ } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
+ final String audioWaveformFilename = parser.getAttributeValue("",
+ ATTR_AUDIO_WAVEFORM_FILENAME);
+ currentMediaItem = new MediaVideoItem(mediaItemId, filename,
+ renderingMode, audioWaveformFilename);
+
+ final long beginTimeMs = Long.parseLong(parser.getAttributeValue("",
+ ATTR_BEGIN_TIME));
+ final long endTimeMs = Long.parseLong(parser.getAttributeValue("",
+ ATTR_END_TIME));
+ ((MediaVideoItem)currentMediaItem).setExtractBoundaries(beginTimeMs,
+ endTimeMs);
+
+ final int volumePercent = Integer.parseInt(parser.getAttributeValue("",
+ ATTR_VOLUME));
+ ((MediaVideoItem)currentMediaItem).setVolume(volumePercent);
} else {
Log.e(TAG, "Unknown media item type: " + type);
- mediaItem = null;
+ currentMediaItem = null;
}
- mMediaItems.add(mediaItem);
+
+ if (currentMediaItem != null) {
+ if (previousMediaItem != null) {
+ currentMediaItem.setBeginTransition(previousMediaItem
+ .getEndTransition());
+ }
+ mMediaItems.add(currentMediaItem);
+ }
+ } else if (name.equals(TAG_BEGIN_TRANSITION)) {
+ final Transition transition = parseTransition(parser, currentMediaItem,
+ null);
+ currentMediaItem.setBeginTransition(transition);
+ } else if (name.equals(TAG_END_TRANSITION)) {
+ final Transition transition = parseTransition(parser, previousMediaItem,
+ currentMediaItem);
+ currentMediaItem.setEndTransition(transition);
+ }
+ break;
+ }
+
+ case XmlPullParser.END_TAG: {
+ name = parser.getName();
+ if (name.equals(TAG_MEDIA_ITEM)) {
+ previousMediaItem = currentMediaItem;
+ currentMediaItem = null;
}
break;
}
@@ -614,6 +708,53 @@ public class VideoEditorTestImpl implements VideoEditor {
computeTimelineDuration();
}
+ /**
+ * Parse the transition
+ *
+ * @param parser The parser
+ * @param afterMediaItem The transition is at the end of this media item
+ * @param beforeMediaItem The transition is at the beginning of this media
+ * item
+ * @return The transition
+ */
+ private Transition parseTransition(XmlPullParser parser, MediaItem beforeMediaItem,
+ MediaItem afterMediaItem) {
+ final String transitionId = parser.getAttributeValue("", ATTR_ID);
+ final String type = parser.getAttributeValue("", ATTR_TYPE);
+ final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
+ final int behavior = Integer.parseInt(parser.getAttributeValue("", ATTR_BEHAVIOR));
+ if (TransitionStartCurtainOpening.class.getSimpleName().equals(type)) {
+ return new TransitionStartCurtainOpening(transitionId, beforeMediaItem, durationMs,
+ behavior);
+ } else if (TransitionStartFadeFromBlack.class.getSimpleName().equals(type)) {
+ return new TransitionStartFadeFromBlack(transitionId, beforeMediaItem, durationMs,
+ behavior);
+ } else if (TransitionAlpha.class.getSimpleName().equals(type)) {
+ final int blending = Integer.parseInt(parser.getAttributeValue("", ATTR_BLENDING));
+ final String maskFilename = parser.getAttributeValue("", ATTR_MASK);
+ final boolean invert = Boolean.getBoolean(parser.getAttributeValue("", ATTR_INVERT));
+ return new TransitionAlpha(transitionId, afterMediaItem, beforeMediaItem, durationMs,
+ behavior, maskFilename, blending, invert);
+ } else if (TransitionAlpha.class.getSimpleName().equals(type)) {
+ return new TransitionCrossfade(transitionId, afterMediaItem, beforeMediaItem,
+ durationMs, behavior);
+ } else if (TransitionSliding.class.getSimpleName().equals(type)) {
+ final int direction = Integer.parseInt(parser.getAttributeValue("", ATTR_DIRECTION));
+ return new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem, durationMs,
+ behavior, direction);
+ } else if (TransitionFadeToBlack.class.getSimpleName().equals(type)) {
+ return new TransitionFadeToBlack(transitionId, afterMediaItem, beforeMediaItem,
+ durationMs, behavior);
+ } else if (TransitionEndCurtainClosing.class.getSimpleName().equals(type)) {
+ return new TransitionEndCurtainClosing(transitionId, beforeMediaItem, durationMs,
+ behavior);
+ } else if (TransitionEndFadeToBlack.class.getSimpleName().equals(type)) {
+ return new TransitionEndFadeToBlack(transitionId, beforeMediaItem, durationMs, behavior);
+ }
+
+ return null;
+ }
+
public void cancelExport(String filename) {
}
@@ -632,7 +773,8 @@ public class VideoEditorTestImpl implements VideoEditor {
}
}
- // This is necessary because the user may had called setDuration on MediaImageItems
+ // This is necessary because the user may had called setDuration on
+ // MediaImageItems
computeTimelineDuration();
}
@@ -647,7 +789,8 @@ public class VideoEditorTestImpl implements VideoEditor {
* {@inheritDoc}
*/
public long getDuration() {
- // Since MediaImageItem can change duration we need to compute the duration here
+ // Since MediaImageItem can change duration we need to compute the
+ // duration here
computeTimelineDuration();
return mDurationMs;
}
@@ -679,9 +822,8 @@ public class VideoEditorTestImpl implements VideoEditor {
/*
* {@inheritDoc}
*/
- public synchronized void startPreview(SurfaceHolder surfaceHolder, long fromMs,
- long toMs, boolean loop, int callbackAfterFrameCount,
- PreviewProgressListener listener) {
+ public synchronized void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs,
+ boolean loop, int callbackAfterFrameCount, PreviewProgressListener listener) {
if (fromMs >= mDurationMs) {
return;
}
@@ -714,7 +856,10 @@ public class VideoEditorTestImpl implements VideoEditor {
// Subtract the transition times
for (Transition transition : mTransitions) {
- if (!(transition instanceof TransitionStartCurtainOpening) && !(transition instanceof TransitionEndFadeToBlack)) {
+ if (!(transition instanceof TransitionStartCurtainOpening)
+ && !(transition instanceof TransitionStartFadeFromBlack)
+ && !(transition instanceof TransitionEndFadeToBlack)
+ && !(transition instanceof TransitionEndCurtainClosing)) {
mDurationMs -= transition.getDuration();
}
}
@@ -742,9 +887,10 @@ public class VideoEditorTestImpl implements VideoEditor {
/**
* Remove the transition before this media item
*
- * @param mediaItem The media item
+ * @param index The media item index
*/
- private void removeTransitionBefore(MediaItem mediaItem) {
+ private void removeTransitionBefore(int index) {
+ final MediaItem mediaItem = mMediaItems.get(0);
final Iterator<Transition> it = mTransitions.iterator();
while (it.hasNext()) {
Transition t = it.next();
@@ -752,6 +898,9 @@ public class VideoEditorTestImpl implements VideoEditor {
it.remove();
t.invalidate();
mediaItem.setBeginTransition(null);
+ if (index > 0) {
+ mMediaItems.get(index - 1).setEndTransition(null);
+ }
break;
}
}
@@ -760,9 +909,10 @@ public class VideoEditorTestImpl implements VideoEditor {
/**
* Remove the transition after this media item
*
- * @param mediaItem The media item
+ * @param index The media item index
*/
- private void removeTransitionAfter(MediaItem mediaItem) {
+ private void removeTransitionAfter(int index) {
+ final MediaItem mediaItem = mMediaItems.get(index);
final Iterator<Transition> it = mTransitions.iterator();
while (it.hasNext()) {
Transition t = it.next();
@@ -770,6 +920,10 @@ public class VideoEditorTestImpl implements VideoEditor {
it.remove();
t.invalidate();
mediaItem.setEndTransition(null);
+ // Invalidate the reference in the next media item
+ if (index < mMediaItems.size() - 1) {
+ mMediaItems.get(index + 1).setBeginTransition(null);
+ }
break;
}
}
diff --git a/media/jni/android_media_MtpClient.cpp b/media/jni/android_media_MtpClient.cpp
index 67740bc..d23185b 100644
--- a/media/jni/android_media_MtpClient.cpp
+++ b/media/jni/android_media_MtpClient.cpp
@@ -161,7 +161,7 @@ android_media_MtpClient_stop(JNIEnv *env, jobject thiz)
static jboolean
android_media_MtpClient_delete_object(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -173,9 +173,9 @@ android_media_MtpClient_delete_object(JNIEnv *env, jobject thiz,
return NULL;
}
-static jint
+static jlong
android_media_MtpClient_get_parent(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -187,9 +187,9 @@ android_media_MtpClient_get_parent(JNIEnv *env, jobject thiz,
return -1;
}
-static jint
+static jlong
android_media_MtpClient_get_storage_id(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -203,7 +203,7 @@ android_media_MtpClient_get_storage_id(JNIEnv *env, jobject thiz,
static jobject
android_media_MtpClient_open_file(JNIEnv *env, jobject thiz,
- jint device_id, jint object_id)
+ jint device_id, jlong object_id)
{
#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
@@ -240,10 +240,10 @@ static JNINativeMethod gMethods[] = {
{"native_finalize", "()V", (void *)android_media_MtpClient_finalize},
{"native_start", "()Z", (void *)android_media_MtpClient_start},
{"native_stop", "()V", (void *)android_media_MtpClient_stop},
- {"native_delete_object", "(II)Z", (void *)android_media_MtpClient_delete_object},
- {"native_get_parent", "(II)I", (void *)android_media_MtpClient_get_parent},
- {"native_get_storage_id", "(II)I", (void *)android_media_MtpClient_get_storage_id},
- {"native_open_file", "(II)Landroid/os/ParcelFileDescriptor;",
+ {"native_delete_object", "(IJ)Z", (void *)android_media_MtpClient_delete_object},
+ {"native_get_parent", "(IJ)J", (void *)android_media_MtpClient_get_parent},
+ {"native_get_storage_id", "(IJ)J", (void *)android_media_MtpClient_get_storage_id},
+ {"native_open_file", "(IJ)Landroid/os/ParcelFileDescriptor;",
(void *)android_media_MtpClient_open_file},
};
diff --git a/media/jni/android_media_MtpCursor.cpp b/media/jni/android_media_MtpCursor.cpp
index 6228b5d..6a65ffd 100644
--- a/media/jni/android_media_MtpCursor.cpp
+++ b/media/jni/android_media_MtpCursor.cpp
@@ -49,7 +49,7 @@ static bool ExceptionCheck(void* env)
static void
android_media_MtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
- jint queryType, jint deviceID, jint storageID, jint objectID, jintArray javaColumns)
+ jint queryType, jint deviceID, jlong storageID, jlong objectID, jintArray javaColumns)
{
#ifdef HAVE_ANDROID_OS
LOGD("android_media_MtpCursor_setup queryType: %d deviceID: %d storageID: %d objectID: %d\n",
@@ -104,7 +104,7 @@ android_media_MtpCursor_fill_window(JNIEnv *env, jobject thiz, jobject javaWindo
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
- {"native_setup", "(Landroid/media/MtpClient;IIII[I)V",
+ {"native_setup", "(Landroid/media/MtpClient;IIJJ[I)V",
(void *)android_media_MtpCursor_setup},
{"native_finalize", "()V", (void *)android_media_MtpCursor_finalize},
{"native_fill_window", "(Landroid/database/CursorWindow;I)I",
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 8ab57c93..03a6bbb 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -239,6 +239,24 @@ extern "C" int Visualizer_process(
}
// all code below assumes stereo 16 bit PCM output and input
+
+ // derive capture scaling factor from peak value in current buffer
+ // this gives more interesting captures for display.
+ int32_t shift = 32;
+ for (size_t i = 0; i < inBuffer->frameCount; i++) {
+ int32_t smp = inBuffer->s16[i];
+ if (smp < 0) smp = -smp;
+ int32_t clz = __builtin_clz(smp);
+ if (shift > clz) shift = clz;
+ }
+ // never scale by less than 8 to avoid returning unaltered PCM signal.
+ // add one to combine the division by 2 needed after summing left and right channels below
+ if (20 > shift) {
+ shift = (31 - 8 + 1) - shift;
+ } else {
+ shift = (3 + 1);
+ }
+
uint32_t captIdx;
uint32_t inIdx;
uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
@@ -246,7 +264,7 @@ extern "C" int Visualizer_process(
inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
inIdx++, captIdx++) {
int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
- smp = (smp + (1 << 8)) >> 9;
+ smp = (smp + (1 << (shift - 1))) >> shift;
buf[captIdx] = ((uint8_t)smp)^0x80;
}
pContext->mCaptureIdx = captIdx;
@@ -369,7 +387,7 @@ extern "C" int Visualizer_command(effect_interface_t self, uint32_t cmdCode, uin
case VISU_CMD_CAPTURE:
- if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+ if (pReplyData == NULL || *replySize != pContext->mCaptureSize) {
LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
*replySize, pContext->mCaptureSize);
return -EINVAL;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 9171aab..3a0fc41 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -132,7 +132,7 @@ size_t PageCache::releaseFromStart(size_t maxBytes) {
}
void PageCache::copy(size_t from, void *data, size_t size) {
- LOG(VERBOSE) << "copy from " << from << " size " << size;
+ LOGV("copy from %d size %d", from, size);
CHECK_LE(from + size, mTotalSize);
@@ -228,7 +228,7 @@ void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
}
void NuCachedSource2::fetchInternal() {
- LOG(VERBOSE) << "fetchInternal";
+ LOGV("fetchInternal");
CHECK_EQ(mFinalStatus, (status_t)OK);
@@ -240,11 +240,11 @@ void NuCachedSource2::fetchInternal() {
Mutex::Autolock autoLock(mLock);
if (n < 0) {
- LOG(ERROR) << "source returned error " << n;
+ LOGE("source returned error %ld", n);
mFinalStatus = n;
mCache->releasePage(page);
} else if (n == 0) {
- LOG(INFO) << "ERROR_END_OF_STREAM";
+ LOGI("ERROR_END_OF_STREAM");
mFinalStatus = ERROR_END_OF_STREAM;
mCache->releasePage(page);
} else {
@@ -254,10 +254,10 @@ void NuCachedSource2::fetchInternal() {
}
void NuCachedSource2::onFetch() {
- LOG(VERBOSE) << "onFetch";
+ LOGV("onFetch");
if (mFinalStatus != OK) {
- LOG(VERBOSE) << "EOS reached, done prefetching for now";
+ LOGV("EOS reached, done prefetching for now");
mFetching = false;
}
@@ -268,7 +268,7 @@ void NuCachedSource2::onFetch() {
if (mFetching || keepAlive) {
if (keepAlive) {
- LOG(INFO) << "Keep alive";
+ LOGI("Keep alive");
}
fetchInternal();
@@ -276,7 +276,7 @@ void NuCachedSource2::onFetch() {
mLastFetchTimeUs = ALooper::GetNowUs();
if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
- LOG(INFO) << "Cache full, done prefetching for now";
+ LOGI("Cache full, done prefetching for now");
mFetching = false;
}
} else {
@@ -289,7 +289,7 @@ void NuCachedSource2::onFetch() {
}
void NuCachedSource2::onRead(const sp<AMessage> &msg) {
- LOG(VERBOSE) << "onRead";
+ LOGV("onRead");
int64_t offset;
CHECK(msg->findInt64("offset", &offset));
@@ -339,14 +339,14 @@ void NuCachedSource2::restartPrefetcherIfNecessary_l() {
size_t actualBytes = mCache->releaseFromStart(maxBytes);
mCacheOffset += actualBytes;
- LOG(INFO) << "restarting prefetcher, totalSize = " << mCache->totalSize();
+ LOGI("restarting prefetcher, totalSize = %d", mCache->totalSize());
mFetching = true;
}
ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) {
Mutex::Autolock autoSerializer(mSerializer);
- LOG(VERBOSE) << "readAt offset " << offset << " size " << size;
+ LOGV("readAt offset %ld, size %d", offset, size);
Mutex::Autolock autoLock(mLock);
@@ -406,7 +406,7 @@ size_t NuCachedSource2::approxDataRemaining_l(bool *eos) {
}
ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
- LOG(VERBOSE) << "readInternal offset " << offset << " size " << size;
+ LOGV("readInternal offset %ld size %d", offset, size);
Mutex::Autolock autoLock(mLock);
@@ -442,7 +442,7 @@ ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
return size;
}
- LOG(VERBOSE) << "deferring read";
+ LOGV("deferring read");
return -EAGAIN;
}
@@ -455,7 +455,7 @@ status_t NuCachedSource2::seekInternal_l(off_t offset) {
return OK;
}
- LOG(INFO) << "new range: offset= " << offset;
+ LOGI("new range: offset= %ld", offset);
mCacheOffset = offset;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4e79575..1b2be41 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1821,7 +1821,7 @@ void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
case OMX_EventError:
{
- LOGE("ERROR(0x%08lx, %ld)", data1, data2);
+ CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
setState(ERROR);
break;
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
index 5add2a5..38c6e2d 100644
--- a/media/libstagefright/ThreadedSource.cpp
+++ b/media/libstagefright/ThreadedSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "ThreadedSource"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
#include "include/ThreadedSource.h"
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index c5b51c0..e4ed5e6 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -123,6 +123,8 @@ status_t AACDecoder::start(MetaData *params) {
mAnchorTimeUs = 0;
mNumSamplesOutput = 0;
mStarted = true;
+ mNumDecodedBuffers = 0;
+ mUpsamplingFactor = 2;
return OK;
}
@@ -207,22 +209,65 @@ status_t AACDecoder::read(
Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
- // Check on the sampling rate to see whether it is changed.
- int32_t sampleRate;
- CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
- if (mConfig->samplingRate != sampleRate) {
- mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
- LOGW("Sample rate was %d, but now is %d",
- sampleRate, mConfig->samplingRate);
- buffer->release();
- mInputBuffer->release();
- mInputBuffer = NULL;
- return INFO_FORMAT_CHANGED;
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (++mNumDecodedBuffers <= 2) {
+ LOGV("audio/extended audio object type: %d + %d",
+ mConfig->audioObjectType, mConfig->extendedAudioObjectType);
+ LOGV("aac+ upsampling factor: %d desired channels: %d",
+ mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
+
+ CHECK(mNumDecodedBuffers > 0);
+ if (mNumDecodedBuffers == 1) {
+ mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
+ // Check on the sampling rate to see whether it is changed.
+ int32_t sampleRate;
+ CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
+ if (mConfig->samplingRate != sampleRate) {
+ mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
+ LOGW("Sample rate was %d Hz, but now is %d Hz",
+ sampleRate, mConfig->samplingRate);
+ buffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return INFO_FORMAT_CHANGED;
+ }
+ } else { // mNumDecodedBuffers == 2
+ if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
+ mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
+ if (mUpsamplingFactor == 2) {
+ // The stream turns out to be not aacPlus mode anyway
+ LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
+ mConfig->extendedAudioObjectType);
+ mConfig->aacPlusEnabled = 0;
+ }
+ } else {
+ if (mUpsamplingFactor == 1) {
+ // aacPlus mode does not buy us anything, but to cause
+ // 1. CPU load to increase, and
+ // 2. a half speed of decoding
+ LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
+ mConfig->aacPlusEnabled = 0;
+ }
+ }
+ }
}
size_t numOutBytes =
mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
- if (mConfig->aacPlusUpsamplingFactor == 2) {
+ if (mUpsamplingFactor == 2) {
if (mConfig->desiredChannels == 1) {
memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
}
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 7483d60..3c0b736 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -232,6 +232,53 @@ static void findNALFragment(
}
}
+MediaBuffer *AVCDecoder::drainOutputBuffer() {
+ int32_t index;
+ int32_t Release;
+ AVCFrameIO Output;
+ Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
+ AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
+
+ if (status != AVCDEC_SUCCESS) {
+ LOGV("PVAVCDecGetOutput returned error %d", status);
+ return NULL;
+ }
+
+ CHECK(index >= 0);
+ CHECK(index < (int32_t)mFrames.size());
+
+ MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (!skipFrame) {
+ mbuf->set_range(0, mbuf->size());
+ mbuf->add_ref();
+
+ return mbuf;
+ }
+
+ return new MediaBuffer(0);
+}
+
status_t AVCDecoder::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
@@ -279,7 +326,8 @@ status_t AVCDecoder::read(
seekOptions.clearSeekTo();
if (err != OK) {
- return err;
+ *out = drainOutputBuffer();
+ return (*out == NULL) ? err : (status_t)OK;
}
if (mInputBuffer->range_length() > 0) {
@@ -415,51 +463,12 @@ status_t AVCDecoder::read(
fragSize);
if (res == AVCDEC_PICTURE_OUTPUT_READY) {
- int32_t index;
- int32_t Release;
- AVCFrameIO Output;
- Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-
- AVCDec_Status status =
- PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
- if (status != AVCDEC_SUCCESS) {
- LOGV("PVAVCDecGetOutput returned error %d", status);
+ MediaBuffer *mbuf = drainOutputBuffer();
+ if (mbuf == NULL) {
break;
}
- CHECK(index >= 0);
- CHECK(index < (int32_t)mFrames.size());
-
- MediaBuffer *mbuf = mFrames.editItemAt(index);
-
- bool skipFrame = false;
-
- if (mTargetTimeUs >= 0) {
- int64_t timeUs;
- CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
- CHECK(timeUs <= mTargetTimeUs);
-
- if (timeUs < mTargetTimeUs) {
- // We're still waiting for the frame with the matching
- // timestamp and we won't return the current one.
- skipFrame = true;
-
- LOGV("skipping frame at %lld us", timeUs);
- } else {
- LOGV("found target frame at %lld us", timeUs);
-
- mTargetTimeUs = -1;
- }
- }
-
- if (!skipFrame) {
- *out = mbuf;
- (*out)->set_range(0, (*out)->size());
- (*out)->add_ref();
- } else {
- *out = new MediaBuffer(0);
- }
+ *out = mbuf;
// Do _not_ release input buffer yet.
@@ -496,6 +505,7 @@ status_t AVCDecoder::read(
case AVC_NALTYPE_AUD:
case AVC_NALTYPE_FILL:
+ case AVC_NALTYPE_EOSEQ:
{
*out = new MediaBuffer(0);
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
deleted file mode 100644
index 16f8b22..0000000
--- a/media/libstagefright/foundation/ADebug.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ADebug.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef ANDROID
-#include <cutils/log.h>
-#endif
-
-namespace android {
-
-Logger::Logger(LogType type)
- : mLogType(type) {
- switch (mLogType) {
- case VERBOSE:
- mMessage = "V ";
- break;
- case INFO:
- mMessage = "I ";
- break;
- case WARNING:
- mMessage = "W ";
- break;
- case ERROR:
- mMessage = "E ";
- break;
- case FATAL:
- mMessage = "F ";
- break;
-
- default:
- break;
- }
-}
-
-Logger::~Logger() {
- if (mLogType == VERBOSE) {
- return;
- }
-
- mMessage.append("\n");
-
-#if defined(ANDROID) && 1
- LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str());
-#else
- fprintf(stderr, mMessage.c_str());
- fflush(stderr);
-#endif
-
- if (mLogType == FATAL) {
- abort();
- }
-}
-
-const char *LeafName(const char *s) {
- const char *lastSlash = strrchr(s, '/');
- return lastSlash != NULL ? lastSlash + 1 : s;
-}
-
-} // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 65f7593..7683113 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -74,7 +74,7 @@ void ALooperRoster::postMessage(
ssize_t index = mHandlers.indexOfKey(msg->target());
if (index < 0) {
- LOG(WARNING) << "failed to post message. Target handler not registered.";
+ LOGW("failed to post message. Target handler not registered.");
return;
}
@@ -83,8 +83,8 @@ void ALooperRoster::postMessage(
sp<ALooper> looper = info.mLooper.promote();
if (looper == NULL) {
- LOG(WARNING) << "failed to post message. "
- "Target handler still registered, but object gone.";
+ LOGW("failed to post message. "
+ "Target handler still registered, but object gone.");
mHandlers.removeItemsAt(index);
return;
@@ -102,8 +102,7 @@ void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
ssize_t index = mHandlers.indexOfKey(msg->target());
if (index < 0) {
- LOG(WARNING) << "failed to deliver message. "
- << "Target handler not registered.";
+ LOGW("failed to deliver message. Target handler not registered.");
return;
}
@@ -111,8 +110,8 @@ void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
handler = info.mHandler.promote();
if (handler == NULL) {
- LOG(WARNING) << "failed to deliver message. "
- "Target handler registered, but object gone.";
+ LOGW("failed to deliver message. "
+ "Target handler registered, but object gone.");
mHandlers.removeItemsAt(index);
return;
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index f6a8a52..ffa7db0 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -5,7 +5,6 @@ LOCAL_SRC_FILES:= \
AAtomizer.cpp \
ABitReader.cpp \
ABuffer.cpp \
- ADebug.cpp \
AHandler.cpp \
ALooper.cpp \
ALooperRoster.cpp \
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
index 093b587..9f6bf9e 100644
--- a/media/libstagefright/foundation/hexdump.cpp
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hexdump"
+#include <utils/Log.h>
+
#include "hexdump.h"
#include "ADebug.h"
@@ -63,7 +67,7 @@ void hexdump(const void *_data, size_t size) {
}
}
- LOG(INFO) << line;
+ LOGI("%s", line.c_str());
offset += 16;
}
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
index 200f93c..886a3b7 100644
--- a/media/libstagefright/include/AACDecoder.h
+++ b/media/libstagefright/include/AACDecoder.h
@@ -53,6 +53,8 @@ private:
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
status_t mInitCheck;
+ int64_t mNumDecodedBuffers;
+ int32_t mUpsamplingFactor;
MediaBuffer *mInputBuffer;
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 898c90a..eb3b142 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -82,6 +82,8 @@ private:
void releaseFrames();
+ MediaBuffer *drainOutputBuffer();
+
AVCDecoder(const AVCDecoder &);
AVCDecoder &operator=(const AVCDecoder &);
};
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72de8d7..9952783 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ATSParser"
+#include <utils/Log.h>
+
#include "ATSParser.h"
#include "AnotherPacketSource.h"
@@ -31,6 +35,10 @@
namespace android {
+// I want the expression "y" evaluated even if verbose logging is off.
+#define MY_LOGV(x, y) \
+ do { unsigned tmp = y; LOGV(x, tmp); } while (0)
+
static const size_t kTSPacketSize = 188;
struct ATSParser::Program : public RefBase {
@@ -115,36 +123,33 @@ bool ATSParser::Program::parsePID(
void ATSParser::Program::parseProgramMap(ABitReader *br) {
unsigned table_id = br->getBits(8);
- LOG(VERBOSE) << " table_id = " << table_id;
+ LOGV(" table_id = %u", table_id);
CHECK_EQ(table_id, 0x02u);
- unsigned section_syntax_indictor = br->getBits(1);
- LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
- CHECK_EQ(section_syntax_indictor, 1u);
+ unsigned section_syntax_indicator = br->getBits(1);
+ LOGV(" section_syntax_indicator = %u", section_syntax_indicator);
+ CHECK_EQ(section_syntax_indicator, 1u);
CHECK_EQ(br->getBits(1), 0u);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ MY_LOGV(" reserved = %u", br->getBits(2));
unsigned section_length = br->getBits(12);
- LOG(VERBOSE) << " section_length = " << section_length;
+ LOGV(" section_length = %u", section_length);
CHECK((section_length & 0xc00) == 0);
CHECK_LE(section_length, 1021u);
- LOG(VERBOSE) << " program_number = " << br->getBits(16);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
- LOG(VERBOSE) << " version_number = " << br->getBits(5);
- LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
- LOG(VERBOSE) << " section_number = " << br->getBits(8);
- LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
-
- LOG(VERBOSE) << " PCR_PID = "
- << StringPrintf("0x%04x", br->getBits(13));
-
- LOG(VERBOSE) << " reserved = " << br->getBits(4);
+ MY_LOGV(" program_number = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", br->getBits(8));
+ MY_LOGV(" reserved = %u", br->getBits(3));
+ MY_LOGV(" PCR_PID = 0x%04x", br->getBits(13));
+ MY_LOGV(" reserved = %u", br->getBits(4));
unsigned program_info_length = br->getBits(12);
- LOG(VERBOSE) << " program_info_length = " << program_info_length;
+ LOGV(" program_info_length = %u", program_info_length);
CHECK((program_info_length & 0xc00) == 0);
br->skipBits(program_info_length * 8); // skip descriptors
@@ -158,19 +163,17 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
CHECK_GE(infoBytesRemaining, 5u);
unsigned streamType = br->getBits(8);
- LOG(VERBOSE) << " stream_type = "
- << StringPrintf("0x%02x", streamType);
+ LOGV(" stream_type = 0x%02x", streamType);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
+ MY_LOGV(" reserved = %u", br->getBits(3));
unsigned elementaryPID = br->getBits(13);
- LOG(VERBOSE) << " elementary_PID = "
- << StringPrintf("0x%04x", elementaryPID);
+ LOGV(" elementary_PID = 0x%04x", elementaryPID);
- LOG(VERBOSE) << " reserved = " << br->getBits(4);
+ MY_LOGV(" reserved = %u", br->getBits(4));
unsigned ES_info_length = br->getBits(12);
- LOG(VERBOSE) << " ES_info_length = " << ES_info_length;
+ LOGV(" ES_info_length = %u", ES_info_length);
CHECK((ES_info_length & 0xc00) == 0);
CHECK_GE(infoBytesRemaining - 5, ES_info_length);
@@ -180,10 +183,10 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
#else
unsigned info_bytes_remaining = ES_info_length;
while (info_bytes_remaining >= 2) {
- LOG(VERBOSE) << " tag = " << StringPrintf("0x%02x", br->getBits(8));
+ MY_LOGV(" tag = 0x%02x", br->getBits(8));
unsigned descLength = br->getBits(8);
- LOG(VERBOSE) << " len = " << descLength;
+ LOGV(" len = %u", descLength);
CHECK_GE(info_bytes_remaining, 2 + descLength);
@@ -209,7 +212,7 @@ void ATSParser::Program::parseProgramMap(ABitReader *br) {
CHECK_EQ(infoBytesRemaining, 0u);
- LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
}
sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
@@ -255,7 +258,7 @@ void ATSParser::Stream::parse(
}
size_t payloadSizeBits = br->numBitsLeft();
- CHECK_EQ(payloadSizeBits % 8, 0u);
+ CHECK((payloadSizeBits % 8) == 0);
CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
@@ -266,16 +269,15 @@ void ATSParser::Stream::parse(
void ATSParser::Stream::parsePES(ABitReader *br) {
unsigned packet_startcode_prefix = br->getBits(24);
- LOG(VERBOSE) << "packet_startcode_prefix = "
- << StringPrintf("0x%08x", packet_startcode_prefix);
+ LOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
CHECK_EQ(packet_startcode_prefix, 0x000001u);
unsigned stream_id = br->getBits(8);
- LOG(VERBOSE) << "stream_id = " << StringPrintf("0x%02x", stream_id);
+ LOGV("stream_id = 0x%02x", stream_id);
unsigned PES_packet_length = br->getBits(16);
- LOG(VERBOSE) << "PES_packet_length = " << PES_packet_length;
+ LOGV("PES_packet_length = %u", PES_packet_length);
if (stream_id != 0xbc // program_stream_map
&& stream_id != 0xbe // padding_stream
@@ -287,33 +289,32 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
&& stream_id != 0xf8) { // H.222.1 type E
CHECK_EQ(br->getBits(2), 2u);
- LOG(VERBOSE) << "PES_scrambling_control = " << br->getBits(2);
- LOG(VERBOSE) << "PES_priority = " << br->getBits(1);
- LOG(VERBOSE) << "data_alignment_indicator = " << br->getBits(1);
- LOG(VERBOSE) << "copyright = " << br->getBits(1);
- LOG(VERBOSE) << "original_or_copy = " << br->getBits(1);
+ MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
+ MY_LOGV("PES_priority = %u", br->getBits(1));
+ MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
+ MY_LOGV("copyright = %u", br->getBits(1));
+ MY_LOGV("original_or_copy = %u", br->getBits(1));
unsigned PTS_DTS_flags = br->getBits(2);
- LOG(VERBOSE) << "PTS_DTS_flags = " << PTS_DTS_flags;
+ LOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
unsigned ESCR_flag = br->getBits(1);
- LOG(VERBOSE) << "ESCR_flag = " << ESCR_flag;
+ LOGV("ESCR_flag = %u", ESCR_flag);
unsigned ES_rate_flag = br->getBits(1);
- LOG(VERBOSE) << "ES_rate_flag = " << ES_rate_flag;
+ LOGV("ES_rate_flag = %u", ES_rate_flag);
unsigned DSM_trick_mode_flag = br->getBits(1);
- LOG(VERBOSE) << "DSM_trick_mode_flag = " << DSM_trick_mode_flag;
+ LOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
unsigned additional_copy_info_flag = br->getBits(1);
- LOG(VERBOSE) << "additional_copy_info_flag = "
- << additional_copy_info_flag;
+ LOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
- LOG(VERBOSE) << "PES_CRC_flag = " << br->getBits(1);
- LOG(VERBOSE) << "PES_extension_flag = " << br->getBits(1);
+ MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
+ MY_LOGV("PES_extension_flag = %u", br->getBits(1));
unsigned PES_header_data_length = br->getBits(8);
- LOG(VERBOSE) << "PES_header_data_length = " << PES_header_data_length;
+ LOGV("PES_header_data_length = %u", PES_header_data_length);
unsigned optional_bytes_remaining = PES_header_data_length;
@@ -331,8 +332,8 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
PTS |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "PTS = " << PTS;
- // LOG(INFO) << "PTS = " << PTS / 90000.0f << " secs";
+ LOGV("PTS = %llu", PTS);
+ // LOGI("PTS = %.2f secs", PTS / 90000.0f);
optional_bytes_remaining -= 5;
@@ -348,7 +349,7 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
DTS |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "DTS = " << DTS;
+ LOGV("DTS = %llu", DTS);
optional_bytes_remaining -= 5;
}
@@ -366,8 +367,8 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
ESCR |= br->getBits(15);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "ESCR = " << ESCR;
- LOG(VERBOSE) << "ESCR_extension = " << br->getBits(9);
+ LOGV("ESCR = %llu", ESCR);
+ MY_LOGV("ESCR_extension = %u", br->getBits(9));
CHECK_EQ(br->getBits(1), 1u);
@@ -378,7 +379,7 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
CHECK_GE(optional_bytes_remaining, 3u);
CHECK_EQ(br->getBits(1), 1u);
- LOG(VERBOSE) << "ES_rate = " << br->getBits(22);
+ MY_LOGV("ES_rate = %u", br->getBits(22));
CHECK_EQ(br->getBits(1), 1u);
optional_bytes_remaining -= 3;
@@ -405,8 +406,7 @@ void ATSParser::Stream::parsePES(ABitReader *br) {
size_t payloadSizeBits = br->numBitsLeft();
CHECK((payloadSizeBits % 8) == 0);
- LOG(VERBOSE) << "There's " << (payloadSizeBits / 8)
- << " bytes of payload.";
+ LOGV("There's %d bytes of payload.", payloadSizeBits / 8);
}
} else if (stream_id == 0xbe) { // padding_stream
CHECK_NE(PES_packet_length, 0u);
@@ -422,9 +422,7 @@ void ATSParser::Stream::flush() {
return;
}
- LOG(VERBOSE) << "flushing stream "
- << StringPrintf("0x%04x", mElementaryPID)
- << " size = " << mBuffer->size();
+ LOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size());
ABitReader br(mBuffer->data(), mBuffer->size());
parsePES(&br);
@@ -493,7 +491,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData(
CHECK(picParamSet != NULL);
buffer->setRange(stopOffset, size - stopOffset);
- LOG(INFO) << "buffer has " << buffer->size() << " bytes left.";
+ LOGI("buffer has %d bytes left.", buffer->size());
size_t csdSize =
1 + 3 + 1 + 1
@@ -617,15 +615,15 @@ static sp<ABuffer> FindMPEG2ADTSConfig(
CHECK_EQ(br.getBits(2), 0u);
br.getBits(1); // protection_absent
unsigned profile = br.getBits(2);
- LOG(INFO) << "profile = " << profile;
+ LOGI("profile = %u", profile);
CHECK_NE(profile, 3u);
unsigned sampling_freq_index = br.getBits(4);
br.getBits(1); // private_bit
unsigned channel_configuration = br.getBits(3);
CHECK_NE(channel_configuration, 0u);
- LOG(INFO) << "sampling_freq_index = " << sampling_freq_index;
- LOG(INFO) << "channel_configuration = " << channel_configuration;
+ LOGI("sampling_freq_index = %u", sampling_freq_index);
+ LOGI("channel_configuration = %u", channel_configuration);
CHECK_LE(sampling_freq_index, 11u);
static const int32_t kSamplingFreq[] = {
@@ -671,8 +669,7 @@ static sp<ABuffer> FindMPEG2ADTSConfig(
void ATSParser::Stream::onPayloadData(
unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
const uint8_t *data, size_t size) {
- LOG(VERBOSE) << "onPayloadData mStreamType="
- << StringPrintf("0x%02x", mStreamType);
+ LOGV("onPayloadData mStreamType=0x%02x", mStreamType);
sp<ABuffer> buffer;
@@ -710,8 +707,8 @@ void ATSParser::Stream::onPayloadData(
sp<ABuffer> csd =
FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
- LOG(INFO) << "sampleRate = " << sampleRate;
- LOG(INFO) << "channelCount = " << channelCount;
+ LOGI("sampleRate = %d", sampleRate);
+ LOGI("channelCount = %d", channelCount);
meta->setInt32(kKeySampleRate, sampleRate);
meta->setInt32(kKeyChannelCount, channelCount);
@@ -719,7 +716,7 @@ void ATSParser::Stream::onPayloadData(
meta->setData(kKeyESDS, 0, csd->data(), csd->size());
}
- LOG(INFO) << "created source!";
+ LOGI("created source!");
mSource = new AnotherPacketSource(meta);
// fall through
@@ -777,12 +774,7 @@ void ATSParser::Stream::extractAACFrames(const sp<ABuffer> &buffer) {
CHECK_LE(scan, buffer->size());
- LOG(VERBOSE)
- << "found aac raw data block at ["
- << StringPrintf("0x%08x", offset)
- << " ; "
- << StringPrintf("0x%08x", scan)
- << ")";
+ LOGV("found aac raw data block at [0x%08x ; 0x%08x)", offset, scan);
memmove(&buffer->data()[dstOffset], &buffer->data()[offset],
scan - offset);
@@ -825,50 +817,48 @@ void ATSParser::feedTSPacket(const void *data, size_t size) {
void ATSParser::parseProgramAssociationTable(ABitReader *br) {
unsigned table_id = br->getBits(8);
- LOG(VERBOSE) << " table_id = " << table_id;
+ LOGV(" table_id = %u", table_id);
CHECK_EQ(table_id, 0x00u);
unsigned section_syntax_indictor = br->getBits(1);
- LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
+ LOGV(" section_syntax_indictor = %u", section_syntax_indictor);
CHECK_EQ(section_syntax_indictor, 1u);
CHECK_EQ(br->getBits(1), 0u);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ MY_LOGV(" reserved = %u", br->getBits(2));
unsigned section_length = br->getBits(12);
- LOG(VERBOSE) << " section_length = " << section_length;
+ LOGV(" section_length = %u", section_length);
CHECK((section_length & 0xc00) == 0);
- LOG(VERBOSE) << " transport_stream_id = " << br->getBits(16);
- LOG(VERBOSE) << " reserved = " << br->getBits(2);
- LOG(VERBOSE) << " version_number = " << br->getBits(5);
- LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
- LOG(VERBOSE) << " section_number = " << br->getBits(8);
- LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
+ MY_LOGV(" transport_stream_id = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", br->getBits(8));
size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
CHECK_EQ((numProgramBytes % 4), 0u);
for (size_t i = 0; i < numProgramBytes / 4; ++i) {
unsigned program_number = br->getBits(16);
- LOG(VERBOSE) << " program_number = " << program_number;
+ LOGV(" program_number = %u", program_number);
- LOG(VERBOSE) << " reserved = " << br->getBits(3);
+ MY_LOGV(" reserved = %u", br->getBits(3));
if (program_number == 0) {
- LOG(VERBOSE) << " network_PID = "
- << StringPrintf("0x%04x", br->getBits(13));
+ MY_LOGV(" network_PID = 0x%04x", br->getBits(13));
} else {
unsigned programMapPID = br->getBits(13);
- LOG(VERBOSE) << " program_map_PID = "
- << StringPrintf("0x%04x", programMapPID);
+ LOGV(" program_map_PID = 0x%04x", programMapPID);
mPrograms.push(new Program(programMapPID));
}
}
- LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
}
void ATSParser::parsePID(
@@ -893,8 +883,7 @@ void ATSParser::parsePID(
}
if (!handled) {
- LOG(WARNING) << "PID " << StringPrintf("0x%04x", PID)
- << " not handled.";
+ LOGV("PID 0x%04x not handled.", PID);
}
}
@@ -906,28 +895,27 @@ void ATSParser::parseAdaptationField(ABitReader *br) {
}
void ATSParser::parseTS(ABitReader *br) {
- LOG(VERBOSE) << "---";
+ LOGV("---");
unsigned sync_byte = br->getBits(8);
CHECK_EQ(sync_byte, 0x47u);
- LOG(VERBOSE) << "transport_error_indicator = " << br->getBits(1);
+ MY_LOGV("transport_error_indicator = %u", br->getBits(1));
unsigned payload_unit_start_indicator = br->getBits(1);
- LOG(VERBOSE) << "payload_unit_start_indicator = "
- << payload_unit_start_indicator;
+ LOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
- LOG(VERBOSE) << "transport_priority = " << br->getBits(1);
+ MY_LOGV("transport_priority = %u", br->getBits(1));
unsigned PID = br->getBits(13);
- LOG(VERBOSE) << "PID = " << StringPrintf("0x%04x", PID);
+ LOGV("PID = 0x%04x", PID);
- LOG(VERBOSE) << "transport_scrambling_control = " << br->getBits(2);
+ MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
unsigned adaptation_field_control = br->getBits(2);
- LOG(VERBOSE) << "adaptation_field_control = " << adaptation_field_control;
+ LOGV("adaptation_field_control = %u", adaptation_field_control);
- LOG(VERBOSE) << "continuity_counter = " << br->getBits(4);
+ MY_LOGV("continuity_counter = %u", br->getBits(4));
if (adaptation_field_control == 2 || adaptation_field_control == 3) {
parseAdaptationField(br);
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index fcf506d..4f28855 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@ status_t Harness::testStateTransitions(
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
+ sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
IOMX::node_id node;
status_t err =
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 154ba31..b1f6e9a 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAMRAssembler"
+#include <utils/Log.h>
+
#include "AAMRAssembler.h"
#include "ARTPSource.h"
@@ -119,9 +123,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -132,7 +134,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "AMR packet too short.";
+ LOGV("AMR packet too short.");
return MALFORMED_PACKET;
}
@@ -150,7 +152,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "Unable to parse TOC.";
+ LOGV("Unable to parse TOC.");
return MALFORMED_PACKET;
}
@@ -164,7 +166,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "Illegal TOC entry.";
+ LOGV("Illegal TOC entry.");
return MALFORMED_PACKET;
}
@@ -191,7 +193,7 @@ ARTPAssembler::AssemblyStatus AAMRAssembler::addPacket(
queue->erase(queue->begin());
++mNextExpectedSeqNo;
- LOG(VERBOSE) << "AMR packet too short.";
+ LOGV("AMR packet too short.");
return MALFORMED_PACKET;
}
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 6b1e292..11c6ae7 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAVCAssembler"
+#include <utils/Log.h>
+
#include "AAVCAssembler.h"
#include "ARTPSource.h"
@@ -25,8 +29,6 @@
#include <stdint.h>
-#define BE_VERBOSE 0
-
namespace android {
// static
@@ -70,9 +72,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -83,7 +83,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
if (size < 1 || (data[0] & 0x80)) {
// Corrupt.
- LOG(ERROR) << "Ignoring corrupt buffer.";
+ LOGV("Ignoring corrupt buffer.");
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -107,7 +107,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
return success ? OK : MALFORMED_PACKET;
} else {
- LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
+ LOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -117,8 +117,8 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
}
void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
+ LOGV("addSingleNALUnit of size %d", buffer->size());
+#if !LOG_NDEBUG
hexdump(buffer->data(), buffer->size());
#endif
@@ -138,7 +138,7 @@ bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
size_t size = buffer->size();
if (size < 3) {
- LOG(ERROR) << "Discarding too small STAP-A packet.";
+ LOGV("Discarding too small STAP-A packet.");
return false;
}
@@ -148,7 +148,7 @@ bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
size_t nalSize = (data[0] << 8) | data[1];
if (size < nalSize + 2) {
- LOG(ERROR) << "Discarding malformed STAP-A packet.";
+ LOGV("Discarding malformed STAP-A packet.");
return false;
}
@@ -164,7 +164,7 @@ bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
}
if (size != 0) {
- LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
+ LOGV("Unexpected padding at end of STAP-A packet.");
}
return true;
@@ -184,7 +184,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
CHECK((indicator & 0x1f) == 28);
if (size < 2) {
- LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
+ LOGV("Ignoring malformed FU buffer (size = %d)", size);
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -194,9 +194,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
if (!(data[1] & 0x80)) {
// Start bit not set on the first buffer.
-#if BE_VERBOSE
- LOG(ERROR) << "Start bit not set on first buffer";
-#endif
+ LOGV("Start bit not set on first buffer");
queue->erase(queue->begin());
++mNextExpectedSeqNo;
@@ -214,17 +212,13 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
if (data[1] & 0x40) {
// Huh? End bit also set on the first buffer.
-#if BE_VERBOSE
- LOG(WARNING) << "Grrr. This isn't fragmented at all.";
-#endif
+ LOGV("Grrr. This isn't fragmented at all.");
complete = true;
} else {
List<sp<ABuffer> >::iterator it = ++queue->begin();
while (it != queue->end()) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "sequence length " << totalCount;
-#endif
+ LOGV("sequence length %d", totalCount);
const sp<ABuffer> &buffer = *it;
@@ -232,11 +226,8 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
size_t size = buffer->size();
if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "sequence not complete, expected seqNo "
- << expectedSeqNo << ", got "
- << (uint32_t)buffer->int32Data();
-#endif
+ LOGV("sequence not complete, expected seqNo %d, got %d",
+ expectedSeqNo, (uint32_t)buffer->int32Data());
return WRONG_SEQUENCE_NUMBER;
}
@@ -245,7 +236,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
|| data[0] != indicator
|| (data[1] & 0x1f) != nalType
|| (data[1] & 0x80)) {
- LOG(ERROR) << "Ignoring malformed FU buffer.\n";
+ LOGV("Ignoring malformed FU buffer.");
// Delete the whole start of the FU.
@@ -296,8 +287,8 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
for (size_t i = 0; i < totalCount; ++i) {
const sp<ABuffer> &buffer = *it;
-#if BE_VERBOSE
- LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
+ LOGV("piece #%d/%d", i + 1, totalCount);
+#if !LOG_NDEBUG
hexdump(buffer->data(), buffer->size());
#endif
@@ -311,9 +302,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
addSingleNALUnit(unit);
-#if BE_VERBOSE
- LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
-#endif
+ LOGV("successfully assembled a NAL unit from fragments.");
return OK;
}
@@ -321,9 +310,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
void AAVCAssembler::submitAccessUnit() {
CHECK(!mNALUnits.empty());
-#if BE_VERBOSE
- LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
-#endif
+ LOGV("Access unit complete (%d nal units)", mNALUnits.size());
size_t totalSize = 0;
for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
@@ -373,7 +360,7 @@ ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
void AAVCAssembler::packetLost() {
CHECK(mNextExpectedSeqNoValid);
- LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+ LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index f68a35b..13988cd 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMPEG4ElementaryAssembler"
+#include <utils/Log.h>
+
#include "AMPEG4ElementaryAssembler.h"
#include "ARTPSource.h"
@@ -28,8 +32,6 @@
#include <ctype.h>
#include <stdint.h>
-#define BE_VERBOSE 0
-
namespace android {
static bool GetAttribute(const char *s, const char *key, AString *value) {
@@ -201,9 +203,7 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
mNextExpectedSeqNoValid = true;
mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
} else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+ LOGV("Not the sequence number I expected");
return WRONG_SEQUENCE_NUMBER;
}
@@ -336,9 +336,7 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
void AMPEG4ElementaryAssembler::submitAccessUnit() {
CHECK(!mPackets.empty());
-#if BE_VERBOSE
- LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " nal units)";
-#endif
+ LOGV("Access unit complete (%d nal units)", mPackets.size());
size_t totalSize = 0;
for (List<sp<ABuffer> >::iterator it = mPackets.begin();
@@ -385,7 +383,7 @@ ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
void AMPEG4ElementaryAssembler::packetLost() {
CHECK(mNextExpectedSeqNoValid);
- LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+ LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index b3e86eb..78754e6 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "APacketSource"
+#include <utils/Log.h>
+
#include "APacketSource.h"
#include "ASessionDescription.h"
@@ -188,7 +192,7 @@ static sp<ABuffer> MakeAVCCodecSpecificData(
if (i == 0) {
FindAVCDimensions(nal, width, height);
- LOG(INFO) << "dimensions " << *width << "x" << *height;
+ LOGI("dimensions %dx%d", *width, *height);
}
}
@@ -412,7 +416,7 @@ static bool ExtractDimensionsFromVOLHeader(
*width = video_object_layer_width;
*height = video_object_layer_height;
- LOG(INFO) << "VOL dimensions = " << *width << "x" << *height;
+ LOGI("VOL dimensions = %dx%d", *width, *height);
return true;
}
@@ -711,7 +715,7 @@ void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) {
void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
int32_t damaged;
if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
- LOG(VERBOSE) << "discarding damaged AU";
+ LOGV("discarding damaged AU");
return;
}
@@ -765,8 +769,9 @@ int64_t APacketSource::getQueueDurationUs(bool *eos) {
CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
if (lastTimeUs < firstTimeUs) {
- LOG(ERROR) << "Huh? Time moving backwards? "
- << firstTimeUs << " > " << lastTimeUs;
+ LOGE("Huh? Time moving backwards? %lld > %lld",
+ firstTimeUs, lastTimeUs);
+
return 0;
}
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 10c9e02..ded3b24 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPConnection"
+#include <utils/Log.h>
+
#include "ARTPConnection.h"
#include "ARTPSource.h"
@@ -319,7 +323,7 @@ void ARTPConnection::onPollStreams() {
}
if (buffer->size() > 0) {
- LOG(VERBOSE) << "Sending RR...";
+ LOGV("Sending RR...");
ssize_t n = sendto(
s->mRTCPSocket, buffer->data(), buffer->size(), 0,
@@ -356,7 +360,7 @@ status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
buffer->setRange(0, nbytes);
- // LOG(INFO) << "received " << buffer->size() << " bytes.";
+ // LOGI("received %d bytes.", buffer->size());
status_t err;
if (receiveRTP) {
@@ -521,9 +525,8 @@ status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
default:
{
- LOG(WARNING) << "Unknown RTCP packet type "
- << (unsigned)data[1]
- << " of size " << headerLength;
+ LOGW("Unknown RTCP packet type %u of size %d",
+ (unsigned)data[1], headerLength);
break;
}
}
@@ -567,10 +570,10 @@ status_t ARTPConnection::parseSR(
uint32_t rtpTime = u32at(&data[16]);
#if 0
- LOG(INFO) << StringPrintf(
- "XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
- id,
- rtpTime, (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
+ LOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
+ id,
+ rtpTime,
+ (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
#endif
sp<ARTPSource> source = findSource(s, id);
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index 8ce93b7..39c6619 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSession"
+#include <utils/Log.h>
+
#include "ARTPSession.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -51,24 +55,24 @@ status_t ARTPSession::setup(const sp<ASessionDescription> &desc) {
if (!mDesc->findAttribute(i, "c=", &connection)) {
// No per-stream connection information, try global fallback.
if (!mDesc->findAttribute(0, "c=", &connection)) {
- LOG(ERROR) << "Unable to find connection attribtue.";
+ LOGE("Unable to find connection attribute.");
return mInitCheck;
}
}
if (!(connection == "IN IP4 127.0.0.1")) {
- LOG(ERROR) << "We only support localhost connections for now.";
+ LOGE("We only support localhost connections for now.");
return mInitCheck;
}
unsigned port;
if (!validateMediaFormat(i, &port) || (port & 1) != 0) {
- LOG(ERROR) << "Invalid media format.";
+ LOGE("Invalid media format.");
return mInitCheck;
}
sp<APacketSource> source = new APacketSource(mDesc, i);
if (source->initCheck() != OK) {
- LOG(ERROR) << "Unsupported format.";
+ LOGE("Unsupported format.");
return mInitCheck;
}
@@ -157,9 +161,8 @@ void ARTPSession::onMessageReceived(const sp<AMessage> &msg) {
printf("access unit complete size=%d\tntp-time=0x%016llx\n",
accessUnit->size(), ntpTime);
#else
- LOG(INFO) << "access unit complete, "
- << "size=" << accessUnit->size() << ", "
- << "ntp-time=" << ntpTime;
+ LOGI("access unit complete, size=%d, ntp-time=%llu",
+ accessUnit->size(), ntpTime);
hexdump(accessUnit->data(), accessUnit->size());
#endif
#endif
@@ -169,9 +172,8 @@ void ARTPSession::onMessageReceived(const sp<AMessage> &msg) {
CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4));
unsigned x = accessUnit->data()[4];
- LOG(INFO) << "access unit complete: "
- << StringPrintf("nalType=0x%02x, nalRefIdc=0x%02x",
- x & 0x1f, (x & 0x60) >> 5);
+ LOGI("access unit complete: nalType=0x%02x, nalRefIdc=0x%02x",
+ x & 0x1f, (x & 0x60) >> 5);
#endif
accessUnit->meta()->setInt64("ntp-time", ntpTime);
@@ -181,7 +183,7 @@ void ARTPSession::onMessageReceived(const sp<AMessage> &msg) {
int32_t damaged;
if (accessUnit->meta()->findInt32("damaged", &damaged)
&& damaged != 0) {
- LOG(INFO) << "ignoring damaged AU";
+ LOGI("ignoring damaged AU");
} else
#endif
{
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 9656ba2..2518264 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSource"
+#include <utils/Log.h>
+
#include "ARTPSource.h"
#include "AAMRAssembler.h"
@@ -27,8 +31,6 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
-#define BE_VERBOSE 0
-
namespace android {
static const uint32_t kSourceID = 0xdeadbeef;
@@ -83,14 +85,10 @@ void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
&& mAssembler != NULL) {
mAssembler->onPacketReceived(this);
}
-
- dump();
}
void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
-#if BE_VERBOSE
- LOG(VERBOSE) << "timeUpdate";
-#endif
+ LOGV("timeUpdate");
mLastNTPTime = ntpTime;
mLastNTPTimeUpdateUs = ALooper::GetNowUs();
@@ -173,7 +171,7 @@ bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
}
if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) {
- LOG(WARNING) << "Discarding duplicate buffer";
+ LOGW("Discarding duplicate buffer");
return false;
}
@@ -182,89 +180,6 @@ bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
return true;
}
-void ARTPSource::dump() const {
- if ((mNumBuffersReceived % 128) != 0) {
- return;
- }
-
-#if 0
- if (mAssembler == NULL) {
- char tmp[20];
- sprintf(tmp, "0x%08x", mID);
-
- int32_t numMissing = 0;
-
- if (!mQueue.empty()) {
- List<sp<ABuffer> >::const_iterator it = mQueue.begin();
- uint32_t expectedSeqNum = (uint32_t)(*it)->int32Data();
- ++expectedSeqNum;
- ++it;
-
- for (; it != mQueue.end(); ++it) {
- uint32_t seqNum = (uint32_t)(*it)->int32Data();
- CHECK_GE(seqNum, expectedSeqNum);
-
- if (seqNum != expectedSeqNum) {
- numMissing += seqNum - expectedSeqNum;
- expectedSeqNum = seqNum;
- }
-
- ++expectedSeqNum;
- }
- }
-
- LOG(VERBOSE) << "[" << tmp << "] Missing " << numMissing
- << " / " << (mNumBuffersReceived + numMissing) << " packets. ("
- << (100.0 * numMissing / (mNumBuffersReceived + numMissing))
- << " %%)";
- }
-#endif
-
-#if 0
- AString out;
-
- out.append(tmp);
- out.append(" [");
-
- List<sp<ABuffer> >::const_iterator it = mQueue.begin();
- while (it != mQueue.end()) {
- uint32_t start = (uint32_t)(*it)->int32Data();
-
- out.append(start);
-
- ++it;
- uint32_t expected = start + 1;
-
- while (it != mQueue.end()) {
- uint32_t seqNum = (uint32_t)(*it)->int32Data();
-
- if (seqNum != expected) {
- if (expected > start + 1) {
- out.append("-");
- out.append(expected - 1);
- }
- out.append(", ");
- break;
- }
-
- ++it;
- ++expected;
- }
-
- if (it == mQueue.end()) {
- if (expected > start + 1) {
- out.append("-");
- out.append(expected - 1);
- }
- }
- }
-
- out.append("]");
-
- LOG(VERBOSE) << out;
-#endif
-}
-
uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
CHECK_EQ(mNumTimes, 2u);
@@ -291,7 +206,7 @@ void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
mLastFIRRequestUs = nowUs;
if (buffer->size() + 20 > buffer->capacity()) {
- LOG(WARNING) << "RTCP buffer too small to accomodate FIR.";
+ LOGW("RTCP buffer too small to accomodate FIR.");
return;
}
@@ -324,12 +239,12 @@ void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
buffer->setRange(buffer->offset(), buffer->size() + 20);
- LOG(VERBOSE) << "Added FIR request.";
+ LOGV("Added FIR request.");
}
void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
if (buffer->size() + 32 > buffer->capacity()) {
- LOG(WARNING) << "RTCP buffer too small to accomodate RR.";
+ LOGW("RTCP buffer too small to accomodate RR.");
return;
}
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 252d6d6..e62c3f1 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -72,7 +72,6 @@ private:
uint64_t RTP2NTP(uint32_t rtpTime) const;
bool queuePacket(const sp<ABuffer> &buffer);
- void dump() const;
DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
};
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index ce1ee0e..155fd96 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -1,3 +1,23 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPWriter"
+#include <utils/Log.h>
+
#include "ARTPWriter.h"
#include <fcntl.h>
@@ -249,7 +269,7 @@ void ARTPWriter::onRead(const sp<AMessage> &msg) {
status_t err = mSource->read(&mediaBuf);
if (err != OK) {
- LOG(INFO) << "reached EOS.";
+ LOGI("reached EOS.");
Mutex::Autolock autoLock(mLock);
mFlags |= kFlagEOS;
@@ -257,7 +277,7 @@ void ARTPWriter::onRead(const sp<AMessage> &msg) {
}
if (mediaBuf->range_length() > 0) {
- LOG(VERBOSE) << "read buffer of size " << mediaBuf->range_length();
+ LOGV("read buffer of size %d", mediaBuf->range_length());
if (mMode == H264) {
StripStartcode(mediaBuf);
@@ -500,7 +520,7 @@ void ARTPWriter::dumpSessionDesc() {
sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
}
- LOG(INFO) << sdp;
+ LOGI("%s", sdp.c_str());
}
void ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index dcff64c..f928c06 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTSPConnection"
+#include <utils/Log.h>
+
#include "ARTSPConnection.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -41,7 +45,7 @@ ARTSPConnection::ARTSPConnection()
ARTSPConnection::~ARTSPConnection() {
if (mSocket >= 0) {
- LOG(ERROR) << "Connection is still open, closing the socket.";
+ LOGE("Connection is still open, closing the socket.");
close(mSocket);
mSocket = -1;
}
@@ -184,7 +188,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
AString host, path;
unsigned port;
if (!ParseURL(url.c_str(), &host, &port, &path)) {
- LOG(ERROR) << "Malformed rtsp url " << url;
+ LOGE("Malformed rtsp url %s", url.c_str());
reply->setInt32("result", ERROR_MALFORMED);
reply->post();
@@ -195,7 +199,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
struct hostent *ent = gethostbyname(host.c_str());
if (ent == NULL) {
- LOG(ERROR) << "Unknown host " << host;
+ LOGE("Unknown host %s", host.c_str());
reply->setInt32("result", -ENOENT);
reply->post();
@@ -300,7 +304,7 @@ void ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
CHECK_EQ(optionLen, (socklen_t)sizeof(err));
if (err != 0) {
- LOG(ERROR) << "err = " << err << " (" << strerror(err) << ")";
+ LOGE("err = %d (%s)", err, strerror(err));
reply->setInt32("result", -err);
@@ -343,7 +347,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
request.insert(cseqHeader, i + 2);
- LOG(VERBOSE) << request;
+ LOGV("%s", request.c_str());
size_t numBytesSent = 0;
while (numBytesSent < request.size()) {
@@ -353,7 +357,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
if (n == 0) {
// Server closed the connection.
- LOG(ERROR) << "Server unexpectedly closed the connection.";
+ LOGE("Server unexpectedly closed the connection.");
reply->setInt32("result", ERROR_IO);
reply->post();
@@ -363,7 +367,7 @@ void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
continue;
}
- LOG(ERROR) << "Error sending rtsp request.";
+ LOGE("Error sending rtsp request.");
reply->setInt32("result", -errno);
reply->post();
return;
@@ -438,14 +442,14 @@ status_t ARTSPConnection::receive(void *data, size_t size) {
ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
if (n == 0) {
// Server closed the connection.
- LOG(ERROR) << "Server unexpectedly closed the connection.";
+ LOGE("Server unexpectedly closed the connection.");
return ERROR_IO;
} else if (n < 0) {
if (errno == EINTR) {
continue;
}
- LOG(ERROR) << "Error reading rtsp response.";
+ LOGE("Error reading rtsp response.");
return -errno;
}
@@ -516,7 +520,7 @@ bool ARTSPConnection::receiveRTSPReponse() {
notify->setObject("buffer", buffer);
notify->post();
} else {
- LOG(WARNING) << "received binary data, but no one cares.";
+ LOGW("received binary data, but no one cares.");
}
return true;
@@ -525,7 +529,7 @@ bool ARTSPConnection::receiveRTSPReponse() {
sp<ARTSPResponse> response = new ARTSPResponse;
response->mStatusLine = statusLine;
- LOG(INFO) << "status: " << response->mStatusLine;
+ LOGI("status: %s", response->mStatusLine.c_str());
ssize_t space1 = response->mStatusLine.find(" ");
if (space1 < 0) {
@@ -555,7 +559,7 @@ bool ARTSPConnection::receiveRTSPReponse() {
break;
}
- LOG(VERBOSE) << "line: " << line;
+ LOGV("line: %s", line.c_str());
ssize_t colonPos = line.find(":");
if (colonPos < 0) {
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 4a8cce8..612caff 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ASessionDescription"
+#include <utils/Log.h>
+
#include "ASessionDescription.h"
#include <media/stagefright/foundation/ADebug.h>
@@ -49,7 +53,7 @@ bool ASessionDescription::parse(const void *data, size_t size) {
mFormats.push(AString("[root]"));
AString desc((const char *)data, size);
- LOG(INFO) << desc;
+ LOGI("%s", desc.c_str());
size_t i = 0;
for (;;) {
@@ -102,7 +106,7 @@ bool ASessionDescription::parse(const void *data, size_t size) {
key.trim();
value.trim();
- LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+ LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
@@ -110,7 +114,8 @@ bool ASessionDescription::parse(const void *data, size_t size) {
case 'm':
{
- LOG(VERBOSE) << "new section '" << AString(line, 2, line.size() - 2) << "'";
+ LOGV("new section '%s'",
+ AString(line, 2, line.size() - 2).c_str());
mTracks.push(Attribs());
mFormats.push(AString(line, 2, line.size() - 2));
@@ -129,7 +134,7 @@ bool ASessionDescription::parse(const void *data, size_t size) {
key.trim();
value.trim();
- LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+ LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index a3864f1..09dc156 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -18,6 +18,10 @@
#define MY_HANDLER_H_
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MyHandler"
+#include <utils/Log.h>
+
#include "APacketSource.h"
#include "ARTPConnection.h"
#include "ARTSPConnection.h"
@@ -137,8 +141,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "connection request completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("connection request completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
AString request;
@@ -173,8 +177,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "DESCRIBE completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("DESCRIBE completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -251,8 +255,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "SETUP(" << index << ") completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("SETUP(%d) completed with result %d (%s)",
+ index, result, strerror(-result));
if (result == OK) {
CHECK(track != NULL);
@@ -326,8 +330,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "PLAY completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("PLAY completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -404,8 +408,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "TEARDOWN completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("TEARDOWN completed with result %d (%s)",
+ result, strerror(-result));
sp<AMessage> reply = new AMessage('disc', id());
@@ -431,7 +435,7 @@ struct MyHandler : public AHandler {
case 'chek':
{
if (mNumAccessUnitsReceived == 0) {
- LOG(INFO) << "stream ended? aborting.";
+ LOGI("stream ended? aborting.");
(new AMessage('abor', id()))->post();
break;
}
@@ -461,7 +465,7 @@ struct MyHandler : public AHandler {
CHECK(msg->findSize("track-index", &trackIndex));
if (trackIndex >= mTracks.size()) {
- LOG(ERROR) << "late packets ignored.";
+ LOGV("late packets ignored.");
break;
}
@@ -469,7 +473,7 @@ struct MyHandler : public AHandler {
int32_t eos;
if (msg->findInt32("eos", &eos)) {
- LOG(INFO) << "received BYE on track index " << trackIndex;
+ LOGI("received BYE on track index %d", trackIndex);
#if 0
track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
#endif
@@ -484,14 +488,13 @@ struct MyHandler : public AHandler {
uint32_t seqNum = (uint32_t)accessUnit->int32Data();
if (mSeekPending) {
- LOG(INFO) << "we're seeking, dropping stale packet.";
+ LOGV("we're seeking, dropping stale packet.");
break;
}
if (seqNum < track->mFirstSeqNumInSegment) {
- LOG(INFO) << "dropping stale access-unit "
- << "(" << seqNum << " < "
- << track->mFirstSeqNumInSegment << ")";
+ LOGV("dropping stale access-unit (%d < %d)",
+ seqNum, track->mFirstSeqNumInSegment);
break;
}
@@ -506,10 +509,8 @@ struct MyHandler : public AHandler {
if (track->mNewSegment) {
track->mNewSegment = false;
- LOG(VERBOSE) << "first segment unit ntpTime="
- << StringPrintf("0x%016llx", ntpTime)
- << " rtpTime=" << rtpTime
- << " seq=" << seqNum;
+ LOGV("first segment unit ntpTime=0x%016llx rtpTime=%u seq=%d",
+ ntpTime, rtpTime, seqNum);
}
if (mFirstAccessUnit) {
@@ -535,7 +536,7 @@ struct MyHandler : public AHandler {
int32_t damaged;
if (accessUnit->meta()->findInt32("damaged", &damaged)
&& damaged != 0) {
- LOG(INFO) << "ignoring damaged AU";
+ LOGI("ignoring damaged AU");
} else
#endif
{
@@ -608,8 +609,8 @@ struct MyHandler : public AHandler {
int32_t result;
CHECK(msg->findInt32("result", &result));
- LOG(INFO) << "PLAY completed with result "
- << result << " (" << strerror(-result) << ")";
+ LOGI("PLAY completed with result %d (%s)",
+ result, strerror(-result));
if (result == OK) {
sp<RefBase> obj;
@@ -622,12 +623,12 @@ struct MyHandler : public AHandler {
} else {
parsePlayResponse(response);
- LOG(INFO) << "seek completed.";
+ LOGI("seek completed.");
}
}
if (result != OK) {
- LOG(ERROR) << "seek failed, aborting.";
+ LOGE("seek failed, aborting.");
(new AMessage('abor', id()))->post();
}
@@ -652,11 +653,10 @@ struct MyHandler : public AHandler {
{
if (!mReceivedFirstRTCPPacket) {
if (mTryTCPInterleaving) {
- LOG(WARNING) << "Never received any data, disconnecting.";
+ LOGW("Never received any data, disconnecting.");
(new AMessage('abor', id()))->post();
} else {
- LOG(WARNING)
- << "Never received any data, switching transports.";
+ LOGW("Never received any data, switching transports.");
mTryTCPInterleaving = true;
@@ -700,7 +700,7 @@ struct MyHandler : public AHandler {
}
AString range = response->mHeaders.valueAt(i);
- LOG(VERBOSE) << "Range: " << range;
+ LOGV("Range: %s", range.c_str());
AString val;
CHECK(GetAttribute(range.c_str(), "npt", &val));
@@ -724,7 +724,7 @@ struct MyHandler : public AHandler {
for (List<AString>::iterator it = streamInfos.begin();
it != streamInfos.end(); ++it) {
(*it).trim();
- LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it;
+ LOGV("streamInfo[%d] = %s", n, (*it).c_str());
CHECK(GetAttribute((*it).c_str(), "url", &val));
@@ -748,8 +748,7 @@ struct MyHandler : public AHandler {
uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
- LOG(VERBOSE) << "track #" << n
- << ": rtpTime=" << rtpTime << " <=> npt=" << npt1;
+ LOGV("track #%d: rtpTime=%u <=> ntp=%.2f", n, rtpTime, npt1);
info->mPacketSource->setNormalPlayTimeMapping(
rtpTime, (int64_t)(npt1 * 1E6));
@@ -806,8 +805,7 @@ private:
new APacketSource(mSessionDesc, index);
if (source->initCheck() != OK) {
- LOG(WARNING) << "Unsupported format. Ignoring track #"
- << index << ".";
+ LOGW("Unsupported format. Ignoring track #%d.", index);
sp<AMessage> reply = new AMessage('setu', id());
reply->setSize("index", index);
@@ -830,7 +828,7 @@ private:
info->mFirstSeqNumInSegment = 0;
info->mNewSegment = true;
- LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL;
+ LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str());
AString request = "SETUP ";
request.append(trackURL);
diff --git a/media/libstagefright/rtsp/UDPPusher.cpp b/media/libstagefright/rtsp/UDPPusher.cpp
index 28a343f..576b3ca 100644
--- a/media/libstagefright/rtsp/UDPPusher.cpp
+++ b/media/libstagefright/rtsp/UDPPusher.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "UDPPusher"
+#include <utils/Log.h>
+
#include "UDPPusher.h"
#include <media/stagefright/foundation/ABuffer.h>
@@ -67,7 +71,7 @@ void UDPPusher::start() {
bool UDPPusher::onPush() {
uint32_t length;
if (fread(&length, 1, sizeof(length), mFile) < sizeof(length)) {
- LOG(INFO) << "No more data to push.";
+ LOGI("No more data to push.");
return false;
}
@@ -77,7 +81,7 @@ bool UDPPusher::onPush() {
sp<ABuffer> buffer = new ABuffer(length);
if (fread(buffer->data(), 1, length, mFile) < length) {
- LOG(ERROR) << "File truncated?.";
+ LOGE("File truncated?.");
return false;
}
@@ -89,7 +93,7 @@ bool UDPPusher::onPush() {
uint32_t timeMs;
if (fread(&timeMs, 1, sizeof(timeMs), mFile) < sizeof(timeMs)) {
- LOG(INFO) << "No more data to push.";
+ LOGI("No more data to push.");
return false;
}
@@ -109,7 +113,7 @@ void UDPPusher::onMessageReceived(const sp<AMessage> &msg) {
case kWhatPush:
{
if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) {
- LOG(INFO) << "emulating BYE packet";
+ LOGI("emulating BYE packet");
sp<ABuffer> buffer = new ABuffer(8);
uint8_t *data = buffer->data();
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
index cec6c0c..f0cb5a5 100644
--- a/media/libstagefright/rtsp/rtp_test.cpp
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "rtp_test"
+#include <utils/Log.h>
+
#include <binder/ProcessState.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -200,8 +204,7 @@ int main(int argc, char **argv) {
continue;
}
- LOG(ERROR) << "decoder returned error "
- << StringPrintf("0x%08x", err);
+ LOGE("decoder returned error 0x%08x", err);
break;
}
diff --git a/media/mtp/MtpCursor.cpp b/media/mtp/MtpCursor.cpp
index 3ba07cc..8c964b4 100644
--- a/media/mtp/MtpCursor.cpp
+++ b/media/mtp/MtpCursor.cpp
@@ -371,7 +371,7 @@ bool MtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
goto fail;
break;
default:
- LOGE("fillStorage: unknown column %d\n", mColumns[i]);
+ LOGE("fillObject: unknown column %d\n", mColumns[i]);
goto fail;
}
}
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
index 33d2976..1d81129 100644
--- a/media/tests/CameraBrowser/Android.mk
+++ b/media/tests/CameraBrowser/Android.mk
@@ -1,6 +1,8 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := CameraBrowser
diff --git a/media/tests/CameraBrowser/res/layout/object_info.xml b/media/tests/CameraBrowser/res/layout/object_info.xml
index c7fd830..ac210b9 100644
--- a/media/tests/CameraBrowser/res/layout/object_info.xml
+++ b/media/tests/CameraBrowser/res/layout/object_info.xml
@@ -41,6 +41,16 @@
style="@style/info_value" />
</TableRow>
<TableRow>
+ <TextView android:id="@+id/format_label"
+ android:text="@string/format_label"
+ android:layout_gravity="right"
+ android:layout_marginRight="8dip"
+ style="@style/info_label" />
+
+ <TextView android:id="@+id/format"
+ style="@style/info_value" />
+ </TableRow>
+ <TableRow>
<TextView android:id="@+id/thumb_width_label"
android:text="@string/thumb_width_label"
android:layout_gravity="right"
diff --git a/media/tests/CameraBrowser/res/values/strings.xml b/media/tests/CameraBrowser/res/values/strings.xml
index 56c5111..cd477f1 100644
--- a/media/tests/CameraBrowser/res/values/strings.xml
+++ b/media/tests/CameraBrowser/res/values/strings.xml
@@ -20,6 +20,7 @@
<!-- for object info -->
<string name="name_label">Name: </string>
<string name="size_label">Size: </string>
+ <string name="format_label">Format: </string>
<string name="thumb_width_label">Thumb Width: </string>
<string name="thumb_height_label">Thumb Height: </string>
<string name="thumb_size_label">Thumb Size: </string>
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
index fc9989d..6d34fd4 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
@@ -44,8 +44,8 @@ public class ObjectBrowser extends ListActivity {
private Cursor mCursor;
private ObjectCursorAdapter mAdapter;
private int mDeviceID;
- private int mStorageID;
- private int mObjectID;
+ private long mStorageID;
+ private long mObjectID;
private static final String[] OBJECT_COLUMNS =
new String[] { Mtp.Object._ID, Mtp.Object.NAME, Mtp.Object.FORMAT, Mtp.Object.THUMB };
@@ -65,8 +65,8 @@ public class ObjectBrowser extends ListActivity {
super.onResume();
mDeviceID = getIntent().getIntExtra("device", 0);
- mStorageID = getIntent().getIntExtra("storage", 0);
- mObjectID = getIntent().getIntExtra("object", 0);
+ mStorageID = getIntent().getLongExtra("storage", 0);
+ mObjectID = getIntent().getLongExtra("object", 0);
if (mDeviceID != 0 && mStorageID != 0) {
Cursor c;
Uri uri;
@@ -88,7 +88,7 @@ public class ObjectBrowser extends ListActivity {
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
- int rowID = (int)mAdapter.getItemId(position);
+ long rowID = mAdapter.getItemId(position);
Cursor c = getContentResolver().query(
Mtp.Object.getContentUri(mDeviceID, rowID),
OBJECT_COLUMNS, null, null, null);
@@ -101,14 +101,14 @@ public class ObjectBrowser extends ListActivity {
format = c.getLong(FORMAT_COLUMN);
Log.d(TAG, "rowId: " + rowId + " name: " + name + " format: " + format);
}
- if (format == MtpConstants.FORMAT_JFIF) {
- Intent intent = new Intent(this, ObjectViewer.class);
+ if (format == MtpConstants.FORMAT_ASSOCIATION) {
+ Intent intent = new Intent(this, ObjectBrowser.class);
intent.putExtra("device", mDeviceID);
intent.putExtra("storage", mStorageID);
- intent.putExtra("object",rowID);
+ intent.putExtra("object", rowID);
startActivity(intent);
} else {
- Intent intent = new Intent(this, ObjectBrowser.class);
+ Intent intent = new Intent(this, ObjectViewer.class);
intent.putExtra("device", mDeviceID);
intent.putExtra("storage", mStorageID);
intent.putExtra("object", rowID);
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
index aa49cd8..5899bc1 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
@@ -51,8 +51,8 @@ public class ObjectViewer extends Activity {
private static final String TAG = "ObjectViewer";
private int mDeviceID;
- private int mStorageID;
- private int mObjectID;
+ private long mStorageID;
+ private long mObjectID;
private static final String[] OBJECT_COLUMNS =
new String[] { Mtp.Object._ID,
@@ -69,6 +69,7 @@ public class ObjectViewer extends Activity {
Mtp.Object.DATE_MODIFIED,
Mtp.Object.KEYWORDS,
Mtp.Object.THUMB,
+ Mtp.Object.FORMAT,
};
@Override
@@ -83,8 +84,8 @@ public class ObjectViewer extends Activity {
super.onResume();
mDeviceID = getIntent().getIntExtra("device", 0);
- mStorageID = getIntent().getIntExtra("storage", 0);
- mObjectID = getIntent().getIntExtra("object", 0);
+ mStorageID = getIntent().getLongExtra("storage", 0);
+ mObjectID = getIntent().getLongExtra("object", 0);
if (mDeviceID != 0 && mObjectID != 0) {
Cursor c = getContentResolver().query(
@@ -125,6 +126,8 @@ public class ObjectViewer extends Activity {
thumbView.setImageBitmap(bitmap);
}
}
+ view = (TextView)findViewById(R.id.format);
+ view.setText(Long.toHexString(c.getLong(14)).toUpperCase());
}
}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
index 6ddf4e7..63e036e 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/StorageBrowser.java
@@ -70,7 +70,7 @@ public class StorageBrowser extends ListActivity {
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, ObjectBrowser.class);
intent.putExtra("device", mDeviceID);
- intent.putExtra("storage", (int)mAdapter.getItemId(position));
+ intent.putExtra("storage", mAdapter.getItemId(position));
startActivity(intent);
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
index db0db70..d5538f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -414,13 +414,13 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -433,11 +433,24 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr
mp = new MediaPlayer();
mp.setDataSource(MediaNames.SINE_200_1000);
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
- getReverb(mp.getAudioSessionId());
- mReverb.setRoomLevel((short)0);
- mReverb.setReverbLevel((short)0);
- mReverb.setDecayTime(2000);
- mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of EnvironmentalReverb constructor otherwise an
+ // auxiliary reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(EnvironmentalReverb.PARAM_ROOM_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_REVERB_LEVEL, (short)0);
+ rvb.setParameter(EnvironmentalReverb.PARAM_DECAY_TIME, 2000);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -460,13 +473,15 @@ public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFr
loge(msg, "sleep() interrupted");
}
finally {
- releaseReverb();
if (mp != null) {
mp.release();
}
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
index c14319a..fbd8a78 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -257,13 +257,13 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi
EnergyProbe probe = null;
AudioEffect vc = null;
MediaPlayer mp = null;
+ AudioEffect rvb = null;
AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
am.setStreamVolume(AudioManager.STREAM_MUSIC,
am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
0);
try {
- probe = new EnergyProbe(0);
// creating a volume controller on output mix ensures that ro.audio.silent mutes
// audio after the effects and not before
vc = new AudioEffect(
@@ -279,6 +279,22 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi
getReverb(mp.getAudioSessionId());
mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
mReverb.setEnabled(true);
+
+ // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
+ // reverb will be chosen by the effect framework as we are on session 0
+ rvb = new AudioEffect(
+ AudioEffect.EFFECT_TYPE_NULL,
+ UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"),
+ 0,
+ 0);
+
+ rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
+ rvb.setEnabled(true);
+
+ // create probe after reverb so that it is chained behind the reverb in the
+ // effect chain
+ probe = new EnergyProbe(0);
+
mp.prepare();
mp.start();
Thread.sleep(1000);
@@ -308,6 +324,9 @@ public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<Medi
if (vc != null) {
vc.release();
}
+ if (rvb != null) {
+ rvb.release();
+ }
if (probe != null) {
probe.release();
}
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 5d6ac26..747c829 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -136,30 +136,24 @@ void* Loader::open(EGLNativeDisplayType display, int impl, egl_connection_t* cnx
*/
void* dso;
- char path[PATH_MAX];
int index = int(display);
driver_t* hnd = 0;
- const char* const format = "/system/lib/egl/lib%s_%s.so";
char const* tag = getTag(index, impl);
if (tag) {
- snprintf(path, PATH_MAX, format, "GLES", tag);
- dso = load_driver(path, cnx, EGL | GLESv1_CM | GLESv2);
+ dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
if (dso) {
hnd = new driver_t(dso);
} else {
// Always load EGL first
- snprintf(path, PATH_MAX, format, "EGL", tag);
- dso = load_driver(path, cnx, EGL);
+ dso = load_driver("EGL", tag, cnx, EGL);
if (dso) {
hnd = new driver_t(dso);
// TODO: make this more automated
- snprintf(path, PATH_MAX, format, "GLESv1_CM", tag);
- hnd->set( load_driver(path, cnx, GLESv1_CM), GLESv1_CM );
+ hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
- snprintf(path, PATH_MAX, format, "GLESv2", tag);
- hnd->set( load_driver(path, cnx, GLESv2), GLESv2 );
+ hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
}
}
}
@@ -222,12 +216,20 @@ void Loader::init_api(void* dso,
}
}
-void *Loader::load_driver(const char* driver_absolute_path,
+void *Loader::load_driver(const char* kind, const char *tag,
egl_connection_t* cnx, uint32_t mask)
{
+ char driver_absolute_path[PATH_MAX];
+ const char* const search1 = "/vendor/lib/egl/lib%s_%s.so";
+ const char* const search2 = "/system/lib/egl/lib%s_%s.so";
+
+ snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag);
if (access(driver_absolute_path, R_OK)) {
- // this happens often, we don't want to log an error
- return 0;
+ snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag);
+ if (access(driver_absolute_path, R_OK)) {
+ // this happens often, we don't want to log an error
+ return 0;
+ }
}
void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 8659b0b..580d6e4 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -74,7 +74,7 @@ public:
private:
Loader();
- void *load_driver(const char* driver, egl_connection_t* cnx, uint32_t mask);
+ void *load_driver(const char* kind, const char *tag, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
void init_api(void* dso,
diff --git a/opengl/tests/testLatency/Android.mk b/opengl/tests/testLatency/Android.mk
new file mode 100644
index 0000000..96417c7
--- /dev/null
+++ b/opengl/tests/testLatency/Android.mk
@@ -0,0 +1,20 @@
+#########################################################################
+# Test end-to-end latency.
+#########################################################################
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SDK_VERSION := 8
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := TestLatency
+
+include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testLatency/AndroidManifest.xml b/opengl/tests/testLatency/AndroidManifest.xml
new file mode 100644
index 0000000..741266e
--- /dev/null
+++ b/opengl/tests/testLatency/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.testlatency">
+ <uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8" />
+
+ <application
+ android:label="@string/testLatency_activity">
+ <activity android:name="TestLatencyActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:launchMode="singleTask"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/opengl/tests/testLatency/res/values/strings.xml b/opengl/tests/testLatency/res/values/strings.xml
new file mode 100644
index 0000000..0309991
--- /dev/null
+++ b/opengl/tests/testLatency/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="testLatency_activity">TestLatency</string>
+
+</resources>
+
diff --git a/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java
new file mode 100644
index 0000000..ed993cb
--- /dev/null
+++ b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testlatency;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.io.File;
+
+
+public class TestLatencyActivity extends Activity {
+
+ TestLatencyView mView;
+
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mView = new TestLatencyView(getApplication());
+ setContentView(mView);
+ mView.setFocusableInTouchMode(true);
+ }
+
+ @Override protected void onPause() {
+ super.onPause();
+ mView.onPause();
+ }
+
+ @Override protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+}
diff --git a/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java
new file mode 100644
index 0000000..d62bf17
--- /dev/null
+++ b/opengl/tests/testLatency/src/com/android/testlatency/TestLatencyView.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testlatency;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+
+/**
+ * An implementation of SurfaceView that uses the dedicated surface for
+ * displaying an OpenGL animation. This allows the animation to run in a
+ * separate thread, without requiring that it be driven by the update mechanism
+ * of the view hierarchy.
+ *
+ * The application-specific rendering code is delegated to a GLView.Renderer
+ * instance.
+ */
+class TestLatencyView extends GLSurfaceView {
+ private static String TAG = "TestLatencyiew";
+ private float mX;
+ private float mY;
+ private float mDX;
+ private float mDY;
+ private long mT;
+ private long mDT;
+
+ public TestLatencyView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ setRenderer(new Renderer());
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_MOVE:
+ float x = event.getX();
+ float y = event.getY();
+ long t = event.getEventTime();
+ synchronized(this) {
+ mDT = t - mT;
+ mT = t;
+ mDX = x - mX;
+ mX = x;
+ mDY = y - mY;
+ mY = y;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ private class Renderer implements GLSurfaceView.Renderer {
+ private float mScaleX, mScaleY, mOffsetX, mOffsetY;
+ private final float MS_PER_FRAME = 1000 / 60;
+ public Renderer() {
+ mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4)
+ .order(ByteOrder.nativeOrder()).asFloatBuffer();
+ }
+
+
+ public void onDrawFrame(GL10 gl) {
+ GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
+ GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+ GLES20.glUseProgram(mProgram);
+ checkGlError("glUseProgram");
+
+ float x, y, dx, dy;
+ long t, dt;
+ synchronized(TestLatencyView.this) {
+ x = mX;
+ y = mY;
+ dx = mDX;
+ dy = mDY;
+ dt = mDT;
+ }
+
+ if (dt > 0) {
+ dx = dx * MS_PER_FRAME / dt;
+ dy = dy * MS_PER_FRAME / dt;
+ }
+
+ GLES20.glEnableVertexAttribArray(mvPositionHandle);
+ checkGlError("glEnableVertexAttribArray");
+ GLES20.glEnableVertexAttribArray(mvColorHandle);
+ checkGlError("glEnableVertexAttribArray");
+ for(int step = 0; step < 8; step++) {
+ float sx = (x + dx * step) * mScaleX + mOffsetX;
+ float sy = (y + dy * step) * mScaleY + mOffsetY;
+ int cbase = step * 4;
+
+ for (int i = 0; i < mTriangleVerticesData.length; i += 6) {
+ mTriangleVerticesData2[i] = sx + mTriangleVerticesData[i];
+ mTriangleVerticesData2[i+1] = -sy + mTriangleVerticesData[i+1];
+ mTriangleVerticesData2[i+2] = mColors[cbase];
+ mTriangleVerticesData2[i+3] = mColors[cbase+1];
+ mTriangleVerticesData2[i+4] = mColors[cbase+2];
+ mTriangleVerticesData2[i+5] = mColors[cbase+3];
+ }
+ mTriangleVertices.position(0);
+ mTriangleVertices.put(mTriangleVerticesData2).position(0);
+
+ GLES20.glVertexAttribPointer(mvPositionHandle, 2, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
+ checkGlError("glVertexAttribPointer mvPosition");
+ mTriangleVertices.put(mTriangleVerticesData2).position(2);
+ GLES20.glVertexAttribPointer(mvColorHandle, 4, GLES20.GL_FLOAT, false, 6*4, mTriangleVertices);
+ checkGlError("glVertexAttribPointer mvColor");
+ GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
+ checkGlError("glDrawArrays");
+ }
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ GLES20.glViewport(0, 0, width, height);
+ mScaleX = 2.0f / width;
+ mScaleY = 2.0f / height;
+ mOffsetX = -1f;
+ mOffsetY = -1f;
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ mProgram = createProgram(mVertexShader, mFragmentShader);
+ if (mProgram == 0) {
+ return;
+ }
+ mvPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+ checkGlError("glGetAttribLocation");
+ if (mvPositionHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for vPosition");
+ }
+ mvColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
+ checkGlError("glGetAttribLocation");
+ if (mvColorHandle == -1) {
+ throw new RuntimeException("Could not get attrib location for vColor");
+ }
+ }
+
+ private int loadShader(int shaderType, String source) {
+ int shader = GLES20.glCreateShader(shaderType);
+ if (shader != 0) {
+ GLES20.glShaderSource(shader, source);
+ GLES20.glCompileShader(shader);
+ int[] compiled = new int[1];
+ GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+ if (compiled[0] == 0) {
+ Log.e(TAG, "Could not compile shader " + shaderType + ":");
+ Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+ GLES20.glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ return shader;
+ }
+
+ private int createProgram(String vertexSource, String fragmentSource) {
+ int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+ if (vertexShader == 0) {
+ return 0;
+ }
+
+ int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+ if (pixelShader == 0) {
+ return 0;
+ }
+
+ int program = GLES20.glCreateProgram();
+ if (program != 0) {
+ GLES20.glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader vertexShader");
+ GLES20.glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader pixelShader");
+ GLES20.glLinkProgram(program);
+ int[] linkStatus = new int[1];
+ GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+ if (linkStatus[0] != GLES20.GL_TRUE) {
+ Log.e(TAG, "Could not link program: ");
+ Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+ GLES20.glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+ }
+
+ private void checkGlError(String op) {
+ int error;
+ while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+ Log.e(TAG, op + ": glError " + error);
+ throw new RuntimeException(op + ": glError " + error);
+ }
+ }
+
+ // X, Y, R G B A
+ private final float[] mTriangleVerticesData = {
+ -0.025f, 0.3f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.0f , 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.025f, 0.3f, 1.0f, 1.0f, 255.0f, 1.0f
+ };
+
+ // Color cascade:
+ private final float[] mColors = {
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.5f, 0.0f, 1.0f,
+ 0.5f, 0.5f, 0.0f, 1.0f,
+
+ 0.0f, 0.0f, 0.5f, 1.0f,
+ 1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f, 1.0f
+ };
+
+ private float[] mTriangleVerticesData2 = new float[mTriangleVerticesData.length];
+ private FloatBuffer mTriangleVertices;
+
+ private final String mVertexShader = "attribute vec4 aPosition;\n"
+ + "attribute vec4 aColor;\n"
+ + "varying vec4 vColor;\n"
+ + "void main() {\n"
+ + " gl_Position = aPosition;\n"
+ + " vColor = aColor;\n"
+ + "}\n";
+
+ private final String mFragmentShader = "precision mediump float;\n"
+ + "varying vec4 vColor;\n"
+ + "void main() {\n"
+ + " gl_FragColor = vColor;\n"
+ + "}\n";
+
+ private int mProgram;
+ private int mvPositionHandle;
+ private int mvColorHandle;
+
+ }
+}
+
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 43bb26a..3980189 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -3,16 +3,16 @@
/**
* Copyright (c) 2009, The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
@@ -24,6 +24,7 @@
<string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string>
<string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi</string>
<bool name="def_auto_time">true</bool>
+ <bool name="def_auto_time_zone">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
<integer name="def_screen_brightness">102</integer>
@@ -31,12 +32,12 @@
<fraction name="def_window_animation_scale">100%</fraction>
<fraction name="def_window_transition_scale">100%</fraction>
<bool name="def_haptic_feedback">true</bool>
-
+
<bool name="def_bluetooth_on">false</bool>
<bool name="def_install_non_market_apps">false</bool>
- <!-- Comma-separated list of location providers.
+ <!-- Comma-separated list of location providers.
Network location is off by default because it requires
- user opt-in via Setup Wizard or Settings.
+ user opt-in via Setup Wizard or Settings.
-->
<string name="def_location_providers_allowed" translatable="false">gps</string>
<bool name="assisted_gps_enabled">true</bool>
@@ -45,11 +46,11 @@
<bool name="def_usb_mass_storage_enabled">true</bool>
<bool name="def_wifi_on">false</bool>
<bool name="def_networks_available_notification_on">true</bool>
-
+
<bool name="def_backup_enabled">false</bool>
<string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string>
- <!-- Default value for whether or not to pulse the notification LED when there is a
+ <!-- Default value for whether or not to pulse the notification LED when there is a
pending notification -->
<bool name="def_notification_pulse">true</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 8eb3fe6..9ac832b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,6 +16,15 @@
package com.android.providers.settings;
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@@ -36,14 +45,6 @@ import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
@@ -60,7 +61,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 58;
+ private static final int DATABASE_VERSION = 59;
private Context mContext;
@@ -757,6 +758,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 58;
}
+ if (upgradeVersion == 58) {
+ /* Add default for new Auto Time Zone */
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT INTO secure(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 59;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -1067,7 +1085,10 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
R.bool.def_auto_time); // Sync time to NITZ
-
+
+ loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+ R.bool.def_auto_time_zone); // Sync timezone to NITZ
+
loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
R.integer.def_screen_brightness);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index 7ccf210..0fc092e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -711,21 +711,20 @@ public class StatusBarPolicy {
ConnectivityManager.EXTRA_NETWORK_INFO));
int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus);
- if (info.isConnected() == false) return;
+
+ int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
switch (info.getType()) {
case ConnectivityManager.TYPE_MOBILE:
- if (info.isConnected()) {
- updateDataNetType(info.getSubtype(), connectionStatus);
- updateDataIcon();
- updateSignalStrength(); // apply any change in connectionStatus
- }
+ mInetCondition = inetCondition;
+ updateDataNetType(info.getSubtype());
+ updateDataIcon();
+ updateSignalStrength(); // apply any change in connectionStatus
break;
case ConnectivityManager.TYPE_WIFI:
+ mInetCondition = inetCondition;
if (info.isConnected()) {
mIsWifiConnected = true;
- mInetCondition =
- (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
int iconId;
if (mLastWifiSignalLevel == -1) {
iconId = sWifiSignalImages[mInetCondition][0];
@@ -738,7 +737,6 @@ public class StatusBarPolicy {
} else {
mLastWifiSignalLevel = -1;
mIsWifiConnected = false;
- mInetCondition = 0;
int iconId = sWifiSignalImages[0][0];
mService.setIcon("wifi", iconId, 0);
@@ -777,9 +775,8 @@ public class StatusBarPolicy {
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
mDataState = state;
- updateDataNetType(networkType, 0);
+ updateDataNetType(networkType);
updateDataIcon();
- updateSignalStrength(); // apply the change in connection status
}
@Override
@@ -940,8 +937,7 @@ public class StatusBarPolicy {
return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
}
- private final void updateDataNetType(int net, int inetCondition) {
- mInetCondition = (inetCondition > INET_CONDITION_THRESHOLD ? 1 : 0);
+ private final void updateDataNetType(int net) {
switch (net) {
case TelephonyManager.NETWORK_TYPE_EDGE:
mDataIconList = sDataNetType_e[mInetCondition];
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
index 55d31ec..29df28e 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
@@ -30,6 +30,7 @@ import android.content.DialogInterface.OnCancelListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.Usb;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -70,11 +71,11 @@ public class UsbStorageActivity extends Activity
static final boolean localLOGV = false;
/** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
+ if (intent.getAction().equals(Usb.ACTION_USB_STATE)) {
+ handleUsbStateChanged(intent);
}
}
};
@@ -139,7 +140,7 @@ public class UsbStorageActivity extends Activity
super.onResume();
mStorageManager.registerListener(mStorageListener);
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ registerReceiver(mUsbStateReceiver, new IntentFilter(Usb.ACTION_USB_STATE));
try {
switchDisplay(mStorageManager.isUsbMassStorageEnabled());
} catch (Exception ex) {
@@ -151,15 +152,15 @@ public class UsbStorageActivity extends Activity
protected void onPause() {
super.onPause();
- unregisterReceiver(mBatteryReceiver);
+ unregisterReceiver(mUsbStateReceiver);
if (mStorageManager == null && mStorageListener != null) {
mStorageManager.unregisterListener(mStorageListener);
}
}
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
+ private void handleUsbStateChanged(Intent intent) {
+ boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
+ if (!connected) {
// It was disconnected from the plug, so finish
finish();
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 315bb87..aae3cff 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -58,6 +58,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.GregorianCalendar;
import java.util.List;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -129,6 +130,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private InetAddress mDefaultDns;
+ // used in DBG mode to track inet condition reports
+ private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
+ private ArrayList mInetLog;
+
private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
@@ -339,6 +344,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mTethering.getTetherableBluetoothRegexs().length != 0) &&
mTethering.getUpstreamIfaceRegexs().length != 0);
+ if (DBG) {
+ mInetLog = new ArrayList();
+ }
}
@@ -1005,11 +1013,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
newNet = tryFailover(prevNetType);
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0; // we're not connected anymore
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
// do this before we broadcast the change
handleConnectivityChange(prevNetType);
@@ -1168,12 +1184,20 @@ public class ConnectivityService extends IConnectivityManager.Stub {
newNet = tryFailover(info.getType());
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0;
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
sendStickyBroadcast(intent);
/*
* If the failover network is already connected, then immediately send
@@ -1598,6 +1622,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
pw.println();
mTethering.dump(fd, pw, args);
+
+ if (mInetLog != null) {
+ pw.println();
+ pw.println("Inet condition reports:");
+ for(int i = 0; i < mInetLog.size(); i++) {
+ pw.println(mInetLog.get(i));
+ }
+ }
}
// must be stateless - things change under us.
@@ -1874,6 +1906,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
android.Manifest.permission.STATUS_BAR,
"ConnectivityService");
+ if (DBG) {
+ int pid = getCallingPid();
+ int uid = getCallingUid();
+ String s = pid + "(" + uid + ") reports inet is " +
+ (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
+ "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
+ mInetLog.add(s);
+ while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
+ mInetLog.remove(0);
+ }
+ }
mHandler.sendMessage(mHandler.obtainMessage(
NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage));
}
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 024aec5..29ca9a4 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -53,10 +53,6 @@ public class InputManager {
private final Context mContext;
private final WindowManagerService mWindowManagerService;
- private int mTouchScreenConfig;
- private int mKeyboardConfig;
- private int mNavigationConfig;
-
private static native void nativeInit(Callbacks callbacks);
private static native void nativeStart();
private static native void nativeSetDisplaySize(int displayId, int width, int height);
@@ -79,6 +75,7 @@ public class InputManager {
private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
private static native void nativeSetFocusedApplication(InputApplication application);
private static native InputDevice nativeGetInputDevice(int deviceId);
+ private static native void nativeGetInputConfiguration(Configuration configuration);
private static native int[] nativeGetInputDeviceIds();
private static native String nativeDump();
@@ -114,10 +111,6 @@ public class InputManager {
this.mCallbacks = new Callbacks();
- mTouchScreenConfig = Configuration.TOUCHSCREEN_NOTOUCH;
- mKeyboardConfig = Configuration.KEYBOARD_NOKEYS;
- mNavigationConfig = Configuration.NAVIGATION_NONAV;
-
init();
}
@@ -154,9 +147,7 @@ public class InputManager {
throw new IllegalArgumentException("config must not be null.");
}
- config.touchscreen = mTouchScreenConfig;
- config.keyboard = mKeyboardConfig;
- config.navigation = mNavigationConfig;
+ nativeGetInputConfiguration(config);
}
/**
@@ -367,12 +358,7 @@ public class InputManager {
}
@SuppressWarnings("unused")
- public void notifyConfigurationChanged(long whenNanos,
- int touchScreenConfig, int keyboardConfig, int navigationConfig) {
- mTouchScreenConfig = touchScreenConfig;
- mKeyboardConfig = keyboardConfig;
- mNavigationConfig = navigationConfig;
-
+ public void notifyConfigurationChanged(long whenNanos) {
mWindowManagerService.sendNewConfiguration();
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 8452a9f..aa1bcf7 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1960,7 +1960,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Geocoder
- public boolean geocoderIsImplemented() {
+ public boolean geocoderIsPresent() {
return mGeocodeProvider != null;
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1069216..c82a085 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -222,6 +222,9 @@ class PackageManagerService extends IPackageManager.Stub {
// This is the object monitoring the system app dir.
final FileObserver mSystemInstallObserver;
+ // This is the object monitoring the system app dir.
+ final FileObserver mVendorInstallObserver;
+
// This is the object monitoring mAppInstallDir.
final FileObserver mAppInstallObserver;
@@ -234,6 +237,7 @@ class PackageManagerService extends IPackageManager.Stub {
final File mFrameworkDir;
final File mSystemAppDir;
+ final File mVendorAppDir;
final File mAppInstallDir;
final File mDalvikCacheDir;
@@ -927,6 +931,14 @@ class PackageManagerService extends IPackageManager.Stub {
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+ // Collect all vendor packages.
+ mVendorAppDir = new File("/vendor/app");
+ mVendorInstallObserver = new AppDirObserver(
+ mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
+ mVendorInstallObserver.startWatching();
+ scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+
if (mInstaller != null) {
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
@@ -2493,9 +2505,13 @@ class PackageManagerService extends IPackageManager.Stub {
}
private void scanDirLI(File dir, int flags, int scanMode) {
- Log.d(TAG, "Scanning app dir " + dir);
-
String[] files = dir.list();
+ if (files == null) {
+ Log.d(TAG, "No files in app dir " + dir);
+ return;
+ }
+
+ Log.d(TAG, "Scanning app dir " + dir);
int i;
for (i=0; i<files.length; i++) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index fb8e888..3e4f522 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -8325,6 +8325,11 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (mDisplay == null) {
+ // Not yet initialized, nothing to do.
+ return;
+ }
+
boolean recoveringMemory = false;
if (mForceRemoves != null) {
recoveringMemory = true;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5432890..c896c94 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -562,6 +562,11 @@ public final class ActivityManagerService extends ActivityManagerNative
BroadcastRecord mPendingBroadcast = null;
/**
+ * The receiver index that is pending, to restart the broadcast if needed.
+ */
+ int mPendingBroadcastRecvIndex;
+
+ /**
* Keeps track of all IIntentReceivers that have been registered for
* broadcasts. Hash keys are the receiver IBinder, hash value is
* a ReceiverList.
@@ -748,6 +753,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName mTopComponent;
String mTopAction;
String mTopData;
+ boolean mProcessesReady = false;
boolean mSystemReady = false;
boolean mBooting = false;
boolean mWaitingUpdate = false;
@@ -965,7 +971,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
- broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
+ Intent intent = new Intent("android.intent.action.ANR");
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
+ broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID);
@@ -1052,7 +1062,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Only process broadcast timeouts if the system is ready. That way
// PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
// to do heavy lifting for system up
- if (mSystemReady) {
+ if (mProcessesReady) {
broadcastTimeout();
}
} break;
@@ -1384,7 +1394,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mBatteryStatsService = new BatteryStatsService(new File(
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
- mBatteryStatsService.getActiveStatistics().writeLocked();
+ mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
@@ -1537,7 +1547,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
mLastWriteTime = now;
- mBatteryStatsService.getActiveStatistics().writeLocked();
+ mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
}
}
}
@@ -1718,10 +1728,12 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!knownToBeDead || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
return app;
} else {
// An application record is attached to a previous process,
// clean it up now.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
handleAppDiedLocked(app, true);
}
}
@@ -1733,6 +1745,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mBadProcesses.get(info.processName, info.uid) != null) {
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ + "/" + info.processName);
return null;
}
} else {
@@ -1740,6 +1754,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ + "/" + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
@@ -1761,12 +1777,13 @@ public final class ActivityManagerService extends ActivityManagerNative
// If the system is not ready yet, then hold off on starting this
// process until it is.
- if (!mSystemReady
+ if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
+ if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
return app;
}
@@ -1788,6 +1805,8 @@ public final class ActivityManagerService extends ActivityManagerNative
app.pid = 0;
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
updateCpuStats();
@@ -3045,11 +3064,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
- synchronized (this) {
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID);
- }
+ broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ null, null, 0, null, null, null, false, false);
} catch (RemoteException e) {
}
} finally {
@@ -3153,6 +3169,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public void closeSystemDialogs(String reason) {
Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
if (reason != null) {
intent.putExtra("reason", reason);
}
@@ -3230,6 +3247,9 @@ public final class ActivityManagerService extends ActivityManagerNative
forceStopPackageLocked(packageName, uid, false, false, true);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -3432,6 +3452,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
scheduleBroadcastsLocked();
}
@@ -3507,7 +3529,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
+ boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
if (!normalMode) {
@@ -3566,6 +3588,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app);
boolean badApp = false;
@@ -3709,7 +3733,9 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<ProcessRecord> procs =
new ArrayList<ProcessRecord>(mProcessesOnHold);
for (int ip=0; ip<NP; ip++) {
- this.startProcessLocked(procs.get(ip), "on-hold", null);
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
+ + procs.get(ip));
+ startProcessLocked(procs.get(ip), "on-hold", null);
}
}
@@ -5260,7 +5286,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
+ if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
&& !cpi.processName.equals("system")) {
// If this content provider does not run in the system
// process, and the system is not yet ready to run other
@@ -6076,6 +6102,11 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true);
}
+
+ // Now that we have cleaned up any update processes, we
+ // are ready to start launching real processes and know that
+ // we won't trample on them any more.
+ mProcessesReady = true;
}
}
@@ -7074,6 +7105,12 @@ public final class ActivityManagerService extends ActivityManagerNative
dumpServicesLocked(fd, pw, args, opti, true);
}
return;
+ } else {
+ // Dumping a single activity?
+ if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
+ return;
+ }
+ pw.println("Bad activity command: " + cmd);
}
}
@@ -7340,8 +7377,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dumpAll) {
pw.println(" Total persistent processes: " + numPers);
pw.println(" mStartRunning=" + mStartRunning
- + " mSystemReady=" + mSystemReady
- + " mBooting=" + mBooting
+ + " mProcessesReady=" + mProcessesReady
+ + " mSystemReady=" + mSystemReady);
+ pw.println(" mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
@@ -7426,6 +7464,82 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ /**
+ * There are three things that cmd can be:
+ * - a flattened component name that matched an existing activity
+ * - the cmd arg isn't the flattened component name of an existing activity:
+ * dump all activity whose component contains the cmd as a substring
+ * - A hex number of the ActivityRecord object instance.
+ */
+ protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+ int opti, boolean dumpAll) {
+ String[] newArgs;
+ ComponentName componentName = ComponentName.unflattenFromString(name);
+ int objectId = 0;
+ try {
+ objectId = Integer.parseInt(name, 16);
+ name = null;
+ componentName = null;
+ } catch (RuntimeException e) {
+ }
+ newArgs = new String[args.length - opti];
+ if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
+
+ ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+ synchronized (this) {
+ for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+ if (componentName != null) {
+ if (r1.intent.getComponent().equals(componentName)) {
+ activities.add(r1);
+ }
+ } else if (name != null) {
+ if (r1.intent.getComponent().flattenToString().contains(name)) {
+ activities.add(r1);
+ }
+ } else if (System.identityHashCode(this) == objectId) {
+ activities.add(r1);
+ }
+ }
+ }
+
+ if (activities.size() <= 0) {
+ return false;
+ }
+
+ for (int i=0; i<activities.size(); i++) {
+ dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
+ }
+ return true;
+ }
+
+ /**
+ * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
+ * there is a thread associated with the activity.
+ */
+ private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
+ boolean dumpAll) {
+ pw.println(" Activity " + r.intent.getComponent().flattenToString());
+ if (dumpAll) {
+ synchronized (this) {
+ pw.print(" * "); pw.println(r);
+ r.dump(pw, " ");
+ }
+ pw.println("");
+ }
+ if (r.app != null && r.app.thread != null) {
+ try {
+ // flush anything that is already in the PrintWriter since the thread is going
+ // to write to the file descriptor directly
+ pw.flush();
+ r.app.thread.dumpActivity(fd, r, args);
+ pw.print("\n");
+ pw.flush();
+ } catch (RemoteException e) {
+ pw.println("got a RemoteException while dumping the activity");
+ }
+ }
+ }
+
boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll) {
boolean needSep = false;
@@ -8155,6 +8269,8 @@ public final class ActivityManagerService extends ActivityManagerNative
restart = true;
}
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
@@ -10175,7 +10291,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
boolean replaced = false;
if (replacePending) {
- for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
+ for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
if (DEBUG_BROADCAST) Slog.v(TAG,
"***** DROPPING ORDERED: " + intent);
@@ -10194,35 +10310,41 @@ public final class ActivityManagerService extends ActivityManagerNative
return BROADCAST_SUCCESS;
}
- public final int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
+ final Intent verifyBroadcastLocked(Intent intent) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- synchronized(this) {
- int flags = intent.getFlags();
-
- if (!mSystemReady) {
- // if the caller really truly claims to know what they're doing, go
- // ahead and allow the broadcast without launching any receivers
- if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
- intent = new Intent(intent);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
- Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
- + " before boot completion");
- throw new IllegalStateException("Cannot broadcast before boot completed");
- }
- }
-
- if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
- throw new IllegalArgumentException(
- "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
+ int flags = intent.getFlags();
+
+ if (!mProcessesReady) {
+ // if the caller really truly claims to know what they're doing, go
+ // ahead and allow the broadcast without launching any receivers
+ if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
+ intent = new Intent(intent);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
+ Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+ + " before boot completion");
+ throw new IllegalStateException("Cannot broadcast before boot completed");
}
+ }
+
+ if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
+ throw new IllegalArgumentException(
+ "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
+ }
+
+ return intent;
+ }
+
+ public final int broadcastIntent(IApplicationThread caller,
+ Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int resultCode, String resultData, Bundle map,
+ String requiredPermission, boolean serialized, boolean sticky) {
+ synchronized(this) {
+ intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
@@ -10243,6 +10365,8 @@ public final class ActivityManagerService extends ActivityManagerNative
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
+ intent = verifyBroadcastLocked(intent);
+
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
resultTo, resultCode, resultData, map, requiredPermission,
@@ -10456,6 +10580,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " for app " + app);
if (app.thread == null) {
throw new RemoteException();
}
@@ -10475,9 +10601,13 @@ public final class ActivityManagerService extends ActivityManagerNative
ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
r.resultCode, r.resultData, r.resultExtras, r.ordered);
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
@@ -10642,6 +10772,8 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
+ " died before responding to broadcast");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
@@ -10672,7 +10804,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// one time heavy lifting after system upgrades and can take
// significant amounts of time.
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
- if (mSystemReady && r.dispatchTime > 0) {
+ if (mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
@@ -10743,7 +10875,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
+ r);
if (DEBUG_BROADCAST) Slog.v(TAG,
- "Submitting BROADCAST_TIMEOUT_MSG for "
+ "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
+ (r.receiverTime + BROADCAST_TIMEOUT));
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
@@ -10811,10 +10943,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (r.curApp != null && r.curApp.crashing) {
// If the target process is crashing, just skip it.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping deliver ordered " + r + " to " + r.curApp
+ + ": process crashing");
skip = true;
}
if (skip) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping delivery of ordered " + r + " for whatever reason");
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
@@ -10846,6 +10983,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// Not running -- get it started, to be executed when the app comes up.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Need to start app " + targetProcess + " for broadcast " + r);
if ((r.curApp=startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
@@ -10867,6 +11006,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
mPendingBroadcast = r;
+ mPendingBroadcastRecvIndex = recIdx;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4fc8020..a4497d6 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1104,26 +1104,30 @@ public class ActivityStack {
// Okay we are now going to start a switch, to 'next'. We may first
// have to pause the current activity, but this is an important point
// where we have decided to go to 'next' so keep track of that.
- if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
- long now = SystemClock.uptimeMillis();
- final boolean inTime = mLastStartedActivity.startTime != 0
- && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
- final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
- final int nextUid = next.info.applicationInfo.uid;
- if (inTime && lastUid != nextUid
- && lastUid != next.launchedFromUid
- && mService.checkPermission(
- android.Manifest.permission.STOP_APP_SWITCHES,
- -1, next.launchedFromUid)
- != PackageManager.PERMISSION_GRANTED) {
- mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ // XXX "App Redirected" dialog is getting too many false positives
+ // at this point, so turn off for now.
+ if (false) {
+ if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
+ long now = SystemClock.uptimeMillis();
+ final boolean inTime = mLastStartedActivity.startTime != 0
+ && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
+ final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
+ final int nextUid = next.info.applicationInfo.uid;
+ if (inTime && lastUid != nextUid
+ && lastUid != next.launchedFromUid
+ && mService.checkPermission(
+ android.Manifest.permission.STOP_APP_SWITCHES,
+ -1, next.launchedFromUid)
+ != PackageManager.PERMISSION_GRANTED) {
+ mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ } else {
+ next.startTime = now;
+ mLastStartedActivity = next;
+ }
} else {
- next.startTime = now;
+ next.startTime = SystemClock.uptimeMillis();
mLastStartedActivity = next;
}
- } else {
- next.startTime = SystemClock.uptimeMillis();
- mLastStartedActivity = next;
}
// We need to start pausing the current activity so the top one
diff --git a/services/java/com/android/server/location/ComprehensiveCountryDetector.java b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
index e692f8d..e9ce3ce 100755
--- a/services/java/com/android/server/location/ComprehensiveCountryDetector.java
+++ b/services/java/com/android/server/location/ComprehensiveCountryDetector.java
@@ -16,10 +16,6 @@
package com.android.server.location;
-import java.util.Locale;
-import java.util.Timer;
-import java.util.TimerTask;
-
import android.content.Context;
import android.location.Country;
import android.location.CountryListener;
@@ -31,6 +27,10 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
+import java.util.Locale;
+import java.util.Timer;
+import java.util.TimerTask;
+
/**
* This class is used to detect the country where the user is. The sources of
* country are queried in order of reliability, like
@@ -354,6 +354,6 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
}
protected boolean isGeoCoderImplemented() {
- return Geocoder.isImplemented();
+ return Geocoder.isPresent();
}
}
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3bf6ee4..39ce0b6 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1171,7 +1171,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
private void reportAGpsStatus(int type, int status) {
switch (status) {
case GPS_REQUEST_AGPS_DATA_CONN:
- int result = mConnMgr.startUsingNetworkFeature(
+ // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
+ // to avoid a race condition with handleUpdateNetworkState()
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ int result = mConnMgr.startUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
if (result == Phone.APN_ALREADY_ACTIVE) {
if (mAGpsApn != null) {
@@ -1179,11 +1182,13 @@ public class GpsLocationProvider implements LocationProviderInterface {
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else {
Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
} else if (result == Phone.APN_REQUEST_STARTED) {
- mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+ // Nothing to do here
} else {
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
break;
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index a2ebc69..f1dcd5a 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -172,7 +172,7 @@ public final class SipService extends ISipService.Stub {
SipSessionGroupExt group = mSipGroups.remove(localProfileUri);
if (group != null) {
notifyProfileRemoved(group.getLocalProfile());
- group.closeToNotReceiveCalls();
+ group.close();
if (isWifiOn() && !anyOpened()) releaseWifiLock();
}
}
@@ -449,9 +449,9 @@ public final class SipService extends ISipService.Stub {
}
}
- public void closeToNotReceiveCalls() {
+ public void close() {
mOpened = false;
- mSipGroup.closeToNotReceiveCalls();
+ mSipGroup.close();
mAutoRegistration.stop();
if (DEBUG) Log.d(TAG, " close: " + getUri() + ": "
+ mIncomingCallBroadcastAction);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index d27c2c6..e3bae56 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -138,6 +138,14 @@ static struct {
jfieldID mMotionRanges;
} gInputDeviceClassInfo;
+static struct {
+ jclass clazz;
+
+ jfieldID touchscreen;
+ jfieldID keyboard;
+ jfieldID navigation;
+} gConfigurationClassInfo;
+
// ----------------------------------------------------------------------------
static inline nsecs_t now() {
@@ -698,11 +706,7 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
JNIEnv* env = jniEnv();
- InputConfiguration config;
- mInputManager->getReader()->getInputConfiguration(& config);
-
- env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
- when, config.touchScreen, config.keyboard, config.navigation);
+ env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged, when);
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
}
@@ -1270,6 +1274,20 @@ static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env
return deviceIdsObj;
}
+static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env,
+ jclass clazz, jobject configObj) {
+ if (checkInputManagerUnitialized(env)) {
+ return;
+ }
+
+ InputConfiguration config;
+ gNativeInputManager->getInputManager()->getReader()->getInputConfiguration(& config);
+
+ env->SetIntField(configObj, gConfigurationClassInfo.touchscreen, config.touchScreen);
+ env->SetIntField(configObj, gConfigurationClassInfo.keyboard, config.keyboard);
+ env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation);
+}
+
static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
if (checkInputManagerUnitialized(env)) {
return NULL;
@@ -1316,6 +1334,8 @@ static JNINativeMethod gInputManagerMethods[] = {
(void*) android_server_InputManager_nativeGetInputDevice },
{ "nativeGetInputDeviceIds", "()[I",
(void*) android_server_InputManager_nativeGetInputDeviceIds },
+ { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V",
+ (void*) android_server_InputManager_nativeGetInputConfiguration },
{ "nativeDump", "()Ljava/lang/String;",
(void*) android_server_InputManager_nativeDump },
};
@@ -1343,7 +1363,7 @@ int register_android_server_InputManager(JNIEnv* env) {
FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
- "notifyConfigurationChanged", "(JIII)V");
+ "notifyConfigurationChanged", "(J)V");
GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
"notifyLidSwitchChanged", "(JZ)V");
@@ -1543,6 +1563,19 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
"mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
+ // Configuration
+
+ FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration");
+
+ GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz,
+ "touchscreen", "I");
+
+ GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz,
+ "keyboard", "I");
+
+ GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
+ "navigation", "I");
+
return 0;
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 833181b..1b21a8d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -367,6 +367,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
Mutex::Autolock _l(mLock);
// zero means default
+ const bool fixedSize = reqWidth && reqHeight;
if (!reqFormat) reqFormat = mFormat;
if (!reqWidth) reqWidth = mWidth;
if (!reqHeight) reqHeight = mHeight;
@@ -380,7 +381,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index,
mReqWidth = reqWidth;
mReqHeight = reqHeight;
mReqFormat = reqFormat;
- mFixedSize = reqWidth && reqHeight;
+ mFixedSize = fixedSize;
lcblk->reallocateAllExcept(index);
}
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 4d8cbf0..23cb42a 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -82,7 +82,7 @@ public final class CallManager {
// Singleton instance
private static final CallManager INSTANCE = new CallManager();
- // list of registered phones
+ // list of registered phones, which are PhoneBase objs
private final ArrayList<Phone> mPhones;
// list of supported ringing calls
@@ -97,7 +97,7 @@ public final class CallManager {
// empty connection list
private final ArrayList<Connection> emptyConnections = new ArrayList<Connection>();
- // default phone as the first phone registered
+ // default phone as the first phone registered, which is PhoneBase obj
private Phone mDefaultPhone;
// state registrants
@@ -181,6 +181,46 @@ public final class CallManager {
}
/**
+ * Get the corresponding PhoneBase obj
+ *
+ * @param phone a Phone object
+ * @return the corresponding PhoneBase obj in Phone if Phone
+ * is a PhoneProxy obj
+ * or the Phone itself if Phone is not a PhoneProxy obj
+ */
+ private static Phone getPhoneBase(Phone phone) {
+ if (phone instanceof PhoneProxy) {
+ return phone.getForegroundCall().getPhone();
+ }
+ return phone;
+ }
+
+ /**
+ * Check if two phones refer to the same PhoneBase obj
+ *
+ * Note: PhoneBase, not PhoneProxy, is to be used inside of CallManager
+ *
+ * Both PhoneBase and PhoneProxy implement Phone interface, so
+ * they have same phone APIs, such as dial(). The real implementation, for
+ * example in GSM, is in GSMPhone as extend from PhoneBase, so that
+ * foregroundCall.getPhone() returns GSMPhone obj. On the other hand,
+ * PhoneFactory.getDefaultPhone() returns PhoneProxy obj, which has a class
+ * member of GSMPhone.
+ *
+ * So for phone returned by PhoneFacotry, which is used by PhoneApp,
+ * phone.getForegroundCall().getPhone() != phone
+ * but
+ * isSamePhone(phone, phone.getForegroundCall().getPhone()) == true
+ *
+ * @param p1 is the first Phone obj
+ * @param p2 is the second Phone obj
+ * @return true if p1 and p2 refer to the same phone
+ */
+ public static boolean isSamePhone(Phone p1, Phone p2) {
+ return (getPhoneBase(p1) == getPhoneBase(p2));
+ }
+
+ /**
* Returns all the registered phone objects.
* @return all the registered phone objects.
*/
@@ -198,9 +238,7 @@ public final class CallManager {
Phone.State s = Phone.State.IDLE;
for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return Phone.State.ANSWERING;
- } else if (phone.getState() == Phone.State.RINGING) {
+ if (phone.getState() == Phone.State.RINGING) {
s = Phone.State.RINGING;
} else if (phone.getState() == Phone.State.OFFHOOK) {
if (s == Phone.State.IDLE) s = Phone.State.OFFHOOK;
@@ -246,25 +284,50 @@ public final class CallManager {
/**
* Register phone to CallManager
- * @param phone
+ * @param phone to be registered
* @return true if register successfully
*/
public boolean registerPhone(Phone phone) {
- if (phone != null && !mPhones.contains(phone)) {
+ Phone basePhone = getPhoneBase(phone);
+
+ if (basePhone != null && !mPhones.contains(basePhone)) {
if (mPhones.isEmpty()) {
- mDefaultPhone = phone;
+ mDefaultPhone = basePhone;
}
- mPhones.add(phone);
- mRingingCalls.add(phone.getRingingCall());
- mBackgroundCalls.add(phone.getBackgroundCall());
- mForegroundCalls.add(phone.getForegroundCall());
- registerForPhoneStates(phone);
+ mPhones.add(basePhone);
+ mRingingCalls.add(basePhone.getRingingCall());
+ mBackgroundCalls.add(basePhone.getBackgroundCall());
+ mForegroundCalls.add(basePhone.getForegroundCall());
+ registerForPhoneStates(basePhone);
return true;
}
return false;
}
/**
+ * unregister phone from CallManager
+ * @param phone to be unregistered
+ */
+ public void unregisterPhone(Phone phone) {
+ Phone basePhone = getPhoneBase(phone);
+
+ if (basePhone != null && mPhones.contains(basePhone)) {
+ mPhones.remove(basePhone);
+ mRingingCalls.remove(basePhone.getRingingCall());
+ mBackgroundCalls.remove(basePhone.getBackgroundCall());
+ mForegroundCalls.remove(basePhone.getForegroundCall());
+ unregisterForPhoneStates(basePhone);
+ if (basePhone == mDefaultPhone) {
+ if (mPhones.isEmpty()) {
+ mDefaultPhone = null;
+ } else {
+ mDefaultPhone = mPhones.get(0);
+ }
+ }
+ }
+ }
+
+ /**
* return the default phone or null if no phone available
*/
public Phone getDefaultPhone() {
@@ -292,39 +355,6 @@ public final class CallManager {
return getFirstActiveRingingCall().getPhone();
}
- /**
- * @return the first answering call
- */
- public Call getFirstAnsweringCall() {
- for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return phone.getForegroundCall();
- }
- }
- return null;
- }
-
- /**
- * unregister phone from CallManager
- * @param phone
- */
- public void unregisterPhone(Phone phone) {
- if (phone != null && mPhones.contains(phone)) {
- mPhones.remove(phone);
- mRingingCalls.remove(phone.getRingingCall());
- mBackgroundCalls.remove(phone.getBackgroundCall());
- mForegroundCalls.remove(phone.getForegroundCall());
- unregisterForPhoneStates(phone);
- if (phone == mDefaultPhone) {
- if (mPhones.isEmpty()) {
- mDefaultPhone = null;
- } else {
- mDefaultPhone = mPhones.get(0);
- }
- }
- }
- }
-
public void setAudioMode() {
Context context = getContext();
if (context == null) return;
@@ -592,8 +622,9 @@ public final class CallManager {
* handled asynchronously.
*/
public Connection dial(Phone phone, String dialString) throws CallStateException {
+ Phone basePhone = getPhoneBase(phone);
if (VDBG) {
- Log.d(LOG_TAG, "CallManager.dial( phone=" + phone + ", dialString="+ dialString + ")");
+ Log.d(LOG_TAG, "CallManager.dial( phone=" + basePhone + ", dialString="+ dialString + ")");
Log.d(LOG_TAG, this.toString());
}
if ( hasActiveFgCall() ) {
@@ -601,10 +632,10 @@ public final class CallManager {
boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
if (DBG) {
- Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone));
+ Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone));
}
- if (activePhone != phone) {
+ if (activePhone != basePhone) {
if (hasBgCall) {
Log.d(LOG_TAG, "Hangup");
getActiveFgCall().hangup();
@@ -614,7 +645,7 @@ public final class CallManager {
}
}
}
- return phone.dial(dialString);
+ return basePhone.dial(dialString);
}
/**
@@ -1312,7 +1343,7 @@ public final class CallManager {
*/
public Call getFirstActiveBgCall() {
for (Call call : mBackgroundCalls) {
- if (!call.isIdle()) {
+ if (call.getState() != Call.State.IDLE) {
return call;
}
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index e5736ca..ec6c023 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -54,12 +54,10 @@ public interface Phone {
* <li>OFFHOOK = The phone is off hook. At least one call
* exists that is dialing, active or holding and no calls are
* ringing or waiting.</li>
- * <li>ANSWERING = The incoming call is picked up but the
- * call is not established yet.</li>
* </ul>
*/
enum State {
- IDLE, RINGING, OFFHOOK, ANSWERING;
+ IDLE, RINGING, OFFHOOK;
};
/**
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 5d4dc58..b71cf13 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,6 +16,16 @@
package com.android.internal.telephony.cdma;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,19 +48,8 @@ import android.telephony.cdma.CdmaCellLocation;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
-import android.util.Config;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -987,7 +986,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1439,7 +1438,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1529,6 +1528,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index b639eea..83ad552 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,6 +16,17 @@
package com.android.internal.telephony.gsm;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -47,17 +58,6 @@ import android.util.EventLog;
import android.util.Log;
import android.util.TimeUtils;
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -995,7 +995,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
mNeedFixZone = false;
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1476,7 +1476,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
if (zone != null) {
- if (getAutoTime()) {
+ if (getAutoTimeZone()) {
setAndBroadcastNetworkSetTimeZone(zone.getID());
}
saveNitzTimeZone(zone.getID());
@@ -1546,6 +1546,15 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
}
+ private boolean getAutoTimeZone() {
+ try {
+ return Settings.System.getInt(phone.getContext().getContentResolver(),
+ Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException snfe) {
+ return true;
+ }
+ }
+
private void saveNitzTimeZone(String zoneId) {
mSavedTimeZone = zoneId;
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 0f2736f..9fcf12d 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -150,23 +150,15 @@ public class SipPhone extends SipPhoneBase {
// in case the active/holding call disappeared and this
// is no longer call waiting
- if (ringingCall.getState() == Call.State.INCOMING) {
+ if ((ringingCall.getState() == Call.State.INCOMING) ||
+ (ringingCall.getState() == Call.State.WAITING)) {
Log.v(LOG_TAG, "acceptCall");
// Always unmute when answering a new call
setMute(false);
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
- } else if (ringingCall.getState() == Call.State.WAITING) {
- setMute(false);
- switchHoldingAndActive();
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
+ ringingCall.acceptCall();
} else {
throw new CallStateException("phone not ringing");
}
- updatePhoneState();
}
}
@@ -485,8 +477,8 @@ public class SipPhone extends SipPhoneBase {
}
void acceptCall() throws CallStateException {
- if (this != foregroundCall) {
- throw new CallStateException("acceptCall() in a non-fg call");
+ if (this != ringingCall) {
+ throw new CallStateException("acceptCall() in a non-ringing call");
}
if (connections.size() != 1) {
throw new CallStateException("acceptCall() in a conf call");
@@ -649,6 +641,18 @@ public class SipPhone extends SipPhoneBase {
if (newState == Call.State.INCOMING) {
setState(mOwner.getState()); // INCOMING or WAITING
} else {
+ if (mOwner == ringingCall) {
+ if (ringingCall.getState() == Call.State.WAITING) {
+ try {
+ switchHoldingAndActive();
+ } catch (CallStateException e) {
+ // disconnect the call.
+ onCallEnded(DisconnectCause.LOCAL);
+ return;
+ }
+ }
+ foregroundCall.switchWith(ringingCall);
+ }
if (newState == Call.State.ACTIVE) call.startAudio();
setState(newState);
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index fec83d6..5f26af4 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -549,8 +549,6 @@ abstract class SipPhoneBase extends PhoneBase {
if (getRingingCall().isRinging()) {
state = State.RINGING;
- } else if (getForegroundCall().isRinging()) {
- state = State.ANSWERING;
} else if (getForegroundCall().isIdle()
&& getBackgroundCall().isIdle()) {
state = State.IDLE;
diff --git a/tests/DumpRenderTree2/assets/run_apache2.py b/tests/DumpRenderTree2/assets/run_apache2.py
index c799b5c..5edead1 100755
--- a/tests/DumpRenderTree2/assets/run_apache2.py
+++ b/tests/DumpRenderTree2/assets/run_apache2.py
@@ -109,18 +109,17 @@ def main(options, args):
# Try to execute the commands
logging.info("Will " + run_cmd + " apache2 server.")
- cmd_template = export_envvars_cmd + " && " + apache2_restart_template + directives + conf_file_cmd
# It is worth noting here that if the configuration file with which we restart the server points
- # to a different PidFile it will not work and result in second apache2 instance.
+ # to a different PidFile it will not work and will result in a second apache2 instance.
if (run_cmd == 'restart'):
logging.info("First will stop...")
- execute_cmd(cmd_template % ('stop'))
+ execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % ('stop')) + directives + conf_file_cmd)
logging.info("Stopped. Will start now...")
# We need to sleep breifly to avoid errors with apache being stopped and started too quickly
time.sleep(0.5)
- execute_cmd(cmd_template % (run_cmd))
+ execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % (run_cmd)) + directives + conf_file_cmd)
def execute_cmd(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
index 96c1e5e..614b03c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
@@ -32,7 +32,7 @@ import java.io.Serializable;
* A class that represent a result of the test. It is responsible for returning the result's
* raw data and generating its own diff in HTML format.
*/
-public abstract class AbstractResult implements Comparable<AbstractResult> {
+public abstract class AbstractResult implements Comparable<AbstractResult>, Serializable {
private static final String LOG_TAG = "AbstractResult";
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index b9fc274..c0ba9e5 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
+import android.net.http.SslError;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -30,19 +31,20 @@ import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.Process;
-import android.os.RemoteException;
import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
import android.util.Log;
import android.view.Window;
import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
import android.webkit.HttpAuthHandler;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
-import android.webkit.GeolocationPermissions;
import android.webkit.WebStorage.QuotaUpdater;
import java.io.File;
@@ -74,7 +76,7 @@ public class LayoutTestsExecutor extends Activity {
}
}
- private static final String LOG_TAG = "LayoutTestExecutor";
+ private static final String LOG_TAG = "LayoutTestsExecutor";
public static final String EXTRA_TESTS_LIST = "TestsList";
public static final String EXTRA_TEST_INDEX = "TestIndex";
@@ -180,6 +182,13 @@ public class LayoutTestsExecutor extends Activity {
}
handler.cancel();
}
+
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ // We ignore SSL errors. In particular, the certificate used by the LayoutTests server
+ // produces an error as it lacks a CN field.
+ handler.proceed();
+ }
};
private WebChromeClient mWebChromeClient = new WebChromeClient() {
@@ -236,7 +245,7 @@ public class LayoutTestsExecutor extends Activity {
* We never display the new window, just create the view and allow it's content to
* execute and be recorded by the executor.
*/
- newWindowWebView = new WebView(LayoutTestsExecutor.this);
+ newWindowWebView = createWebViewWithJavascriptInterfaces();
setupWebView(newWindowWebView);
}
@@ -317,7 +326,7 @@ public class LayoutTestsExecutor extends Activity {
mCurrentResult = null;
mCurrentAdditionalTextOutput = null;
- mCurrentWebView = new WebView(this);
+ mCurrentWebView = createWebViewWithJavascriptInterfaces();
setupWebView(mCurrentWebView);
mEventSender.reset(mCurrentWebView);
@@ -329,11 +338,26 @@ public class LayoutTestsExecutor extends Activity {
}
}
+ private static class WebViewWithJavascriptInterfaces extends WebView {
+ public WebViewWithJavascriptInterfaces(
+ Context context, Map<String, Object> javascriptInterfaces) {
+ super(context,
+ null, // attribute set
+ 0, // default style resource ID
+ javascriptInterfaces,
+ false); // is private browsing
+ }
+ }
+ private WebView createWebViewWithJavascriptInterfaces() {
+ Map<String, Object> javascriptInterfaces = new HashMap<String, Object>();
+ javascriptInterfaces.put("layoutTestController", mLayoutTestController);
+ javascriptInterfaces.put("eventSender", mEventSender);
+ return new WebViewWithJavascriptInterfaces(this, javascriptInterfaces);
+ }
+
private void setupWebView(WebView webView) {
webView.setWebViewClient(mWebViewClient);
webView.setWebChromeClient(mWebChromeClient);
- webView.addJavascriptInterface(mLayoutTestController, "layoutTestController");
- webView.addJavascriptInterface(mEventSender, "eventSender");
/**
* Setting a touch interval of -1 effectively disables the optimisation in WebView
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 8a08c48..af71a0f 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -31,6 +31,15 @@
</activity>
<activity
+ android:name="AdvancedGradientsActivity"
+ android:label="_Advanced Gradients">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ResizeActivity"
android:label="_Resize"
android:windowSoftInputMode="adjustResize">
@@ -250,7 +259,7 @@
<activity
android:name="AdvancedBlendActivity"
- android:label="_AdvancedBlend">
+ android:label="_Advanced Blend">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
new file mode 100644
index 0000000..27974e7
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class AdvancedGradientsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new GradientsView(this));
+ }
+
+ static class GradientsView extends View {
+ private final Paint mPaint;
+ private final SweepGradient mSweepGradient;
+ private final RadialGradient mRadialGradient;
+ private final Matrix mMatrix;
+ private final Matrix mMatrix2;
+ private final Matrix mMatrix3;
+
+ GradientsView(Context c) {
+ super(c);
+
+ mSweepGradient = new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff);
+ mRadialGradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff,
+ Shader.TileMode.MIRROR);
+
+ mMatrix = new Matrix();
+ mMatrix.setRotate(-45, 0.0f, 0.0f);
+ mMatrix.postTranslate(100.0f, 100.0f);
+
+ mMatrix2 = new Matrix();
+ mMatrix2.setScale(1.0f, 2.0f);
+ mMatrix2.postRotate(-45, 0.0f, 0.0f);
+
+ mMatrix3 = new Matrix();
+ mMatrix3.setTranslate(100.0f, 100.0f);
+
+ mPaint = new Paint();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(255, 255, 255);
+
+ canvas.save();
+ canvas.translate(130.0f, 100.0f);
+
+ mSweepGradient.setLocalMatrix(mMatrix3);
+ mPaint.setShader(mSweepGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mSweepGradient.setLocalMatrix(mMatrix);
+ mPaint.setShader(mSweepGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mSweepGradient.setLocalMatrix(mMatrix2);
+ mPaint.setShader(mSweepGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(-800.0f, 300.0f);
+
+ mRadialGradient.setLocalMatrix(null);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mRadialGradient.setLocalMatrix(mMatrix);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+ canvas.translate(400.0f, 000.0f);
+
+ mRadialGradient.setLocalMatrix(mMatrix2);
+ mPaint.setShader(mRadialGradient);
+ canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+
+ canvas.restore();
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 0910d79..4bc8855 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -116,10 +116,10 @@ public final class BridgeInflater extends LayoutInflater {
}
@Override
- public View createViewFromTag(String name, AttributeSet attrs) {
+ public View createViewFromTag(View parent, String name, AttributeSet attrs) {
View view = null;
try {
- view = super.createViewFromTag(name, attrs);
+ view = super.createViewFromTag(parent, name, attrs);
} catch (InflateException e) {
// try to load the class from using the custom view loader
try {
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 09b392b..c59e20d 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -4,68 +4,196 @@
- Description -
---------------
-makeLayoutLib generates a library used by the Eclipse graphical layout editor
+Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor
to perform layout.
-
- Usage -
---------
- ./makeLayoutLib path/to/android.jar destination.jar
+ ./layoutlib_create path/to/android.jar destination.jar
+
+
+- Design Overview -
+-------------------
+
+Layoutlib_create uses the "android.jar" containing all the Java code used by Android
+as generated by the Android build, right before the classes are converted to a DEX format.
+
+The Android JAR can't be used directly in Eclipse:
+- it contains references to native code (which we want to avoid in Eclipse),
+- some classes need to be overridden, for example all the drawing code that is
+ replaced by Java 2D calls in Eclipse.
+- some of the classes that need to be changed are final and/or we need access
+ to their private internal state.
+
+Consequently this tool:
+- parses the input JAR,
+- modifies some of the classes directly using some bytecode manipulation,
+- filters some packages and removes some that we don't want to end in the output JAR,
+- injects some new classes,
+- and generates a modified JAR file that is suitable for the Android plugin
+ for Eclipse to perform rendering.
+
+The ASM library is used to do the bytecode modification using its visitor pattern API.
+
+The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the
+configuration is done in the main() method and the CreateInfo structure is expected to
+change with the Android platform as new classes are added, changed or removed.
+
+The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the
+platform, that provides all the necessary missing implementation for rendering graphics
+in Eclipse.
- Implementation Notes -
------------------------
-The goal of makeLayoutLib is to list all the classes from the input jar and create a new
-jar that only keeps certain classes and create stubs for all their dependencies.
+The tool works in two phases:
+- first analyze the input jar (AsmAnalyzer class)
+- then generate the output jar (AsmGenerator class),
+
+
+- Analyzer
+----------
+
+The goal of the analyzer is to create a graph of all the classes from the input JAR
+with their dependencies and then only keep the ones we want.
+
+To do that, the analyzer is created with a list of base classes to keep -- everything
+that derives from these is kept. Currently the one such class is android.view.View:
+since we want to render layouts, anything that is sort of the view needs to be kept.
+
+The analyzer is also given a list of class names to keep in the output.
+This is done using shell-like glob patterns that filter on the fully-qualified
+class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does,
+and "." and "$" are interpreted as-is).
+In practice we almost but not quite request the inclusion of full packages.
+
+With this information, the analyzer parses the input zip to find all the classes.
+All classes deriving from the requested bases classes are kept.
+All classes which name matched the glob pattern are kept.
+The analysis then finds all the dependencies of the classes that are to be kept
+using an ASM visitor on the class, the field types, the method types and annotations types.
+Classes that belong to the current JRE are excluded.
+
+The output of the analyzer is a set of ASM ClassReader instances which are then
+fed to the generator.
+
+
+- Generator
+-----------
-First the input jar is parsed to find all the classes defined.
+The generator is constructed from a CreateInfo struct that acts as a config file
+and lists:
+- the classes to inject in the output JAR -- these classes are directly implemented
+ in layoutlib_create and will be used to interface with the renderer in Eclipse.
+- specific methods to override (see method stubs details below).
+- specific methods to remove based on their return type.
+- specific classes to rename.
-In the Main(), the following list of classes are hardcoded (TODO config file later):
-- keep all classes that derive from android.view.View.
-- keep all classes in the android.view and android.widget packages (sub-packages excluded).
-- keep specific classes such as android.policy.PhoneLayoutInflater.
+Each of these are specific strategies we use to be able to modify the Android code
+to fit within the Eclipse renderer. These strategies are explained beow.
-For each class to keep, their dependencies are examined using BCEL.
-A dependency is defined as a class needed to instantiate the given class that should be kept,
-directly or indirectly. So a dependency is a class that is used by the input class, that is
-defined in the input jar and that is not part of the current JRE.
+The core method of the generator is transform(): it takes an input ASM ClassReader
+and modifies it to produce a byte array suitable for the final JAR file.
-Dependencies are computed recursively.
+The first step of the transformation is changing the name of the class in case
+we requested the class to be renamed. This uses the RenameClassAdapter to also rename
+all inner classes and references in methods and types. Note that other classes are
+not transformed and keep referencing the original name.
-Once all dependencies are found, the final jar can be created.
-There are three kind of classes to write:
-- classes that are to be kept as-is. They are just dumped in the new jar unchanged.
-- classes that are to be kept yet contain native methods or fields.
-- classes that are just dependencies. We don't want to expose their implementation in the final
- jar.
+The TransformClassAdapter is then used to process the potentially renamed class.
+All protected or private classes are market as public.
+All classes are made non-final.
+Interfaces are left as-is.
-The implementation of native methods and all methods of mock classes is replaced by a stub
-that throws UnsupportedOperationException.
+If a method has a return type that must be erased, the whole method is skipped.
+Methods are also changed from protected/private to public.
+The code of the methods is then kept as-is, except for native methods which are
+replaced by a stub. Methods that are to be overridden are also replaced by a stub.
-Incidentally, the access level of native and mock classes needs to be changed in order for
-native methods to be later overridden. Methods that are "final private native" must become
-non-final, non-native and at most protected. Package-default access is changed to public.
-Classes that are final are made non-final. Abstract methods are left untouched.
+Finally fields are also visited and changed from protected/private to public.
+- Method stubs
+--------------
-----
-20080617 Replace Class
+As indicated above, all native and overridden methods are replaced by a stub.
+We don't have the code to replace with in layoutlib_create.
+Instead the StubMethodAdapter replaces the code of the method by a call to
+OverrideMethod.invokeX(). When using the final JAR, the bridge can register
+listeners from these overridden method calls based on the method signatures.
-Some classes are basically wrappers over native objects.
-Subclassing doesn't work as most methods are either static or we don't
-control object creation. In this scenario the idea is to be able to
-replace classes in the final jar.
+The listeners are currently pretty basic: we only pass the signature of the
+method being called, its caller object and a flag indicating whether the
+method was native. We do not currently provide the parameters. The listener
+can however specify the return value of the overridden method.
-Example: android.graphics.Paint would get renamed to OriginalPaint
-in the generated jar. Then in the bridge we'll introduce a replacement
-Paint class that derives from OriginalPaint.
+An extension being worked on is to actually replace these listeners by
+direct calls to a delegate class, complete with parameters.
+
+
+- Strategies
+------------
+
+We currently have 4 strategies to deal with overriding the rendering code
+and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
+by the bridge (which runs in Eclipse) and the generator.
+
+
+1- Class Injection
+
+This is the easiest: we currently inject 4 classes, namely:
+- OverrideMethod and its associated MethodListener and MethodAdapter are used
+ to intercept calls to some specific methods that are stubbed out and change
+ their return value.
+- CreateInfo class, which configured the generator. Not used yet, but could
+ in theory help us track what the generator changed.
+
+
+2- Overriding methods
+
+As explained earlier, the creator doesn't have any replacement code for
+methods to override. Instead it removes the original code and replaces it
+by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
+a listener on the method signature and can provide an implementation.
+
+
+3- Renaming classes
+
+This simply changes the name of a class in its definition, as well as all its
+references in internal inner classes and methods.
+Calls from other classes are not modified -- they keep referencing the original
+class name. This allows the bridge to literally replace an implementation.
+
+An example will make this easier: android.graphics.Paint is the main drawing
+class that we need to replace. To do so, the generator renames Paint to _original_Paint.
+Later the bridge provides its own replacement version of Paint which will be used
+by the rest of the Android stack. The replacement version of Paint can still use
+(either by inheritance or delegation) all the original non-native code of _original_Paint
+if it so desires.
+
+Some of the Android classes are basically wrappers over native objects and since
+we don't have the native code in Eclipse, we need to provide a full alternate
+implementation. Sub-classing doesn't work as some native methods are static and
+we don't control object creation.
This won't rename/replace the inner static methods of a given class.
+4- Method erasure based on return type
+
+This is mostly an implementation detail of the bridge: in the Paint class
+mentioned above, some inner static classes are used to pass around
+attributes (e.g. FontMetrics, or the Style enum) and all the original implementation
+is native.
+
+In this case we have a strategy that tells the generator that anything returning, for
+example, the inner class Paint$Style in the Paint class should be discarded and the
+bridge will provide its own implementation.
+
+--
+end
diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh
new file mode 100755
index 0000000..f4cae9a
--- /dev/null
+++ b/tools/obbtool/mkobb.sh
@@ -0,0 +1,260 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# mkobb.sh - Creates OBB files on Linux machines
+
+# Directory where we should temporarily mount the OBB loopback to copy files
+MOUNTDIR=/tmp
+
+# Presets. Changing these will probably break your OBB on the device
+CRYPTO=blowfish
+FS=vfat
+MKFS=mkfs.vfat
+LOSETUP=losetup
+BLOCK_SIZE=512
+SLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks
+
+find_binaries() {
+ MKFSBIN=`which ${MKFS}`
+ LOSETUPBIN=`which ${LOSETUP}`
+ MOUNTBIN=`which mount`
+ UMOUNTBIN=`which umount`
+ DDBIN=`which dd`
+ RSYNCBIN=`which rsync`
+}
+
+check_prereqs() {
+ if [ "`uname -s`x" != "Linuxx" ]; then \
+ echo "ERROR: This script only works on Linux!"
+ exit 1
+ fi
+
+ if ! egrep -q "^cryptoloop " /proc/modules; then \
+ echo "ERROR: Could not find cryptoloop in the kernel."
+ echo "Perhaps you need to: modprobe cryptoloop"
+ exit 1
+ fi
+
+ if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \
+ echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel."
+ echo "Perhaps you need to: modprobe ${CRYPTO}"
+ exit 1
+ fi
+
+ if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \
+ echo "ERROR: Could not find filesystem \`${FS}' in the kernel."
+ echo "Perhaps you need to: modprobe ${FS}"
+ exit 1
+ fi
+
+ if [ "${MKFSBIN}x" = "x" ]; then \
+ echo "ERROR: Could not find ${MKFS} in your path!"
+ exit 1
+ elif [ ! -x "${MKFSBIN}" ]; then \
+ echo "ERROR: ${MKFSBIN} is not executable!"
+ exit 1
+ fi
+
+ if [ "${LOSETUPBIN}x" = "x" ]; then \
+ echo "ERROR: Could not find ${LOSETUP} in your path!"
+ exit 1
+ elif [ ! -x "${LOSETUPBIN}" ]; then \
+ echo "ERROR: ${LOSETUPBIN} is not executable!"
+ exit 1
+ fi
+}
+
+cleanup() {
+ if [ "${loopdev}x" != "x" ]; then \
+ ${LOSETUPBIN} -d ${loopdev}
+ fi
+}
+
+hidden_prompt() {
+ unset output
+ prompt="$1"
+ outvar="$2"
+ while read -s -n 1 -p "$prompt" c; do \
+ if [ "x$c" = "x" ]; then \
+ break
+ fi
+ prompt='*'
+ output="${output}${c}"
+ done
+ echo
+ eval $outvar="$output"
+ unset output
+}
+
+read_key() {
+ hidden_prompt " Encryption key: " key
+
+ if [ "${key}x" = "x" ]; then \
+ echo "ERROR: An empty key is not allowed!"
+ exit 1
+ fi
+
+ hidden_prompt "Encryption key (again): " key2
+
+ if [ "${key}x" != "${key2}x" ]; then \
+ echo "ERROR: Encryption keys do not match!"
+ exit 1
+ fi
+}
+
+onexit() {
+ if [ "x${temp_mount}" != "x" ]; then \
+ ${UMOUNTBIN} ${temp_mount}
+ rmdir ${temp_mount}
+ fi
+ if [ "x${loop_dev}" != "x" ]; then \
+ ${LOSETUPBIN} -d ${loop_dev}
+ fi
+ if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
+ rm -f ${tempfile}
+ fi
+ if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
+ rm -f ${keyfile}
+ fi
+ echo "Fatal error."
+ exit 1
+}
+
+usage() {
+ echo "mkobb.sh -- Create OBB files for use on Android"
+ echo ""
+ echo " -c Use an encrypted OBB; must specify key"
+ echo " -d <directory> Use <directory> as input for OBB files"
+ echo " -k <key> Use <key> to encrypt OBB file"
+ echo " -K Prompt for key to encrypt OBB file"
+ echo " -o <filename> Write OBB file out to <filename>"
+ echo " -v Verbose mode"
+ echo " -h Help; this usage screen"
+}
+
+find_binaries
+check_prereqs
+
+use_crypto=0
+
+args=`getopt -o cd:hk:Ko:v -- "$@"`
+eval set -- "$args"
+
+while true; do \
+ case "$1" in
+ -c) use_crypto=1; shift;;
+ -d) directory=$2; shift 2;;
+ -h) usage; exit 1;;
+ -k) key=$2; shift 2;;
+ -K) prompt_key=1; shift;;
+ -v) verbose=1; shift;;
+ -o) filename=$2; shift 2;;
+ --) shift; break;;
+ *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
+ esac
+done
+
+if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
+ echo "ERROR: Must specify valid input directory"
+ echo ""
+ usage
+ exit 1;
+fi
+
+if [ "${filename}x" = "x" ]; then \
+ echo "ERROR: Must specify filename"
+ echo ""
+ usage
+ exit 1;
+fi
+
+if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
+ echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
+ exit 1
+fi
+
+if [ 0${prompt_key} -eq 1 ]; then \
+ read_key
+fi
+
+outdir=`dirname ${filename}`
+if [ ! -d "${outdir}" ]; then \
+ echo "ERROR: Output directory does not exist: ${outdir}"
+ exit 1
+fi
+
+# Make sure we clean up any stuff we create from here on during error conditions
+trap onexit ERR
+
+tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
+
+block_count=`du --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
+if [ $? -ne 0 ]; then \
+ echo "ERROR: Couldn't read size of input directory ${directory}"
+ exit 1
+fi
+
+echo "Creating temporary file..."
+${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
+if [ $? -ne 0 ]; then \
+ echo "ERROR: creating temporary file: $?"
+fi
+
+loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
+
+if [ ${use_crypto} -eq 1 ]; then \
+ keyfile=$(tempfile -d ${outdir}) || ( echo "ERROR: could not create temporary key file"; exit 1 )
+ ${LOSETUPBIN} -p 5 -e ${CRYPTO} ${loop_dev} ${tempfile} 5< ${keyfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+ rm -f ${keyfile}
+else \
+ ${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+fi
+
+#
+# Create the filesystem
+#
+echo ""
+${MKFSBIN} -I ${loop_dev}
+echo ""
+
+#
+# Make the temporary mount point and mount it
+#
+temp_mount="${MOUNTDIR}/${RANDOM}"
+mkdir ${temp_mount}
+${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
+
+#
+# rsync the files!
+#
+echo "Copying files:"
+${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
+echo ""
+
+echo "Successfully created \`${filename}'"
+
+#
+# Undo all the temporaries
+#
+umount ${temp_mount}
+rmdir ${temp_mount}
+${LOSETUPBIN} -d ${loop_dev}
+mv ${tempfile} ${filename}
+
+trap - ERR
+
+exit 0