summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk14
-rw-r--r--api/current.xml299
-rw-r--r--cmds/surfaceflinger/Android.mk2
-rw-r--r--cmds/surfaceflinger/main_surfaceflinger.cpp31
-rw-r--r--cmds/system_server/library/Android.mk6
-rw-r--r--core/java/android/app/ActionBar.java18
-rw-r--r--core/java/android/app/Activity.java35
-rw-r--r--core/java/android/app/ActivityManager.java40
-rw-r--r--core/java/android/app/ActivityThread.java26
-rw-r--r--core/java/android/app/ContextImpl.java5
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java66
-rw-r--r--core/java/android/net/DownloadManager.java12
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java21
-rw-r--r--core/java/android/provider/Calendar.java1
-rw-r--r--core/java/android/provider/Downloads.java21
-rw-r--r--core/java/android/view/SurfaceView.java3
-rw-r--r--core/java/android/view/View.java629
-rw-r--r--core/java/android/view/ViewGroup.java142
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java30
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java8
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java24
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/android_database_SQLiteDatabase.cpp72
-rw-r--r--core/res/res/values-xlarge/config.xml27
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--docs/html/guide/topics/resources/available-resources.jd17
-rw-r--r--docs/html/guide/topics/resources/drawable-resource.jd1309
-rw-r--r--docs/html/guide/topics/resources/layout-resource.jd81
-rw-r--r--docs/html/guide/topics/resources/menu-resource.jd12
-rw-r--r--docs/html/guide/topics/resources/more-resources.jd125
-rw-r--r--docs/html/images/resources/clip.pngbin0 -> 2464 bytes
-rw-r--r--docs/html/images/resources/layers.pngbin0 -> 8248 bytes
-rw-r--r--graphics/java/android/graphics/ImageFormat.java121
-rw-r--r--graphics/java/android/graphics/drawable/AnimationDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/BitmapDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java9
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java7
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java5
-rw-r--r--graphics/java/android/graphics/drawable/LevelListDrawable.java5
-rw-r--r--graphics/java/android/graphics/drawable/RotateDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/TransitionDrawable.java8
-rw-r--r--include/binder/BinderService.h60
-rw-r--r--include/gui/ISensorEventConnection.h57
-rw-r--r--include/gui/ISensorServer.h57
-rw-r--r--include/gui/Sensor.h88
-rw-r--r--include/gui/SensorChannel.h53
-rw-r--r--include/gui/SensorEventQueue.h71
-rw-r--r--include/gui/SensorManager.h63
-rw-r--r--include/media/stagefright/MPEG4Writer.h2
-rw-r--r--include/media/stagefright/MetaData.h1
-rw-r--r--libs/gui/Android.mk25
-rw-r--r--libs/gui/ISensorEventConnection.cpp108
-rw-r--r--libs/gui/ISensorServer.cpp100
-rw-r--r--libs/gui/Sensor.cpp165
-rw-r--r--libs/gui/SensorChannel.cpp93
-rw-r--r--libs/gui/SensorEventQueue.cpp97
-rw-r--r--libs/gui/SensorManager.cpp68
-rw-r--r--libs/hwui/Matrix.h3
-rw-r--r--libs/hwui/OpenGLRenderer.cpp15
-rw-r--r--libs/hwui/OpenGLRenderer.h3
-rw-r--r--libs/hwui/Snapshot.h12
-rw-r--r--libs/ui/PixelFormat.cpp1
-rw-r--r--libs/ui/tests/Android.mk5
-rw-r--r--libs/utils/tests/Android.mk5
-rw-r--r--media/jni/Android.mk2
-rw-r--r--media/jni/android_media_MtpClient.cpp20
-rw-r--r--media/jni/android_media_MtpCursor.cpp8
-rw-r--r--media/jni/android_media_MtpDatabase.cpp7
-rw-r--r--media/jni/android_media_MtpServer.cpp14
-rw-r--r--media/libmedia/MediaScanner.cpp4
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp84
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h10
-rw-r--r--media/libstagefright/MPEG4Writer.cpp102
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp2
-rw-r--r--media/libstagefright/OMXCodec.cpp6
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp2
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp2
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp2
-rw-r--r--media/libstagefright/rtsp/MyHandler.h2
-rw-r--r--media/mediaserver/Android.mk4
-rw-r--r--media/mtp/Android.mk5
-rw-r--r--media/mtp/MtpEventPacket.cpp2
-rw-r--r--media/mtp/MtpServer.cpp2
-rw-r--r--media/mtp/f_mtp.h53
-rw-r--r--native/android/Android.mk4
-rw-r--r--native/android/sensor.cpp150
-rw-r--r--native/glue/threaded_app/Android.mk18
-rw-r--r--native/glue/threaded_app/threaded_app.c338
-rw-r--r--native/include/android/tts.h5
-rw-r--r--native/include/android_glue/threaded_app.h197
-rw-r--r--packages/SystemUI/AndroidManifest.xml7
-rw-r--r--packages/SystemUI/res/drawable/notification_dragger.pngbin0 -> 3495 bytes
-rw-r--r--packages/SystemUI/res/layout-xlarge/status_bar.xml155
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml27
-rw-r--r--packages/SystemUI/res/layout/unused.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CloseDragHandle.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandedView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java1552
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java1546
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/TrackingView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java102
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java4
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp (renamed from libs/audioflinger/A2dpAudioInterface.cpp)0
-rw-r--r--services/audioflinger/A2dpAudioInterface.h (renamed from libs/audioflinger/A2dpAudioInterface.h)0
-rw-r--r--services/audioflinger/Android.mk (renamed from libs/audioflinger/Android.mk)0
-rw-r--r--services/audioflinger/AudioBufferProvider.h (renamed from libs/audioflinger/AudioBufferProvider.h)0
-rw-r--r--services/audioflinger/AudioDumpInterface.cpp (renamed from libs/audioflinger/AudioDumpInterface.cpp)0
-rw-r--r--services/audioflinger/AudioDumpInterface.h (renamed from libs/audioflinger/AudioDumpInterface.h)0
-rw-r--r--services/audioflinger/AudioFlinger.cpp (renamed from libs/audioflinger/AudioFlinger.cpp)7
-rw-r--r--services/audioflinger/AudioFlinger.h (renamed from libs/audioflinger/AudioFlinger.h)11
-rw-r--r--services/audioflinger/AudioHardwareGeneric.cpp (renamed from libs/audioflinger/AudioHardwareGeneric.cpp)0
-rw-r--r--services/audioflinger/AudioHardwareGeneric.h (renamed from libs/audioflinger/AudioHardwareGeneric.h)0
-rw-r--r--services/audioflinger/AudioHardwareInterface.cpp (renamed from libs/audioflinger/AudioHardwareInterface.cpp)0
-rw-r--r--services/audioflinger/AudioHardwareStub.cpp (renamed from libs/audioflinger/AudioHardwareStub.cpp)0
-rw-r--r--services/audioflinger/AudioHardwareStub.h (renamed from libs/audioflinger/AudioHardwareStub.h)0
-rw-r--r--services/audioflinger/AudioMixer.cpp (renamed from libs/audioflinger/AudioMixer.cpp)0
-rw-r--r--services/audioflinger/AudioMixer.h (renamed from libs/audioflinger/AudioMixer.h)0
-rw-r--r--services/audioflinger/AudioPolicyManagerBase.cpp (renamed from libs/audioflinger/AudioPolicyManagerBase.cpp)0
-rw-r--r--services/audioflinger/AudioPolicyService.cpp (renamed from libs/audioflinger/AudioPolicyService.cpp)0
-rw-r--r--services/audioflinger/AudioPolicyService.h (renamed from libs/audioflinger/AudioPolicyService.h)0
-rw-r--r--services/audioflinger/AudioResampler.cpp (renamed from libs/audioflinger/AudioResampler.cpp)0
-rw-r--r--services/audioflinger/AudioResampler.h (renamed from libs/audioflinger/AudioResampler.h)0
-rw-r--r--services/audioflinger/AudioResamplerCubic.cpp (renamed from libs/audioflinger/AudioResamplerCubic.cpp)0
-rw-r--r--services/audioflinger/AudioResamplerCubic.h (renamed from libs/audioflinger/AudioResamplerCubic.h)0
-rw-r--r--services/audioflinger/AudioResamplerSinc.cpp (renamed from libs/audioflinger/AudioResamplerSinc.cpp)0
-rw-r--r--services/audioflinger/AudioResamplerSinc.h (renamed from libs/audioflinger/AudioResamplerSinc.h)0
-rw-r--r--services/camera/libcameraservice/Android.mk (renamed from camera/libcameraservice/Android.mk)0
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.cpp (renamed from camera/libcameraservice/CameraHardwareStub.cpp)0
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h (renamed from camera/libcameraservice/CameraHardwareStub.h)0
-rw-r--r--services/camera/libcameraservice/CameraService.cpp (renamed from camera/libcameraservice/CameraService.cpp)5
-rw-r--r--services/camera/libcameraservice/CameraService.h (renamed from camera/libcameraservice/CameraService.h)9
-rw-r--r--services/camera/libcameraservice/CannedJpeg.h (renamed from camera/libcameraservice/CannedJpeg.h)0
-rw-r--r--services/camera/libcameraservice/FakeCamera.cpp (renamed from camera/libcameraservice/FakeCamera.cpp)0
-rw-r--r--services/camera/libcameraservice/FakeCamera.h (renamed from camera/libcameraservice/FakeCamera.h)0
-rw-r--r--services/camera/tests/CameraServiceTest/Android.mk (renamed from camera/tests/CameraServiceTest/Android.mk)0
-rw-r--r--services/camera/tests/CameraServiceTest/CameraServiceTest.cpp (renamed from camera/tests/CameraServiceTest/CameraServiceTest.cpp)0
-rw-r--r--services/java/com/android/server/ViewServer.java33
-rw-r--r--services/java/com/android/server/WindowManagerService.java25
-rw-r--r--services/surfaceflinger/Android.mk (renamed from libs/surfaceflinger/Android.mk)0
-rw-r--r--services/surfaceflinger/Barrier.h (renamed from libs/surfaceflinger/Barrier.h)0
-rw-r--r--services/surfaceflinger/BlurFilter.cpp (renamed from libs/surfaceflinger/BlurFilter.cpp)0
-rw-r--r--services/surfaceflinger/BlurFilter.h (renamed from libs/surfaceflinger/BlurFilter.h)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.cpp (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardware.h (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardware.h)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp)0
-rw-r--r--services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h (renamed from libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h)0
-rw-r--r--services/surfaceflinger/GLExtensions.cpp (renamed from libs/surfaceflinger/GLExtensions.cpp)0
-rw-r--r--services/surfaceflinger/GLExtensions.h (renamed from libs/surfaceflinger/GLExtensions.h)0
-rw-r--r--services/surfaceflinger/Layer.cpp (renamed from libs/surfaceflinger/Layer.cpp)0
-rw-r--r--services/surfaceflinger/Layer.h (renamed from libs/surfaceflinger/Layer.h)0
-rw-r--r--services/surfaceflinger/LayerBase.cpp (renamed from libs/surfaceflinger/LayerBase.cpp)0
-rw-r--r--services/surfaceflinger/LayerBase.h (renamed from libs/surfaceflinger/LayerBase.h)0
-rw-r--r--services/surfaceflinger/LayerBlur.cpp (renamed from libs/surfaceflinger/LayerBlur.cpp)0
-rw-r--r--services/surfaceflinger/LayerBlur.h (renamed from libs/surfaceflinger/LayerBlur.h)0
-rw-r--r--services/surfaceflinger/LayerBuffer.cpp (renamed from libs/surfaceflinger/LayerBuffer.cpp)0
-rw-r--r--services/surfaceflinger/LayerBuffer.h (renamed from libs/surfaceflinger/LayerBuffer.h)0
-rw-r--r--services/surfaceflinger/LayerDim.cpp (renamed from libs/surfaceflinger/LayerDim.cpp)0
-rw-r--r--services/surfaceflinger/LayerDim.h (renamed from libs/surfaceflinger/LayerDim.h)0
-rw-r--r--services/surfaceflinger/MODULE_LICENSE_APACHE2 (renamed from libs/surfaceflinger/MODULE_LICENSE_APACHE2)0
-rw-r--r--services/surfaceflinger/MessageQueue.cpp (renamed from libs/surfaceflinger/MessageQueue.cpp)0
-rw-r--r--services/surfaceflinger/MessageQueue.h (renamed from libs/surfaceflinger/MessageQueue.h)0
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp (renamed from libs/surfaceflinger/SurfaceFlinger.cpp)14
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h (renamed from libs/surfaceflinger/SurfaceFlinger.h)9
-rw-r--r--services/surfaceflinger/TextureManager.cpp (renamed from libs/surfaceflinger/TextureManager.cpp)2
-rw-r--r--services/surfaceflinger/TextureManager.h (renamed from libs/surfaceflinger/TextureManager.h)0
-rw-r--r--services/surfaceflinger/Transform.cpp (renamed from libs/surfaceflinger/Transform.cpp)0
-rw-r--r--services/surfaceflinger/Transform.h (renamed from libs/surfaceflinger/Transform.h)0
-rw-r--r--services/surfaceflinger/clz.cpp (renamed from libs/surfaceflinger/clz.cpp)0
-rw-r--r--services/surfaceflinger/clz.h (renamed from libs/surfaceflinger/clz.h)0
-rw-r--r--services/surfaceflinger/tests/Android.mk (renamed from libs/surfaceflinger/tests/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/overlays/Android.mk (renamed from libs/surfaceflinger/tests/overlays/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/overlays/overlays.cpp (renamed from libs/surfaceflinger/tests/overlays/overlays.cpp)0
-rw-r--r--services/surfaceflinger/tests/resize/Android.mk (renamed from libs/surfaceflinger/tests/resize/Android.mk)0
-rw-r--r--services/surfaceflinger/tests/resize/resize.cpp (renamed from libs/surfaceflinger/tests/resize/resize.cpp)0
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java1
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java7
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/google/android/test/hwui/MultisamplingActivity.java141
-rw-r--r--tests/HwAccelerationTest/src/com/google/android/test/hwui/RotationActivity.java63
-rw-r--r--tools/layoutlib/Android.mk8
189 files changed, 6499 insertions, 2802 deletions
diff --git a/Android.mk b/Android.mk
index ca81fc1..27f9e1e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -24,7 +24,7 @@ LOCAL_PATH := $(call my-dir)
# Instead, it depends on the R.stamp file, which lists the corresponding
# R.java file as a prerequisite.
# TODO: find a more appropriate way to do this.
-framework-res-source-path := APPS/framework-res_intermediates/src
+framework_res_source_path := APPS/framework-res_intermediates/src
# the library
# ============================================================
@@ -189,9 +189,9 @@ LOCAL_SRC_FILES += \
LOCAL_AIDL_INCLUDES += $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
LOCAL_INTERMEDIATE_SOURCES := \
- $(framework-res-source-path)/android/R.java \
- $(framework-res-source-path)/android/Manifest.java \
- $(framework-res-source-path)/com/android/internal/R.java
+ $(framework_res_source_path)/android/R.java \
+ $(framework_res_source_path)/android/Manifest.java \
+ $(framework_res_source_path)/com/android/internal/R.java
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit ext
@@ -337,9 +337,9 @@ framework_docs_LOCAL_DROIDDOC_SOURCE_PATH := \
$(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
framework_docs_LOCAL_INTERMEDIATE_SOURCES := \
- $(framework-res-source-path)/android/R.java \
- $(framework-res-source-path)/android/Manifest.java \
- $(framework-res-source-path)/com/android/internal/R.java
+ $(framework_res_source_path)/android/R.java \
+ $(framework_res_source_path)/android/Manifest.java \
+ $(framework_res_source_path)/com/android/internal/R.java
framework_docs_LOCAL_JAVA_LIBRARIES := \
bouncycastle \
diff --git a/api/current.xml b/api/current.xml
index 9486ca6..7131eb9 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19890,6 +19890,17 @@
visibility="public"
>
</method>
+<method name="getCustomView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getMenu"
return="android.view.Menu"
abstract="true"
@@ -19901,6 +19912,28 @@
visibility="public"
>
</method>
+<method name="getSubtitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="invalidate"
return="void"
abstract="true"
@@ -68614,6 +68647,17 @@
visibility="public"
>
</field>
+<field name="YV12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="842094169"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="Interpolator"
extends="java.lang.Object"
@@ -184234,6 +184278,17 @@
visibility="public"
>
</method>
+<method name="getAlpha"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getAnimation"
return="android.view.animation.Animation"
abstract="false"
@@ -184667,6 +184722,17 @@
<parameter name="location" type="int[]">
</parameter>
</method>
+<method name="getMatrix"
+ return="android.graphics.Matrix"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getMeasuredHeight"
return="int"
abstract="false"
@@ -184799,6 +184865,28 @@
visibility="public"
>
</method>
+<method name="getPivotX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPivotY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getResources"
return="android.content.res.Resources"
abstract="false"
@@ -184854,6 +184942,39 @@
visibility="public"
>
</method>
+<method name="getRotation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScaleX"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getScaleY"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getScrollBarStyle"
return="int"
abstract="false"
@@ -185100,6 +185221,28 @@
<parameter name="outRect" type="android.graphics.Rect">
</parameter>
</method>
+<method name="getX"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getY"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="hasFocus"
return="boolean"
abstract="false"
@@ -186430,6 +186573,19 @@
<parameter name="event" type="android.view.accessibility.AccessibilityEvent">
</parameter>
</method>
+<method name="setAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="alpha" type="float">
+</parameter>
+</method>
<method name="setAnimation"
return="void"
abstract="false"
@@ -186482,6 +186638,19 @@
<parameter name="resid" type="int">
</parameter>
</method>
+<method name="setBottom"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="bottom" type="int">
+</parameter>
+</method>
<method name="setClickable"
return="void"
abstract="false"
@@ -186690,6 +186859,19 @@
<parameter name="params" type="android.view.ViewGroup.LayoutParams">
</parameter>
</method>
+<method name="setLeft"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="left" type="int">
+</parameter>
+</method>
<method name="setLongClickable"
return="void"
abstract="false"
@@ -186893,6 +187075,32 @@
<parameter name="bottom" type="int">
</parameter>
</method>
+<method name="setPivotX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pivotX" type="float">
+</parameter>
+</method>
+<method name="setPivotY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pivotY" type="float">
+</parameter>
+</method>
<method name="setPressed"
return="void"
abstract="false"
@@ -186906,6 +187114,32 @@
<parameter name="pressed" type="boolean">
</parameter>
</method>
+<method name="setRight"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="right" type="int">
+</parameter>
+</method>
+<method name="setRotation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rotation" type="float">
+</parameter>
+</method>
<method name="setSaveEnabled"
return="void"
abstract="false"
@@ -186932,6 +187166,32 @@
<parameter name="enabled" type="boolean">
</parameter>
</method>
+<method name="setScaleX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scaleX" type="float">
+</parameter>
+</method>
+<method name="setScaleY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="scaleY" type="float">
+</parameter>
+</method>
<method name="setScrollBarStyle"
return="void"
abstract="false"
@@ -187025,6 +187285,19 @@
<parameter name="tag" type="java.lang.Object">
</parameter>
</method>
+<method name="setTop"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="top" type="int">
+</parameter>
+</method>
<method name="setTouchDelegate"
return="void"
abstract="false"
@@ -187103,6 +187376,32 @@
<parameter name="willNotDraw" type="boolean">
</parameter>
</method>
+<method name="setX"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="int">
+</parameter>
+</method>
+<method name="setY"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="y" type="int">
+</parameter>
+</method>
<method name="showContextMenu"
return="boolean"
abstract="false"
diff --git a/cmds/surfaceflinger/Android.mk b/cmds/surfaceflinger/Android.mk
index bfa58a1..1df32bb 100644
--- a/cmds/surfaceflinger/Android.mk
+++ b/cmds/surfaceflinger/Android.mk
@@ -10,7 +10,7 @@ LOCAL_SHARED_LIBRARIES := \
libutils
LOCAL_C_INCLUDES := \
- $(LOCAL_PATH)/../../libs/surfaceflinger
+ $(LOCAL_PATH)/../../services/surfaceflinger
LOCAL_MODULE:= surfaceflinger
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index d650721..78b1007 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -1,18 +1,25 @@
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
+/*
+ * 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 <binder/BinderService.h>
#include <SurfaceFlinger.h>
using namespace android;
-int main(int argc, char** argv)
-{
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("ServiceManager: %p", sm.get());
- SurfaceFlinger::instantiate();
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
+int main(int argc, char** argv) {
+ SurfaceFlinger::publishAndJoinThreadPool();
+ return 0;
}
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 1813d3e..a880a91 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -7,9 +7,9 @@ LOCAL_SRC_FILES:= \
base = $(LOCAL_PATH)/../../..
LOCAL_C_INCLUDES := \
- $(base)/camera/libcameraservice \
- $(base)/libs/audioflinger \
- $(base)/libs/surfaceflinger \
+ $(base)/services/camera/libcameraservice \
+ $(base)/services/audioflinger \
+ $(base)/services/surfaceflinger \
$(base)/media/libmediaplayerservice \
$(JNI_H_INCLUDE)
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index d0b3ac4..3cd2b9e 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -368,6 +368,24 @@ public abstract class ActionBar {
* @return The context mode's menu.
*/
public abstract Menu getMenu();
+
+ /**
+ * Returns the current title of this context mode.
+ * @return Title text
+ */
+ public abstract CharSequence getTitle();
+
+ /**
+ * Returns the current subtitle of this context mode.
+ * @return Subtitle text
+ */
+ public abstract CharSequence getSubtitle();
+
+ /**
+ * Returns the current custom view for this context mode.
+ * @return The current custom view
+ */
+ public abstract View getCustomView();
}
/**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a1cf233..91e4cd5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -71,6 +71,7 @@ import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.android.internal.app.ActionBarImpl;
@@ -1270,19 +1271,37 @@ public class Activity extends ContextThemeWrapper
* @see #onPause
*/
public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas) {
- final View view = mDecor;
- if (view == null) {
+ if (mDecor == null) {
return false;
}
- final int vw = view.getWidth();
- final int vh = view.getHeight();
- final int dw = outBitmap.getWidth();
- final int dh = outBitmap.getHeight();
+ int paddingLeft = 0;
+ int paddingRight = 0;
+ int paddingTop = 0;
+ int paddingBottom = 0;
+
+ // Find System window and use padding so we ignore space reserved for decorations
+ // like the status bar and such.
+ final FrameLayout top = (FrameLayout) mDecor;
+ for (int i = 0; i < top.getChildCount(); i++) {
+ View child = top.getChildAt(i);
+ if (child.isFitsSystemWindowsFlagSet()) {
+ paddingLeft = child.getPaddingLeft();
+ paddingRight = child.getPaddingRight();
+ paddingTop = child.getPaddingTop();
+ paddingBottom = child.getPaddingBottom();
+ break;
+ }
+ }
+
+ final int visibleWidth = mDecor.getWidth() - paddingLeft - paddingRight;
+ final int visibleHeight = mDecor.getHeight() - paddingTop - paddingBottom;
canvas.save();
- canvas.scale(((float)dw)/vw, ((float)dh)/vh);
- view.draw(canvas);
+ canvas.scale( (float) outBitmap.getWidth() / visibleWidth,
+ (float) outBitmap.getHeight() / visibleHeight);
+ canvas.translate(-paddingLeft, -paddingTop);
+ mDecor.draw(canvas);
canvas.restore();
return true;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index eb7520f..d66e98b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -285,24 +285,54 @@ public class ActivityManager {
* @param maxNum The maximum number of entries to return in the list. The
* actual number returned may be smaller, depending on how many tasks the
* user has started.
- *
+ *
+ * @param flags Optional flags
+ * @param receiver Optional receiver for delayed thumbnails
+ *
* @return Returns a list of RunningTaskInfo records describing each of
* the running tasks.
*
+ * Some thumbnails may not be available at the time of this call. The optional
+ * receiver may be used to receive those thumbnails.
+ *
* @throws SecurityException Throws SecurityException if the caller does
* not hold the {@link android.Manifest.permission#GET_TASKS} permission.
+ *
+ * @hide
*/
- public List<RunningTaskInfo> getRunningTasks(int maxNum)
+ public List<RunningTaskInfo> getRunningTasks(int maxNum, int flags, IThumbnailReceiver receiver)
throws SecurityException {
try {
- return (List<RunningTaskInfo>)ActivityManagerNative.getDefault()
- .getTasks(maxNum, 0, null);
+ return ActivityManagerNative.getDefault().getTasks(maxNum, flags, receiver);
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return null;
}
}
-
+
+ /**
+ * Return a list of the tasks that are currently running, with
+ * the most recent being first and older ones after in order. Note that
+ * "running" does not mean any of the task's code is currently loaded or
+ * activity -- the task may have been frozen by the system, so that it
+ * can be restarted in its previous state when next brought to the
+ * foreground.
+ *
+ * @param maxNum The maximum number of entries to return in the list. The
+ * actual number returned may be smaller, depending on how many tasks the
+ * user has started.
+ *
+ * @return Returns a list of RunningTaskInfo records describing each of
+ * the running tasks.
+ *
+ * @throws SecurityException Throws SecurityException if the caller does
+ * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
+ */
+ public List<RunningTaskInfo> getRunningTasks(int maxNum)
+ throws SecurityException {
+ return getRunningTasks(maxNum, 0, null);
+ }
+
/**
* Information you can retrieve about a particular Service that is
* currently running in the system.
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index aa207e8..c800fbe 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -116,6 +116,7 @@ final class RemoteServiceException extends AndroidRuntimeException {
*/
public final class ActivityThread {
static final String TAG = "ActivityThread";
+ private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
private static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
static final boolean DEBUG_BROADCAST = false;
@@ -2245,13 +2246,24 @@ public final class ActivityThread {
h = mThumbnailHeight;
}
- // XXX Only set hasAlpha if needed?
- thumbnail = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
- thumbnail.eraseColor(0);
- Canvas cv = new Canvas(thumbnail);
- if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
- thumbnail = null;
+ // On platforms where we don't want thumbnails, set dims to (0,0)
+ if ((w > 0) && (h > 0)) {
+ View topView = r.activity.getWindow().getDecorView();
+
+ // Maximize bitmap by capturing in native aspect.
+ if (topView.getWidth() >= topView.getHeight()) {
+ thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
+ } else {
+ thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT);
+ }
+
+ thumbnail.eraseColor(0);
+ Canvas cv = new Canvas(thumbnail);
+ if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
+ thumbnail = null;
+ }
}
+
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
@@ -2382,7 +2394,7 @@ public final class ActivityThread {
if (info != null) {
try {
// First create a thumbnail for the activity...
- //info.thumbnail = createThumbnailBitmap(r);
+ info.thumbnail = createThumbnailBitmap(r);
info.description = r.activity.onCreateDescription();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6e9586c..a2a74f8 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1715,8 +1715,9 @@ class ContextImpl extends Context {
if (resolveInfo == null) {
return null;
}
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(packageName, resolveInfo.activityInfo.name);
+ Intent intent = new Intent(intentToResolve);
+ intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
+ resolveInfo.activityInfo.name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 441370a..c0226f8 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1047,6 +1047,7 @@ public class SQLiteDatabase extends SQLiteClosable {
closeClosable();
// finalize ALL statements queued up so far
closePendingStatements();
+ releaseCustomFunctions();
// close this database instance - regardless of its reference count value
dbclose();
if (mConnectionPool != null) {
@@ -1083,6 +1084,54 @@ public class SQLiteDatabase extends SQLiteClosable {
private native void dbclose();
/**
+ * A callback interface for a custom sqlite3 function.
+ * This can be used to create a function that can be called from
+ * sqlite3 database triggers.
+ * @hide
+ */
+ public interface CustomFunction {
+ public void callback(String[] args);
+ }
+
+ /**
+ * Registers a CustomFunction callback as a function that can be called from
+ * sqlite3 database triggers.
+ * @param name the name of the sqlite3 function
+ * @param numArgs the number of arguments for the function
+ * @param function callback to call when the function is executed
+ * @hide
+ */
+ public void addCustomFunction(String name, int numArgs, CustomFunction function) {
+ verifyDbIsOpen();
+ synchronized (mCustomFunctions) {
+ int ref = native_addCustomFunction(name, numArgs, function);
+ if (ref != 0) {
+ // save a reference to the function for cleanup later
+ mCustomFunctions.add(new Integer(ref));
+ } else {
+ throw new SQLiteException("failed to add custom function " + name);
+ }
+ }
+ }
+
+ private void releaseCustomFunctions() {
+ synchronized (mCustomFunctions) {
+ for (int i = 0; i < mCustomFunctions.size(); i++) {
+ Integer function = mCustomFunctions.get(i);
+ native_releaseCustomFunction(function.intValue());
+ }
+ mCustomFunctions.clear();
+ }
+ }
+
+ // list of CustomFunction references so we can clean up when the database closes
+ private final ArrayList<Integer> mCustomFunctions =
+ new ArrayList<Integer>();
+
+ private native int native_addCustomFunction(String name, int numArgs, CustomFunction function);
+ private native void native_releaseCustomFunction(int function);
+
+ /**
* Gets the database version.
*
* @return the database version
@@ -1959,12 +2008,17 @@ public class SQLiteDatabase extends SQLiteClosable {
}
@Override
- protected void finalize() {
- if (isOpen()) {
- Log.e(TAG, "close() was never explicitly called on database '" +
- mPath + "' ", mStackTrace);
- closeClosable();
- onAllReferencesReleased();
+ protected void finalize() throws Throwable {
+ try {
+ if (isOpen()) {
+ Log.e(TAG, "close() was never explicitly called on database '" +
+ mPath + "' ", mStackTrace);
+ closeClosable();
+ onAllReferencesReleased();
+ releaseCustomFunctions();
+ }
+ } finally {
+ super.finalize();
}
}
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index 02b6210..00b6864 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -350,8 +350,7 @@ public class DownloadManager {
}
if (!mRequestHeaders.isEmpty()) {
- // TODO request headers support
- throw new UnsupportedOperationException();
+ encodeHttpHeaders(values);
}
putIfNonNull(values, Downloads.COLUMN_TITLE, mTitle);
@@ -367,6 +366,15 @@ public class DownloadManager {
return values;
}
+ private void encodeHttpHeaders(ContentValues values) {
+ int index = 0;
+ for (Map.Entry<String, String> entry : mRequestHeaders.entrySet()) {
+ String headerString = entry.getKey() + ": " + entry.getValue();
+ values.put(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX + index, headerString);
+ index++;
+ }
+ }
+
private void putIfNonNull(ContentValues contentValues, String key, String value) {
if (value != null) {
contentValues.put(key, value);
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 9ad125b..31acb5b 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -247,13 +247,16 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
/**
* {@inheritDoc}
*
- * <p>This method verifies the peer's certificate hostname after connecting.
+ * <p>This method verifies the peer's certificate hostname after connecting
+ * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
*/
@Override
public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
s.setHandshakeTimeout(mHandshakeTimeoutMillis);
- verifyHostname(s, host);
+ if (mSecure) {
+ verifyHostname(s, host);
+ }
return s;
}
@@ -305,7 +308,8 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
/**
* {@inheritDoc}
*
- * <p>This method verifies the peer's certificate hostname after connecting.
+ * <p>This method verifies the peer's certificate hostname after connecting
+ * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
*/
@Override
public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
@@ -313,20 +317,25 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
host, port, localAddr, localPort);
s.setHandshakeTimeout(mHandshakeTimeoutMillis);
- verifyHostname(s, host);
+ if (mSecure) {
+ verifyHostname(s, host);
+ }
return s;
}
/**
* {@inheritDoc}
*
- * <p>This method verifies the peer's certificate hostname after connecting.
+ * <p>This method verifies the peer's certificate hostname after connecting
+ * (unless created with {@link #getInsecure(int, SSLSessionCache)}).
*/
@Override
public Socket createSocket(String host, int port) throws IOException {
OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
s.setHandshakeTimeout(mHandshakeTimeoutMillis);
- verifyHostname(s, host);
+ if (mSecure) {
+ verifyHostname(s, host);
+ }
return s;
}
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index a23a5a7..10f1d2b 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -289,6 +289,7 @@ public final class Calendar {
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Calendars.SYNC1);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Calendars.SYNC2);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Calendars.SYNC3);
+ DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Calendars.SYNC4);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, Calendars.NAME);
DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv,
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 1a4f8c0..2a612fe 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -1115,5 +1115,26 @@ public final class Downloads {
* This download doesn't show in the UI or in the notifications.
*/
public static final int VISIBILITY_HIDDEN = 2;
+
+ /**
+ * Constants related to HTTP request headers associated with each download.
+ */
+ public static class RequestHeaders {
+ public static final String HEADERS_DB_TABLE = "request_headers";
+ public static final String COLUMN_DOWNLOAD_ID = "download_id";
+ public static final String COLUMN_HEADER = "header";
+ public static final String COLUMN_VALUE = "value";
+
+ /**
+ * Path segment to add to a download URI to retrieve request headers
+ */
+ public static final String URI_SEGMENT = "headers";
+
+ /**
+ * Prefix for ContentValues keys that contain HTTP header lines, to be passed to
+ * DownloadProvider.insert().
+ */
+ public static final String INSERT_KEY_PREFIX = "http_header_";
+ }
}
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index c469bcc..54cb4ca 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -543,6 +543,9 @@ public class SurfaceView extends View {
}
if (creating || formatChanged || sizeChanged
|| visibleChanged || realSizeChanged) {
+ for (SurfaceHolder.Callback c : callbacks) {
+ c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
+ }
}
if (redrawNeeded) {
for (SurfaceHolder.Callback c : callbacks) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 05d380e..3a3ad8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.RectF;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
@@ -1585,6 +1586,87 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
int mViewFlags;
/**
+ * The transform matrix for the View. This transform is calculated internally
+ * based on the rotation, scaleX, and scaleY properties. The identity matrix
+ * is used by default. Do *not* use this variable directly; instead call
+ * getMatrix(), which will automatically recalculate the matrix if necessary
+ * to get the correct matrix based on the latest rotation and scale properties.
+ */
+ private final Matrix mMatrix = new Matrix();
+
+ /**
+ * The transform matrix for the View. This transform is calculated internally
+ * based on the rotation, scaleX, and scaleY properties. The identity matrix
+ * is used by default. Do *not* use this variable directly; instead call
+ * getMatrix(), which will automatically recalculate the matrix if necessary
+ * to get the correct matrix based on the latest rotation and scale properties.
+ */
+ private Matrix mInverseMatrix;
+
+ /**
+ * An internal variable that tracks whether we need to recalculate the
+ * transform matrix, based on whether the rotation or scaleX/Y properties
+ * have changed since the matrix was last calculated.
+ */
+ private boolean mMatrixDirty = false;
+
+ /**
+ * An internal variable that tracks whether we need to recalculate the
+ * transform matrix, based on whether the rotation or scaleX/Y properties
+ * have changed since the matrix was last calculated.
+ */
+ private boolean mInverseMatrixDirty = true;
+
+ /**
+ * A variable that tracks whether we need to recalculate the
+ * transform matrix, based on whether the rotation or scaleX/Y properties
+ * have changed since the matrix was last calculated. This variable
+ * is only valid after a call to getMatrix().
+ */
+ boolean mMatrixIsIdentity = true;
+
+ /**
+ * The degrees rotation around the pivot point.
+ */
+ @ViewDebug.ExportedProperty
+ private float mRotation = 0f;
+
+ /**
+ * The amount of scale in the x direction around the pivot point. A
+ * value of 1 means no scaling is applied.
+ */
+ @ViewDebug.ExportedProperty
+ private float mScaleX = 1f;
+
+ /**
+ * The amount of scale in the y direction around the pivot point. A
+ * value of 1 means no scaling is applied.
+ */
+ @ViewDebug.ExportedProperty
+ private float mScaleY = 1f;
+
+ /**
+ * The amount of scale in the x direction around the pivot point. A
+ * value of 1 means no scaling is applied.
+ */
+ @ViewDebug.ExportedProperty
+ private float mPivotX = 0f;
+
+ /**
+ * The amount of scale in the y direction around the pivot point. A
+ * value of 1 means no scaling is applied.
+ */
+ @ViewDebug.ExportedProperty
+ private float mPivotY = 0f;
+
+ /**
+ * The opacity of the View. This is a value from 0 to 1, where 0 means
+ * completely transparent and 1 means completely opaque.
+ */
+ @ViewDebug.ExportedProperty
+ private float mAlpha = 1f;
+
+ /**
* The distance in pixels from the left edge of this view's parent
* to the left edge of this view.
* {@hide}
@@ -3019,6 +3101,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Determine if this view has the FITS_SYSTEM_WINDOWS flag set.
+ * @return True if window has FITS_SYSTEM_WINDOWS set
+ *
+ * @hide
+ */
+ public boolean isFitsSystemWindowsFlagSet() {
+ return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
+ }
+
+ /**
* Returns the visibility status for this view.
*
* @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -4406,9 +4498,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final int y = (int) event.getY();
// Be lenient about moving outside of buttons
- int slop = mTouchSlop;
- if ((x < 0 - slop) || (x >= getWidth() + slop) ||
- (y < 0 - slop) || (y >= getHeight() + slop)) {
+ if (!pointInView(x, y, mTouchSlop)) {
// Outside button
removeTapCallback();
if ((mPrivateFlags & PRESSED) != 0) {
@@ -4754,6 +4844,234 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * The transform matrix of this view, which is calculated based on the current
+ * roation, scale, and pivot properties.
+ *
+ * @see #getRotation()
+ * @see #getScaleX()
+ * @see #getScaleY()
+ * @see #getPivotX()
+ * @see #getPivotY()
+ * @return The current transform matrix for the view
+ */
+ public Matrix getMatrix() {
+ if (mMatrixDirty) {
+ // transform-related properties have changed since the last time someone
+ // asked for the matrix; recalculate it with the current values
+ mMatrix.reset();
+ mMatrix.setRotate(mRotation, mPivotX, mPivotY);
+ mMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ mMatrixDirty = false;
+ mMatrixIsIdentity = mMatrix.isIdentity();
+ mInverseMatrixDirty = true;
+ }
+ return mMatrix;
+ }
+
+ /**
+ * Utility method to retrieve the inverse of the current mMatrix property.
+ * We cache the matrix to avoid recalculating it when transform properties
+ * have not changed.
+ *
+ * @return The inverse of the current matrix of this view.
+ */
+ Matrix getInverseMatrix() {
+ if (mInverseMatrixDirty) {
+ if (mInverseMatrix == null) {
+ mInverseMatrix = new Matrix();
+ }
+ mMatrix.invert(mInverseMatrix);
+ mInverseMatrixDirty = false;
+ }
+ return mInverseMatrix;
+ }
+
+ /**
+ * The degrees that the view is rotated around the pivot point.
+ *
+ * @see #getPivotX()
+ * @see #getPivotY()
+ * @return The degrees of rotation.
+ */
+ public float getRotation() {
+ return mRotation;
+ }
+
+ /**
+ * Sets the degrees that the view is rotated around the pivot point.
+ *
+ * @param rotation The degrees of rotation.
+ * @see #getPivotX()
+ * @see #getPivotY()
+ */
+ public void setRotation(float rotation) {
+ if (mRotation != rotation) {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ mRotation = rotation;
+ mMatrixDirty = true;
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+
+ /**
+ * The amount that the view is scaled in x around the pivot point, as a proportion of
+ * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
+ *
+ * @default 1.0f
+ * @see #getPivotX()
+ * @see #getPivotY()
+ * @return The scaling factor.
+ */
+ public float getScaleX() {
+ return mScaleX;
+ }
+
+ /**
+ * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
+ * the view's unscaled width. A value of 1 means that no scaling is applied.
+ *
+ * @param scaleX The scaling factor.
+ * @see #getPivotX()
+ * @see #getPivotY()
+ */
+ public void setScaleX(float scaleX) {
+ if (mScaleX != scaleX) {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ mScaleX = scaleX;
+ mMatrixDirty = true;
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+
+ /**
+ * The amount that the view is scaled in y around the pivot point, as a proportion of
+ * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
+ *
+ * @default 1.0f
+ * @see #getPivotX()
+ * @see #getPivotY()
+ * @return The scaling factor.
+ */
+ public float getScaleY() {
+ return mScaleY;
+ }
+
+ /**
+ * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
+ * the view's unscaled width. A value of 1 means that no scaling is applied.
+ *
+ * @param scaleY The scaling factor.
+ * @see #getPivotX()
+ * @see #getPivotY()
+ */
+ public void setScaleY(float scaleY) {
+ if (mScaleY != scaleY) {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ mScaleY = scaleY;
+ mMatrixDirty = true;
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+
+ /**
+ * The x location of the point around which the view is {@link #setRotation(float) rotated}
+ * and {@link #setScaleX(float) scaled}.
+ *
+ * @see #getRotation()
+ * @see #getScaleX()
+ * @see #getScaleY()
+ * @see #getPivotY()
+ * @return The x location of the pivot point.
+ */
+ public float getPivotX() {
+ return mPivotX;
+ }
+
+ /**
+ * Sets the x location of the point around which the view is
+ * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
+ *
+ * @param pivotX The x location of the pivot point.
+ * @see #getRotation()
+ * @see #getScaleX()
+ * @see #getScaleY()
+ * @see #getPivotY()
+ */
+ public void setPivotX(float pivotX) {
+ if (mPivotX != pivotX) {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ mPivotX = pivotX;
+ mMatrixDirty = true;
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+
+ /**
+ * The y location of the point around which the view is {@link #setRotation(float) rotated}
+ * and {@link #setScaleY(float) scaled}.
+ *
+ * @see #getRotation()
+ * @see #getScaleX()
+ * @see #getScaleY()
+ * @see #getPivotY()
+ * @return The y location of the pivot point.
+ */
+ public float getPivotY() {
+ return mPivotY;
+ }
+
+ /**
+ * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
+ * and {@link #setScaleY(float) scaled}.
+ *
+ * @param pivotY The y location of the pivot point.
+ * @see #getRotation()
+ * @see #getScaleX()
+ * @see #getScaleY()
+ * @see #getPivotY()
+ */
+ public void setPivotY(float pivotY) {
+ if (mPivotY != pivotY) {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ mPivotY = pivotY;
+ mMatrixDirty = true;
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+
+ /**
+ * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
+ * completely transparent and 1 means the view is completely opaque.
+ *
+ * @default 1.0f
+ * @return The opacity of the view.
+ */
+ public float getAlpha() {
+ return mAlpha;
+ }
+
+ /**
+ * Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
+ * completely transparent and 1 means the view is completely opaque.
+ *
+ * @param alpha The opacity of the view.
+ */
+ public void setAlpha(float alpha) {
+ mAlpha = alpha;
+ invalidate();
+ }
+
+ /**
* Top position of this view relative to its parent.
*
* @return The top of this view, in pixels.
@@ -4764,6 +5082,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Sets the top position of this view relative to its parent.
+ *
+ * @param top The top of this view, in pixels.
+ */
+ public final void setTop(int top) {
+ if (top != mTop) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int minTop = Math.min(mTop, top);
+ location[0] = mLeft;
+ location[1] = minTop;
+ r.set(0, 0, mRight - mLeft, mBottom - minTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ }
+ mTop = top;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+ }
+
+ /**
* Bottom position of this view relative to its parent.
*
* @return The bottom of this view, in pixels.
@@ -4774,6 +5123,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Sets the bottom position of this view relative to its parent.
+ *
+ * @param bottom The bottom of this view, in pixels.
+ */
+ public final void setBottom(int bottom) {
+ if (bottom != mBottom) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int maxBottom = Math.max(mBottom, bottom);
+ location[0] = mLeft;
+ location[1] = mTop;
+ r.set(0, 0, mRight - mLeft, maxBottom - mTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ }
+ mBottom = bottom;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+ }
+
+ /**
* Left position of this view relative to its parent.
*
* @return The left edge of this view, in pixels.
@@ -4784,6 +5164,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Sets the left position of this view relative to its parent.
+ *
+ * @param left The bottom of this view, in pixels.
+ */
+ public final void setLeft(int left) {
+ if (left != mLeft) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int minLeft = Math.min(mLeft, left);
+ location[0] = minLeft;
+ location[1] = mTop;
+ r.set(0, 0, mRight - minLeft, mBottom - mTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ }
+ mLeft = left;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+ }
+
+ /**
* Right position of this view relative to its parent.
*
* @return The right edge of this view, in pixels.
@@ -4794,12 +5205,149 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Sets the right position of this view relative to its parent.
+ *
+ * @param right The bottom of this view, in pixels.
+ */
+ public final void setRight(int right) {
+ if (right != mRight) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int maxRight = Math.max(mRight, right);
+ location[0] = mLeft;
+ location[1] = mTop;
+ r.set(0, 0, maxRight - mLeft, mBottom - mTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ // Double-invalidation is necessary to capture view's old and new areas
+ invalidate();
+ }
+ mRight = right;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
+ }
+
+ /**
+ * The horizontal location of this view relative to its parent. This value is equivalent to the
+ * {@link #getLeft() left} property.
+ *
+ * @return The horizontal position of this view, in pixels.
+ */
+ public int getX() {
+ return mLeft;
+ }
+
+ /**
+ * Sets the horizontal location of this view relative to its parent. Setting this value will
+ * affect both the {@link #setLeft(int) left} and {@link #setRight(int) right} properties
+ * of this view.
+ *
+ * @param x The horizontal position of this view, in pixels.
+ */
+ public void setX(int x) {
+ offsetLeftAndRight(x - mLeft);
+ }
+
+ /**
+ * The vertical location of this view relative to its parent. This value is equivalent to the
+ * {@link #getTop() left} property.
+ *
+ * @return The vertical position of this view, in pixels.
+ */
+ public int getY() {
+ return mTop;
+ }
+
+ /**
+ * Sets the vertical location of this view relative to its parent. Setting this value will
+ * affect both the {@link #setTop(int) left} and {@link #setBottom(int) right} properties
+ * of this view.
+ *
+ * @param y The vertical position of this view, in pixels.
+ */
+ public void setY(int y) {
+ offsetTopAndBottom(y - mTop);
+ }
+
+ /**
* Hit rectangle in parent's coordinates
*
* @param outRect The hit rectangle of the view.
*/
public void getHitRect(Rect outRect) {
- outRect.set(mLeft, mTop, mRight, mBottom);
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity || mAttachInfo == null) {
+ outRect.set(mLeft, mTop, mRight, mBottom);
+ } else {
+ final RectF tmpRect = mAttachInfo.mTmpTransformRect;
+ tmpRect.set(-mPivotX, -mPivotY,
+ getWidth() - mPivotX, getHeight() - mPivotY);
+ m.mapRect(tmpRect);
+ outRect.set((int)tmpRect.left + mLeft, (int)tmpRect.top + mTop,
+ (int)tmpRect.right + mLeft, (int)tmpRect.bottom + mTop);
+ }
+ }
+
+ /**
+ * This method detects whether the given event is inside the view and, if so,
+ * handles it via the dispatchEvent(MotionEvent) method.
+ *
+ * @param ev The event that is being dispatched.
+ * @param parentX The x location of the event in the parent's coordinates.
+ * @param parentY The y location of the event in the parent's coordinates.
+ * @return true if the event was inside this view, false otherwise.
+ */
+ boolean dispatchTouchEvent(MotionEvent ev, float parentX, float parentY) {
+ float localX = parentX - mLeft;
+ float localY = parentY - mTop;
+ Matrix m = getMatrix();
+ if (!mMatrixIsIdentity && mAttachInfo != null) {
+ // non-identity matrix: transform the point into the view's coordinates
+ final float[] localXY = mAttachInfo.mTmpTransformLocation;
+ localXY[0] = localX;
+ localXY[1] = localY;
+ getInverseMatrix().mapPoints(localXY);
+ localX = localXY[0];
+ localY = localXY[1];
+ }
+ if (localX >= 0 && localY >= 0 &&
+ localX < (mRight - mLeft) && localY < (mBottom - mTop)) {
+ ev.setLocation(localX, localY);
+ return dispatchTouchEvent(ev);
+ }
+ return false;
+ }
+
+ /**
+ * Utility method to determine whether the given point, in local coordinates,
+ * is inside the view, where the area of the view is expanded by the slop factor.
+ * This method is called while processing touch-move events to determine if the event
+ * is still within the view.
+ */
+ private boolean pointInView(float localX, float localY, float slop) {
+ Matrix m = getMatrix();
+ if (!mMatrixIsIdentity && mAttachInfo != null) {
+ // non-identity matrix: transform the point into the view's coordinates
+ final float[] localXY = mAttachInfo.mTmpTransformLocation;
+ localXY[0] = localX;
+ localXY[1] = localY;
+ getInverseMatrix().mapPoints(localXY);
+ localX = localXY[0];
+ localY = localXY[1];
+ }
+ if (localX > -slop && localY > -slop &&
+ localX < ((mRight - mLeft) + slop) && localY < ((mBottom - mTop) + slop)) {
+ return true;
+ }
+ return false;
}
/**
@@ -4862,8 +5410,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @param offset the number of pixels to offset the view by
*/
public void offsetTopAndBottom(int offset) {
- mTop += offset;
- mBottom += offset;
+ if (offset != 0) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int minTop = offset < 0 ? mTop + offset : mTop;
+ int maxBottom = offset < 0 ? mBottom : mBottom + offset;
+ location[0] = mLeft;
+ location[1] = minTop;
+ r.set(0, 0, mRight - mLeft, maxBottom - minTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ invalidate();
+ }
+ mTop += offset;
+ mBottom += offset;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
}
/**
@@ -4872,8 +5442,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @param offset the numer of pixels to offset the view by
*/
public void offsetLeftAndRight(int offset) {
- mLeft += offset;
- mRight += offset;
+ if (offset != 0) {
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity) {
+ final ViewParent p = mParent;
+ if (p != null && mAttachInfo != null) {
+ final int[] location = mAttachInfo.mInvalidateChildLocation;
+ final Rect r = mAttachInfo.mTmpInvalRect;
+ int minLeft = offset < 0 ? mLeft + offset : mLeft;
+ int maxRight = offset < 0 ? mRight : mRight + offset;
+ location[0] = minLeft;
+ location[1] = mTop;
+ r.set(0, 0, maxRight - minLeft, mBottom - mTop);
+ p.invalidateChildInParent(location, r);
+ }
+ } else {
+ invalidate();
+ }
+ mLeft += offset;
+ mRight += offset;
+ if (!mMatrixIsIdentity) {
+ mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+ invalidate();
+ }
+ }
}
/**
@@ -7936,7 +8528,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* without resorting to another data structure.
*
* The specified key should be an id declared in the resources of the
- * application to ensure it is unique. Keys identified as belonging to
+ * application to ensure it is unique (see the <a
+ * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
+ * Keys identified as belonging to
* the Android framework or not associated with any package will cause
* an {@link IllegalArgumentException} to be thrown.
*
@@ -9191,6 +9785,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
final int[] mInvalidateChildLocation = new int[2];
+
+ /**
+ * Global to the view hierarchy used as a temporary for dealing with
+ * x/y location when view is transformed.
+ */
+ final float[] mTmpTransformLocation = new float[2];
+
/**
* The view tree observer used to dispatch global events like
* layout, pre-draw, touch mode change, etc.
@@ -9227,6 +9828,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final Rect mTmpInvalRect = new Rect();
/**
+ * Temporary for use in computing hit areas with transformed views
+ */
+ final RectF mTmpTransformRect = new RectF();
+
+ /**
+ * Temporary for use in computing invalidation areas with transformed views
+ */
+ final float[] mTmpTransformBounds = new float[8];
+
+ /**
* Temporary list for use in collecting focusable descendents of a view.
*/
final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 34777ce..22ad27a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Matrix;
import com.android.internal.R;
import android.content.Context;
@@ -867,21 +868,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
- child.getHitRect(frame);
- if (frame.contains(scrolledXInt, scrolledYInt)) {
- // 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);
+ if (child.dispatchTouchEvent(ev, scrolledXFloat, scrolledYFloat)) {
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.
+ mMotionTarget = child;
+ return true;
}
}
}
@@ -937,8 +927,21 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// finally offset the event to the target's coordinate system and
// dispatch the event.
- final float xc = scrolledXFloat - (float) target.mLeft;
- final float yc = scrolledYFloat - (float) target.mTop;
+ float xc;
+ float yc;
+ Matrix m = getMatrix();
+ if (mMatrixIsIdentity || mAttachInfo == null) {
+ xc = scrolledXFloat - (float) target.mLeft;
+ yc = scrolledYFloat - (float) target.mTop;
+ } else {
+ // non-identity matrix: transform the point into the view's coordinates
+ final float[] localXY = mAttachInfo.mTmpTransformLocation;
+ localXY[0] = scrolledXFloat;
+ localXY[1] = scrolledYFloat;
+ getInverseMatrix().mapPoints(localXY);
+ xc = localXY[0] - (float) target.mLeft;
+ yc = localXY[1] - (float) target.mTop;
+ }
ev.setLocation(xc, yc);
if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
@@ -1609,25 +1612,36 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- float alpha = 1.0f;
+ float alpha = child.getAlpha();
+ Matrix childMatrix = child.getMatrix();
- if (transformToApply != null) {
- if (concatMatrix) {
- int transX = 0;
- int transY = 0;
- if (hasNoCache) {
- transX = -sx;
- transY = -sy;
+ if (transformToApply != null || alpha < 1.0f || !child.mMatrixIsIdentity) {
+ int transX = 0;
+ int transY = 0;
+ if (hasNoCache) {
+ transX = -sx;
+ transY = -sy;
+ }
+ if (transformToApply != null) {
+ if (concatMatrix) {
+ // Undo the scroll translation, apply the transformation matrix,
+ // then redo the scroll translate to get the correct result.
+ canvas.translate(-transX, -transY);
+ canvas.concat(transformToApply.getMatrix());
+ canvas.translate(transX, transY);
+ mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
}
- // Undo the scroll translation, apply the transformation matrix,
- // then redo the scroll translate to get the correct result.
+ float transformAlpha = transformToApply.getAlpha();
+ if (transformAlpha < 1.0f) {
+ alpha *= transformToApply.getAlpha();
+ mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
+ }
+ }
+ if (!child.mMatrixIsIdentity) {
canvas.translate(-transX, -transY);
- canvas.concat(transformToApply.getMatrix());
+ canvas.concat(child.getMatrix());
canvas.translate(transX, transY);
- mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
}
-
- alpha = transformToApply.getAlpha();
if (alpha < 1.0f) {
mGroupFlags |= FLAG_CLEAR_TRANSFORMATION;
}
@@ -2498,6 +2512,41 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int[] location = attachInfo.mInvalidateChildLocation;
location[CHILD_LEFT_INDEX] = child.mLeft;
location[CHILD_TOP_INDEX] = child.mTop;
+ Matrix childMatrix = child.getMatrix();
+ if (!childMatrix.isIdentity()) {
+ float[] boundingRectPoints = attachInfo.mTmpTransformBounds;
+ boundingRectPoints[0] = dirty.left; // upper left
+ boundingRectPoints[1] = dirty.top;
+ boundingRectPoints[2] = dirty.right; // upper right
+ boundingRectPoints[3] = dirty.top;
+ boundingRectPoints[4] = dirty.right; // lower right
+ boundingRectPoints[5] = dirty.bottom;
+ boundingRectPoints[6] = dirty.left; // lower left
+ boundingRectPoints[7] = dirty.bottom;
+ childMatrix.mapPoints(boundingRectPoints);
+ // find the mind/max points to get the bounding rect
+ float left = Float.MAX_VALUE;
+ float top = Float.MAX_VALUE;
+ float right = -Float.MAX_VALUE;
+ float bottom = -Float.MAX_VALUE;
+ for (int i = 0; i < 8; i += 2) {
+ float x = boundingRectPoints[i];
+ float y = boundingRectPoints[i+1];
+ if (x < left) {
+ left = x;
+ }
+ if (x > right) {
+ right = x;
+ }
+ if (y < top) {
+ top = y;
+ }
+ if (y > bottom) {
+ bottom = y;
+ }
+ }
+ dirty.set((int)left, (int)top, (int)(right + .5f), (int)(bottom + .5f));
+ }
// If the child is drawing an animation, we want to copy this flag onto
// ourselves and the parent to make sure the invalidate request goes
@@ -2532,6 +2581,39 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
parent = parent.invalidateChildInParent(location, dirty);
+ Matrix m = getMatrix();
+ if (!m.isIdentity()) {
+ float[] boundingRectPoints = {
+ dirty.left - mLeft, dirty.top - mTop, // upper left
+ dirty.right - mLeft, dirty.top - mTop, // upper right
+ dirty.right - mLeft, dirty.bottom - mTop, // lower right
+ dirty.left - mLeft, dirty.bottom - mTop // lower left
+ };
+ m.mapPoints(boundingRectPoints);
+ // find the mind/max points to get the bounding rect
+ float left = Float.MAX_VALUE;
+ float top = Float.MAX_VALUE;
+ float right = Float.MIN_VALUE;
+ float bottom = Float.MIN_VALUE;
+ for (int i = 0; i < 8; i += 2) {
+ float x = boundingRectPoints[i];
+ float y = boundingRectPoints[i+1];
+ if (x < left) {
+ left = x;
+ }
+ if (x > right) {
+ right = x;
+ }
+ if (y < top) {
+ top = y;
+ }
+ if (y > bottom) {
+ bottom = y;
+ }
+ }
+ dirty.set((int)left + mLeft, (int)top + mTop, (int)(right + .5f) + mLeft,
+ (int)(bottom + .5f) + mTop);
+ }
} while (parent != null);
}
}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 6cf455c..f37021b 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -34,6 +34,7 @@ import android.widget.LinearLayout;
import android.widget.SpinnerAdapter;
import android.widget.ViewAnimator;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
@@ -70,6 +71,8 @@ public class ActionBarImpl extends ActionBar {
private int mContextDisplayMode;
+ private boolean mClosingContext;
+
final Handler mHandler = new Handler();
final Runnable mCloseContext = new Runnable() {
public void run() {
@@ -77,6 +80,7 @@ public class ActionBarImpl extends ActionBar {
if (mLowerContextView != null) {
mLowerContextView.removeAllViews();
}
+ mClosingContext = false;
}
};
@@ -195,6 +199,14 @@ public class ActionBarImpl extends ActionBar {
if (mContextMode != null) {
mContextMode.finish();
}
+
+ // Don't wait for the close context mode animation to finish.
+ if (mClosingContext) {
+ mAnimatorView.clearAnimation();
+ mHandler.removeCallbacks(mCloseContext);
+ mCloseContext.run();
+ }
+
mContextMode = new ContextMode(callback);
if (callback.onCreateContextMode(mContextMode, mContextMode.getMenu())) {
mContextMode.invalidate();
@@ -327,6 +339,7 @@ public class ActionBarImpl extends ActionBar {
public class ContextMode extends ActionBar.ContextMode {
private ContextModeCallback mCallback;
private ActionMenu mMenu;
+ private WeakReference<View> mCustomView;
public ContextMode(ContextModeCallback callback) {
mCallback = callback;
@@ -344,6 +357,7 @@ public class ActionBarImpl extends ActionBar {
mAnimatorView.setDisplayedChild(NORMAL_VIEW);
// Clear out the context mode views after the animation finishes
+ mClosingContext = true;
mHandler.postDelayed(mCloseContext, mAnimatorView.getOutAnimation().getDuration());
if (mLowerContextView != null && mLowerContextView.getVisibility() != View.GONE) {
@@ -363,6 +377,7 @@ public class ActionBarImpl extends ActionBar {
@Override
public void setCustomView(View view) {
mUpperContextView.setCustomView(view);
+ mCustomView = new WeakReference<View>(view);
}
@Override
@@ -374,7 +389,22 @@ public class ActionBarImpl extends ActionBar {
public void setTitle(CharSequence title) {
mUpperContextView.setTitle(title);
}
+
+ @Override
+ public CharSequence getTitle() {
+ return mUpperContextView.getTitle();
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ return mUpperContextView.getSubtitle();
+ }
+ @Override
+ public View getCustomView() {
+ return mCustomView != null ? mCustomView.get() : null;
+ }
+
public void dispatchOnContextItemClicked(MenuItem item) {
ActionMenuItem actionItem = (ActionMenuItem) item;
if (!actionItem.invoke()) {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 0f895f0..b57b7a8 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -105,6 +105,14 @@ public class ActionBarContextView extends ViewGroup {
initTitle();
}
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ public CharSequence getSubtitle() {
+ return mSubtitle;
+ }
+
private void initTitle() {
if (mTitleLayout == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 48707b9..fbff8ae 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -91,6 +91,7 @@ public class ActionBarView extends ViewGroup {
private View mCustomNavView;
private boolean mShowMenu;
+ private boolean mUserTitle;
private MenuBuilder mOptionsMenu;
private ActionMenuView mMenuView;
@@ -212,7 +213,30 @@ public class ActionBarView extends ViewGroup {
return mTitle;
}
+ /**
+ * Set the action bar title. This will always replace or override window titles.
+ * @param title Title to set
+ *
+ * @see #setWindowTitle(CharSequence)
+ */
public void setTitle(CharSequence title) {
+ mUserTitle = true;
+ setTitleImpl(title);
+ }
+
+ /**
+ * Set the window title. A window title will always be replaced or overridden by a user title.
+ * @param title Title to set
+ *
+ * @see #setTitle(CharSequence)
+ */
+ public void setWindowTitle(CharSequence title) {
+ if (!mUserTitle) {
+ setTitleImpl(title);
+ }
+ }
+
+ private void setTitleImpl(CharSequence title) {
mTitle = title;
if (mTitleView != null) {
mTitleView.setText(title);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index d19cae4..d61d56e 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -188,7 +188,6 @@ LOCAL_SHARED_LIBRARIES := \
libssl \
libicuuc \
libicui18n \
- libicudata \
libmedia \
libwpa_client \
libjpeg
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 5a92193..290b532 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -62,6 +62,7 @@ enum {
};
static jfieldID offset_db_handle;
+static jmethodID method_custom_function_callback;
static char *createStr(const char *path, short extra) {
int len = strlen(path) + extra;
@@ -458,6 +459,62 @@ static void native_finalize(JNIEnv* env, jobject object, jint statementId)
}
}
+static void custom_function_callback(sqlite3_context * context, int argc, sqlite3_value ** argv) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (!env) {
+ LOGE("custom_function_callback cannot call into Java on this thread");
+ return;
+ }
+
+ // pack up the arguments into a string array
+ jobjectArray strArray = env->NewObjectArray(argc, env->FindClass("java/lang/String"), NULL);
+ if (!strArray) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return;
+ }
+ for (int i = 0; i < argc; i++) {
+ char* arg = (char *)sqlite3_value_text(argv[i]);
+ jobject obj = env->NewStringUTF(arg);
+ if (!obj) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return;
+ }
+ env->SetObjectArrayElement(strArray, i, obj);
+ env->DeleteLocalRef(obj);
+ }
+
+ // get global ref to CustomFunction object from our user data
+ jobject function = (jobject)sqlite3_user_data(context);
+ env->CallVoidMethod(function, method_custom_function_callback, strArray);
+}
+
+static jint native_addCustomFunction(JNIEnv* env, jobject object,
+ jstring name, jint numArgs, jobject function)
+{
+ sqlite3 * handle = (sqlite3 *)env->GetIntField(object, offset_db_handle);
+ char const *nameStr = env->GetStringUTFChars(name, NULL);
+ jobject ref = env->NewGlobalRef(function);
+ LOGD("native_addCustomFunction %s ref: %d", nameStr, ref);
+ int err = sqlite3_create_function(handle, nameStr, numArgs, SQLITE_UTF8,
+ (void *)ref, custom_function_callback, NULL, NULL);
+ env->ReleaseStringUTFChars(name, nameStr);
+
+ if (err == SQLITE_OK)
+ return (int)ref;
+ else {
+ LOGE("sqlite3_create_function returned %d", err);
+ env->DeleteGlobalRef(ref);
+ throw_sqlite3_exception(env, handle);
+ return 0;
+ }
+}
+
+static void native_releaseCustomFunction(JNIEnv* env, jobject object, jint ref)
+{
+ LOGD("native_releaseCustomFunction %d", ref);
+ env->DeleteGlobalRef((jobject)ref);
+}
+
static JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
@@ -472,6 +529,10 @@ static JNINativeMethod sMethods[] =
{"native_getDbLookaside", "()I", (void *)native_getDbLookaside},
{"releaseMemory", "()I", (void *)native_releaseMemory},
{"native_finalize", "(I)V", (void *)native_finalize},
+ {"native_addCustomFunction",
+ "(Ljava/lang/String;ILandroid/database/sqlite/SQLiteDatabase$CustomFunction;)I",
+ (void *)native_addCustomFunction},
+ {"native_releaseCustomFunction", "(I)V", (void *)native_releaseCustomFunction},
};
int register_android_database_SQLiteDatabase(JNIEnv *env)
@@ -490,6 +551,17 @@ int register_android_database_SQLiteDatabase(JNIEnv *env)
return -1;
}
+ clazz = env->FindClass("android/database/sqlite/SQLiteDatabase$CustomFunction");
+ if (clazz == NULL) {
+ LOGE("Can't find android/database/sqlite/SQLiteDatabase$CustomFunction\n");
+ return -1;
+ }
+ method_custom_function_callback = env->GetMethodID(clazz, "callback", "([Ljava/lang/String;)V");
+ if (method_custom_function_callback == NULL) {
+ LOGE("Can't find method SQLiteDatabase.CustomFunction.callback\n");
+ return -1;
+ }
+
return AndroidRuntime::registerNativeMethods(env, "android/database/sqlite/SQLiteDatabase",
sMethods, NELEM(sMethods));
}
diff --git a/core/res/res/values-xlarge/config.xml b/core/res/res/values-xlarge/config.xml
new file mode 100644
index 0000000..2640662
--- /dev/null
+++ b/core/res/res/values-xlarge/config.xml
@@ -0,0 +1,27 @@
+<?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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Component to be used as the status bar service. Must implement the IStatusBar
+ interface. This name is in the ComponentName flattened format (package/class) -->
+ <string name="config_statusBarComponent">com.android.systemui/com.android.systemui.statusbar.tablet.TabletStatusBarService</string>
+</resources>
+
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 689f73a..ec0d83c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -22,7 +22,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Component to be used as the status bar service. Must implement the IStatusBar
interface. This name is in the ComponentName flattened format (package/class) -->
- <string name="config_statusBarComponent">com.android.systemui/com.android.systemui.statusbar.StatusBarService</string>
+ <string name="config_statusBarComponent">com.android.systemui/com.android.systemui.statusbar.PhoneStatusBarService</string>
<!-- Do not translate. Defines the slots for the right-hand side icons. That is to say, the
icons in the status bar that are not notifications. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4d67bdd..679e642 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -19,9 +19,9 @@
-->
<resources>
<!-- The width that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_width">84dp</dimen>
+ <dimen name="thumbnail_width">0dp</dimen>
<!-- The height that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_height">63dp</dimen>
+ <dimen name="thumbnail_height">0dp</dimen>
<!-- The standard size (both width and height) of an application icon that
will be displayed in the app launcher and elsewhere. -->
<dimen name="app_icon_size">48dip</dimen>
diff --git a/docs/html/guide/topics/resources/available-resources.jd b/docs/html/guide/topics/resources/available-resources.jd
index 09c55a5..19babee 100644
--- a/docs/html/guide/topics/resources/available-resources.jd
+++ b/docs/html/guide/topics/resources/available-resources.jd
@@ -18,23 +18,6 @@ of application resource that you can provide in your resources directory ({@code
<p>Here's a brief summary of each resource type:</p>
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>{@code R.id} Is Not a Resource</h2>
-
-<p>You will often use an {@code R.id} integer to handle {@link android.view.View} objects in
-your UI. Although the {@code id} is a subclass of the {@code R} class, it is not considered a
-"resource" because it is not a reference to an externalized application resource. The {@code id}
-is simply a unique identifier that allows you to handle elements in your UI by instantiating
-objects with {@link android.app.Activity#findViewById(int) findViewById()}.</p>
-
-<p>For information about using {@code R.id} with your UI, see <a
-href="{@docRoot}guide/topics/ui/declaring-layout.html#attributes">Declaring Layout</a>.</p>
-
-</div>
-</div>
-
-
<dl>
<dt><a href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a></dt>
<dd>Define pre-determined animations.<br/>
diff --git a/docs/html/guide/topics/resources/drawable-resource.jd b/docs/html/guide/topics/resources/drawable-resource.jd
index d8de16a..1e4cca7 100644
--- a/docs/html/guide/topics/resources/drawable-resource.jd
+++ b/docs/html/guide/topics/resources/drawable-resource.jd
@@ -18,32 +18,50 @@ and draw on the screen. There are several different types of drawables:</p>
<dl>
<dt><a href="#Bitmap">Bitmap File</a><dt>
<dd>A bitmap graphic file ({@code .png}, {@code .jpg}, or {@code .gif}).
- A {@link android.graphics.drawable.BitmapDrawable}.</dd>
+ Creates a {@link android.graphics.drawable.BitmapDrawable}.</dd>
<dt><a href="#NinePatch">Nine-Patch File</a></dt>
<dd>A PNG file with stretchable regions to allow image resizing based on content ({@code
-.9.png}). A {@link android.graphics.drawable.NinePatchDrawable}.</dd>
-<!-- <dt><a href="#BitmapAlias">Bitmap Alias</a><dt>
- <dd>An alias for a drawable.</dd> -->
+.9.png}). Creates a {@link android.graphics.drawable.NinePatchDrawable}.</dd>
+ <dt><a href="#LayerList">Layer List</a></dt>
+ <dd>A Drawable that manages an array of other Drawables. These are drawn in array order, so the
+element with the largest index is be drawn on top. Creates a {@link
+android.graphics.drawable.LayerDrawable}.</dd>
<dt><a href="#StateList">State List</a></dt>
<dd>An XML file that references different bitmap graphics
for different states (for example, to use a different image when a button is pressed).
- A {@link android.graphics.drawable.StateListDrawable}.</dd>
- <dt><a href="#Color">Color</a></dt>
- <dd>A resource defined in XML that specifies a rectangle of color, with
- optionally rounded corners. A {@link android.graphics.drawable.PaintDrawable}.</dd>
- <dt><a href="#Shape">Shape</a></dt>
+ Creates a {@link android.graphics.drawable.StateListDrawable}.</dd>
+ <dt><a href="#LevelList">Level List</a></dt>
+ <dd>An XML file that defines a Drawable that manages a number of alternate Drawables, each
+assigned a maximum numerical value. Creates a {@link
+android.graphics.drawable.LevelListDrawable}.</dd>
+ <dt><a href="#Transition">Transition Drawable</a></dt>
+ <dd>An XML file that defines a Drawable that can cross-fade between two drawable resources.
+Creates a {@link android.graphics.drawable.TransitionDrawable}.</dd>
+ <dt><a href="#Clip">Clip Drawable</a></dt>
+ <dd>An XML file that defines a drawable that clips another Drawable based on this Drawable's
+current level value. Creates a {@link android.graphics.drawable.ClipDrawable}.</dd>
+ <dt><a href="#Scale">Scale Drawable</a></dt>
+ <dd>An XML file that defines a drawable that changes the size of another Drawable based on its
+current level value. Creates a {@link android.graphics.drawable.ScaleDrawable}</dd>
+ <dt><a href="#Shape">Shape Drawable</a></dt>
<dd>An XML file that defines a geometric shape, including colors and gradients.
- A {@link android.graphics.drawable.ShapeDrawable}.</dd>
+ Creates a {@link android.graphics.drawable.ShapeDrawable}.</dd>
</dl>
-<p>Documentation for the {@link android.graphics.drawable.AnimationDrawable} resource
-is in the <a href="animation-resource.html">Animation Resource</a> document.</p>
+<p>Also see the <a href="animation-resource.html">Animation Resource</a> document for how to
+create an {@link android.graphics.drawable.AnimationDrawable}.</p>
+
+
-<h2 id="Bitmap">Bitmap File</h2>
-<p>A basic bitmap image. Android supports basic bitmap files in a few different formats:
+<h2 id="Bitmap">Bitmap</h2>
+
+<p>A bitmap image. Android supports bitmap files in a three formats:
{@code .png} (preferred), {@code .jpg} (acceptable), {@code .gif} (discouraged).</p>
+<p>You can reference a bitmap file directly, using the filename as the resource ID, or create an
+alias resource ID in XML.</p>
+
<p class="note"><strong>Note:</strong> Bitmap files may be automatically optimized with lossless
image compression by the <a href="{@docRoot}guide/developing/tools/aapt.html">aapt</a> tool. For
example, a true-color PNG that does not require more than 256 colors may be converted to an 8-bit
@@ -52,11 +70,18 @@ memory. So be aware that the image binaries placed in this directory can change
you plan on reading an image as a bit stream in order to convert it to a bitmap, put your images in
the <code>res/raw/</code> folder instead, where they will not be optimized.</p>
+
+<h3 id="BitmapFile">Bitmap File</h3>
+
+<p>A bitmap file is a {@code .png}, {@code .jpg}, or {@code .gif} file. Android creates a {@link
+android.graphics.drawable.Drawable}
+resource for any of these files when you save them in the {@code res/drawable/} directory.</p>
+
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/drawable/<em>filename</em>.png</code> ({@code .png}, {@code .jpg}, or {@code .gif})<br/>
-The filename will be used as the resource ID.</dd>
+The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.graphics.drawable.BitmapDrawable}.</dd>
@@ -68,15 +93,16 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>example:</dt>
-<dd>With an image saved at <code>res/drawable/myimage.png</code>, this layout XML will apply
+
+<dd>With an image saved at <code>res/drawable/myimage.png</code>, this layout XML applies
the image to a View:
<pre>
&lt;ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- <strong>android:src="@drawable/myimage"</strong> />
+ android:src="@drawable/myimage" />
</pre>
-<p>This application code will retrieve the image as a {@link
+<p>The following application code retrieves the image as a {@link
android.graphics.drawable.Drawable}:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
@@ -97,50 +123,218 @@ Drawable drawable = res.{@link android.content.res.Resources#getDrawable(int) ge
+<h3 id="XmlBitmap">XML Bitmap</h3>
+
+<p>An XML bitmap is a resource defined in XML that points to a bitmap file. The effect is an alias for a
+raw bitmap file. The XML can specify additional properties for the bitmap such as dithering and tiling.</p>
+<p class="note"><strong>Note:</strong> You can use a {@code &lt;bitmap&gt;} element as a child of
+an {@code &lt;item&gt;} element. For
+example, when creating a <a href="#StateList">state list</a> or <a href="#LayerList">layer list</a>,
+you can exclude the {@code android:drawable}
+attribute from an {@code &lt;item&gt;} element and nest a {@code &lt;bitmap&gt;} inside it
+that defines the drawable item.</p>
+<dl class="xml">
-<h2 id="NinePatch">Nine-Patch File</h2>
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.BitmapDrawable}.</dd>
+
+<dt>resource reference:</dt>
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code></li><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;<a href="#bitmap-element">bitmap</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@[package:]drawable/<em>drawable_resource</em>"
+ android:antialias=["true" | "false"]
+ android:dither=["true" | "false"]
+ android:filter=["true" | "false"]
+ android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
+ "fill_vertical" | "center_horizontal" | "fill_horizontal" |
+ "center" | "fill" | "clip_vertical" | "clip_horizontal"]
+ android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] /&gt;
+</pre>
+</dd>
+
+
+<dt>elements:</dt>
+<dd>
+<dl class="tag-list">
+
+ <dt id="bitmap-element"><code>&lt;bitmap&gt;</code></dt>
+ <dd>Defines the bitmap source and its properties.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>. This is required only if the
+<code>&lt;bitmap&gt;</code> is the root element&mdash;it is not needed when the
+<code>&lt;bitmap&gt;</code> is nested inside an <code>&lt;item&gt;</code>.</dd>
+ <dt><code>android:src</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource.</dd>
+ <dt><code>android:antialias</code></dt>
+ <dd><em>Boolean</em>. Enables or disables antialiasing.</dd>
+ <dt><code>android:dither</code></dt>
+ <dd><em>Boolean</em>. Enables or disables dithering of the bitmap if the bitmap does not
+have the same pixel configuration as the screen (for instance: a ARGB 8888 bitmap with an RGB 565
+screen).</dd>
+ <dt><code>android:filter</code></dt>
+ <dd><em>Boolean</em>. Enables or disables bitmap filtering. Filtering is used when the
+bitmap is shrunk or stretched to smooth its apperance.</dd>
+ <dt><code>android:gravity</code></dt>
+ <dd><em>Keyword</em>. Defines the gravity for the bitmap. The gravity indicates where to
+position the drawable in its container if the bitmap is smaller than the container.
+ <p>Must be one or more (separated by '|') of the following constant values:</p>
+<table>
+<tr><th>Value</th><th>Description</th></tr>
+<tr><td><code>top</code></td>
+<td>Put the object at the top of its container, not changing its size.</td></tr>
+<tr><td><code>bottom</code></td>
+<td>Put the object at the bottom of its container, not changing its size. </td></tr>
+<tr><td><code>left</code></td>
+<td>Put the object at the left edge of its container, not changing its size. </td></tr>
+<tr><td><code>right</code></td>
+<td>Put the object at the right edge of its container, not changing its size. </td></tr>
+<tr><td><code>center_vertical</code></td>
+<td>Place object in the vertical center of its container, not changing its size. </td></tr>
+<tr><td><code>fill_vertical</code></td>
+<td>Grow the vertical size of the object if needed so it completely fills its container. </td></tr>
+<tr><td><code>center_horizontal</code></td>
+<td>Place object in the horizontal center of its container, not changing its size. </td></tr>
+<tr><td><code>fill_horizontal</code></td>
+<td>Grow the horizontal size of the object if needed so it completely fills its container.
+</td></tr>
+<tr><td><code>center</code></td>
+<td>Place the object in the center of its container in both the vertical and horizontal axis, not
+changing its size. </td></tr>
+<tr><td><code>fill</code></td>
+<td>Grow the horizontal and vertical size of the object if needed so it completely fills its
+container. This is the default.</td></tr>
+<tr><td><code>clip_vertical</code></td>
+<td>Additional option that can be set to have the top and/or bottom edges of the child clipped to
+its container's bounds. The clip is based on the vertical gravity: a top gravity clips the
+bottom edge, a bottom gravity clips the top edge, and neither clips both edges.
+</td></tr>
+<tr><td><code>clip_horizontal</code></td>
+<td>Additional option that can be set to have the left and/or right edges of the child clipped to
+its container's bounds. The clip is based on the horizontal gravity: a left gravity clips
+the right edge, a right gravity clips the left edge, and neither clips both edges.
+</td></tr>
+</table>
+ </dd>
+ <dt><code>android:tileMode</code></dt>
+ <dd><em>Keyword</em>. Defines the tile mode. When the tile mode is enabled, the bitmap is
+repeated. Gravity is ignored when the tile mode is enabled.
+ <p>Must be one of the following constant values:</p>
+<table>
+<tr><th>Value</th><th>Description</th></tr>
+<tr><td><code>disabled</code></td>
+<td>Do not tile the bitmap. This is the default value.</td></tr>
+<tr><td><code>clamp</code></td>
+<td>Replicates the edge color if the shader draws outside of its original bounds</td></tr>
+<tr><td><code>repeat</code></td>
+<td>Repeats the shader's image horizontally and vertically.</td></tr>
+<tr><td><code>mirror</code></td>
+<td>Repeats the shader's image horizontally and vertically, alternating mirror images so that
+adjacent images always seam.</td></tr>
+</table>
+
+ </dd>
+ </dl>
+ </dd>
+
+</dl>
+</dd> <!-- end elements and attributes -->
+
+<dt>example:</dt>
+<dd>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/icon"
+ android:tileMode="repeat" /&gt;
+</pre>
+
+</dd>
+
+<dt>see also:</dt>
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.BitmapDrawable}</li>
+ <li><a href="{@docRoot}guide/topics/resources/providing-resources.html#AliasResources">Creating
+alias resources</a>
+</ul>
+</dd>
+
+</dl>
+
+
+
+
+
+
+<h2 id="NinePatch">Nine-Patch</h2>
<p>A {@link android.graphics.NinePatch} is a PNG image in which you can define stretchable regions
-that Android will scale when content within the View exceeds the normal image bounds. You will
+that Android scales when content within the View exceeds the normal image bounds. You
typically assign this type of image as the background of a View that has at least one dimension set
to {@code "wrap_content"}, and when the View grows to accomodate the content, the Nine-Patch image
-will also be scaled to match the size of the View. An example use of a Nine-Patch image is the
+is also scaled to match the size of the View. An example use of a Nine-Patch image is the
background used by Android's standard {@link android.widget.Button} widget, which must stretch to
accommodate the text (or image) inside the button.</p>
-<p>For a complete discussion about how to define a Nine-Patch file with stretchable regions,
+<p>Same as with a normal <a href="#Bitmap">bitmap</a>, you can reference a Nine-Patch file directly
+or from a resource defined by XML.</p>
+
+<p>For a complete discussion about how to create a Nine-Patch file with stretchable regions,
see the <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D Graphics</a>
document.</p>
+
+<h3 id="NinePatchFile">Nine-Patch File</h3>
+
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/drawable/<em>filename</em>.9.png</code><br/>
-The filename will be used as the resource ID.</dd>
+The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.graphics.drawable.NinePatchDrawable}.</dd>
<dt>resource reference:</dt>
+
<dd>
In Java: <code>R.drawable.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>example:</dt>
-<dd>With an image saved at <code>res/drawable/myninepatch.9.png</code>, this layout XML will
-apply the Nine-Patch to a View:
+
+<dd>With an image saved at <code>res/drawable/myninepatch.9.png</code>, this layout XML
+applies the Nine-Patch to a View:
<pre>
&lt;Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- <strong>android:background="@drawable/myninepatch"</strong> />
+ android:background="@drawable/myninepatch" />
</pre>
</dd>
<dt>see also:</dt>
+
<dd>
<ul>
<li><a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">2D Graphics</a></li>
@@ -153,6 +347,238 @@ apply the Nine-Patch to a View:
+<h3 id="NinePatchXml">XML Nine-Patch</h3>
+
+<p>An XML Nine-Patch is a resource defined in XML that points to a Nine-Patch file. The XML can
+specify dithering for the image.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.NinePatchDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;<a href="#bitmap-element">nine-patch</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@[package:]drawable/<em>drawable_resource</em>"
+ android:dither=["true" | "false"] /&gt;
+</pre>
+</dd>
+
+
+<dt>elements:</dt>
+
+<dd>
+<dl class="tag-list">
+
+ <dt id="layerlist-element"><code>&lt;bitmap&gt;</code></dt>
+ <dd>Defines the bitmap source and its properties.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ <dt><code>android:src</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a Nine-Patch
+file.</dd>
+ <dt><code>android:dither</code></dt>
+ <dd><em>Boolean</em>. Enables or disables dithering of the bitmap if the bitmap does not
+have the same pixel configuration as the screen (for instance: a ARGB 8888 bitmap with an RGB 565
+screen).</dd>
+ </dl>
+ </dd>
+</dl>
+</dd>
+
+
+<dt>example:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/myninepatch"
+ android:dither="false" /&gt;
+</pre>
+</dd>
+</dl>
+
+
+
+
+
+
+<h2 id="LayerList">Layer List</h2>
+
+<p>A {@link android.graphics.drawable.LayerDrawable} is a drawable object
+that manages an array of other drawables. Each drawable in the list is drawn in the order of the
+list&mdash;the last drawable in the list is drawn on top.</p>
+
+<p>Each drawable is represented by an {@code &lt;item&gt;} element inside a single {@code
+&lt;layer-list&gt;} element.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.LayerDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#layerlist-element">layer-list</a>
+ xmlns:android="http://schemas.android.com/apk/res/android" &gt;
+ &lt;<a href="#layerlist-item-element">item</a>
+ android:drawable="@[package:]drawable/<em>drawable_resource</em>"
+ android:id="@[+][<em>package</em>:]id/<i>resource_name</i>"
+ android:top="<em>dimension</em>"
+ android:right="<em>dimension</em>"
+ android:bottom="<em>dimension</em>"
+ android:left="<em>dimension</em>" /&gt;
+&lt;/selector>
+</pre>
+</dd>
+
+<dt>elements:</dt>
+
+<dd>
+<dl class="tag-list">
+
+ <dt id="layerlist-element"><code>&lt;layer-list&gt;</code></dt>
+ <dd><strong>Required.</strong> This must be the root element. Contains one or more {@code
+&lt;item>} elements.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ </dl>
+ </dd>
+ <dt id="layerlist-item-element"><code>&lt;item&gt;</code></dt>
+ <dd>Defines a drawable to place in the layer drawable, in a position defined by its attributes.
+Must be a child of a <code>&lt;selector&gt;</code> element. Accepts child {@code &lt;bitmap&gt;}
+elements.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource.</dd>
+ <dt><code>android:id</code></dt>
+ <dd><em>Resource ID</em>. A unique resource ID for this drawable. To create a new resource
+ID for this item, use the form:
+<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new
+ID. You can use this identifier to
+retrieve and modify the drawable with {@link android.view.View#findViewById(int)
+View.findViewById()} or {@link android.app.Activity#findViewById(int) Activity.findViewById()}.</dd>
+ <dt><code>android:top</code></dt>
+ <dd><em>Integer</em>. The top offset in pixels.</dd>
+ <dt><code>android:right</code></dt>
+ <dd><em>Integer</em>. The right offset in pixels.</dd>
+ <dt><code>android:bottom</code></dt>
+ <dd><em>Integer</em>. The bottom offset in pixels.</dd>
+ <dt><code>android:left</code></dt>
+ <dd><em>Integer</em>. The left offset in pixels.</dd>
+ </dl>
+ <p>All drawable items are scaled to fit the size of the containing View, by default. Thus,
+placing your images in a layer list at different positions might increase the size of the View and
+some images scale as appropriate. To avoid
+scaling items in the list, use a {@code &lt;bitmap&gt;} element inside the {@code
+&lt;item&gt;} element to specify the drawable and define the gravity to something that does not
+scale, such as {@code "center"}. For example, the following {@code &lt;item&gt;} defines an item
+that scales to fit its container View:</p>
+<pre>
+&lt;item android:drawable="@drawable/image" /&gt;
+</pre>
+
+<p>To avoid scaling, the following example uses a {@code &lt;bitmap&gt;} element with centered
+gravity:</p>
+<pre>
+&lt;item&gt;
+ &lt;bitmap android:src="<b>@drawable/image</b>"
+ android:gravity="center" /&gt;
+&lt;/item&gt;
+</pre>
+ </dd>
+
+</dl>
+</dd> <!-- end elements and attributes -->
+
+<dt>example:</dt>
+
+<dd>XML file saved at <code>res/drawable/layers.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;layer-list xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ &lt;item&gt;
+ &lt;bitmap android:src="@drawable/android_red"
+ android:gravity="center" /&gt;
+ &lt;/item&gt;
+ &lt;item android:top="10dp" android:left="10dp"&gt;
+ &lt;bitmap android:src="@drawable/android_green"
+ android:gravity="center" /&gt;
+ &lt;/item&gt;
+ &lt;item android:top="20dp" android:left="20dp"&gt;
+ &lt;bitmap android:src="@drawable/android_blue"
+ android:gravity="center" /&gt;
+ &lt;/item&gt;
+&lt;/layer-list&gt;
+</pre>
+<p>Notice that this example uses a nested {@code &lt;bitmap&gt;} element to define the drawable
+resource for each item with a "center" gravity. This ensures that none of the images are scaled to
+fit the size of the container, due to resizing caused by the offset images.</p>
+
+<p>This layout XML applies the drawable to a View:</p>
+<pre>
+&lt;ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:src="@drawable/layers" /&gt;
+</pre>
+
+<p>The result is a stack of increasingly offset images:</p>
+<img src="{@docRoot}images/resources/layers.png" alt="" />
+</dd> <!-- end example -->
+
+<dt>see also:</dt>
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.LayerDrawable}</li>
+</ul>
+</dd>
+
+</dl>
+
+
+
+
@@ -163,33 +589,36 @@ apply the Nine-Patch to a View:
that uses a several different images to represent the same graphic, depending on the state of
the object. For example, a {@link
android.widget.Button} widget can exist in one of several different states (pressed, focused,
-or niether) and, using a state list drawable, you can provide a different button image for each
+or niether) and, using a state list drawable, you can provide a different background image for each
state.</p>
<p>You can describe the state list in an XML file. Each graphic is represented by an {@code
&lt;item>} element inside a single {@code &lt;selector>} element. Each {@code &lt;item>}
uses various attributes to describe the state in which it should be used as the graphic for the
drawable.</p>
+
<p>During each state change, the state list is traversed top to bottom and the first item that
-matches the current state will be used&mdash;the selection is <em>not</em> based on the "best
+matches the current state is used&mdash;the selection is <em>not</em> based on the "best
match," but simply the first item that meets the minimum criteria of the state.</p>
<dl class="xml">
<dt>file location:</dt>
<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
-The filename will be used as the resource ID.</dd>
+The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.graphics.drawable.StateListDrawable}.</dd>
<dt>resource reference:</dt>
+
<dd>
In Java: <code>R.drawable.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
+
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
@@ -212,6 +641,7 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>elements:</dt>
+
<dd>
<dl class="tag-list">
@@ -224,8 +654,8 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
<dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
<code>"http://schemas.android.com/apk/res/android"</code>.
<dt><code>android:constantSize</code></dt>
- <dd><em>Boolean</em>. "true" if the drawable's reported internal size will remain constant as the state
-changes (the size will be the maximum of all of the states); "false" if the size will vary based on
+ <dd><em>Boolean</em>. "true" if the drawable's reported internal size remains constant as the state
+changes (the size is the maximum of all of the states); "false" if the size varies based on
the current state. Default is false.</dd>
<dt><code>android:dither</code></dt>
<dd><em>Boolean</em>. "true" to enable dithering of the bitmap if the bitmap does not have the same pixel
@@ -270,9 +700,9 @@ receiving touch/click events); "false" if it should be used when the object is d
application is in the foreground), "false" if this item should be used when the application
window does not have focus (for example, if the notification shade is pulled down or a dialog appears).</dd>
</dl>
- <p class="note"><strong>Note:</strong>Remember that the first item in the state list that
-matches the current state of the object will be applied. So if the first item in the list contains
-none of the state attributes above, then it will be applied every time, which is why your
+ <p class="note"><strong>Note:</strong> Remember that Android applies the first item in the state list that
+matches the current state of the object. So, if the first item in the list contains
+none of the state attributes above, then it is applied every time, which is why your
default value should always be last (as demonstrated in the following example).</p>
</dd>
@@ -280,6 +710,7 @@ default value should always be last (as demonstrated in the following example).<
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
+
<dd>XML file saved at <code>res/drawable/button.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
@@ -292,12 +723,12 @@ default value should always be last (as demonstrated in the following example).<
&lt;/selector>
</pre>
-<p>This layout XML will apply the drawable to a View:</p>
+<p>This layout XML applies the drawable to a View:</p>
<pre>
&lt;ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- <strong>android:src="@drawable/button"</strong> />
+ android:src="@drawable/button" />
</pre>
</dd> <!-- end example -->
@@ -317,106 +748,513 @@ default value should always be last (as demonstrated in the following example).<
+<h2 id="LevelList">Level List</h2>
+<p>A Drawable that manages a number of alternate Drawables, each assigned a maximum numerical
+value. Setting the level value of the drawable with {@link
+android.graphics.drawable.Drawable#setLevel(int) setLevel()} loads the drawable resource in the
+level list that has a {@code android:maxLevel} value greater than or equal to the value
+passed to the method.</p>
+<dl class="xml">
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.LevelListDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#levellist-element">level-list</a>
+ xmlns:android="http://schemas.android.com/apk/res/android" &gt;
+ &lt;<a href="#levellist-item-element">item</a>
+ android:drawable="@drawable/<i>drawable_resource</i>"
+ android:maxLevel="<i>integer</i>"
+ android:minLevel="<i>integer</i>" /&gt;
+&lt;/level-list&gt;
+</pre>
+</dd>
+
+<dt>elements:</dt>
+
+<dd>
+<dl class="tag-list">
+
+ <dt id="levellist-element"><code>&lt;level-list&gt;</code></dt>
+ <dd>This must be the root element. Contains one or more {@code &lt;item&gt;} elements.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ </dl>
+ </dd>
+
+ <dt id="levellist-item-element"><code>&lt;item&gt;</code></dt>
+ <dd>Defines a drawable to use at a certain level.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource to be inset.</dd>
+ <dt><code>android:maxLevel</code></dt>
+ <dd><em>Integer</em>. The maximum level allowed for this item.</dd>
+ <dt><code>android:minLevel</code></dt>
+ <dd><em>Integer</em>. The minimum level allowed for this item.</dd>
+ </dl>
+ </dd>
+</dl>
+
+</dd>
+
+<dt>example:</dt>
+
+<dd>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;level-list xmlns:android="http://schemas.android.com/apk/res/android" &gt;
+ &lt;item
+ android:drawable="@drawable/status_off"
+ android:maxLevel="0" /&gt;
+ &lt;item
+ android:drawable="@drawable/status_on"
+ android:maxLevel="1" /&gt;
+&lt;/level-list&gt;
+</pre>
+<p>Once this is applied to a {@link android.view.View}, the level can be changed with {@link
+android.graphics.drawable.Drawable#setLevel(int) setLevel()} or {@link
+android.widget.ImageView#setImageLevel(int) setImageLevel()}.</p>
+
+</dd>
+
+<dt>see also:</dt>
+
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.LevelListDrawable}</li>
+</ul>
+</dd>
+
+</dl>
-<h2 id="Color">Color</h2>
-<p>This is a color defined in XML that's used as a drawable to fill a rectangular space,
-with optionally rounded corners. This kind of drawable behaves like a color fill.</p>
-<p class="note"><strong>Note:</strong> A color drawable is a simple resource that is referenced
-using the value provided in the {@code name} attribute (not the name of the XML file). As
-such, you can combine a color drawable resources with other simple resources in the one XML file,
-under one {@code &lt;resources>} element.</p>
+<h2 id="Transition">Transition Drawable</h2>
+
+<p>A {@link android.graphics.drawable.TransitionDrawable} is a drawable object
+that can cross-fade between the two drawable resources.</p>
+
+<p>Each drawable is represented by an {@code &lt;item&gt;} element inside a single {@code
+&lt;transition&gt;} element. No more than two items are supported. To transition forward, call
+{@link android.graphics.drawable.TransitionDrawable#startTransition(int) startTransition()}. To
+transition backward, call {@link android.graphics.drawable.TransitionDrawable#reverseTransition(int)
+reverseTransition()}.</p>
+
<dl class="xml">
<dt>file location:</dt>
-<dd><code>res/drawable/<em>filename</em>.png</code><br/>
-The filename is arbitrary. The element's {@code name} will be used as the resource ID.</dd>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
-<dd>Resource pointer to a {@link android.graphics.drawable.PaintDrawable}.</dd>
+<dd>Resource pointer to a {@link android.graphics.drawable.TransitionDrawable}.</dd>
<dt>resource reference:</dt>
+
<dd>
-In Java: <code>R.drawable.<em>color_name</em></code><br/>
-In XML: <code>@[<em>package</em>:]drawable/<em>color_name</em></code>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
+
<dd>
<pre class="stx">
-&lt;?xml version="1.0" encoding="utf-8"?&gt;
-&lt;<a href="#color-resources-element">resources</a>>
- &lt;<a href="#drawable-element">drawable</a>
- name="<em>color_name</em>"
- &gt;<em>color</em>&lt;/drawable&gt;
-&lt;/resources&gt;
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#transition-element">layer-list</a>
+xmlns:android="http://schemas.android.com/apk/res/android" &gt;
+ &lt;<a href="#transition-item-element">item</a>
+ android:drawable="@[package:]drawable/<em>drawable_resource</em>"
+ android:id="@[+][<em>package</em>:]id/<i>resource_name</i>"
+ android:top="<em>dimension</em>"
+ android:right="<em>dimension</em>"
+ android:bottom="<em>dimension</em>"
+ android:left="<em>dimension</em>" /&gt;
+&lt;/selector>
</pre>
</dd>
<dt>elements:</dt>
+
<dd>
<dl class="tag-list">
- <dt id="color-resources-element"><code>&lt;resources&gt;</code></dt>
- <dd><strong>Required.</strong> This must be the root node.
- <p>No attributes.</p>
+ <dt id="transition-element"><code>&lt;transition&gt;</code></dt>
+ <dd><strong>Required.</strong> This must be the root element. Contains one or more {@code
+&lt;item>} elements.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ </dl>
</dd>
- <dt id="drawable-element"><code>&lt;drawable&gt;</code></dt>
- <dd>A color to use as a drawable rectangle. The value can be
- any valid hexadecimal color value or a <a href="more-resources.html#Color">color
- resource</a>. A color value always begins with a pound (#) character, followed
- by the Alpha-Red-Green-Blue information in one of the following formats:
- #<em>RGB</em>, #<em>RRGGBB</em>, #<em>ARGB</em>, or #<em>AARRGGBB</em>.
+ <dt id="transition-item-element"><code>&lt;item&gt;</code></dt>
+ <dd>Defines a drawable to place in the layer drawable, in a position defined by its attributes.
+Must be a child of a <code>&lt;selector&gt;</code> element. Accepts child {@code &lt;bitmap&gt;}
+elements.
<p class="caps">attributes:</p>
<dl class="atn-list">
- <dt><code>name</code></dt>
- <dd><em>String</em>. <strong>Required</strong>.
- A name for the color. This name will be used as the resource ID.</dd>
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource.</dd>
+ <dt><code>android:id</code></dt>
+ <dd><em>Resource ID</em>. A unique resource ID for this drawable. To create a new resource
+ID for this item, use the form:
+<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new
+ID. You can use this identifier to
+retrieve and modify the drawable with {@link android.view.View#findViewById(int)
+View.findViewById()} or {@link android.app.Activity#findViewById(int) Activity.findViewById()}.</dd>
+ <dt><code>android:top</code></dt>
+ <dd><em>Integer</em>. The top offset in pixels.</dd>
+ <dt><code>android:right</code></dt>
+ <dd><em>Integer</em>. The right offset in pixels.</dd>
+ <dt><code>android:bottom</code></dt>
+ <dd><em>Integer</em>. The bottom offset in pixels.</dd>
+ <dt><code>android:left</code></dt>
+ <dd><em>Integer</em>. The left offset in pixels.</dd>
</dl>
-
</dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
-<dd>XML file saved at <code>res/drawable/colors.xml</code>:
+
+<dd>XML file saved at <code>res/drawable/transition.xml</code>:
<pre>
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;resources>
- &lt;drawable name="solid_red">#f00&lt;/drawable>
- &lt;drawable name="solid_blue">#0000ff&lt;/drawable>
-&lt;/resources>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;transition xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+ &lt;item android:drawable="@drawable/on" /&gt;
+ &lt;item android:drawable="@drawable/off" /&gt;
+&lt;/layer-list&gt;
</pre>
- <p>This layout XML will apply a color drawable to a View:</p>
+
+<p>This layout XML applies the drawable to a View:</p>
<pre>
-&lt;TextView
- android:layout_width="fill_parent"
+&lt;ImageButton
+ android:id="@+id/button"
android:layout_height="wrap_content"
- <strong>android:background="@drawable/solid_blue"</strong> />
+ android:layout_width="wrap_content"
+ android:src="@drawable/transition" /&gt;
</pre>
- <p>This application code will get a color drawable and apply it to a View:</p>
+
+<p>And the following code performs a 500ms transition from the first item to the second:</p>
<pre>
-Resources res = {@link android.content.Context#getResources()};
-Drawable redDrawable = res.{@link android.content.res.Resources#getDrawable(int) getDrawable}(R.drawable.solid_red);
+ImageButton button = (ImageButton) findViewById(R.id.button);
+TransitionDrawable drawable = (TransitionDrawable) button.getDrawable();
+drawable.startTransition(500);
+</pre>
+
+</dd> <!-- end example -->
-TextView tv = (TextView) findViewByID(R.id.text);
-tv.setBackground(redDrawable);
+<dt>see also:</dt>
+
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.TransitionDrawable}</li>
+</ul>
+</dd>
+
+</dl>
+
+
+
+
+
+
+
+
+<h2 id="Inset">Inset Drawable</h2>
+
+<p>A drawable defined in XML that insets another drawable by a specified distance. This is used when
+a View needs a background that is smaller than the View's actual bounds.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.InsetDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#inset-element">inset</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/<i>drawable_resource</i>"
+ android:insetTop="<i>dimension</i>"
+ android:insetRight="<i>dimension</i>"
+ android:insetBottom="<i>dimension</i>"
+ android:insetLeft="<i>dimension</i>" /&gt;
</pre>
+</dd>
+
+<dt>elements:</dt>
+
+<dd>
+<dl class="tag-list">
+
+ <dt id="inset-element"><code>&lt;inset&gt;</code></dt>
+ <dd>Defines the inset drawable. This must be the root element.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource to be inset.</dd>
+ <dt><code>android:insetTop</code></dt>
+ <dd><em>Dimension</em>. The top inset, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a></dd>
+ <dt><code>android:insetRight</code></dt>
+ <dd><em>Dimension</em>. The right inset, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a></dd>
+ <dt><code>android:insetBottom</code></dt>
+ <dd><em>Dimension</em>. The bottom inset, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a></dd>
+ <dt><code>android:insetLeft</code></dt>
+ <dd><em>Dimension</em>. The left inset, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a></dd>
+ </dl>
+ </dd>
+</dl>
+
+</dd>
+
+<dt>example:</dt>
+
+<dd>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/background"
+ android:insetTop="10dp"
+ android:insetLeft="10dp" /&gt;
+</pre>
+</dd>
+
+<dt>see also:</dt>
+
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.InsetDrawable}</li>
+</ul>
+</dd>
+
+</dl>
+
+
+
+
+
+
+
+
+<h2 id="Clip">Clip Drawable</h2>
+
+<p>A drawable defined in XML that clips another drawable based on this Drawable's current level. You
+can control how much the child drawable gets clipped in width and height based on the level, as well
+as a gravity to control where it is placed in its overall container. Most often used to implement
+things like progress bars.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.ClipDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#clip-element">clip</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/<i>drawable_resource</i>"
+ android:clipOrientation=["horizontal" | "vertical"]
+ android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
+ "fill_vertical" | "center_horizontal" | "fill_horizontal" |
+ "center" | "fill" | "clip_vertical" | "clip_horizontal"] /&gt;
+</pre>
+</dd>
+
+<dt>elements:</dt>
+
+<dd>
+<dl class="tag-list">
+
+ <dt id="clip-element"><code>&lt;clip&gt;</code></dt>
+ <dd>Defines the clip drawable. This must be the root element.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource to be clipped.</dd>
+ <dt><code>android:clipOrientation</code></dt>
+ <dd><em>Keyword</em>. The orientation for the clip.
+ <p>Must be one of the following constant values:</p>
+<table>
+<tr><th>Value</th><th>Description</th></tr>
+<tr><td><code>horizontal</code></td>
+<td>Clip the drawable horizontally.</td></tr>
+<tr><td><code>vertical</code></td>
+<td>Clip the drawable vertically.</td></tr>
+</table>
+ </dd>
+ <dt><code>android:gravity</code></dt>
+ <dd><em>Keyword</em>. Specifies where to clip within the drawable.
+ <p>Must be one or more (separated by '|') of the following constant values:</p>
+<table>
+<tr><th>Value</th><th>Description</th></tr>
+<tr><td><code>top</code></td>
+<td>Put the object at the top of its container, not changing its size. When {@code
+clipOrientation} is {@code "vertical"}, clipping occurs at the bottom of the drawable.</td></tr>
+<tr><td><code>bottom</code></td>
+<td>Put the object at the bottom of its container, not changing its size. When {@code
+clipOrientation} is {@code "vertical"}, clipping occurs at the top of the drawable.</td></tr>
+<tr><td><code>left</code></td>
+<td>Put the object at the left edge of its container, not changing its size. This is the
+default. When {@code clipOrientation} is {@code "horizontal"}, clipping occurs at the right side of
+the drawable. This is the default.</td></tr>
+<tr><td><code>right</code></td>
+<td>Put the object at the right edge of its container, not changing its size. When {@code
+clipOrientation} is {@code "horizontal"}, clipping occurs at the left side of
+the drawable.</td></tr>
+<tr><td><code>center_vertical</code></td>
+<td>Place object in the vertical center of its container, not changing its size. Clipping behaves
+the same as when gravity is {@code "center"}.</td></tr>
+<tr><td><code>fill_vertical</code></td>
+<td>Grow the vertical size of the object if needed so it completely fills its container. When {@code
+clipOrientation} is {@code "vertical"}, no clipping occurs because the drawable fills the
+vertical space (unless the drawable level is 0, in which case it's not visible).</td></tr>
+<tr><td><code>center_horizontal</code></td>
+<td>Place object in the horizontal center of its container, not changing its size.
+Clipping behaves the same as when gravity is {@code "center"}.</td></tr>
+<tr><td><code>fill_horizontal</code></td>
+<td>Grow the horizontal size of the object if needed so it completely fills its container. When
+{@code clipOrientation} is {@code "horizontal"}, no clipping occurs because the drawable fills the
+horizontal space (unless the drawable level is 0, in which case it's not visible).
+</td></tr>
+<tr><td><code>center</code></td>
+<td>Place the object in the center of its container in both the vertical and horizontal axis, not
+changing its size. When {@code
+clipOrientation} is {@code "horizontal"}, clipping occurs on the left and right. When {@code
+clipOrientation} is {@code "vertical"}, clipping occurs on the top and bottom.</td></tr>
+<tr><td><code>fill</code></td>
+<td>Grow the horizontal and vertical size of the object if needed so it completely fills its
+container. No clipping occurs because the drawable fills the
+horizontal and vertical space (unless the drawable level is 0, in which case it's not
+visible).</td></tr>
+<tr><td><code>clip_vertical</code></td>
+<td>Additional option that can be set to have the top and/or bottom edges of the child clipped to
+its container's bounds. The clip is based on the vertical gravity: a top gravity clips the
+bottom edge, a bottom gravity clips the top edge, and neither clips both edges.
+</td></tr>
+<tr><td><code>clip_horizontal</code></td>
+<td>Additional option that can be set to have the left and/or right edges of the child clipped to
+its container's bounds. The clip is based on the horizontal gravity: a left gravity clips
+the right edge, a right gravity clips the left edge, and neither clips both edges.
+</td></tr>
+</table></dd>
+ </dl>
+ </dd>
+</dl>
+
+</dd> <!-- end elements and attributes -->
+
+<dt>example:</dt>
+
+<dd>XML file saved at <code>res/drawable/clip.xml</code>:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/android"
+ android:clipOrientation="horizontal"
+ android:gravity="left" /&gt;
+&lt;/shape>
+</pre>
+ <p>The following layout XML applies the clip drawable to a View:</p>
+<pre>
+&lt;ImageView
+ android:id="@+id/image"
+ android:background="@drawable/clip"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content" />
+</pre>
+
+ <p>The following code gets the drawable and increases the amount of clipping in order to
+progressively reveal the image:</p>
+<pre>
+ImageView imageview = (ImageView) findViewById(R.id.image);
+ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
+drawable.setLevel(drawable.getLevel() + 1000);
+</pre>
+
+<p>Increasing the level reduces the amount of clipping and slowly reveals the image. Here it is
+at a level of 7000:</p>
+<img src="{@docRoot}images/resources/clip.png" alt="" />
+
+<p class="note"><strong>Note:</strong> The default level is 0, which is fully clipped so the image
+is not visible. When the level is 10,000, the image is not clipped and completely visible.</p>
</dd> <!-- end example -->
<dt>see also:</dt>
+
<dd>
<ul>
- <li>{@link android.graphics.drawable.PaintDrawable}</li>
+ <li>{@link android.graphics.drawable.ClipDrawable}</li>
</ul>
</dd>
@@ -430,10 +1268,139 @@ tv.setBackground(redDrawable);
+<h2 id="Scale">Scale Drawable</h2>
+
+<p>A drawable defined in XML that changes the size of another drawable based on its current
+level.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
+The filename is used as the resource ID.</dd>
+
+<dt>compiled resource datatype:</dt>
+<dd>Resource pointer to a {@link android.graphics.drawable.ScaleDrawable}.</dd>
+
+<dt>resource reference:</dt>
+
+<dd>
+In Java: <code>R.drawable.<em>filename</em></code><br/>
+In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
+</dd>
+
+<dt>syntax:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#scale-element">scale</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/<i>drawable_resource</i>"
+ android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
+ "fill_vertical" | "center_horizontal" | "fill_horizontal" |
+ "center" | "fill" | "clip_vertical" | "clip_horizontal"]
+ android:scaleHeight="<i>percentage</i>"
+ android:scaleWidth="<i>percentage</i>" /&gt;
+</pre>
+</dd>
+
+<dt>elements:</dt>
+<dd>
+<dl class="tag-list">
+ <dt id="scale-element"><code>&lt;scale&gt;</code></dt>
+ <dd>Defines the scale drawable. This must be the root element.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
+ <dt><code>android:drawable</code></dt>
+ <dd><em>Drawable resource</em>. <strong>Required</strong>. Reference to a drawable
+resource.</dd>
+ <dt><code>android:scaleGravity</code></dt>
+ <dd><em>Keyword</em>. Specifies the gravity position after scaling.
+ <p>Must be one or more (separated by '|') of the following constant values:</p>
+<table>
+<tr><th>Value</th><th>Description</th></tr>
+<tr><td><code>top</code></td>
+<td>Put the object at the top of its container, not changing its size.</td></tr>
+<tr><td><code>bottom</code></td>
+<td>Put the object at the bottom of its container, not changing its size. </td></tr>
+<tr><td><code>left</code></td>
+<td>Put the object at the left edge of its container, not changing its size. This is the
+default.</td></tr>
+<tr><td><code>right</code></td>
+<td>Put the object at the right edge of its container, not changing its size. </td></tr>
+<tr><td><code>center_vertical</code></td>
+<td>Place object in the vertical center of its container, not changing its size. </td></tr>
+<tr><td><code>fill_vertical</code></td>
+<td>Grow the vertical size of the object if needed so it completely fills its container. </td></tr>
+<tr><td><code>center_horizontal</code></td>
+<td>Place object in the horizontal center of its container, not changing its size. </td></tr>
+<tr><td><code>fill_horizontal</code></td>
+<td>Grow the horizontal size of the object if needed so it completely fills its container.
+</td></tr>
+<tr><td><code>center</code></td>
+<td>Place the object in the center of its container in both the vertical and horizontal axis, not
+changing its size. </td></tr>
+<tr><td><code>fill</code></td>
+<td>Grow the horizontal and vertical size of the object if needed so it completely fills its
+container. </td></tr>
+<tr><td><code>clip_vertical</code></td>
+<td>Additional option that can be set to have the top and/or bottom edges of the child clipped to
+its container's bounds. The clip is based on the vertical gravity: a top gravity clips the
+bottom edge, a bottom gravity clips the top edge, and neither clips both edges.
+</td></tr>
+<tr><td><code>clip_horizontal</code></td>
+<td>Additional option that can be set to have the left and/or right edges of the child clipped to
+its container's bounds. The clip is based on the horizontal gravity: a left gravity clips
+the right edge, a right gravity clips the left edge, and neither clips both edges.
+</td></tr>
+</table></dd>
+ <dt><code>android:scaleHeight</code></dt>
+ <dd><em>Percentage</em>. The scale height, expressed as a percentage of the drawable's
+bound. The value's format is XX%. For instance: 100%, 12.5%, etc.</dd>
+ <dt><code>android:scaleWidth</code></dt>
+ <dd><em>Percentage</em>. The scale width, expressed as a percentage of the drawable's
+bound. The value's format is XX%. For instance: 100%, 12.5%, etc.</dd>
+ </dl>
+ </dd>
+</dl>
-<h2 id="Shape">Shape</h2>
+</dd>
+
+<dt>example:</dt>
+
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;scale xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/logo"
+ android:scaleGravity="center_vertical|center_horizontal"
+ android:scaleHeight="80%"
+ android:scaleWidth="80%" /&gt;
+</pre>
+</dd>
+
+<dt>see also:</dt>
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.ScaleDrawable}</li>
+</ul>
+</dd>
+
+</dl>
+
+
+
+
+
+
+
+<h2 id="Shape">Shape Drawable</h2>
<p>This is a generic shape defined in XML.</p>
@@ -441,23 +1408,32 @@ tv.setBackground(redDrawable);
<dt>file location:</dt>
<dd><code>res/drawable/<em>filename</em>.xml</code><br/>
-The filename will be used as the resource ID.</dd>
+The filename is used as the resource ID.</dd>
<dt>compiled resource datatype:</dt>
<dd>Resource pointer to a {@link android.graphics.drawable.ShapeDrawable}.</dd>
<dt>resource reference:</dt>
+
<dd>
In Java: <code>R.drawable.<em>filename</em></code><br/>
In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
</dd>
<dt>syntax:</dt>
+
<dd>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;<a href="#shape-element">shape</a> xmlns:android="http://schemas.android.com/apk/res/android"
+&lt;<a href="#shape-element">shape</a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:shape=["rectangle" | "oval" | "line" | "ring"] >
+ &lt;<a href="#corners-element">corners</a>
+ android:radius="<em>integer</em>"
+ android:topLeftRadius="<em>integer</em>"
+ android:topRightRadius="<em>integer</em>"
+ android:bottomLeftRadius="<em>integer</em>"
+ android:bottomRightRadius="<em>integer</em>" /&gt;
&lt;<a href="#gradient-element">gradient</a>
android:angle="<em>integer</em>"
android:centerX="<em>integer</em>"
@@ -467,37 +1443,40 @@ In XML: <code>@[<em>package</em>:]drawable/<em>filename</em></code>
android:gradientRadius="<em>integer</em>"
android:startColor="<em>color</em>"
android:type=["linear" | "radial" | "sweep"]
- android:usesLevel=["true" | "false"] />
+ android:usesLevel=["true" | "false"] /&gt;
+ &lt;<a href="#padding-element">padding</a>
+ android:left="<em>integer</em>"
+ android:top="<em>integer</em>"
+ android:right="<em>integer</em>"
+ android:bottom="<em>integer</em>" /&gt;
+ &lt;<a href="#size-element">size</a>
+ android:width="<em>integer</em>"
+ android:color="<em>color</em>"
+ android:dashWidth="<em>integer</em>"
+ android:dashGap="<em>integer</em>" /&gt;
&lt;<a href="#solid-element">solid</a>
- android:color="<em>color</em>" />
+ android:color="<em>color</em>" /&gt;
&lt;<a href="#stroke-element">stroke</a>
android:width="<em>integer</em>"
android:color="<em>color</em>"
android:dashWidth="<em>integer</em>"
- android:dashGap="<em>integer</em>" />
- &lt;<a href="#padding-element">padding</a>
- android:left="<em>integer</em>"
- android:top="<em>integer</em>"
- android:right="<em>integer</em>"
- android:bottom="<em>integer</em>" />
- &lt;<a href="#corners-element">corners</a>
- android:radius="<em>integer</em>"
- android:topLeftRadius="<em>integer</em>"
- android:topRightRadius="<em>integer</em>"
- android:bottomLeftRadius="<em>integer</em>"
- android:bottomRightRadius="<em>integer</em>" />
+ android:dashGap="<em>integer</em>" /&gt;
&lt;/shape>
</pre>
</dd>
<dt>elements:</dt>
+
<dd>
<dl class="tag-list">
<dt id="shape-element"><code>&lt;shape&gt;</code></dt>
- <dd><strong>Required.</strong> This must be the root element.
+ <dd>The shape drawable. This must be the root element.
<p class="caps">attributes:</p>
<dl class="atn-list">
+ <dt><code>xmlns:android</code></dt>
+ <dd><em>String</em>. <strong>Required.</strong> Defines the XML namespace, which must be
+ <code>"http://schemas.android.com/apk/res/android"</code>.
<dt><code>android:shape</code></dt>
<dd><em>Keyword</em>. Defines the type of shape. Valid values are:
<table>
@@ -525,7 +1504,7 @@ href="more-resources.html#Dimension">dimension resource</a>.</dd>
<dd><em>Float</em>. The radius for the inner
part of the ring, expressed as a ratio of the ring's width. For instance, if {@code
android:innerRadiusRatio="5"}, then the inner radius equals the ring's width divided by 5. This
-value will be overridden by {@code android:innerRadius}. Default value is 9.</dd>
+value is overridden by {@code android:innerRadius}. Default value is 9.</dd>
<dt><code>android:thickness</code></dt>
<dd><em>Dimension</em>. The thickness of the
ring, as a dimension value or <a
@@ -533,13 +1512,40 @@ href="more-resources.html#Dimension">dimension resource</a>.</dd>
<dt><code>android:thicknessRatio</code></dt>
<dd><em>Float</em>. The thickness of the ring,
expressed as a ratio of the ring's width. For instance, if {@code android:thicknessRatio="2"}, then
-the thickness equals the ring's width divided by 2. This value will be overridden by {@code
+the thickness equals the ring's width divided by 2. This value is overridden by {@code
android:innerRadius}. Default value is 3.</dd>
<dt><code>android:useLevel</code></dt>
<dd><em>Boolean</em>. "true" if this is used as
a {@link android.graphics.drawable.LevelListDrawable}. This should normally be "false"
or your shape may not appear.</dd>
</dl>
+ <dt id="corners-element"><code>&lt;corners&gt;</code></dt>
+ <dd>Creates rounded corners for the shape. Applies only when the shape is a rectangle.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>android:radius</code></dt>
+ <dd><em>Dimension</em>. The radius for all corners, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>. This is overridden for each
+corner by the following attributes.</dd>
+ <dt><code>android:topLeftRadius</code></dt>
+ <dd><em>Dimension</em>. The radius for the top-left corner, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:topRightRadius</code></dt>
+ <dd><em>Dimension</em>. The radius for the top-right corner, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:bottomLeftRadius</code></dt>
+ <dd><em>Dimension</em>. The radius for the bottom-left corner, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:bottomRightRadius</code></dt>
+ <dd><em>Dimension</em>. The radius for the bottom-right corner, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ </dl>
+ <p class="note"><strong>Note:</strong> Every corner must (initially) be provided a corner
+radius greater than 1, or else no corners are rounded. If you want specific corners
+to <em>not</em> be rounded, a work-around is to use {@code android:radius} to set a default corner
+radius greater than 1, but then override each and every corner with the values you really
+want, providing zero ("0dp") where you don't want rounded corners.</p>
+ </dd>
<dt id="gradient-element"><code>&lt;gradient&gt;</code></dt>
<dd>Specifies a gradient color for the shape.
<p class="caps">attributes:</p>
@@ -582,6 +1588,42 @@ value or <a href="more-resources.html#Color">color resource</a>.</dd>
android.graphics.drawable.LevelListDrawable}.</dd>
</dl>
</dd>
+ <dt id="padding-element"><code>&lt;padding&gt;</code></dt>
+ <dd>Padding to apply to the containing View element (this pads the position of the View
+content, not the shape).
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>android:left</code></dt>
+ <dd><em>Dimension</em>. Left padding, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:top</code></dt>
+ <dd><em>Dimension</em>. Top padding, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:right</code></dt>
+ <dd><em>Dimension</em>. Right padding, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:bottom</code></dt>
+ <dd><em>Dimension</em>. Bottom padding, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ </dl>
+ </dd>
+ <dt id="solid-element"><code>&lt;size&gt;</code></dt>
+ <dd>The size of the shape.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>android:height</code></dt>
+ <dd><em>Dimension</em>. The height of the shape, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ <dt><code>android:width</code></dt>
+ <dd><em>Dimension</em>. The width of the shape, as a dimension value or <a
+href="more-resources.html#Dimension">dimension resource</a>.</dd>
+ </dl>
+ <p class="note"><strong>Note:</strong> The shape scales to the size of the container
+View proportionate to the dimensions defined here, by default. When you use the shape in an {@link
+android.widget.ImageView}, you can restrict scaling by setting the <a
+href="{@docRoot}reference/android/widget/ImageView.html#attr_android:scaleType">{@code
+android:scaleType}</a> to {@code "center"}.</p>
+ </dd>
<dt id="solid-element"><code>&lt;solid&gt;</code></dt>
<dd>A solid color to fill the shape.
<p class="caps">attributes:</p>
@@ -611,57 +1653,12 @@ href="more-resources.html#Dimension">dimension resource</a>. Only valid if {@cod
android:dashGap} is set.</dd>
</dl>
</dd>
- <dt id="padding-element"><code>&lt;padding&gt;</code></dt>
- <dd>Padding to apply to the containing View element (this pads the position of the View
-content, not the shape).
- <p class="caps">attributes:</p>
- <dl class="atn-list">
- <dt><code>android:left</code></dt>
- <dd><em>Dimension</em>. Left padding, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:top</code></dt>
- <dd><em>Dimension</em>. Top padding, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:right</code></dt>
- <dd><em>Dimension</em>. Right padding, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:bottom</code></dt>
- <dd><em>Dimension</em>. Bottom padding, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- </dl>
- </dd>
- <dt id="corners-element"><code>&lt;corners&gt;</code></dt>
- <dd>Creates rounded corners for the shape. Applies only when the shape is a rectangle.
- <p class="caps">attributes:</p>
- <dl class="atn-list">
- <dt><code>android:radius</code></dt>
- <dd><em>Dimension</em>. The radius for all corners, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>. This will be overridden for each
-corner by the following attributes.</dd>
- <dt><code>android:topLeftRadius</code></dt>
- <dd><em>Dimension</em>. The radius for the top-left corner, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:topRightRadius</code></dt>
- <dd><em>Dimension</em>. The radius for the top-right corner, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:bottomLeftRadius</code></dt>
- <dd><em>Dimension</em>. The radius for the bottom-left corner, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- <dt><code>android:bottomRightRadius</code></dt>
- <dd><em>Dimension</em>. The radius for the bottom-right corner, as a dimension value or <a
-href="more-resources.html#Dimension">dimension resource</a>.</dd>
- </dl>
- <p class="note"><strong>Note:</strong> Every corner must (initially) be provided a corner
-radius greater than zero, or else no corners will be rounded. If you want specific corners
-to <em>not</em> be rounded, a work-around is to use {@code android:radius} to set a default corner
-radius greater than zero, but then override each and every corner with the values you really
-want, providing zero ("0dp") where you don't want rounded corners.</p>
- </dd>
</dl>
</dd> <!-- end elements and attributes -->
<dt>example:</dt>
+
<dd>XML file saved at <code>res/drawable/gradient_box.xml</code>:
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
@@ -678,14 +1675,16 @@ want, providing zero ("0dp") where you don't want rounded corners.</p>
&lt;corners android:radius="8dp" />
&lt;/shape>
</pre>
- <p>This layout XML will apply the shape drawable to a View:</p>
+
+ <p>This layout XML applies the shape drawable to a View:</p>
<pre>
&lt;TextView
android:background="@drawable/gradient_box"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</pre>
- <p>This application code will get the shape drawable and apply it to a View:</p>
+
+ <p>This application code gets the shape drawable and applies it to a View:</p>
<pre>
Resources res = {@link android.content.Context#getResources()};
Drawable shape = res. {@link android.content.res.Resources#getDrawable(int) getDrawable}(R.drawable.gradient_box);
@@ -695,6 +1694,14 @@ tv.setBackground(shape);
</pre>
</dd> <!-- end example -->
+<dt>see also:</dt>
+
+<dd>
+<ul>
+ <li>{@link android.graphics.drawable.ShapeDrawable}</li>
+</ul>
+</dd>
+
</dl>
diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd
index 0688a18..111851c 100644
--- a/docs/html/guide/topics/resources/layout-resource.jd
+++ b/docs/html/guide/topics/resources/layout-resource.jd
@@ -35,12 +35,12 @@ In XML: <code>@[<em>package</em>:]layout/<em>filename</em></code>
<pre class="stx">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a> xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/<em>name</em>"
+ android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
[<em>ViewGroup-specific attributes</em>] &gt;
&lt;<a href="#view-element"><em>View</em></a>
- android:id="@+id/<em>name</em>"
+ android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
[<em>View-specific attributes</em>] &gt;
@@ -49,10 +49,12 @@ In XML: <code>@[<em>package</em>:]layout/<em>filename</em></code>
&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a> &gt;
&lt;<a href="#view-element"><em>View</em></a> /&gt;
&lt;/<em>ViewGroup</em>&gt;
+ &lt;<a href="#include-element">include</a> layout="@layout/<i>layout_resource</i>"/&gt;
&lt;/<em>ViewGroup</em>&gt;
</pre>
<p class="note"><strong>Note:</strong> The root element can be either a
-{@link android.view.ViewGroup} or a {@link android.view.View}, but there must be only
+{@link android.view.ViewGroup}, a {@link android.view.View}, or a <a
+href="#merge-element">{@code &lt;merge&gt;}</a> element, but there must be only
one root element and it must contain the {@code xmlns:android} attribute with the {@code android}
namespace as shown.</p>
</dd>
@@ -74,10 +76,9 @@ namespace as shown.</p>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
- <dd><em>Resource name</em>. A unique resource name for the element, which you can
-use to obtain a reference to the {@link android.view.ViewGroup} from your application.
- The value takes the form: <code>"@+id/<em>name</em>"</code>. See more about the
- <a href="#idvalue">value for {@code android:id}</a> below.
+ <dd><em>Resource ID</em>. A unique resource name for the element, which you can
+use to obtain a reference to the {@link android.view.ViewGroup} from your application. See more
+about the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the group, as a
@@ -107,10 +108,9 @@ attributes</a>).</p>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
- <dd><em>Resource name</em>. A unique resource name for the element, which you can use to
- obtain a reference to the {@link android.view.View} from your application.
- The value takes the form: <code>"@+id/<em>name</em>"</code>. See more about the
- <a href="#idvalue">value for {@code android:id}</a> below.
+ <dd><em>Resource ID</em>. A unique resource name for the element, which you can use to
+ obtain a reference to the {@link android.view.View} from your application. See more about
+the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the element, as
@@ -137,20 +137,71 @@ or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> bel
which gives it's parent initial focus on the screen. You can have only one of these
elements per file.</dd>
+ <dt id="include-element"><code>&lt;include&gt;</code></dt>
+ <dd>Includes a layout file into this layout.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>layout</code></dt>
+ <dd><em>Layout resource</em>. <strong>Required</strong>. Reference to a layout
+resource.</dd>
+ <dt><code>android:id</code></dt>
+ <dd><em>Resource ID</em>. Overrides the ID given to the root view in the included layout.
+ </dd>
+ <dt><code>android:layout_height</code></dt>
+ <dd><em>Dimension or keyword</em>. Overrides the height given to the root view in the
+included layout.
+ </dd>
+ <dt><code>android:layout_width</code></dt>
+ <dd><em>Dimension or keyword</em>. Overrides the width given to the root view in the
+included layout.
+ </dd>
+ </dl>
+ <p>You can include any other layout attributes in the <code>&lt;include&gt;</code> that are
+supported by the root element in the included layout and they will override those defined in the
+root element.</p>
+
+ <p>Another way to include a layout is to use {@link android.view.ViewStub}. It is a lightweight
+View that consumes no layout space until you explicitly inflate it, at which point, it includes a
+layout file defined by its {@code android:layout} attribute. For more information about using {@link
+android.view.ViewStub}, read <a href="{@docRoot}resources/articles/layout-tricks-stubs.html">Layout
+Tricks: ViewStubs</a>.</p>
+ </dd>
+
+ <dt id="merge-element"><code>&lt;merge&gt;</code></dt>
+ <dd>An alternative root element that is not drawn in the layout hierarchy. Using this as the
+root element is useful when you know that this layout will be placed into a layout
+that already contains the appropriate parent View to contain the children of the
+<code>&lt;merge&gt;</code> element. This is particularly useful when you plan to include this layout
+in another layout file using <a href="#include-element"><code>&lt;include&gt;</code></a> and
+this layout doesn't require a different {@link android.view.ViewGroup} container. For more
+information about merging layouts, read <a
+href="{@docRoot}resources/articles/layout-tricks-merging.html">Layout
+Tricks: Merging</a>.</dd>
+
</dl>
+
+
<h4 id="idvalue">Value for <code>android:id</code></h4>
-<p>For the ID value, you should use this syntax form: <code>"@+id/<em>name</em>"</code>. The plus symbol,
-{@code +}, indicates that this is a new resource ID and the aapt tool will create
-a new resource number to the {@code R.java} class, if it doesn't already exist. For example:</p>
+<p>For the ID value, you should usually use this syntax form: <code>"@+id/<em>name</em>"</code>. The
+plus symbol, {@code +}, indicates that this is a new resource ID and the <code>aapt</code> tool will
+create a new resource integer in the {@code R.java} class, if it doesn't already exist. For
+example:</p>
<pre>
&lt;TextView android:id="@+id/nameTextbox"/>
</pre>
-<p>You can then refer to it this way in Java:</p>
+<p>The <code>nameTextbox</code> name is now a resource ID attached to this element. You can then
+refer to the {@link android.widget.TextView} to which the ID is associated in Java:</p>
<pre>
findViewById(R.id.nameTextbox);
</pre>
+<p>This code returns the {@link android.widget.TextView} object.</p>
+
+<p>However, if you have already defined an <a
+href="{@docRoot}guide/topics/resources/drawable-resource.html#Id">ID resource</a> (and it is not
+already used), then you can apply that ID to a {@link android.view.View} element by excluding the
+plus symbol in the <code>android:id</code> value.</p>
<h4 id="layoutvalues">Value for <code>android:layout_height</code> and
<code>android:layout_width</code>:</h4>
diff --git a/docs/html/guide/topics/resources/menu-resource.jd b/docs/html/guide/topics/resources/menu-resource.jd
index badc403..cde72bd 100644
--- a/docs/html/guide/topics/resources/menu-resource.jd
+++ b/docs/html/guide/topics/resources/menu-resource.jd
@@ -35,7 +35,7 @@ In XML: <code>@[<em>package</em>:]menu.<em>filename</em></code>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;<a href="#menu-element">menu</a> xmlns:android="http://schemas.android.com/apk/res/android">
- &lt;<a href="#item-element">item</a> android:id="@+id/<em>id_name</em>"
+ &lt;<a href="#item-element">item</a> android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="<em>integer</em>"
android:title="<em>string</em>"
@@ -46,7 +46,7 @@ In XML: <code>@[<em>package</em>:]menu.<em>filename</em></code>
android:checkable=["true" | "false"]
android:visible=["visible" | "invisible" | "gone"]
android:enabled=["enabled" | "disabled"] /&gt;
- &lt;<a href="#group-element">group</a> android:id="<em>resource ID</em>"
+ &lt;<a href="#group-element">group</a> android:id="@[+][<em>package</em>:]id/<em>resource name</em>"
android:menuCategory=["container" | "system" | "secondary" | "alternative"]
android:orderInCategory="<em>integer</em>"
android:checkableBehavior=["none" | "all" | "single"]
@@ -84,8 +84,8 @@ child of a <code>&lt;menu&gt;</code> element.
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
- <dd><em>Resource name</em>. A unique resource name. The value takes the form:
-<code>"@+id/<em>name</em>"</code>.</dd>
+ <dd><em>Resource ID</em>. A unique resource ID. To create a new resource ID for this item, use the form:
+<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new ID.</dd>
<dt><code>android:menuCategory</code></dt>
<dd><em>Keyword</em>. Value corresponding to {@link android.view.Menu} {@code CATEGORY_*}
constants, which define the group's priority. Valid values:
@@ -124,8 +124,8 @@ on the data that is currently displayed.</td></tr>
<p class="caps">attributes:</p>
<dl class="atn-list">
<dt><code>android:id</code></dt>
- <dd><em>Resource name</em>. A unique resource name. The value takes the form:
-<code>"@+id/<em>name</em>"</code>.</dd>
+ <dd><em>Resource ID</em>. A unique resource ID. To create a new resource ID for this item, use the form:
+<code>"@+id/<em>name</em>"</code>. The plus symbol indicates that this should be created as a new ID.</dd>
<dt><code>android:menuCategory</code></dt>
<dd><em>Keyword</em>. Value corresponding to {@link android.view.Menu} {@code CATEGORY_*}
constants, which define the item's priority. Valid values:
diff --git a/docs/html/guide/topics/resources/more-resources.jd b/docs/html/guide/topics/resources/more-resources.jd
index 0e2b30b..22abbb2 100644
--- a/docs/html/guide/topics/resources/more-resources.jd
+++ b/docs/html/guide/topics/resources/more-resources.jd
@@ -12,6 +12,9 @@ parent.link=available-resources.html
<dd>XML resource that carries a color value (a hexadecimal color).</dd>
<dt><a href="#Dimension">Dimension</a></dt>
<dd>XML resource that carries a dimension value (with a unit of measure).</dd>
+ <dt><a href="#Id">ID</a></dt>
+ <dd>XML resource that provides a unique identifier for application resources and
+components.</dd>
<dt><a href="#Integer">Integer</a></dt>
<dd>XML resource that carries an integer value.</dd>
<dt><a href="#IntegerArray">Integer Array</a></dt>
@@ -111,8 +114,8 @@ boolean screenIsSmall = res.{@link android.content.res.Resources#getBoolean(int)
<h2 id="Color">Color</h2>
<p>A color value defined in XML.
-The color is specified with an RGB value and alpha channel. A color resource can be used
-any place that expects a hexadecimal color value.</p>
+The color is specified with an RGB value and alpha channel. You can use color resource
+any place that accepts a hexadecimal color value.</p>
<p>The value always begins with a pound (#) character and then followed by the
Alpha-Red-Green-Blue information in one of the following formats:</p>
@@ -318,6 +321,118 @@ float fontSize = res.{@link android.content.res.Resources#getDimension(int) getD
+<h2 id="Id">ID</h2>
+
+<p>A unique resource ID defined in XML. Using the name you provide in the {@code &lt;item&gt;}
+element, the Android developer tools create a unique integer in your project's {@code
+R.java} class, which you can use as an
+identifier for an application resources (for example, a {@link android.view.View} in your UI layout)
+or a unique integer for use in your application code (for example, as an ID for a dialog or a
+result code).</p>
+
+<p class="note"><strong>Note:</strong> An ID is a simple resource that is referenced
+using the value provided in the {@code name} attribute (not the name of the XML file). As
+such, you can combine ID resources with other simple resources in the one XML file,
+under one {@code &lt;resources&gt;} element. Also, remember that an ID resources does not reference
+an actual resource item; it is simply a unique ID that you can attach to other resources or use
+as a unique integer in your application.</p>
+
+<dl class="xml">
+
+<dt>file location:</dt>
+<dd><code>res/values/<em>filename.xml</em></code><br/>
+The filename is arbitrary.</dd>
+
+<dt>resource reference:</dt>
+<dd>
+In Java: <code>R.id.<em>name</em></code><br/>
+In XML: <code>@[<em>package</em>:]id/<em>name</em></code>
+</dd>
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;<a href="#id-resources-element">resources</a>&gt;
+ &lt;<a href="#id-item-element">item</a>
+ type="id"
+ name="<em>id_name</em>" /&gt;
+&lt;/resources&gt;
+</pre>
+</dd>
+
+<dt>elements:</dt>
+<dd>
+<dl class="tag-list">
+
+ <dt id="integer-resources-element"><code>&lt;resources&gt;</code></dt>
+ <dd><strong>Required.</strong> This must be the root node.
+ <p>No attributes.</p>
+ </dd>
+ <dt id="integer-element"><code>&lt;integer&gt;</code></dt>
+ <dd>Defines a unique ID. Takes no value, only attributes.
+ <p class="caps">attributes:</p>
+ <dl class="atn-list">
+ <dt><code>type</code></dt>
+ <dd>Must be "id".</dd>
+ <dt><code>name</code></dt>
+ <dd><em>String</em>. A unique name for the ID.</dd>
+ </dl>
+ </dd>
+
+</dl>
+</dd> <!-- end elements and attributes -->
+
+<dt>example:</dt>
+<dd>
+ <p>XML file saved at <code>res/values/ids.xml</code>:</p>
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+ &lt;item type="id" name="button_ok" /&gt;
+ &lt;item type="id" name="dialog_exit" /&gt;
+&lt;/resources>
+</pre>
+
+ <p>Then, this layout snippet uses the "button_ok" ID for a Button widget:</p>
+<pre>
+&lt;Button android:id="<b>@id/button_ok</b>"
+ style="@style/button_style" /&gt;
+</pre>
+
+ <p>Notice that the {@code android:id} value does not include the plus sign in the ID reference,
+because the ID already exists, as defined in the {@code ids.xml} example above. (When you specify an
+ID to an XML resource using the plus sign&mdash;in the format {@code
+android:id="@+id/name"}&mdash;it means that the "name" ID does not exist and should be created.)</p>
+
+ <p>As another example, the following code snippet uses the "dialog_exit" ID as a unique identifier
+for a dialog:</p>
+<pre>
+{@link android.app.Activity#showDialog(int) showDialog}(<b>R.id.dialog_exit</b>);
+</pre>
+ <p>In the same application, the "dialog_exit" ID is compared when creating a dialog:</p>
+<pre>
+protected Dialog {@link android.app.Activity#onCreateDialog(int)}(int id) {
+ Dialog dialog;
+ switch(id) {
+ case <b>R.id.dialog_exit</b>:
+ ...
+ break;
+ default:
+ dialog = null;
+ }
+ return dialog;
+}
+</pre>
+</dd> <!-- end example -->
+
+
+</dl>
+
+
+
+
+
<h2 id="Integer">Integer</h2>
<p>An integer defined in XML.</p>
@@ -347,7 +462,7 @@ In XML: <code>@[<em>package</em>:]integer/<em>integer_name</em></code>
&lt;<a href="#integer-resources-element">resources</a>>
&lt;<a href="#integer-element">integer</a>
name="<em>integer_name</em>"
- &gt;<em>integer</em>&lt;/dimen&gt;
+ &gt;<em>integer</em>&lt;/integer&gt;
&lt;/resources&gt;
</pre>
</dd>
@@ -379,8 +494,8 @@ In XML: <code>@[<em>package</em>:]integer/<em>integer_name</em></code>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
- &lt;integer name="max_speed">75&lt;/dimen>
- &lt;integer name="min_speed">5&lt;/dimen>
+ &lt;integer name="max_speed">75&lt;/integer>
+ &lt;integer name="min_speed">5&lt;/integer>
&lt;/resources>
</pre>
<p>This application code retrieves an integer:</p>
diff --git a/docs/html/images/resources/clip.png b/docs/html/images/resources/clip.png
new file mode 100644
index 0000000..9196b3f
--- /dev/null
+++ b/docs/html/images/resources/clip.png
Binary files differ
diff --git a/docs/html/images/resources/layers.png b/docs/html/images/resources/layers.png
new file mode 100644
index 0000000..f7e6929
--- /dev/null
+++ b/docs/html/images/resources/layers.png
Binary files differ
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index f126374..3f9f961 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,61 +16,84 @@
package android.graphics;
-public class ImageFormat
-{
- /* these constants are chosen to be binary compatible with
- * their previous location in PixelFormat.java */
-
- public static final int UNKNOWN = 0;
+public class ImageFormat {
+ /*
+ * these constants are chosen to be binary compatible with their previous
+ * location in PixelFormat.java
+ */
- /** RGB format used for pictures encoded as RGB_565
- * see {@link android.hardware.Camera.Parameters#setPictureFormat(int)}.
- */
- public static final int RGB_565 = 4;
+ public static final int UNKNOWN = 0;
- /**
- * YCbCr formats, used for video. These are not necessarily supported
- * by the hardware.
- */
- public static final int NV16 = 0x10;
+ /**
+ * RGB format used for pictures encoded as RGB_565 see
+ * {@link android.hardware.Camera.Parameters#setPictureFormat(int)}.
+ */
+ public static final int RGB_565 = 4;
-
- /** YCrCb format used for images, which uses the NV21 encoding format.
- * This is the default format for camera preview images, when not
- * otherwise set with
- * {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
- */
- public static final int NV21 = 0x11;
+ /**
+ * Planar 4:2:0 YCrCb format. This format assumes an horizontal stride of 16
+ * pixels for all planes and an implicit vertical stride of the image
+ * height's next multiple of two.
+ * y_size = stride * ALIGN(height, 2)
+ * c_size = ALIGN(stride/2, 16) * height
+ * size = y_size + c_size * 2
+ * cr_offset = y_size
+ * cb_offset = y_size + c_size
+ *
+ * Whether this format is supported by the camera hardware can be determined
+ * by
+ * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ */
+ public static final int YV12 = 0x32315659;
+ /**
+ * YCbCr format, used for video. Whether this format is supported by the
+ * camera hardware can be determined by
+ * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ */
+ public static final int NV16 = 0x10;
- /** YCbCr format used for images, which uses YUYV (YUY2) encoding format.
- * This is an alternative format for camera preview images. Whether this
- * format is supported by the camera hardware can be determined by
- * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
- */
- public static final int YUY2 = 0x14;
+ /**
+ * YCrCb format used for images, which uses the NV21 encoding format. This
+ * is the default format for camera preview images, when not otherwise set
+ * with {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
+ */
+ public static final int NV21 = 0x11;
-
- /**
- * Encoded formats. These are not necessarily supported by the hardware.
- */
- public static final int JPEG = 0x100;
+ /**
+ * YCbCr format used for images, which uses YUYV (YUY2) encoding format.
+ * This is an alternative format for camera preview images. Whether this
+ * format is supported by the camera hardware can be determined by
+ * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ */
+ public static final int YUY2 = 0x14;
+ /**
+ * Encoded formats. These are not necessarily supported by the hardware.
+ */
+ public static final int JPEG = 0x100;
- /**
- * Use this function to retrieve the number of bits per pixel of
- * an ImageFormat.
- * @param format
- * @return the number of bits per pixel of the given format or -1 if the
- * format doesn't exist or is not supported.
- */
- public static int getBitsPerPixel(int format) {
- switch (format) {
- case RGB_565: return 16;
- case NV16: return 16;
- case NV21: return 12;
- case YUY2: return 16;
- }
- return -1;
- }
+ /**
+ * Use this function to retrieve the number of bits per pixel of an
+ * ImageFormat.
+ *
+ * @param format
+ * @return the number of bits per pixel of the given format or -1 if the
+ * format doesn't exist or is not supported.
+ */
+ public static int getBitsPerPixel(int format) {
+ switch (format) {
+ case RGB_565:
+ return 16;
+ case NV16:
+ return 16;
+ case YUY2:
+ return 16;
+ case YV12:
+ return 12;
+ case NV21:
+ return 12;
+ }
+ return -1;
+ }
}
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index fdc4c92..e275ba8 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -64,6 +64,8 @@ import android.util.AttributeSet;
* // Start the animation (looped playback by default).
* frameAnimation.start()
* </pre>
+ * <p>For more information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
*
* @attr ref android.R.styleable#AnimationDrawable_visible
* @attr ref android.R.styleable#AnimationDrawable_variablePadding
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 29e14d2..32111e8 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -40,7 +40,9 @@ import java.io.IOException;
* A Drawable that wraps a bitmap and can be tiled, stretched, or aligned. You can create a
* BitmapDrawable from a file path, an input stream, through XML inflation, or from
* a {@link android.graphics.Bitmap} object.
- * <p>It can be defined in an XML file with the <code>&lt;bitmap></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;bitmap></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
* <p>
* Also see the {@link android.graphics.Bitmap} class, which handles the management and
* transformation of raw bitmap graphics, and should be used when drawing to a
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index c387a9b..a772871 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -32,9 +32,14 @@ import java.io.IOException;
* level value. You can control how much the child Drawable gets clipped in width
* and height based on the level, as well as a gravity to control where it is
* placed in its overall container. Most often used to implement things like
- * progress bars.
+ * progress bars, by increasing the drawable's level with {@link
+ * android.graphics.drawable.Drawable#setLevel(int) setLevel()}.
+ * <p class="note"><strong>Note:</strong> The drawable is clipped completely and not visible when
+ * the level is 0 and fully revealed when the level is 10,000.</p>
*
- * <p>It can be defined in an XML file with the <code>&lt;clip></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;clip></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#ClipDrawable_clipOrientation
* @attr ref android.R.styleable#ClipDrawable_gravity
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 4c1d243..7b2d9d7 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -102,8 +102,8 @@ import java.util.Arrays;
* whose overall size is modified based on the current level.
* </ul>
* <p>For information and examples of creating drawable resources (XML or bitmap files that
- * can be loaded in code), see <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources
- * and Internationalization</a>.
+ * can be loaded in code), see <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
public abstract class Drawable {
private static final Rect ZERO_BOUNDS_RECT = new Rect();
@@ -720,8 +720,7 @@ public abstract class Drawable {
/**
* Create a drawable from an XML document. For more information on how to
* create resources in XML, see
- * <a href="{@docRoot}guide/topics/resources/resources-i18n.html">Resources and
- * Internationalization</a>.
+ * <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
public static Drawable createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 63d1446..33ecbea 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -42,7 +42,9 @@ import java.io.IOException;
/**
* A Drawable with a color gradient for buttons, backgrounds, etc.
*
- * <p>It can be defined in an XML file with the <code>&lt;shape></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;shape></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#GradientDrawable_visible
* @attr ref android.R.styleable#GradientDrawable_shape
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 4fa9d44..a9c983e 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -32,7 +32,9 @@ import java.io.IOException;
* This is used when a View needs a background that is smaller than
* the View's actual bounds.
*
- * <p>It can be defined in an XML file with the <code>&lt;inset></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;inset></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#InsetDrawable_visible
* @attr ref android.R.styleable#InsetDrawable_drawable
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index b727d47..501cca9 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -32,8 +32,9 @@ import java.io.IOException;
* order, so the element with the largest index will be drawn on top.
* <p>
* It can be defined in an XML file with the <code>&lt;layer-list></code> element.
- * Each Drawable in the layer is defined in a nested <code>&lt;item></code>.
- * </p>
+ * Each Drawable in the layer is defined in a nested <code>&lt;item></code>. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#LayerDrawableItem_left
* @attr ref android.R.styleable#LayerDrawableItem_top
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index ae8f224..21be983 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -47,7 +47,10 @@ import android.util.AttributeSet;
* <p>With this XML saved into the res/drawable/ folder of the project, it can be referenced as
* the drawable for an {@link android.widget.ImageView}. The default image is the first in the list.
* It can then be changed to one of the other levels with
- * {@link android.widget.ImageView#setImageLevel(int)}.</p>
+ * {@link android.widget.ImageView#setImageLevel(int)}. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ *
* @attr ref android.R.styleable#LevelListDrawableItem_minLevel
* @attr ref android.R.styleable#LevelListDrawableItem_maxLevel
* @attr ref android.R.styleable#LevelListDrawableItem_drawable
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 2083e05..9c47dab 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -35,7 +35,9 @@ import java.io.IOException;
* value. The start and end angles of rotation can be controlled to map any
* circular arc to the level values range.</p>
*
- * <p>It can be defined in an XML file with the <code>&lt;rotate></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;rotate></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
*
* @attr ref android.R.styleable#RotateDrawable_visible
* @attr ref android.R.styleable#RotateDrawable_fromDegrees
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 275e36f..b623d80 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -34,7 +34,9 @@ import java.io.IOException;
* placed in its overall container. Most often used to implement things like
* progress bars.
*
- * <p>It can be defined in an XML file with the <code>&lt;scale></code> element.</p>
+ * <p>It can be defined in an XML file with the <code>&lt;scale></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#ScaleDrawable_scaleWidth
* @attr ref android.R.styleable#ScaleDrawable_scaleHeight
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index c699a82..be1892e 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -34,6 +34,10 @@ import java.io.IOException;
* the ShapeDrawable will default to a
* {@link android.graphics.drawable.shapes.RectShape}.
*
+ * <p>It can be defined in an XML file with the <code>&lt;shape></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ *
* @attr ref android.R.styleable#ShapeDrawablePadding_left
* @attr ref android.R.styleable#ShapeDrawablePadding_top
* @attr ref android.R.styleable#ShapeDrawablePadding_right
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index b94df84..239be40 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -31,7 +31,9 @@ import android.util.StateSet;
* ID value.
* <p/>
* <p>It can be defined in an XML file with the <code>&lt;selector></code> element.
- * Each state Drawable is defined in a nested <code>&lt;item></code> element.</p>
+ * Each state Drawable is defined in a nested <code>&lt;item></code> element. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
*
* @attr ref android.R.styleable#StateListDrawable_visible
* @attr ref android.R.styleable#StateListDrawable_variablePadding
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 97b45d8..4470356 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -26,8 +26,10 @@ import android.os.SystemClock;
* display just the first layer, call {@link #resetTransition()}.
* <p>
* It can be defined in an XML file with the <code>&lt;transition></code> element.
- * Each Drawable in the transition is defined in a nested <code>&lt;item></code>.
- * </p>
+ * Each Drawable in the transition is defined in a nested <code>&lt;item></code>. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ *
* @attr ref android.R.styleable#LayerDrawableItem_left
* @attr ref android.R.styleable#LayerDrawableItem_top
* @attr ref android.R.styleable#LayerDrawableItem_right
@@ -212,7 +214,7 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba
* Enables or disables the cross fade of the drawables. When cross fade
* is disabled, the first drawable is always drawn opaque. With cross
* fade enabled, the first drawable is drawn with the opposite alpha of
- * the second drawable.
+ * the second drawable. Cross fade is disabled by default.
*
* @param enabled True to enable cross fading, false otherwise.
*/
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
new file mode 100644
index 0000000..2316fef
--- /dev/null
+++ b/include/binder/BinderService.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_BINDER_SERVICE_H
+#define ANDROID_BINDER_SERVICE_H
+
+#include <stdint.h>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+template<typename SERVICE>
+class BinderService
+{
+public:
+ static status_t publish() {
+ sp<IServiceManager> sm(defaultServiceManager());
+ return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
+ }
+
+ static void publishAndJoinThreadPool() {
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm(defaultServiceManager());
+ sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+ }
+
+ static void instantiate() { publish(); }
+
+ static status_t shutdown() {
+ return NO_ERROR;
+ }
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_BINDER_SERVICE_H
diff --git a/include/gui/ISensorEventConnection.h b/include/gui/ISensorEventConnection.h
new file mode 100644
index 0000000..ed4e4cc
--- /dev/null
+++ b/include/gui/ISensorEventConnection.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_ISENSOR_EVENT_CONNECTION_H
+#define ANDROID_GUI_ISENSOR_EVENT_CONNECTION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class SensorChannel;
+
+class ISensorEventConnection : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SensorEventConnection);
+
+ virtual sp<SensorChannel> getSensorChannel() const = 0;
+ virtual status_t enableDisable(int handle, bool enabled) = 0;
+ virtual status_t setEventRate(int handle, nsecs_t ns) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSensorEventConnection : public BnInterface<ISensorEventConnection>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_ISENSOR_EVENT_CONNECTION_H
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
new file mode 100644
index 0000000..3e05076
--- /dev/null
+++ b/include/gui/ISensorServer.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_ISENSORSERVER_H
+#define ANDROID_GUI_ISENSORSERVER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class Sensor;
+class ISensorEventConnection;
+
+class ISensorServer : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SensorServer);
+
+ virtual Vector<Sensor> getSensorList()= 0;
+ virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnSensorServer : public BnInterface<ISensorServer>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_ISENSORSERVER_H
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
new file mode 100644
index 0000000..86a16f1
--- /dev/null
+++ b/include/gui/Sensor.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_SENSOR_H
+#define ANDROID_GUI_SENSOR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Flattenable.h>
+
+#include <hardware/sensors.h>
+
+#include <android/sensor.h>
+
+// ----------------------------------------------------------------------------
+// Concrete types for the NDK
+struct ASensor { };
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class Parcel;
+
+// ----------------------------------------------------------------------------
+
+class Sensor : public ASensor, public Flattenable
+{
+public:
+ enum {
+ TYPE_ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER,
+ TYPE_MAGNETIC_FIELD = ASENSOR_TYPE_MAGNETIC_FIELD,
+ TYPE_GYROSCOPE = ASENSOR_TYPE_GYROSCOPE,
+ TYPE_LIGHT = ASENSOR_TYPE_LIGHT,
+ TYPE_PROXIMITY = ASENSOR_TYPE_PROXIMITY
+ };
+
+ Sensor();
+ virtual ~Sensor();
+
+ const String8& getName() const;
+ const String8& getVendor() const;
+ int32_t getHandle() const;
+ int32_t getType() const;
+ float getMinValue() const;
+ float getMaxValue() const;
+ float getResolution() const;
+ float getPowerUsage() const;
+
+ // Flattenable interface
+ virtual size_t getFlattenedSize() const;
+ virtual size_t getFdCount() const;
+ virtual status_t flatten(void* buffer, size_t size,
+ int fds[], size_t count) const;
+ virtual status_t unflatten(void const* buffer, size_t size,
+ int fds[], size_t count);
+
+private:
+ String8 mName;
+ String8 mVendor;
+ int32_t mHandle;
+ int32_t mType;
+ float mMinValue;
+ float mMaxValue;
+ float mResolution;
+ float mPower;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SENSOR_H
diff --git a/include/gui/SensorChannel.h b/include/gui/SensorChannel.h
new file mode 100644
index 0000000..bb54618
--- /dev/null
+++ b/include/gui/SensorChannel.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_SENSOR_CHANNEL_H
+#define ANDROID_GUI_SENSOR_CHANNEL_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+
+namespace android {
+// ----------------------------------------------------------------------------
+class Parcel;
+
+class SensorChannel : public RefBase
+{
+public:
+
+ SensorChannel();
+ SensorChannel(const Parcel& data);
+ virtual ~SensorChannel();
+
+ int getFd() const;
+ ssize_t write(void const* vaddr, size_t size);
+ ssize_t read(void* vaddr, size_t size);
+
+ status_t writeToParcel(Parcel* reply) const;
+
+private:
+ int mSendFd;
+ mutable int mReceiveFd;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SENSOR_CHANNEL_H
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
new file mode 100644
index 0000000..d8d8128
--- /dev/null
+++ b/include/gui/SensorEventQueue.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_EVENT_QUEUE_H
+#define ANDROID_SENSOR_EVENT_QUEUE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <gui/SensorChannel.h>
+
+// ----------------------------------------------------------------------------
+
+struct ALooper;
+struct ASensorEvent;
+
+// Concrete types for the NDK
+struct ASensorEventQueue {
+ ALooper* looper;
+};
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISensorEventConnection;
+class Sensor;
+
+// ----------------------------------------------------------------------------
+
+class SensorEventQueue : public ASensorEventQueue, public RefBase
+{
+public:
+ SensorEventQueue(const sp<ISensorEventConnection>& connection);
+ virtual ~SensorEventQueue();
+ virtual void onFirstRef();
+
+ int getFd() const;
+ ssize_t write(ASensorEvent const* events, size_t numEvents);
+ ssize_t read(ASensorEvent* events, size_t numEvents);
+
+ status_t enableSensor(Sensor const* sensor) const;
+ status_t disableSensor(Sensor const* sensor) const;
+ status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
+
+private:
+ sp<ISensorEventConnection> mSensorEventConnection;
+ sp<SensorChannel> mSensorChannel;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SENSOR_EVENT_QUEUE_H
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
new file mode 100644
index 0000000..0d65334
--- /dev/null
+++ b/include/gui/SensorManager.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_SENSOR_MANAGER_H
+#define ANDROID_GUI_SENSOR_MANAGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+#include <utils/Vector.h>
+
+#include <gui/SensorEventQueue.h>
+
+// ----------------------------------------------------------------------------
+// Concrete types for the NDK
+struct ASensorManager { };
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+class ISensorServer;
+class Sensor;
+class SensorEventQueue;
+
+// ----------------------------------------------------------------------------
+
+class SensorManager : public ASensorManager, public Singleton<SensorManager>
+{
+public:
+ SensorManager();
+ ~SensorManager();
+
+ ssize_t getSensorList(Sensor**) const;
+ Sensor* getDefaultSensor(int type);
+ sp<SensorEventQueue> createEventQueue();
+
+private:
+ sp<ISensorServer> mSensorServer;
+ Sensor* mSensorList;
+ Vector<Sensor> mSensors;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SENSOR_MANAGER_H
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 962b38b..232583a 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -52,6 +52,7 @@ public:
void endBox();
uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
status_t setInterleaveDuration(uint32_t duration);
+ int32_t getTimeScale() const { return mTimeScale; }
protected:
virtual ~MPEG4Writer();
@@ -72,6 +73,7 @@ private:
bool mStreamableFile;
off_t mEstimatedMoovBoxSize;
uint32_t mInterleaveDurationUs;
+ int32_t mTimeScale;
int64_t mStartTimestampUs;
Mutex mLock;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 73f5547..cdbf483 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -68,6 +68,7 @@ enum {
kKeyDiscNumber = 'dnum', // cstring
kKeyDate = 'date', // cstring
kKeyWriter = 'writ', // cstring
+ kKeyTimeScale = 'tmsl', // int32_t
// video profile and level
kKeyVideoProfile = 'vprf', // int32_t
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
new file mode 100644
index 0000000..249558a
--- /dev/null
+++ b/libs/gui/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ ISensorEventConnection.cpp \
+ ISensorServer.cpp \
+ Sensor.cpp \
+ SensorChannel.cpp \
+ SensorEventQueue.cpp \
+ SensorManager.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libbinder \
+ libhardware \
+ libhardware_legacy
+
+LOCAL_MODULE:= libgui
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -lpthread
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp
new file mode 100644
index 0000000..3e9d456
--- /dev/null
+++ b/libs/gui/ISensorEventConnection.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <gui/ISensorEventConnection.h>
+#include <gui/SensorChannel.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+ GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
+ ENABLE_DISABLE,
+ SET_EVENT_RATE
+};
+
+class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
+{
+public:
+ BpSensorEventConnection(const sp<IBinder>& impl)
+ : BpInterface<ISensorEventConnection>(impl)
+ {
+ }
+
+ virtual sp<SensorChannel> getSensorChannel() const
+ {
+ Parcel data, reply;
+ remote()->transact(GET_SENSOR_CHANNEL, data, &reply);
+ return new SensorChannel(reply);
+ }
+
+ virtual status_t enableDisable(int handle, bool enabled)
+ {
+ Parcel data, reply;
+ data.writeInt32(handle);
+ data.writeInt32(enabled);
+ remote()->transact(ENABLE_DISABLE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setEventRate(int handle, nsecs_t ns)
+ {
+ Parcel data, reply;
+ data.writeInt32(handle);
+ data.writeInt64(ns);
+ remote()->transact(SET_EVENT_RATE, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection");
+
+// ----------------------------------------------------------------------------
+
+status_t BnSensorEventConnection::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case GET_SENSOR_CHANNEL: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ sp<SensorChannel> channel(getSensorChannel());
+ channel->writeToParcel(reply);
+ return NO_ERROR;
+ } break;
+ case ENABLE_DISABLE: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ int handle = data.readInt32();
+ int enabled = data.readInt32();
+ status_t result = enableDisable(handle, enabled);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ } break;
+ case SET_EVENT_RATE: {
+ CHECK_INTERFACE(ISensorEventConnection, data, reply);
+ int handle = data.readInt32();
+ int ns = data.readInt64();
+ status_t result = setEventRate(handle, ns);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ } break;
+ }
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
new file mode 100644
index 0000000..c6177bc
--- /dev/null
+++ b/libs/gui/ISensorServer.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/Timers.h>
+
+#include <binder/Parcel.h>
+#include <binder/IInterface.h>
+
+#include <gui/Sensor.h>
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+enum {
+ GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
+ CREATE_SENSOR_EVENT_CONNECTION,
+};
+
+class BpSensorServer : public BpInterface<ISensorServer>
+{
+public:
+ BpSensorServer(const sp<IBinder>& impl)
+ : BpInterface<ISensorServer>(impl)
+ {
+ }
+
+ virtual Vector<Sensor> getSensorList()
+ {
+ Parcel data, reply;
+ remote()->transact(GET_SENSOR_LIST, data, &reply);
+ Sensor s;
+ Vector<Sensor> v;
+ int32_t n = reply.readInt32();
+ v.setCapacity(n);
+ while (n--) {
+ reply.read(static_cast<Flattenable&>(s));
+ v.add(s);
+ }
+ return v;
+ }
+
+ virtual sp<ISensorEventConnection> createSensorEventConnection()
+ {
+ Parcel data, reply;
+ remote()->transact(CREATE_SENSOR_EVENT_CONNECTION, data, &reply);
+ return interface_cast<ISensorEventConnection>(reply.readStrongBinder());
+ }
+};
+
+IMPLEMENT_META_INTERFACE(SensorServer, "android.gui.SensorServer");
+
+// ----------------------------------------------------------------------
+
+status_t BnSensorServer::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case GET_SENSOR_LIST: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ Vector<Sensor> v(getSensorList());
+ size_t n = v.size();
+ reply->writeInt32(n);
+ for (size_t i=0 ; i<n ; i++) {
+ reply->write(static_cast<const Flattenable&>(v[i]));
+ }
+ return NO_ERROR;
+ } break;
+ case CREATE_SENSOR_EVENT_CONNECTION: {
+ CHECK_INTERFACE(ISensorServer, data, reply);
+ sp<ISensorEventConnection> connection(createSensorEventConnection());
+ reply->writeStrongBinder(connection->asBinder());
+ return NO_ERROR;
+ } break;
+ }
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
new file mode 100644
index 0000000..1fdd285
--- /dev/null
+++ b/libs/gui/Sensor.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Flattenable.h>
+
+#include <hardware/sensors.h>
+
+#include <gui/Sensor.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+Sensor::Sensor()
+ : mHandle(0), mType(0),
+ mMinValue(0), mMaxValue(0), mResolution(0),
+ mPower(0)
+{
+}
+
+Sensor::~Sensor()
+{
+}
+
+const String8& Sensor::getName() const {
+ return mName;
+}
+
+const String8& Sensor::getVendor() const {
+ return mVendor;
+}
+
+int32_t Sensor::getHandle() const {
+ return mHandle;
+}
+
+int32_t Sensor::getType() const {
+ return mType;
+}
+
+float Sensor::getMinValue() const {
+ return mMinValue;
+}
+
+float Sensor::getMaxValue() const {
+ return mMaxValue;
+}
+
+float Sensor::getResolution() const {
+ return mResolution;
+}
+
+float Sensor::getPowerUsage() const {
+ return mPower;
+}
+
+size_t Sensor::getFlattenedSize() const
+{
+ return sizeof(int32_t) + ((mName.length() + 3) & ~3) +
+ sizeof(int32_t) + ((mVendor.length() + 3) & ~3) +
+ sizeof(int32_t) * 2 +
+ sizeof(float) * 3;
+}
+
+size_t Sensor::getFdCount() const
+{
+ return 0;
+}
+
+static inline
+size_t write(void* buffer, size_t offset, const String8& value) {
+ memcpy(static_cast<char*>(buffer) + offset, value.string(), value.length());
+ return (value.length() + 3) & ~3;
+}
+
+static inline
+size_t write(void* buffer, size_t offset, float value) {
+ *reinterpret_cast<float*>(static_cast<char*>(buffer) + offset) = value;
+ return sizeof(float);
+}
+
+static inline
+size_t write(void* buffer, size_t offset, int32_t value) {
+ *reinterpret_cast<int32_t*>(static_cast<char*>(buffer) + offset) = value;
+ return sizeof(int32_t);
+}
+
+status_t Sensor::flatten(void* buffer, size_t size,
+ int fds[], size_t count) const
+{
+ if (size < Sensor::getFlattenedSize())
+ return -ENOMEM;
+
+ size_t offset = 0;
+ offset += write(buffer, offset, int32_t(mName.length()));
+ offset += write(buffer, offset, mName);
+ offset += write(buffer, offset, int32_t(mVendor.length()));
+ offset += write(buffer, offset, mVendor);
+ offset += write(buffer, offset, mHandle);
+ offset += write(buffer, offset, mType);
+ offset += write(buffer, offset, mMinValue);
+ offset += write(buffer, offset, mMaxValue);
+ offset += write(buffer, offset, mResolution);
+ offset += write(buffer, offset, mPower);
+
+ return NO_ERROR;
+}
+
+static inline
+size_t read(void const* buffer, size_t offset, String8* value, int32_t len) {
+ value->setTo(static_cast<char const*>(buffer) + offset, len);
+ return (len + 3) & ~3;
+}
+
+static inline
+size_t read(void const* buffer, size_t offset, float* value) {
+ *value = *reinterpret_cast<float const*>(static_cast<char const*>(buffer) + offset);
+ return sizeof(float);
+}
+
+static inline
+size_t read(void const* buffer, size_t offset, int32_t* value) {
+ *value = *reinterpret_cast<int32_t const*>(static_cast<char const*>(buffer) + offset);
+ return sizeof(int32_t);
+}
+
+status_t Sensor::unflatten(void const* buffer, size_t size,
+ int fds[], size_t count)
+{
+ int32_t len;
+ size_t offset = 0;
+ offset += read(buffer, offset, &len);
+ offset += read(buffer, offset, &mName, len);
+ offset += read(buffer, offset, &len);
+ offset += read(buffer, offset, &mVendor, len);
+ offset += read(buffer, offset, &mHandle);
+ offset += read(buffer, offset, &mType);
+ offset += read(buffer, offset, &mMinValue);
+ offset += read(buffer, offset, &mMaxValue);
+ offset += read(buffer, offset, &mResolution);
+ offset += read(buffer, offset, &mPower);
+
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/gui/SensorChannel.cpp b/libs/gui/SensorChannel.cpp
new file mode 100644
index 0000000..147e1c2
--- /dev/null
+++ b/libs/gui/SensorChannel.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <utils/Errors.h>
+
+#include <binder/Parcel.h>
+
+#include <gui/SensorChannel.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+SensorChannel::SensorChannel()
+ : mSendFd(-1), mReceiveFd(-1)
+{
+ int fds[2];
+ if (pipe(fds) == 0) {
+ mReceiveFd = fds[0];
+ mSendFd = fds[1];
+ fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
+ fcntl(mSendFd, F_SETFL, O_NONBLOCK);
+ }
+}
+
+SensorChannel::SensorChannel(const Parcel& data)
+ : mSendFd(-1), mReceiveFd(-1)
+{
+ mReceiveFd = dup(data.readFileDescriptor());
+ fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
+}
+
+SensorChannel::~SensorChannel()
+{
+ if (mSendFd >= 0)
+ close(mSendFd);
+
+ if (mReceiveFd >= 0)
+ close(mReceiveFd);
+}
+
+int SensorChannel::getFd() const
+{
+ return mReceiveFd;
+}
+
+ssize_t SensorChannel::write(void const* vaddr, size_t size)
+{
+ ssize_t len = ::write(mSendFd, vaddr, size);
+ if (len < 0)
+ return -errno;
+ return len;
+}
+
+ssize_t SensorChannel::read(void* vaddr, size_t size)
+{
+ ssize_t len = ::read(mReceiveFd, vaddr, size);
+ if (len < 0)
+ return -errno;
+ return len;
+}
+
+status_t SensorChannel::writeToParcel(Parcel* reply) const
+{
+ if (mReceiveFd < 0)
+ return -EINVAL;
+
+ status_t result = reply->writeDupFileDescriptor(mReceiveFd);
+ close(mReceiveFd);
+ mReceiveFd = -1;
+ return result;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
new file mode 100644
index 0000000..f922ac4
--- /dev/null
+++ b/libs/gui/SensorEventQueue.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+#include <gui/Sensor.h>
+#include <gui/SensorChannel.h>
+#include <gui/SensorEventQueue.h>
+#include <gui/ISensorEventConnection.h>
+
+#include <android/sensor.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+SensorEventQueue::SensorEventQueue(const sp<ISensorEventConnection>& connection)
+ : mSensorEventConnection(connection)
+{
+}
+
+SensorEventQueue::~SensorEventQueue()
+{
+}
+
+void SensorEventQueue::onFirstRef()
+{
+ mSensorChannel = mSensorEventConnection->getSensorChannel();
+}
+
+int SensorEventQueue::getFd() const
+{
+ return mSensorChannel->getFd();
+}
+
+ssize_t SensorEventQueue::write(ASensorEvent const* events, size_t numEvents)
+{
+ ssize_t size = mSensorChannel->write(events, numEvents * sizeof(events[0]));
+ if (size >= 0) {
+ if (size % sizeof(events[0])) {
+ // partial write!!! should never happen.
+ return -EINVAL;
+ }
+ // returns number of events written
+ size /= sizeof(events[0]);
+ }
+ return size;
+}
+
+ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
+{
+ ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0]));
+ if (size >= 0) {
+ if (size % sizeof(events[0])) {
+ // partial write!!! should never happen.
+ return -EINVAL;
+ }
+ // returns number of events read
+ size /= sizeof(events[0]);
+ }
+ return size;
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor) const
+{
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), true);
+}
+
+status_t SensorEventQueue::disableSensor(Sensor const* sensor) const
+{
+ return mSensorEventConnection->enableDisable(sensor->getHandle(), false);
+}
+
+status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
+{
+ return mSensorEventConnection->setEventRate(sensor->getHandle(), ns);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
new file mode 100644
index 0000000..cd89285
--- /dev/null
+++ b/libs/gui/SensorManager.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Singleton.h>
+
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+#include <gui/Sensor.h>
+#include <gui/SensorManager.h>
+#include <gui/SensorEventQueue.h>
+
+// ----------------------------------------------------------------------------
+namespace android {
+// ----------------------------------------------------------------------------
+
+ANDROID_SINGLETON_STATIC_INSTANCE(SensorManager)
+
+SensorManager::SensorManager()
+ : mSensorList(0)
+{
+ mSensors = mSensorServer->getSensorList();
+ // TODO: needs implementation
+}
+
+SensorManager::~SensorManager()
+{
+ // TODO: needs implementation
+}
+
+ssize_t SensorManager::getSensorList(Sensor** list) const
+{
+ *list = mSensorList;
+ return mSensors.size();
+}
+
+Sensor* SensorManager::getDefaultSensor(int type)
+{
+ // TODO: needs implementation
+ return mSensorList;
+}
+
+sp<SensorEventQueue> SensorManager::createEventQueue()
+{
+ sp<SensorEventQueue> result = new SensorEventQueue(
+ mSensorServer->createSensorEventConnection());
+ return result;
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 40c80fa..ba5be03 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -88,6 +88,9 @@ public:
void copyTo(float* v) const;
void copyTo(SkMatrix& v) const;
+ /**
+ * Does not apply rotations!
+ */
void mapRect(Rect& r) const;
float getTranslateX();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9739b9b..12b0dea 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -406,7 +406,7 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto
}
bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) {
- bool clipped = mSnapshot->clipRect.intersect(left, top, right, bottom);
+ bool clipped = mSnapshot->clip(left, top, right, bottom);
if (clipped) {
mSnapshot->flags |= Snapshot::kFlagClipSet;
setScissorFromClip();
@@ -492,8 +492,8 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
- const Rect& clip = mSnapshot->clipRect;
- drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode);
+ const Rect& clip = mSnapshot->getMappedClip();
+ drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
}
void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) {
@@ -524,7 +524,7 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
- int color, SkXfermode::Mode mode) {
+ int color, SkXfermode::Mode mode, bool ignoreTransform) {
const int alpha = (color >> 24) & 0xFF;
const GLfloat a = alpha / 255.0f;
const GLfloat r = ((color >> 16) & 0xFF) / 255.0f;
@@ -538,7 +538,12 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot
mModelView.scale(right - left, bottom - top, 1.0f);
const bool inUse = useShader(mDrawColorShader);
- mDrawColorShader->set(mOrthoMatrix, mModelView, mSnapshot->transform);
+ if (!ignoreTransform) {
+ mDrawColorShader->set(mOrthoMatrix, mModelView, mSnapshot->transform);
+ } else {
+ mat4 identity;
+ mDrawColorShader->set(mOrthoMatrix, mModelView, identity);
+ }
if (!inUse) {
const GLvoid* p = &gDrawColorVertices[0].position[0];
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1165ab6..8083038 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -160,9 +160,10 @@ private:
* @param bottom The bottom coordinate of the rectangle
* @param color The rectangle's ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
+ * @param ignoreTransform True if the current transform should be ignored
*/
void drawColorRect(float left, float top, float right, float bottom,
- int color, SkXfermode::Mode mode);
+ int color, SkXfermode::Mode mode, bool ignoreTransform = false);
/**
* Draws a textured rectangle with the specified texture. The specified coordinates
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index ef9269f..7265d91 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -56,6 +56,8 @@ public:
previous(s),
layer(NULL),
fbo(s->fbo) {
+ mappedClip.set(s->clipRect);
+ transform.mapRect(mappedClip);
}
/**
@@ -87,12 +89,20 @@ public:
* Returns the current clip region mapped by the current transform.
*/
const Rect& getMappedClip() {
+ return mappedClip;
+ }
+
+ /**
+ * Intersects the current clip with the new clip rectangle.
+ */
+ bool clip(float left, float top, float right, float bottom) {
+ bool clipped = clipRect.intersect(left, top, right, bottom);
if (flags & kFlagDirtyTransform) {
flags &= ~kFlagDirtyTransform;
mappedClip.set(clipRect);
transform.mapRect(mappedClip);
}
- return mappedClip;
+ return clipped;
}
/**
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index b205418..edf1aed 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -60,7 +60,6 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info)
switch (format) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCbCr_422_I:
- case HAL_PIXEL_FORMAT_YV16:
info->bitsPerPixel = 16;
goto done;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 46d7493..62f824f 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -2,6 +2,9 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
+ifneq ($(TARGET_SIMULATOR),true)
+
+# Build the unit tests.
test_src_files := \
InputChannel_test.cpp \
InputDispatcher_test.cpp \
@@ -43,3 +46,5 @@ $(foreach file,$(test_src_files), \
# Build the manual test programs.
include $(call all-subdir-makefiles)
+
+endif \ No newline at end of file
diff --git a/libs/utils/tests/Android.mk b/libs/utils/tests/Android.mk
index f1b8cd5..b9f206a 100644
--- a/libs/utils/tests/Android.mk
+++ b/libs/utils/tests/Android.mk
@@ -2,6 +2,9 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+ifneq ($(TARGET_SIMULATOR),true)
+
+# Build the unit tests.
test_src_files := \
ObbFile_test.cpp \
PollLoop_test.cpp
@@ -37,3 +40,5 @@ $(foreach file,$(test_src_files), \
$(eval LOCAL_MODULE_TAGS := $(module_tags)) \
$(eval include $(BUILD_EXECUTABLE)) \
)
+
+endif \ No newline at end of file
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 6fe3c3b..653532c 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -40,7 +40,9 @@ else
LOCAL_CFLAGS += -DNO_OPENCORE
endif
+ifneq ($(TARGET_SIMULATOR),true)
LOCAL_STATIC_LIBRARIES := libmtp libusbhost
+endif
LOCAL_C_INCLUDES += \
external/tremor/Tremor \
diff --git a/media/jni/android_media_MtpClient.cpp b/media/jni/android_media_MtpClient.cpp
index 5c397a6..f69053c 100644
--- a/media/jni/android_media_MtpClient.cpp
+++ b/media/jni/android_media_MtpClient.cpp
@@ -38,6 +38,8 @@ static jmethodID method_deviceAdded;
static jmethodID method_deviceRemoved;
static jfieldID field_context;
+#ifdef HAVE_ANDROID_OS
+
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
if (env->ExceptionCheck()) {
LOGE("An exception was thrown by callback '%s'.", methodName);
@@ -94,52 +96,66 @@ void MyClient::deviceRemoved(MtpDevice *device) {
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
+#endif // HAVE_ANDROID_OS
+
// ----------------------------------------------------------------------------
static void
android_media_MtpClient_setup(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("setup\n");
MyClient* client = new MyClient(env, thiz);
client->start();
env->SetIntField(thiz, field_context, (int)client);
+#endif
}
static void
android_media_MtpClient_finalize(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("finalize\n");
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
client->cleanup(env);
delete client;
env->SetIntField(thiz, field_context, 0);
+#endif
}
static jboolean
android_media_MtpClient_start(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("start\n");
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
return client->start();
+#else
+ return false;
+#endif
}
static void
android_media_MtpClient_stop(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("stop\n");
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
client->stop();
+#endif
}
static jboolean
android_media_MtpClient_delete_object(JNIEnv *env, jobject thiz,
jint device_id, jint object_id)
{
+#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
MtpDevice* device = client->getDevice(device_id);
if (device)
return device->deleteObject(object_id);
else
+ #endif
return NULL;
}
@@ -147,11 +163,13 @@ static jint
android_media_MtpClient_get_parent(JNIEnv *env, jobject thiz,
jint device_id, jint object_id)
{
+#ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
MtpDevice* device = client->getDevice(device_id);
if (device)
return device->getParent(object_id);
else
+#endif
return -1;
}
@@ -159,11 +177,13 @@ static jint
android_media_MtpClient_get_storage_id(JNIEnv *env, jobject thiz,
jint device_id, jint object_id)
{
+ #ifdef HAVE_ANDROID_OS
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
MtpDevice* device = client->getDevice(device_id);
if (device)
return device->getStorageID(object_id);
else
+#endif
return -1;
}
diff --git a/media/jni/android_media_MtpCursor.cpp b/media/jni/android_media_MtpCursor.cpp
index 470fa05..6228b5d 100644
--- a/media/jni/android_media_MtpCursor.cpp
+++ b/media/jni/android_media_MtpCursor.cpp
@@ -51,6 +51,7 @@ static void
android_media_MtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
jint queryType, jint deviceID, jint storageID, jint objectID, jintArray javaColumns)
{
+#ifdef HAVE_ANDROID_OS
LOGD("android_media_MtpCursor_setup queryType: %d deviceID: %d storageID: %d objectID: %d\n",
queryType, deviceID, storageID, objectID);
@@ -68,19 +69,23 @@ android_media_MtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
if (columns)
env->ReleaseIntArrayElements(javaColumns, columns, 0);
env->SetIntField(thiz, field_context, (int)cursor);
+#endif
}
static void
android_media_MtpCursor_finalize(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("finalize\n");
MtpCursor *cursor = (MtpCursor *)env->GetIntField(thiz, field_context);
delete cursor;
+#endif
}
static jint
android_media_MtpCursor_fill_window(JNIEnv *env, jobject thiz, jobject javaWindow, jint startPos)
{
+#ifdef HAVE_ANDROID_OS
CursorWindow* window = get_window_from_object(env, javaWindow);
if (!window) {
LOGE("Invalid CursorWindow");
@@ -91,6 +96,9 @@ android_media_MtpCursor_fill_window(JNIEnv *env, jobject thiz, jobject javaWindo
MtpCursor *cursor = (MtpCursor *)env->GetIntField(thiz, field_context);
return cursor->fillWindow(window, startPos);
+#else
+ return 0;
+#endif
}
// ----------------------------------------------------------------------------
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index 53e41e8..be59362 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -49,6 +49,7 @@ MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
return (MtpDatabase *)env->GetIntField(database, field_context);
}
+#ifdef HAVE_ANDROID_OS
// ----------------------------------------------------------------------------
class MyMtpDatabase : public MtpDatabase {
@@ -368,26 +369,32 @@ static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodNa
}
}
+#endif // HAVE_ANDROID_OS
+
// ----------------------------------------------------------------------------
static void
android_media_MtpDatabase_setup(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("setup\n");
MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
env->SetIntField(thiz, field_context, (int)database);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
+#endif
}
static void
android_media_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("finalize\n");
MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
database->cleanup(env);
delete database;
env->SetIntField(thiz, field_context, 0);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
+#endif
}
// ----------------------------------------------------------------------------
diff --git a/media/jni/android_media_MtpServer.cpp b/media/jni/android_media_MtpServer.cpp
index 0883527..eddad57 100644
--- a/media/jni/android_media_MtpServer.cpp
+++ b/media/jni/android_media_MtpServer.cpp
@@ -42,6 +42,8 @@ extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
// ----------------------------------------------------------------------------
+#ifdef HAVE_ANDROID_OS
+
static bool ExceptionCheck(void* env)
{
return ((JNIEnv *)env)->ExceptionCheck();
@@ -111,9 +113,12 @@ public:
}
};
+#endif // HAVE_ANDROID_OS
+
static void
android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jstring storagePath)
{
+#ifdef HAVE_ANDROID_OS
LOGD("setup\n");
MtpDatabase* database = getMtpDatabase(env, javaDatabase);
@@ -123,6 +128,7 @@ android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, j
env->SetIntField(thiz, field_context, (int)thread);
env->ReleaseStringUTFChars(storagePath, storagePathStr);
+#endif
}
static void
@@ -135,42 +141,50 @@ android_media_MtpServer_finalize(JNIEnv *env, jobject thiz)
static void
android_media_MtpServer_start(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("start\n");
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
thread->run("MtpThread");
+#endif // HAVE_ANDROID_OS
}
static void
android_media_MtpServer_stop(JNIEnv *env, jobject thiz)
{
+#ifdef HAVE_ANDROID_OS
LOGD("stop\n");
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
if (thread) {
thread->setDone();
env->SetIntField(thiz, field_context, 0);
}
+#endif
}
static void
android_media_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
{
+#ifdef HAVE_ANDROID_OS
LOGD("send_object_added %d\n", handle);
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
if (thread)
thread->sendObjectAdded(handle);
else
LOGE("sendObjectAdded called while disconnected\n");
+#endif
}
static void
android_media_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
{
+#ifdef HAVE_ANDROID_OS
LOGD("send_object_removed %d\n", handle);
MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
if (thread)
thread->sendObjectRemoved(handle);
else
LOGE("sendObjectRemoved called while disconnected\n");
+#endif
}
// ----------------------------------------------------------------------------
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 24426ff..ba98f04 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -81,13 +81,13 @@ status_t MediaScanner::processDirectory(
}
static bool fileMatchesExtension(const char* path, const char* extensions) {
- char* extension = strrchr(path, '.');
+ const char* extension = strrchr(path, '.');
if (!extension) return false;
++extension; // skip the dot
if (extension[0] == 0) return false;
while (extensions[0]) {
- char* comma = strchr(extensions, ',');
+ const char* comma = strchr(extensions, ',');
size_t length = (comma ? comma - extensions : strlen(extensions));
if (length == strlen(extension) && strncasecmp(extension, extensions, length) == 0) return true;
extensions += length;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3beae7f..24b0e7b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -381,12 +381,12 @@ status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
return OK;
}
-// If interval < 0, only the first frame is I frame, and rest are all P frames
-// If interval == 0, all frames are encoded as I frames. No P frames
-// If interval > 0, it is the time spacing (seconds) between 2 neighboring I frames
-status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) {
- LOGV("setParamVideoIFramesInterval: %d seconds", interval);
- mIFramesInterval = interval;
+// If seconds < 0, only the first frame is I frame, and rest are all P frames
+// If seconds == 0, all frames are encoded as I frames. No P frames
+// If seconds > 0, it is the time spacing (seconds) between 2 neighboring I frames
+status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
+ LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
+ mIFramesIntervalSec = seconds;
return OK;
}
@@ -444,6 +444,44 @@ status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
return OK;
}
+status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
+ LOGV("setParamMovieTimeScale: %d", timeScale);
+
+ // The range is set to be the same as the audio's time scale range
+ // since audio's time scale has a wider range.
+ if (timeScale < 600 || timeScale > 96000) {
+ LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
+ return BAD_VALUE;
+ }
+ mMovieTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
+ LOGV("setParamVideoTimeScale: %d", timeScale);
+
+ // 60000 is chosen to make sure that each video frame from a 60-fps
+ // video has 1000 ticks.
+ if (timeScale < 600 || timeScale > 60000) {
+ LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
+ return BAD_VALUE;
+ }
+ mVideoTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
+ LOGV("setParamAudioTimeScale: %d", timeScale);
+
+ // 96000 Hz is the highest sampling rate support in AAC.
+ if (timeScale < 600 || timeScale > 96000) {
+ LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+ return BAD_VALUE;
+ }
+ mAudioTimeScale = timeScale;
+ return OK;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -462,6 +500,11 @@ status_t StagefrightRecorder::setParameter(
if (safe_strtoi32(value.string(), &durationUs)) {
return setParamInterleaveDuration(durationUs);
}
+ } else if (key == "param-movie-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamMovieTimeScale(timeScale);
+ }
} else if (key == "param-use-64bit-offset") {
int32_t use64BitOffset;
if (safe_strtoi32(value.string(), &use64BitOffset)) {
@@ -492,15 +535,20 @@ status_t StagefrightRecorder::setParameter(
if (safe_strtoi32(value.string(), &audio_bitrate)) {
return setParamAudioEncodingBitRate(audio_bitrate);
}
+ } else if (key == "audio-param-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamAudioTimeScale(timeScale);
+ }
} else if (key == "video-param-encoding-bitrate") {
int32_t video_bitrate;
if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
} else if (key == "video-param-i-frames-interval") {
- int32_t interval;
- if (safe_strtoi32(value.string(), &interval)) {
- return setParamVideoIFramesInterval(interval);
+ int32_t seconds;
+ if (safe_strtoi32(value.string(), &seconds)) {
+ return setParamVideoIFramesInterval(seconds);
}
} else if (key == "video-param-encoder-profile") {
int32_t profile;
@@ -517,6 +565,11 @@ status_t StagefrightRecorder::setParameter(
if (safe_strtoi32(value.string(), &cameraId)) {
return setParamVideoCameraId(cameraId);
}
+ } else if (key == "video-param-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamVideoTimeScale(timeScale);
+ }
} else {
LOGE("setParameter: failed to find key %s", key.string());
}
@@ -637,6 +690,7 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
encMeta->setInt32(kKeyChannelCount, mAudioChannels);
encMeta->setInt32(kKeySampleRate, mSampleRate);
encMeta->setInt32(kKeyBitRate, mAudioBitRate);
+ encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
OMXClient client;
CHECK_EQ(client.connect(), OK);
@@ -880,10 +934,11 @@ status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
- enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval);
+ enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
enc_meta->setInt32(kKeyStride, stride);
enc_meta->setInt32(kKeySliceHeight, sliceHeight);
enc_meta->setInt32(kKeyColorFormat, colorFormat);
+ enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
if (mVideoEncoderProfile != -1) {
enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
}
@@ -921,6 +976,7 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
+
writer->addSource(audioEncoder);
return OK;
}
@@ -957,6 +1013,7 @@ status_t StagefrightRecorder::startMPEG4Recording() {
meta->setInt32(kKeyFileType, mOutputFormat);
meta->setInt32(kKeyBitRate, totalBitRate);
meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+ meta->setInt32(kKeyTimeScale, mMovieTimeScale);
if (mTrackEveryNumberOfFrames > 0) {
meta->setInt32(kKeyTrackFrameStatus, mTrackEveryNumberOfFrames);
}
@@ -1027,9 +1084,12 @@ status_t StagefrightRecorder::reset() {
mAudioChannels = 1;
mAudioBitRate = 12200;
mInterleaveDurationUs = 0;
- mIFramesInterval = 1;
+ mIFramesIntervalSec = 1;
mAudioSourceNode = 0;
mUse64BitFileOffset = false;
+ mMovieTimeScale = 1000;
+ mAudioTimeScale = 1000;
+ mVideoTimeScale = 1000;
mCameraId = 0;
mVideoEncoderProfile = -1;
mVideoEncoderLevel = -1;
@@ -1112,7 +1172,7 @@ status_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const {
result.append(buffer);
snprintf(buffer, SIZE, " Encoder level: %d\n", mVideoEncoderLevel);
result.append(buffer);
- snprintf(buffer, SIZE, " I frames interval (s): %d\n", mIFramesInterval);
+ snprintf(buffer, SIZE, " I frames interval (s): %d\n", mIFramesIntervalSec);
result.append(buffer);
snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
result.append(buffer);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 58f0031..f51d7f8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -81,10 +81,13 @@ private:
int32_t mAudioChannels;
int32_t mSampleRate;
int32_t mInterleaveDurationUs;
- int32_t mIFramesInterval;
+ int32_t mIFramesIntervalSec;
int32_t mCameraId;
int32_t mVideoEncoderProfile;
int32_t mVideoEncoderLevel;
+ int32_t mMovieTimeScale;
+ int32_t mVideoTimeScale;
+ int32_t mAudioTimeScale;
int64_t mMaxFileSizeBytes;
int64_t mMaxFileDurationUs;
int32_t mTrackEveryNumberOfFrames;
@@ -111,17 +114,20 @@ private:
status_t setParamAudioEncodingBitRate(int32_t bitRate);
status_t setParamAudioNumberOfChannels(int32_t channles);
status_t setParamAudioSamplingRate(int32_t sampleRate);
+ status_t setParamAudioTimeScale(int32_t timeScale);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
- status_t setParamVideoIFramesInterval(int32_t interval);
+ status_t setParamVideoIFramesInterval(int32_t seconds);
status_t setParamVideoEncoderProfile(int32_t profile);
status_t setParamVideoEncoderLevel(int32_t level);
status_t setParamVideoCameraId(int32_t cameraId);
+ status_t setParamVideoTimeScale(int32_t timeScale);
status_t setParamTrackTimeStatus(int64_t timeDurationUs);
status_t setParamTrackFrameStatus(int32_t nFrames);
status_t setParamInterleaveDuration(int32_t durationUs);
status_t setParam64BitFileOffset(bool use64BitFileOffset);
status_t setParamMaxFileDurationUs(int64_t timeUs);
status_t setParamMaxFileSizeBytes(int64_t bytes);
+ status_t setParamMovieTimeScale(int32_t timeScale);
void clipVideoBitRate();
void clipVideoFrameRate();
void clipVideoFrameWidth();
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6a4a131..b7388bb 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,6 +41,7 @@ namespace android {
class MPEG4Writer::Track {
public:
Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+
~Track();
status_t start(MetaData *params);
@@ -61,12 +62,13 @@ private:
volatile bool mResumed;
int64_t mMaxTimeStampUs;
int64_t mEstimatedTrackSizeBytes;
+ int32_t mTimeScale;
pthread_t mThread;
struct SampleInfo {
size_t size;
- int64_t timestamp;
+ int64_t timestampUs;
};
List<SampleInfo> mSampleInfos;
bool mSamplesHaveSameSize;
@@ -92,11 +94,11 @@ private:
struct SttsTableEntry {
- SttsTableEntry(uint32_t count, uint32_t duration)
- : sampleCount(count), sampleDuration(duration) {}
+ SttsTableEntry(uint32_t count, uint32_t durationUs)
+ : sampleCount(count), sampleDurationUs(durationUs) {}
uint32_t sampleCount;
- uint32_t sampleDuration;
+ uint32_t sampleDurationUs;
};
List<SttsTableEntry> mSttsTableEntries;
@@ -270,6 +272,13 @@ status_t MPEG4Writer::start(MetaData *param) {
return OK;
}
+ if (!param ||
+ !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
+ LOGV("movie time scale: %d", mTimeScale);
+
mStreamableFile = true;
mWriteMoovBoxToMemory = false;
mMoovBoxBuffer = NULL;
@@ -336,14 +345,14 @@ void MPEG4Writer::stop() {
return;
}
- int64_t max_duration = 0;
+ int64_t maxDurationUs = 0;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
(*it)->stop();
- int64_t duration = (*it)->getDurationUs();
- if (duration > max_duration) {
- max_duration = duration;
+ int64_t durationUs = (*it)->getDurationUs();
+ if (durationUs > maxDurationUs) {
+ maxDurationUs = durationUs;
}
}
@@ -367,8 +376,7 @@ void MPEG4Writer::stop() {
mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
mMoovBoxBufferOffset = 0;
CHECK(mMoovBoxBuffer != NULL);
- int32_t timeScale = 1000;
- int32_t duration = max_duration / timeScale;
+ int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
beginBox("moov");
@@ -376,7 +384,7 @@ void MPEG4Writer::stop() {
writeInt32(0); // version=0, flags=0
writeInt32(now); // creation time
writeInt32(now); // modification time
- writeInt32(timeScale); // timescale
+ writeInt32(mTimeScale); // mvhd timescale
writeInt32(duration);
writeInt32(0x10000); // rate: 1.0
writeInt16(0x100); // volume
@@ -655,7 +663,6 @@ void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
}
int64_t MPEG4Writer::getStartTimestampUs() {
- LOGI("getStartTimestampUs: %lld", mStartTimestampUs);
Mutex::Autolock autoLock(mLock);
return mStartTimestampUs;
}
@@ -683,6 +690,11 @@ MPEG4Writer::Track::Track(
mGotAllCodecSpecificData(false),
mReachedEOS(false) {
getCodecSpecificDataFromInputFormatIfPossible();
+
+ if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
}
void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
@@ -927,9 +939,9 @@ void MPEG4Writer::Track::threadEntry() {
int64_t chunkTimestampUs = 0;
int32_t nChunks = 0;
int32_t nZeroLengthFrames = 0;
- int64_t lastTimestamp = 0; // Timestamp of the previous sample
- int64_t lastDuration = 0; // Time spacing between the previous two samples
- int32_t sampleCount = 1; // Sample count in the current stts table entry
+ int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
+ int64_t lastDurationUs = 0; // Between the previous two samples in ms
+ int32_t sampleCount = 1; // Sample count in the current stts table entry
uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
sp<MetaData> meta_data;
@@ -1113,7 +1125,7 @@ void MPEG4Writer::Track::threadEntry() {
}
if (mResumed) {
- previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration);
+ previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs);
mResumed = false;
}
@@ -1124,12 +1136,11 @@ void MPEG4Writer::Track::threadEntry() {
mMaxTimeStampUs = timestampUs;
}
- // Our timestamp is in ms.
- info.timestamp = (timestampUs + 500) / 1000;
+ info.timestampUs = timestampUs;
mSampleInfos.push_back(info);
if (mSampleInfos.size() > 2) {
- if (lastDuration != info.timestamp - lastTimestamp) {
- SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ if (lastDurationUs != info.timestampUs - lastTimestampUs) {
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
mSttsTableEntries.push_back(sttsEntry);
sampleCount = 1;
} else {
@@ -1142,8 +1153,8 @@ void MPEG4Writer::Track::threadEntry() {
}
previousSampleSize = info.size;
}
- lastDuration = info.timestamp - lastTimestamp;
- lastTimestamp = info.timestamp;
+ lastDurationUs = info.timestampUs - lastTimestampUs;
+ lastTimestampUs = info.timestampUs;
if (isSync != 0) {
mStssTableEntries.push_back(mSampleInfos.size());
@@ -1213,11 +1224,11 @@ void MPEG4Writer::Track::threadEntry() {
// there is no frame time after it, just repeat the previous
// frame's duration.
if (mSampleInfos.size() == 1) {
- lastDuration = 0; // A single sample's duration
+ lastDurationUs = 0; // A single sample's duration
} else {
++sampleCount; // Count for the last sample
}
- SttsTableEntry sttsEntry(sampleCount, lastDuration);
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
mSttsTableEntries.push_back(sttsEntry);
mReachedEOS = true;
LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
@@ -1249,12 +1260,13 @@ void MPEG4Writer::Track::trackProgressStatus(int32_t nFrames, int64_t timeUs) {
void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
int32_t *min, int32_t *avg, int32_t *max) {
CHECK(!mSampleInfos.empty());
- int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000/ mSampleInfos.size();
+ int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mSampleInfos.size();
int32_t minSampleDurationMs = 0x7FFFFFFF;
int32_t maxSampleDurationMs = 0;
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
- int32_t sampleDurationMs = static_cast<int32_t>(it->sampleDuration);
+ int32_t sampleDurationMs =
+ (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
if (sampleDurationMs > maxSampleDurationMs) {
maxSampleDurationMs = sampleDurationMs;
} else if (sampleDurationMs < minSampleDurationMs) {
@@ -1370,10 +1382,13 @@ void MPEG4Writer::Track::writeTrackHeader(
CHECK(success);
bool is_audio = !strncasecmp(mime, "audio/", 6);
- int32_t timeScale = 1000;
- int32_t duration = getDurationUs() / timeScale;
+ LOGV("%s track time scale: %d",
+ is_audio? "Audio": "Video", mTimeScale);
+
time_t now = time(NULL);
+ int32_t mvhdTimeScale = mOwner->getTimeScale();
+ int64_t trakDurationUs = getDurationUs();
mOwner->beginBox("trak");
@@ -1385,7 +1400,9 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(trackID);
mOwner->writeInt32(0); // reserved
- mOwner->writeInt32(duration);
+ int32_t tkhdDuration =
+ (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(tkhdDuration); // in mvhd timescale
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // layer
@@ -1423,12 +1440,17 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->beginBox("elst");
mOwner->writeInt32(0); // version=0, flags=0: 32-bit time
mOwner->writeInt32(2); // never ends with an empty list
- int64_t durationMs =
- (mStartTimestampUs - moovStartTimeUs) / 1000;
- mOwner->writeInt32(durationMs); // edit duration
- mOwner->writeInt32(-1); // empty edit box to signal starting time offset
- mOwner->writeInt32(1 << 16); // x1 rate
- mOwner->writeInt32(duration);
+
+ // First elst entry: specify the starting time offset
+ int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+ int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(seg); // in mvhd timecale
+ mOwner->writeInt32(-1); // starting time offset
+ mOwner->writeInt32(1 << 16); // rate = 1.0
+
+ // Second elst entry: specify the track duration
+ seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(seg); // in mvhd timescale
mOwner->writeInt32(0);
mOwner->writeInt32(1 << 16);
mOwner->endBox();
@@ -1441,8 +1463,9 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(timeScale); // timescale
- mOwner->writeInt32(duration); // duration
+ mOwner->writeInt32(mTimeScale); // media timescale
+ int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(mdhdDuration); // use media timescale
// Language follows the three letter standard ISO-639-2/T
// 'e', 'n', 'g' for "English", for instance.
// Each character is packed as the difference between its ASCII value and 0x60.
@@ -1664,7 +1687,8 @@ void MPEG4Writer::Track::writeTrackHeader(
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
mOwner->writeInt32(it->sampleCount);
- mOwner->writeInt32(it->sampleDuration);
+ int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(dur);
}
mOwner->endBox(); // stts
@@ -1717,7 +1741,7 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt64((*it));
}
}
- mOwner->endBox(); // co64
+ mOwner->endBox(); // stco or co64
mOwner->endBox(); // stbl
mOwner->endBox(); // minf
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index ab9285d..332bab3 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -42,7 +42,7 @@ static bool ParseURL(
path->setTo(slashPos);
}
- char *colonPos = strchr(host->string(), ':');
+ const char *colonPos = strchr(host->string(), ':');
if (colonPos != NULL) {
unsigned long x;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 077e123..157897b 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3212,6 +3212,12 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
mOutputFormat = new MetaData;
mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
+ if (mIsEncoder) {
+ int32_t timeScale;
+ if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
+ mOutputFormat->setInt32(kKeyTimeScale, timeScale);
+ }
+ }
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index edd8648..17771c4 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -90,7 +90,7 @@ static bool MakeURL(const char *baseURL, const char *url, AString *out) {
out->setTo(baseURL);
out->append(url);
} else {
- char *slashPos = strrchr(baseURL, '/');
+ const char *slashPos = strrchr(baseURL, '/');
if (slashPos > &baseURL[6]) {
out->setTo(baseURL, slashPos - baseURL);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index e9162c0..9826990 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -116,7 +116,7 @@ bool ARTSPConnection::ParseURL(
path->setTo(slashPos);
}
- char *colonPos = strchr(host->c_str(), ':');
+ const char *colonPos = strchr(host->c_str(), ':');
if (colonPos != NULL) {
unsigned long x;
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index ca4c55e..25b9ce2 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -164,7 +164,7 @@ void ASessionDescription::getFormatType(
AString format;
getFormat(index, &format);
- char *lastSpacePos = strrchr(format.c_str(), ' ');
+ const char *lastSpacePos = strrchr(format.c_str(), ' ');
CHECK(lastSpacePos != NULL);
char *end;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 74bb798..719ebf3 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -419,7 +419,7 @@ private:
out->setTo(baseURL);
out->append(url);
} else {
- char *slashPos = strrchr(baseURL, '/');
+ const char *slashPos = strrchr(baseURL, '/');
if (slashPos > &baseURL[6]) {
out->setTo(baseURL, slashPos - baseURL);
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index a92cea8..0559812 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -14,8 +14,8 @@ LOCAL_SHARED_LIBRARIES := \
base := $(LOCAL_PATH)/../..
LOCAL_C_INCLUDES := \
- $(base)/libs/audioflinger \
- $(base)/camera/libcameraservice \
+ $(base)/services/audioflinger \
+ $(base)/services/camera/libcameraservice \
$(base)/media/libmediaplayerservice
LOCAL_MODULE:= mediaserver
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index 4659709..40adf18 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -13,6 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+ifneq ($(TARGET_SIMULATOR),true)
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -41,3 +44,5 @@ LOCAL_MODULE:= libmtp
LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/media/mtp/MtpEventPacket.cpp b/media/mtp/MtpEventPacket.cpp
index 651761e..089278e 100644
--- a/media/mtp/MtpEventPacket.cpp
+++ b/media/mtp/MtpEventPacket.cpp
@@ -21,7 +21,7 @@
#include <fcntl.h>
#include <sys/ioctl.h>
-#include <f_mtp.h>
+#include <linux/usb/f_mtp.h>
#include "MtpEventPacket.h"
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index fda5f8f..163c05b 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -31,7 +31,7 @@
#include "MtpStorage.h"
#include "MtpStringBuffer.h"
-#include "f_mtp.h"
+#include <linux/usb/f_mtp.h>
namespace android {
diff --git a/media/mtp/f_mtp.h b/media/mtp/f_mtp.h
deleted file mode 100644
index 426c6b5..0000000
--- a/media/mtp/f_mtp.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Gadget Function Driver for MTP
- *
- * Copyright (C) 2010 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __LINUX_USB_F_MTP_H
-#define __LINUX_USB_F_MTP_H
-
-/* Constants for MTP_SET_INTERFACE_MODE */
-#define MTP_INTERFACE_MODE_MTP 0
-#define MTP_INTERFACE_MODE_PTP 1
-
-
-struct mtp_file_range {
- /* file descriptor for file to transfer */
- int fd;
- /* offset in file for start of transfer */
- loff_t offset;
- /* number of bytes to transfer */
- size_t length;
-};
-
-struct mtp_event {
- /* size of the event */
- size_t length;
- /* event data to send */
- void *data;
-};
-
-/* Sends the specified file range to the host */
-#define MTP_SEND_FILE _IOW('M', 0, struct mtp_file_range)
-/* Receives data from the host and writes it to a file.
- * The file is created if it does not exist.
- */
-#define MTP_RECEIVE_FILE _IOW('M', 1, struct mtp_file_range)
-/* Sets the driver mode to either MTP or PTP */
-#define MTP_SET_INTERFACE_MODE _IOW('M', 2, int)
-/* Sends an event to the host via the interrupt endpoint */
-#define MTP_SEND_EVENT _IOW('M', 3, struct mtp_event)
-
-#endif /* __LINUX_USB_F_MTP_H */
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 509a379..2fe0679 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -9,13 +9,15 @@ LOCAL_SRC_FILES:= \
input.cpp \
looper.cpp \
native_activity.cpp \
- native_window.cpp
+ native_window.cpp \
+ sensor.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libui \
+ libgui \
libsurfaceflinger_client \
libandroid_runtime
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
new file mode 100644
index 0000000..7a3907e
--- /dev/null
+++ b/native/android/sensor.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "sensor"
+#include <utils/Log.h>
+
+#include <android/looper.h>
+#include <android/sensor.h>
+
+#include <utils/RefBase.h>
+#include <utils/PollLoop.h>
+#include <utils/Timers.h>
+
+#include <gui/Sensor.h>
+#include <gui/SensorManager.h>
+#include <gui/SensorEventQueue.h>
+
+#include <poll.h>
+
+using android::sp;
+using android::Sensor;
+using android::SensorManager;
+using android::SensorEventQueue;
+using android::String8;
+
+/*****************************************************************************/
+
+ASensorManager* ASensorManager_getInstance()
+{
+ return &SensorManager::getInstance();
+}
+
+int ASensorManager_getSensorList(ASensorManager* manager, ASensor** list)
+{
+ Sensor* l;
+ int c = static_cast<SensorManager*>(manager)->getSensorList(&l);
+ if (list) {
+ *list = l;
+ }
+ return c;
+}
+
+ASensor* ASensorManager_getDefaultSensor(ASensorManager* manager, int type)
+{
+ return static_cast<SensorManager*>(manager)->getDefaultSensor(type);
+}
+
+ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager,
+ ALooper* looper, ALooper_callbackFunc* callback, void* data)
+{
+ sp<SensorEventQueue> queue =
+ static_cast<SensorManager*>(manager)->createEventQueue();
+ if (queue != 0) {
+ ALooper_addFd(looper, queue->getFd(), POLLIN, callback, data);
+ queue->looper = looper;
+ queue->incStrong(manager);
+ }
+ return static_cast<ASensorEventQueue*>(queue.get());
+}
+
+int ASensorManager_destroyEventQueue(ASensorManager* manager,
+ ASensorEventQueue* inQueue)
+{
+ sp<SensorEventQueue> queue = static_cast<SensorEventQueue*>(inQueue);
+ ALooper_removeFd(queue->looper, queue->getFd());
+ queue->decStrong(manager);
+ return 0;
+}
+
+/*****************************************************************************/
+
+int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor* sensor)
+{
+ return static_cast<SensorEventQueue*>(queue)->enableSensor(
+ static_cast<Sensor*>(sensor));
+}
+
+int ASensorEventQueue_disableSensor(ASensorEventQueue* queue, ASensor* sensor)
+{
+ return static_cast<SensorEventQueue*>(queue)->disableSensor(
+ static_cast<Sensor*>(sensor));
+}
+
+int ASensorEventQueue_setEventRate(ASensorEventQueue* queue, ASensor* sensor,
+ int32_t usec)
+{
+ return static_cast<SensorEventQueue*>(queue)->setEventRate(
+ static_cast<Sensor*>(sensor), us2ns(usec));
+}
+
+int ASensorEventQueue_hasEvents(ASensorEventQueue* queue)
+{
+ struct pollfd pfd;
+ pfd.fd = static_cast<SensorEventQueue*>(queue)->getFd();
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ int nfd = poll(&pfd, 1, 0);
+
+ if (nfd < 0)
+ return -errno;
+
+ if (pfd.revents != POLLIN)
+ return -1;
+
+ return (nfd == 0) ? 0 : 1;
+}
+
+ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue,
+ ASensorEvent* events, size_t count)
+{
+ return static_cast<SensorEventQueue*>(queue)->read(events, count);
+}
+
+
+/*****************************************************************************/
+
+const char* ASensor_getName(ASensor* sensor)
+{
+ return static_cast<Sensor*>(sensor)->getName().string();
+}
+
+const char* ASensor_getVendor(ASensor* sensor)
+{
+ return static_cast<Sensor*>(sensor)->getVendor().string();
+}
+
+int ASensor_getType(ASensor* sensor)
+{
+ return static_cast<Sensor*>(sensor)->getType();
+}
+
+float ASensor_getResolution(ASensor* sensor)
+{
+ return static_cast<Sensor*>(sensor)->getResolution();
+}
+
diff --git a/native/glue/threaded_app/Android.mk b/native/glue/threaded_app/Android.mk
deleted file mode 100644
index cfc9b2a..0000000
--- a/native/glue/threaded_app/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-BASE_PATH := $(call my-dir)
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# our source files
-#
-LOCAL_SRC_FILES:= \
- threaded_app.c
-
-LOCAL_C_INCLUDES += \
- frameworks/base/native/include \
- frameworks/base/core/jni/android \
- dalvik/libnativehelper/include/nativehelper
-
-LOCAL_MODULE:= libthreaded_app
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/native/glue/threaded_app/threaded_app.c b/native/glue/threaded_app/threaded_app.c
deleted file mode 100644
index 452c735..0000000
--- a/native/glue/threaded_app/threaded_app.c
+++ /dev/null
@@ -1,338 +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 <jni.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/resource.h>
-
-#include <android_glue/threaded_app.h>
-
-#include <android/log.h>
-
-#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
-#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "threaded_app", __VA_ARGS__))
-
-int8_t android_app_read_cmd(struct android_app* android_app) {
- int8_t cmd;
- if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
- return cmd;
- } else {
- LOGW("No data on command pipe!");
- }
- return -1;
-}
-
-int32_t android_app_exec_cmd(struct android_app* android_app, int8_t cmd) {
- switch (cmd) {
- case APP_CMD_INPUT_CHANGED:
- LOGI("APP_CMD_INPUT_CHANGED\n");
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- android_app->inputQueue = android_app->pendingInputQueue;
- if (android_app->inputQueue != NULL) {
- LOGI("Attaching input queue to looper");
- AInputQueue_attachLooper(android_app->inputQueue,
- android_app->looper, NULL, (void*)LOOPER_ID_EVENT);
- }
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_WINDOW_CHANGED:
- LOGI("APP_CMD_WINDOW_CHANGED\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->window = android_app->pendingWindow;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_START:
- case APP_CMD_RESUME:
- case APP_CMD_PAUSE:
- case APP_CMD_STOP:
- LOGI("activityState=%d\n", cmd);
- pthread_mutex_lock(&android_app->mutex);
- android_app->activityState = cmd;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_WINDOW_REDRAW_NEEDED:
- LOGI("APP_CMD_WINDOW_REDRAW_NEEDED\n");
- pthread_mutex_lock(&android_app->mutex);
- android_app->redrawNeeded = 0;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- break;
-
- case APP_CMD_CONTENT_RECT_CHANGED:
- LOGI("APP_CMD_CONTENT_RECT_CHANGED\n");
- android_app->contentRect = android_app->pendingContentRect;
- break;
-
- case APP_CMD_DESTROY:
- LOGI("APP_CMD_DESTROY\n");
- android_app->destroyRequested = 1;
- break;
- }
-
- return android_app->destroyRequested ? 0 : 1;
-}
-
-static void android_app_destroy(struct android_app* android_app) {
- LOGI("android_app_destroy!");
- pthread_mutex_lock(&android_app->mutex);
- if (android_app->inputQueue != NULL) {
- AInputQueue_detachLooper(android_app->inputQueue);
- }
- android_app->destroyed = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
- // Can't touch android_app object after this.
-}
-
-static void* android_app_entry(void* param) {
- struct android_app* android_app = (struct android_app*)param;
-
- ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
- ALooper_addFd(looper, android_app->msgread, POLLIN, NULL, (void*)LOOPER_ID_MAIN);
- android_app->looper = looper;
-
- pthread_mutex_lock(&android_app->mutex);
- android_app->running = 1;
- pthread_cond_broadcast(&android_app->cond);
- pthread_mutex_unlock(&android_app->mutex);
-
- android_main(android_app);
-
- android_app_destroy(android_app);
- return NULL;
-}
-
-// --------------------------------------------------------------------
-// Native activity interaction (called from main thread)
-// --------------------------------------------------------------------
-
-static struct android_app* android_app_create(ANativeActivity* activity) {
- struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
- memset(android_app, 0, sizeof(struct android_app));
- android_app->activity = activity;
-
- pthread_mutex_init(&android_app->mutex, NULL);
- pthread_cond_init(&android_app->cond, NULL);
-
- int msgpipe[2];
- if (pipe(msgpipe)) {
- LOGI("could not create pipe: %s", strerror(errno));
- }
- android_app->msgread = msgpipe[0];
- android_app->msgwrite = msgpipe[1];
- int result = fcntl(android_app->msgread, F_SETFL, O_NONBLOCK);
- if (result != 0) LOGW("Could not make message read pipe "
- "non-blocking: %s", strerror(errno));
- result = fcntl(android_app->msgwrite, F_SETFL, O_NONBLOCK);
- if (result != 0) LOGW("Could not make message write pipe "
- "non-blocking: %s", strerror(errno));
-
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
-
- // Wait for thread to start.
- pthread_mutex_lock(&android_app->mutex);
- while (!android_app->running) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- return android_app;
-}
-
-static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
- if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
- LOGI("Failure writing android_app cmd: %s\n", strerror(errno));
- }
-}
-
-static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->pendingInputQueue = inputQueue;
- android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
- while (android_app->inputQueue != android_app->pendingInputQueue) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->pendingWindow = window;
- android_app_write_cmd(android_app, APP_CMD_WINDOW_CHANGED);
- while (android_app->window != android_app->pendingWindow) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, cmd);
- while (android_app->activityState != cmd) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_wait_redraw(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->redrawNeeded = 1;
- android_app_write_cmd(android_app, APP_CMD_WINDOW_REDRAW_NEEDED);
- while (android_app->redrawNeeded) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_set_content_rect(struct android_app* android_app, const ARect* rect) {
- pthread_mutex_lock(&android_app->mutex);
- android_app->pendingContentRect = *rect;
- android_app_write_cmd(android_app, APP_CMD_CONTENT_RECT_CHANGED);
- pthread_mutex_unlock(&android_app->mutex);
-}
-
-static void android_app_free(struct android_app* android_app) {
- pthread_mutex_lock(&android_app->mutex);
- android_app_write_cmd(android_app, APP_CMD_DESTROY);
- while (!android_app->destroyed) {
- pthread_cond_wait(&android_app->cond, &android_app->mutex);
- }
- pthread_mutex_unlock(&android_app->mutex);
-
- close(android_app->msgread);
- close(android_app->msgwrite);
- pthread_cond_destroy(&android_app->cond);
- pthread_mutex_destroy(&android_app->mutex);
- free(android_app);
-}
-
-static void onDestroy(ANativeActivity* activity) {
- LOGI("Destroy: %p\n", activity);
- android_app_free((struct android_app*)activity->instance);
-}
-
-static void onStart(ANativeActivity* activity) {
- LOGI("Start: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
-}
-
-static void onResume(ANativeActivity* activity) {
- LOGI("Resume: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
-}
-
-static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
- LOGI("SaveInstanceState: %p\n", activity);
- return NULL;
-}
-
-static void onPause(ANativeActivity* activity) {
- LOGI("Pause: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
-}
-
-static void onStop(ANativeActivity* activity) {
- LOGI("Stop: %p\n", activity);
- android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
-}
-
-static void onLowMemory(ANativeActivity* activity) {
- LOGI("LowMemory: %p\n", activity);
- android_app_write_cmd((struct android_app*)activity->instance,
- APP_CMD_LOW_MEMORY);
-}
-
-static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
- LOGI("WindowFocusChanged: %p -- %d\n", activity, focused);
- android_app_write_cmd((struct android_app*)activity->instance,
- focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
-}
-
-static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowCreated: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, window);
-}
-
-static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowResized: %p -- %p\n", activity, window);
- android_app_write_cmd((struct android_app*)activity->instance,
- APP_CMD_WINDOW_RESIZED);
-}
-
-static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowRedrawNeeded: %p -- %p\n", activity, window);
- android_app_wait_redraw((struct android_app*)activity->instance);
-}
-
-static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) {
- LOGI("ContentRectChanged: %p -- (%d,%d)-(%d,%d)\n", activity, rect->left,
- rect->top, rect->right, rect->bottom);
- android_app_set_content_rect((struct android_app*)activity->instance, rect);
-}
-
-static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
- LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
- android_app_set_window((struct android_app*)activity->instance, NULL);
-}
-
-static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
- LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, queue);
-}
-
-static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
- LOGI("InputQueueDestroyed: %p -- %p\n", activity, queue);
- android_app_set_input((struct android_app*)activity->instance, NULL);
-}
-
-void ANativeActivity_onCreate(ANativeActivity* activity,
- void* savedState, size_t savedStateSize) {
- LOGI("Creating: %p\n", activity);
- activity->callbacks->onDestroy = onDestroy;
- activity->callbacks->onStart = onStart;
- activity->callbacks->onResume = onResume;
- activity->callbacks->onSaveInstanceState = onSaveInstanceState;
- activity->callbacks->onPause = onPause;
- activity->callbacks->onStop = onStop;
- activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
- activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
- activity->callbacks->onNativeWindowResized = onNativeWindowResized;
- activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
- activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
- activity->callbacks->onInputQueueCreated = onInputQueueCreated;
- activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
- activity->callbacks->onContentRectChanged = onContentRectChanged;
- activity->callbacks->onLowMemory = onLowMemory;
-
- activity->instance = android_app_create(activity);
-}
diff --git a/native/include/android/tts.h b/native/include/android/tts.h
index e5c99f7..fb15108 100644
--- a/native/include/android/tts.h
+++ b/native/include/android/tts.h
@@ -87,6 +87,11 @@ typedef struct {
*/
extern android_tts_engine_t *android_getTtsEngine();
+/* Including the old version for legacy support (Froyo compatibility).
+ * This should return the same thing as android_getTtsEngine.
+ */
+extern "C" android_tts_engine_t *getTtsEngine();
+
// A callback type used to notify the framework of new synthetized
// audio samples, status will be SYNTH_DONE for the last sample of
// the last request, of SYNTH_PENDING otherwise.
diff --git a/native/include/android_glue/threaded_app.h b/native/include/android_glue/threaded_app.h
deleted file mode 100644
index 2b58e9c..0000000
--- a/native/include/android_glue/threaded_app.h
+++ /dev/null
@@ -1,197 +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 <poll.h>
-#include <pthread.h>
-#include <sched.h>
-
-#include <android/native_activity.h>
-#include <android/looper.h>
-
-/**
- * This is the interface for the standard glue code of a threaded
- * application. In this model, the application's code is running
- * in its own thread separate from the main thread of the process.
- * It is not required that this thread be associated with the Java
- * VM, although it will need to be in order to make JNI calls any
- * Java objects.
- */
-struct android_app {
- // The application can place a pointer to its own state object
- // here if it likes.
- void* userData;
-
- // The ANativeActivity object instance that this app is running in.
- ANativeActivity* activity;
-
- // The ALooper associated with the app's thread.
- ALooper* looper;
-
- // When non-NULL, this is the input queue from which the app will
- // receive user input events.
- AInputQueue* inputQueue;
-
- // When non-NULL, this is the window surface that the app can draw in.
- ANativeWindow* window;
-
- // Current content rectangle of the window; this is the area where the
- // window's content should be placed to be seen by the user.
- ARect contentRect;
-
- // Current state of the app's activity. May be either APP_CMD_START,
- // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
- int activityState;
-
- // -------------------------------------------------
- // Below are "private" implementation of the glue code.
-
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- int msgread;
- int msgwrite;
-
- pthread_t thread;
-
- // This is non-zero when the application's NativeActivity is being
- // destroyed and waiting for the app thread to complete.
- int destroyRequested;
-
- int running;
- int destroyed;
- int redrawNeeded;
- AInputQueue* pendingInputQueue;
- ANativeWindow* pendingWindow;
- ARect pendingContentRect;
-};
-
-enum {
- /**
- * Looper data ID of commands coming from the app's main thread.
- * These can be retrieved and processed with android_app_read_cmd()
- * and android_app_exec_cmd().
- */
- LOOPER_ID_MAIN = 1,
-
- /**
- * Looper data ID of events coming from the AInputQueue of the
- * application's window. These can be read via the inputQueue
- * object of android_app.
- */
- LOOPER_ID_EVENT = 2
-};
-
-enum {
- /**
- * Command from main thread: the AInputQueue has changed. Upon processing
- * this command, android_app->inputQueue will be updated to the new queue
- * (or NULL).
- */
- APP_CMD_INPUT_CHANGED,
-
- /**
- * Command from main thread: the ANativeWindow has changed. Upon processing
- * this command, android_app->window will be updated to the new window surface
- * (or NULL).
- */
- APP_CMD_WINDOW_CHANGED,
-
- /**
- * Command from main thread: the current ANativeWindow has been resized.
- * Please redraw with its new size.
- */
- APP_CMD_WINDOW_RESIZED,
-
- /**
- * Command from main thread: the system needs that the current ANativeWindow
- * be redrawn. You should redraw the window before handing this to
- * android_app_exec_cmd() in order to avoid transient drawing glitches.
- */
- APP_CMD_WINDOW_REDRAW_NEEDED,
-
- /**
- * Command from main thread: the content area of the window has changed,
- * such as from the soft input window being shown or hidden. You can
- * find the new content rect in android_app::contentRect.
- */
- APP_CMD_CONTENT_RECT_CHANGED,
-
- /**
- * Command from main thread: the app's activity window has gained
- * input focus.
- */
- APP_CMD_GAINED_FOCUS,
-
- /**
- * Command from main thread: the app's activity window has lost
- * input focus.
- */
- APP_CMD_LOST_FOCUS,
-
- /**
- * Command from main thread: the system is running low on memory.
- * Try to reduce your memory use.
- */
- APP_CMD_LOW_MEMORY,
-
- /**
- * Command from main thread: the app's activity has been started.
- */
- APP_CMD_START,
-
- /**
- * Command from main thread: the app's activity has been resumed.
- */
- APP_CMD_RESUME,
-
- /**
- * Command from main thread: the app's activity has been paused.
- */
- APP_CMD_PAUSE,
-
- /**
- * Command from main thread: the app's activity has been stopped.
- */
- APP_CMD_STOP,
-
- /**
- * Command from main thread: the app's activity is being destroyed,
- * and waiting for the app thread to clean up and exit before proceeding.
- */
- APP_CMD_DESTROY,
-};
-
-/**
- * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
- * app command message.
- */
-int8_t android_app_read_cmd(struct android_app* android_app);
-
-/**
- * Call with the command returned by android_app_read_cmd() to do the
- * default processing of the given command.
- *
- * Important: returns 0 if the app should exit. You must ALWAYS check for
- * a zero return and, if found, exit your android_main() function.
- */
-int32_t android_app_exec_cmd(struct android_app* android_app, int8_t cmd);
-
-/**
- * This is the function that application code must implement, representing
- * the main entry to the app.
- */
-extern void android_main(struct android_app* app);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 75045d7..6d77a3a 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -12,7 +12,12 @@
android:icon="@drawable/ic_launcher_settings">
<service
- android:name=".statusbar.StatusBarService"
+ android:name=".statusbar.PhoneStatusBarService"
+ android:exported="false"
+ />
+
+ <service
+ android:name=".statusbar.tablet.TabletStatusBarService"
android:exported="false"
/>
diff --git a/packages/SystemUI/res/drawable/notification_dragger.png b/packages/SystemUI/res/drawable/notification_dragger.png
new file mode 100644
index 0000000..fad1f32
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_dragger.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
new file mode 100644
index 0000000..1e93bee
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** 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.
+*/
+-->
+
+<!-- android:background="@drawable/status_bar_closed_default_background" -->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:background="@drawable/status_bar_background"
+ android:orientation="vertical"
+ android:focusable="true"
+ android:descendantFocusability="afterDescendants"
+ >
+
+ <RelativeLayout android:id="@+id/icons"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+<!--
+ <LinearLayout android:id="@+id/statusIcons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:paddingRight="6dip"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"/>
+-->
+
+ <com.android.systemui.statusbar.tablet.NotificationIconArea
+ android:id="@+id/notificationIcons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="10dp"
+ android:paddingLeft="6dip"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ />
+
+ <RelativeLayout android:id="@+id/icons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ >
+
+ <com.android.systemui.statusbar.Clock
+ android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:singleLine="true"
+ android:textSize="16sp"
+ android:textStyle="bold"
+ />
+ </RelativeLayout>
+
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/back"
+ android:layout_width="wrap_content"
+ android:layout_height="@*android:dimen/status_bar_height"
+ android:layout_toLeftOf="@+id/menu"
+ android:layout_marginRight="10dp"
+ android:src="@drawable/status_bar_back"
+ systemui:keyCode="4"
+ />
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/menu"
+ android:layout_width="wrap_content"
+ android:layout_height="@*android:dimen/status_bar_height"
+ android:layout_toLeftOf="@+id/home"
+ android:src="@drawable/status_bar_menu"
+ android:layout_marginRight="10dp"
+ systemui:keyCode="82"
+ />
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/home"
+ android:layout_width="wrap_content"
+ android:layout_height="@*android:dimen/status_bar_height"
+ android:layout_alignParentRight="true"
+ android:layout_marginRight="10dp"
+ android:src="@drawable/status_bar_home"
+ systemui:keyCode="3"
+ />
+
+ </RelativeLayout>
+<!--
+
+ <LinearLayout android:id="@+id/ticker"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="6dip"
+ android:animationCache="false"
+ android:orientation="horizontal" >
+ <ImageSwitcher android:id="@+id/tickerIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginRight="8dip"
+ >
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:layout_width="25dip"
+ android:layout_height="25dip"
+ />
+ <com.android.systemui.statusbar.AnimatedImageView
+ android:layout_width="25dip"
+ android:layout_height="25dip"
+ />
+ </ImageSwitcher>
+ <com.android.systemui.statusbar.TickerView android:id="@+id/tickerText"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:paddingTop="2dip"
+ android:paddingRight="10dip">
+ <TextView
+ android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ />
+ <TextView
+ android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ />
+ </com.android.systemui.statusbar.TickerView>
+ </LinearLayout>
+
+ <com.android.systemui.statusbar.DateView android:id="@+id/date"
+ android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:singleLine="true"
+ android:gravity="center_vertical|left"
+ android:paddingLeft="6px"
+ android:paddingRight="6px"
+ android:background="@drawable/status_bar_background"
+ />
+-->
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 4667149..2f1b36e 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -60,33 +60,6 @@
android:textStyle="bold"
android:gravity="center_vertical|left"
/>
-
- <LinearLayout android:id="@+id/buttons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="6dip"
- android:orientation="horizontal" >
-
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/back"
- android:layout_width="wrap_content"
- android:layout_height="@*android:dimen/status_bar_height"
- android:src="@drawable/status_bar_back"
- systemui:keyCode="4"
- />
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/menu"
- android:layout_width="wrap_content"
- android:layout_height="@*android:dimen/status_bar_height"
- android:src="@drawable/status_bar_menu"
- systemui:keyCode="82"
- />
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/home"
- android:layout_width="wrap_content"
- android:layout_height="@*android:dimen/status_bar_height"
- android:src="@drawable/status_bar_home"
- systemui:keyCode="3"
- />
- </LinearLayout>
-
</LinearLayout>
<LinearLayout android:id="@+id/ticker"
diff --git a/packages/SystemUI/res/layout/unused.xml b/packages/SystemUI/res/layout/unused.xml
deleted file mode 100644
index 05a7d7d..0000000
--- a/packages/SystemUI/res/layout/unused.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<Unused
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/buttons">
-</Unused>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CloseDragHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/CloseDragHandle.java
index f45caf5..0f6723e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CloseDragHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CloseDragHandle.java
@@ -23,7 +23,7 @@ import android.widget.LinearLayout;
public class CloseDragHandle extends LinearLayout {
- StatusBarService mService;
+ PhoneStatusBarService mService;
public CloseDragHandle(Context context, AttributeSet attrs) {
super(context, attrs);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f9347b1..2c0af65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -32,7 +32,7 @@ import com.android.internal.statusbar.StatusBarNotification;
* coalescing these calls so they don't stack up. For the calls
* are coalesced, note that they are all idempotent.
*/
-class CommandQueue extends IStatusBar.Stub {
+public class CommandQueue extends IStatusBar.Stub {
private static final String TAG = "StatusBar.CommandQueue";
private static final int MSG_MASK = 0xffff0000;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandedView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandedView.java
index 3d85f27..a2d4b95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandedView.java
@@ -27,7 +27,7 @@ import android.util.Slog;
public class ExpandedView extends LinearLayout {
- StatusBarService mService;
+ PhoneStatusBarService mService;
int mPrevHeight = -1;
public ExpandedView(Context context, AttributeSet attrs) {
@@ -53,7 +53,7 @@ public class ExpandedView extends LinearLayout {
//Slog.d(StatusBarService.TAG, "height changed old=" + mPrevHeight
// + " new=" + height);
mPrevHeight = height;
- mService.updateExpandedViewPos(StatusBarService.EXPANDED_LEAVE_ALONE);
+ mService.updateExpandedViewPos(PhoneStatusBarService.EXPANDED_LEAVE_ALONE);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
new file mode 100644
index 0000000..eff9a1d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -0,0 +1,1552 @@
+/*
+ * 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.systemui.statusbar;
+
+import android.app.Service;
+import android.app.ActivityManagerNative;
+import android.app.Dialog;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManagerImpl;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RemoteViews;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.FrameLayout;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+
+import com.android.internal.statusbar.IStatusBar;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.StatusBarPolicy;
+
+
+
+public class PhoneStatusBarService extends StatusBarService {
+ static final String TAG = "PhoneStatusBarService";
+ static final boolean SPEW = false;
+
+ public static final String ACTION_STATUSBAR_START
+ = "com.android.internal.policy.statusbar.START";
+
+ static final int EXPANDED_LEAVE_ALONE = -10000;
+ static final int EXPANDED_FULL_OPEN = -10001;
+
+ private static final int MSG_ANIMATE = 1000;
+ private static final int MSG_ANIMATE_REVEAL = 1001;
+ private static final int MSG_SHOW_INTRUDER = 1002;
+ private static final int MSG_HIDE_INTRUDER = 1003;
+
+ // will likely move to a resource or other tunable param at some point
+ private static final int INTRUDER_ALERT_DECAY_MS = 10000;
+
+ StatusBarPolicy mIconPolicy;
+
+ int mIconSize;
+ Display mDisplay;
+
+ StatusBarView mStatusBarView;
+ int mPixelFormat;
+ H mHandler = new H();
+ Object mQueueLock = new Object();
+
+ // icons
+ LinearLayout mIcons;
+ IconMerger mNotificationIcons;
+ LinearLayout mStatusIcons;
+
+ // expanded notifications
+ Dialog mExpandedDialog;
+ ExpandedView mExpandedView;
+ WindowManager.LayoutParams mExpandedParams;
+ ScrollView mScrollView;
+ View mNotificationLinearLayout;
+ View mExpandedContents;
+ // top bar
+ TextView mNoNotificationsTitle;
+ TextView mClearButton;
+ // drag bar
+ CloseDragHandle mCloseView;
+ // ongoing
+ NotificationData mOngoing = new NotificationData();
+ TextView mOngoingTitle;
+ LinearLayout mOngoingItems;
+ // latest
+ NotificationData mLatest = new NotificationData();
+ TextView mLatestTitle;
+ LinearLayout mLatestItems;
+ // position
+ int[] mPositionTmp = new int[2];
+ boolean mExpanded;
+ boolean mExpandedVisible;
+
+ // the date view
+ DateView mDateView;
+
+ // for immersive activities
+ private View mIntruderAlertView;
+
+ // the tracker view
+ TrackingView mTrackingView;
+ WindowManager.LayoutParams mTrackingParams;
+ int mTrackingPosition; // the position of the top of the tracking view.
+ private boolean mPanelSlightlyVisible;
+
+ // ticker
+ private Ticker mTicker;
+ private View mTickerView;
+ private boolean mTicking;
+
+ // Tracking finger for opening/closing.
+ int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
+ boolean mTracking;
+ VelocityTracker mVelocityTracker;
+
+ static final int ANIM_FRAME_DURATION = (1000/60);
+
+ boolean mAnimating;
+ long mCurAnimationTime;
+ float mDisplayHeight;
+ float mAnimY;
+ float mAnimVel;
+ float mAnimAccel;
+ long mAnimLastTime;
+ boolean mAnimatingReveal = false;
+ int mViewDelta;
+ int[] mAbsPos = new int[2];
+
+ // for disabling the status bar
+ int mDisabled = 0;
+
+ private class ExpandedDialog extends Dialog {
+ ExpandedDialog(Context context) {
+ super(context, com.android.internal.R.style.Theme_Light_NoTitleBar);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_BACK:
+ if (!down) {
+ animateCollapse();
+ }
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ mDisplay = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+
+ super.onCreate();
+
+ addIntruderView();
+
+ // Lastly, call to the icon policy to install/update all the icons.
+ mIconPolicy = new StatusBarPolicy(this);
+ }
+
+ @Override
+ public void onDestroy() {
+ // we're never destroyed
+ }
+
+ // ================================================================================
+ // Constructing the view
+ // ================================================================================
+ protected View makeStatusBarView() {
+ final Context context = this;
+
+ Resources res = context.getResources();
+
+ mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+
+ ExpandedView expanded = (ExpandedView)View.inflate(context,
+ R.layout.status_bar_expanded, null);
+ expanded.mService = this;
+
+ mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null);
+ mIntruderAlertView.setVisibility(View.GONE);
+ mIntruderAlertView.setClickable(true);
+
+ StatusBarView sb = (StatusBarView)View.inflate(context, R.layout.status_bar, null);
+ sb.mService = this;
+
+ // figure out which pixel-format to use for the status bar.
+ mPixelFormat = PixelFormat.TRANSLUCENT;
+ Drawable bg = sb.getBackground();
+ if (bg != null) {
+ mPixelFormat = bg.getOpacity();
+ }
+
+ mStatusBarView = sb;
+ mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
+ mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
+ mIcons = (LinearLayout)sb.findViewById(R.id.icons);
+ mTickerView = sb.findViewById(R.id.ticker);
+ mDateView = (DateView)sb.findViewById(R.id.date);
+
+ mExpandedDialog = new ExpandedDialog(context);
+ mExpandedView = expanded;
+ mExpandedContents = expanded.findViewById(R.id.notificationLinearLayout);
+ mOngoingTitle = (TextView)expanded.findViewById(R.id.ongoingTitle);
+ mOngoingItems = (LinearLayout)expanded.findViewById(R.id.ongoingItems);
+ mLatestTitle = (TextView)expanded.findViewById(R.id.latestTitle);
+ mLatestItems = (LinearLayout)expanded.findViewById(R.id.latestItems);
+ mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
+ mClearButton = (TextView)expanded.findViewById(R.id.clear_all_button);
+ mClearButton.setOnClickListener(mClearButtonListener);
+ mScrollView = (ScrollView)expanded.findViewById(R.id.scroll);
+ mNotificationLinearLayout = expanded.findViewById(R.id.notificationLinearLayout);
+
+ mOngoingTitle.setVisibility(View.GONE);
+ mLatestTitle.setVisibility(View.GONE);
+
+ mTicker = new MyTicker(context, sb);
+
+ TickerView tickerView = (TickerView)sb.findViewById(R.id.tickerText);
+ tickerView.mTicker = mTicker;
+
+ mTrackingView = (TrackingView)View.inflate(context, R.layout.status_bar_tracking, null);
+ mTrackingView.mService = this;
+ mCloseView = (CloseDragHandle)mTrackingView.findViewById(R.id.close);
+ mCloseView.mService = this;
+
+ mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
+
+ // the more notifications icon
+ StatusBarIconView moreView = new StatusBarIconView(this, "more");
+ moreView.set(new StatusBarIcon(null, R.drawable.stat_notify_more, 0));
+ mNotificationIcons.addMoreView(moreView,
+ new LinearLayout.LayoutParams(mIconSize, mIconSize));
+
+ // set the inital view visibility
+ setAreThereNotifications();
+ mDateView.setVisibility(View.INVISIBLE);
+
+ // receive broadcasts
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ context.registerReceiver(mBroadcastReceiver, filter);
+
+ return sb;
+ }
+
+ protected int getStatusBarGravity() {
+ return Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ }
+
+ private void addIntruderView() {
+ final Resources res = getResources();
+ final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ PixelFormat.TRANSLUCENT);
+ lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ lp.y += height * 1.5; // FIXME
+ lp.setTitle("IntruderAlert");
+ lp.windowAnimations = com.android.internal.R.style.Animation_StatusBar_IntruderAlert;
+
+ WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
+ }
+
+ public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
+ if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ + " icon=" + icon);
+ StatusBarIconView view = new StatusBarIconView(this, slot);
+ view.set(icon);
+ mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ }
+
+ public void updateIcon(String slot, int index, int viewIndex,
+ StatusBarIcon old, StatusBarIcon icon) {
+ if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ + " old=" + old + " icon=" + icon);
+ StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
+ view.set(icon);
+ }
+
+ public void removeIcon(String slot, int index, int viewIndex) {
+ if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
+ mStatusIcons.removeViewAt(viewIndex);
+ }
+
+ public void addNotification(IBinder key, StatusBarNotification notification) {
+ StatusBarIconView iconView = addNotificationViews(key, notification);
+ if (iconView == null) return;
+
+ boolean immersive = false;
+ try {
+ immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
+ Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
+ } catch (RemoteException ex) {
+ }
+ if (immersive) {
+ if ((notification.notification.flags & Notification.FLAG_HIGH_PRIORITY) != 0) {
+ Slog.d(TAG, "Presenting high-priority notification in immersive activity");
+ // @@@ special new transient ticker mode
+ // 1. Populate mIntruderAlertView
+
+ ImageView alertIcon = (ImageView) mIntruderAlertView.findViewById(R.id.alertIcon);
+ TextView alertText = (TextView) mIntruderAlertView.findViewById(R.id.alertText);
+ alertIcon.setImageDrawable(StatusBarIconView.getIcon(
+ alertIcon.getContext(),
+ iconView.getStatusBarIcon()));
+ alertText.setText(notification.notification.tickerText);
+
+ View button = mIntruderAlertView.findViewById(R.id.intruder_alert_content);
+ button.setOnClickListener(
+ new Launcher(notification.notification.contentIntent,
+ notification.pkg, notification.tag, notification.id));
+
+ // 2. Animate mIntruderAlertView in
+ mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
+
+ // 3. Set alarm to age the notification off (TODO)
+ mHandler.removeMessages(MSG_HIDE_INTRUDER);
+ mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
+ }
+ } else if (notification.notification.fullScreenIntent != null) {
+ // not immersive & a full-screen alert should be shown
+ Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+ + " sending fullScreenIntent");
+ try {
+ notification.notification.fullScreenIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ }
+ } else {
+ // usual case: status bar visible & not immersive
+
+ // show the ticker
+ tick(notification);
+ }
+
+ // Recalculate the position of the sliding windows and the titles.
+ setAreThereNotifications();
+ updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+ }
+
+ public void updateNotification(IBinder key, StatusBarNotification notification) {
+ Slog.d(TAG, "updateNotification key=" + key + " notification=" + notification);
+
+ NotificationData oldList;
+ int oldIndex = mOngoing.findEntry(key);
+ if (oldIndex >= 0) {
+ oldList = mOngoing;
+ } else {
+ oldIndex = mLatest.findEntry(key);
+ if (oldIndex < 0) {
+ Slog.w(TAG, "updateNotification for unknown key: " + key);
+ return;
+ }
+ oldList = mLatest;
+ }
+ final NotificationData.Entry oldEntry = oldList.getEntryAt(oldIndex);
+ final StatusBarNotification oldNotification = oldEntry.notification;
+ final RemoteViews oldContentView = oldNotification.notification.contentView;
+
+ final RemoteViews contentView = notification.notification.contentView;
+
+ if (false) {
+ Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
+ + " ongoing=" + oldNotification.isOngoing()
+ + " expanded=" + oldEntry.expanded
+ + " contentView=" + oldContentView);
+ Slog.d(TAG, "new notification: when=" + notification.notification.when
+ + " ongoing=" + oldNotification.isOngoing()
+ + " contentView=" + contentView);
+ }
+
+ // Can we just reapply the RemoteViews in place? If when didn't change, the order
+ // didn't change.
+ if (notification.notification.when == oldNotification.notification.when
+ && notification.isOngoing() == oldNotification.isOngoing()
+ && oldEntry.expanded != null
+ && contentView != null && oldContentView != null
+ && contentView.getPackage() != null
+ && oldContentView.getPackage() != null
+ && oldContentView.getPackage().equals(contentView.getPackage())
+ && oldContentView.getLayoutId() == contentView.getLayoutId()) {
+ if (SPEW) Slog.d(TAG, "reusing notification");
+ oldEntry.notification = notification;
+ try {
+ // Reapply the RemoteViews
+ contentView.reapply(this, oldEntry.content);
+ // update the contentIntent
+ final PendingIntent contentIntent = notification.notification.contentIntent;
+ if (contentIntent != null) {
+ oldEntry.content.setOnClickListener(new Launcher(contentIntent,
+ notification.pkg, notification.tag, notification.id));
+ }
+ // Update the icon.
+ final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
+ notification.notification.icon, notification.notification.iconLevel,
+ notification.notification.number);
+ if (!oldEntry.icon.set(ic)) {
+ handleNotificationError(key, notification, "Couldn't update icon: " + ic);
+ return;
+ }
+ }
+ catch (RuntimeException e) {
+ // It failed to add cleanly. Log, and remove the view from the panel.
+ Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
+ removeNotificationViews(key);
+ addNotificationViews(key, notification);
+ }
+ } else {
+ if (SPEW) Slog.d(TAG, "not reusing notification");
+ removeNotificationViews(key);
+ addNotificationViews(key, notification);
+ }
+
+ // Restart the ticker if it's still running
+ tick(notification);
+
+ // Recalculate the position of the sliding windows and the titles.
+ setAreThereNotifications();
+ updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+ }
+
+ public void removeNotification(IBinder key) {
+ if (SPEW) Slog.d(TAG, "removeNotification key=" + key);
+ StatusBarNotification old = removeNotificationViews(key);
+
+ if (old != null) {
+ // Cancel the ticker if it's still running
+ mTicker.removeEntry(old);
+
+ // Recalculate the position of the sliding windows and the titles.
+ setAreThereNotifications();
+ updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+ }
+ }
+
+ private int chooseIconIndex(boolean isOngoing, int viewIndex) {
+ final int latestSize = mLatest.size();
+ if (isOngoing) {
+ return latestSize + (mOngoing.size() - viewIndex);
+ } else {
+ return latestSize - viewIndex;
+ }
+ }
+
+ View[] makeNotificationView(StatusBarNotification notification, ViewGroup parent) {
+ Notification n = notification.notification;
+ RemoteViews remoteViews = n.contentView;
+ if (remoteViews == null) {
+ return null;
+ }
+
+ // create the row view
+ LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
+
+ // bind the click event to the content area
+ ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
+ content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+ content.setOnFocusChangeListener(mFocusChangeListener);
+ PendingIntent contentIntent = n.contentIntent;
+ if (contentIntent != null) {
+ content.setOnClickListener(new Launcher(contentIntent, notification.pkg,
+ notification.tag, notification.id));
+ }
+
+ View expanded = null;
+ Exception exception = null;
+ try {
+ expanded = remoteViews.apply(this, content);
+ }
+ catch (RuntimeException e) {
+ exception = e;
+ }
+ if (expanded == null) {
+ String ident = notification.pkg + "/0x" + Integer.toHexString(notification.id);
+ Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
+ return null;
+ } else {
+ content.addView(expanded);
+ row.setDrawingCacheEnabled(true);
+ }
+
+ return new View[] { row, content, expanded };
+ }
+
+ StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
+ NotificationData list;
+ ViewGroup parent;
+ final boolean isOngoing = notification.isOngoing();
+ if (isOngoing) {
+ list = mOngoing;
+ parent = mOngoingItems;
+ } else {
+ list = mLatest;
+ parent = mLatestItems;
+ }
+ // Construct the expanded view.
+ final View[] views = makeNotificationView(notification, parent);
+ if (views == null) {
+ handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ + notification);
+ return null;
+ }
+ final View row = views[0];
+ final View content = views[1];
+ final View expanded = views[2];
+ // Construct the icon.
+ final StatusBarIconView iconView = new StatusBarIconView(this,
+ notification.pkg + "/0x" + Integer.toHexString(notification.id));
+ final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon,
+ notification.notification.iconLevel, notification.notification.number);
+ if (!iconView.set(ic)) {
+ handleNotificationError(key, notification, "Coulding create icon: " + ic);
+ return null;
+ }
+ // Add the expanded view.
+ final int viewIndex = list.add(key, notification, row, content, expanded, iconView);
+ parent.addView(row, viewIndex);
+ // Add the icon.
+ final int iconIndex = chooseIconIndex(isOngoing, viewIndex);
+ mNotificationIcons.addView(iconView, iconIndex,
+ new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ return iconView;
+ }
+
+ StatusBarNotification removeNotificationViews(IBinder key) {
+ NotificationData.Entry entry = mOngoing.remove(key);
+ if (entry == null) {
+ entry = mLatest.remove(key);
+ if (entry == null) {
+ Slog.w(TAG, "removeNotification for unknown key: " + key);
+ return null;
+ }
+ }
+ // Remove the expanded view.
+ ((ViewGroup)entry.row.getParent()).removeView(entry.row);
+ // Remove the icon.
+ ((ViewGroup)entry.icon.getParent()).removeView(entry.icon);
+
+ return entry.notification;
+ }
+
+ private void setAreThereNotifications() {
+ boolean ongoing = mOngoing.hasVisibleItems();
+ boolean latest = mLatest.hasVisibleItems();
+
+ // (no ongoing notifications are clearable)
+ if (mLatest.hasClearableItems()) {
+ mClearButton.setVisibility(View.VISIBLE);
+ } else {
+ mClearButton.setVisibility(View.INVISIBLE);
+ }
+
+ mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
+ mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
+
+ if (ongoing || latest) {
+ mNoNotificationsTitle.setVisibility(View.GONE);
+ } else {
+ mNoNotificationsTitle.setVisibility(View.VISIBLE);
+ }
+ }
+
+
+ /**
+ * State is one or more of the DISABLE constants from StatusBarManager.
+ */
+ public void disable(int state) {
+ final int old = mDisabled;
+ final int diff = state ^ old;
+ mDisabled = state;
+
+ if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
+ if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
+ Slog.d(TAG, "DISABLE_EXPAND: yes");
+ animateCollapse();
+ }
+ }
+ if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
+ if (mTicking) {
+ mTicker.halt();
+ } else {
+ setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
+ }
+ } else {
+ Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
+ if (!mExpandedVisible) {
+ setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
+ }
+ }
+ } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
+ if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
+ Slog.d(TAG, "DISABLE_NOTIFICATION_TICKER: yes");
+ mTicker.halt();
+ }
+ }
+ }
+
+ /**
+ * All changes to the status bar and notifications funnel through here and are batched.
+ */
+ private class H extends Handler {
+ public void handleMessage(Message m) {
+ switch (m.what) {
+ case MSG_ANIMATE:
+ doAnimation();
+ break;
+ case MSG_ANIMATE_REVEAL:
+ doRevealAnimation();
+ break;
+ case MSG_SHOW_INTRUDER:
+ setIntruderAlertVisibility(true);
+ break;
+ case MSG_HIDE_INTRUDER:
+ setIntruderAlertVisibility(false);
+ break;
+ }
+ }
+ }
+
+ View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
+ public void onFocusChange(View v, boolean hasFocus) {
+ // Because 'v' is a ViewGroup, all its children will be (un)selected
+ // too, which allows marqueeing to work.
+ v.setSelected(hasFocus);
+ }
+ };
+
+ private void makeExpandedVisible() {
+ if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
+ if (mExpandedVisible) {
+ return;
+ }
+ mExpandedVisible = true;
+ visibilityChanged(true);
+
+ updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
+ mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+ mExpandedView.requestFocus(View.FOCUS_FORWARD);
+ mTrackingView.setVisibility(View.VISIBLE);
+
+ if (!mTicking) {
+ setDateViewVisibility(true, com.android.internal.R.anim.fade_in);
+ }
+ }
+
+ public void animateExpand() {
+ if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
+ if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+ return ;
+ }
+ if (mExpanded) {
+ return;
+ }
+
+ prepareTracking(0, true);
+ performFling(0, 2000.0f, true);
+ }
+
+ public void animateCollapse() {
+ if (SPEW) {
+ Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+ + " mExpandedVisible=" + mExpandedVisible
+ + " mExpanded=" + mExpanded
+ + " mAnimating=" + mAnimating
+ + " mAnimY=" + mAnimY
+ + " mAnimVel=" + mAnimVel);
+ }
+
+ if (!mExpandedVisible) {
+ return;
+ }
+
+ int y;
+ if (mAnimating) {
+ y = (int)mAnimY;
+ } else {
+ y = mDisplay.getHeight()-1;
+ }
+ // Let the fling think that we're open so it goes in the right direction
+ // and doesn't try to re-open the windowshade.
+ mExpanded = true;
+ prepareTracking(y, false);
+ performFling(y, -2000.0f, true);
+ }
+
+ void performExpand() {
+ if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
+ if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+ return ;
+ }
+ if (mExpanded) {
+ return;
+ }
+
+ mExpanded = true;
+ makeExpandedVisible();
+ updateExpandedViewPos(EXPANDED_FULL_OPEN);
+
+ if (false) postStartTracing();
+ }
+
+ void performCollapse() {
+ if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
+ + " mExpandedVisible=" + mExpandedVisible);
+
+ if (!mExpandedVisible) {
+ return;
+ }
+ mExpandedVisible = false;
+ visibilityChanged(false);
+ mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+ mTrackingView.setVisibility(View.GONE);
+
+ if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
+ setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
+ }
+ setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
+
+ if (!mExpanded) {
+ return;
+ }
+ mExpanded = false;
+ }
+
+ void doAnimation() {
+ if (mAnimating) {
+ if (SPEW) Slog.d(TAG, "doAnimation");
+ if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
+ incrementAnim();
+ if (SPEW) Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
+ if (mAnimY >= mDisplay.getHeight()-1) {
+ if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
+ mAnimating = false;
+ updateExpandedViewPos(EXPANDED_FULL_OPEN);
+ performExpand();
+ }
+ else if (mAnimY < mStatusBarView.getHeight()) {
+ if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
+ mAnimating = false;
+ updateExpandedViewPos(0);
+ performCollapse();
+ }
+ else {
+ updateExpandedViewPos((int)mAnimY);
+ mCurAnimationTime += ANIM_FRAME_DURATION;
+ mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurAnimationTime);
+ }
+ }
+ }
+
+ void stopTracking() {
+ mTracking = false;
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ void incrementAnim() {
+ long now = SystemClock.uptimeMillis();
+ float t = ((float)(now - mAnimLastTime)) / 1000; // ms -> s
+ final float y = mAnimY;
+ final float v = mAnimVel; // px/s
+ final float a = mAnimAccel; // px/s/s
+ mAnimY = y + (v*t) + (0.5f*a*t*t); // px
+ mAnimVel = v + (a*t); // px/s
+ mAnimLastTime = now; // ms
+ //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
+ // + " mAnimAccel=" + mAnimAccel);
+ }
+
+ void doRevealAnimation() {
+ final int h = mCloseView.getHeight() + mStatusBarView.getHeight();
+ if (mAnimatingReveal && mAnimating && mAnimY < h) {
+ incrementAnim();
+ if (mAnimY >= h) {
+ mAnimY = h;
+ updateExpandedViewPos((int)mAnimY);
+ } else {
+ updateExpandedViewPos((int)mAnimY);
+ mCurAnimationTime += ANIM_FRAME_DURATION;
+ mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE_REVEAL),
+ mCurAnimationTime);
+ }
+ }
+ }
+
+ void prepareTracking(int y, boolean opening) {
+ mTracking = true;
+ mVelocityTracker = VelocityTracker.obtain();
+ if (opening) {
+ mAnimAccel = 2000.0f;
+ mAnimVel = 200;
+ mAnimY = mStatusBarView.getHeight();
+ updateExpandedViewPos((int)mAnimY);
+ mAnimating = true;
+ mAnimatingReveal = true;
+ mHandler.removeMessages(MSG_ANIMATE);
+ mHandler.removeMessages(MSG_ANIMATE_REVEAL);
+ long now = SystemClock.uptimeMillis();
+ mAnimLastTime = now;
+ mCurAnimationTime = now + ANIM_FRAME_DURATION;
+ mAnimating = true;
+ mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE_REVEAL),
+ mCurAnimationTime);
+ makeExpandedVisible();
+ } else {
+ // it's open, close it?
+ if (mAnimating) {
+ mAnimating = false;
+ mHandler.removeMessages(MSG_ANIMATE);
+ }
+ updateExpandedViewPos(y + mViewDelta);
+ }
+ }
+
+ void performFling(int y, float vel, boolean always) {
+ mAnimatingReveal = false;
+ mDisplayHeight = mDisplay.getHeight();
+
+ mAnimY = y;
+ mAnimVel = vel;
+
+ //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
+
+ if (mExpanded) {
+ if (!always && (
+ vel > 200.0f
+ || (y > (mDisplayHeight-25) && vel > -200.0f))) {
+ // We are expanded, but they didn't move sufficiently to cause
+ // us to retract. Animate back to the expanded position.
+ mAnimAccel = 2000.0f;
+ if (vel < 0) {
+ mAnimVel = 0;
+ }
+ }
+ else {
+ // We are expanded and are now going to animate away.
+ mAnimAccel = -2000.0f;
+ if (vel > 0) {
+ mAnimVel = 0;
+ }
+ }
+ } else {
+ if (always || (
+ vel > 200.0f
+ || (y > (mDisplayHeight/2) && vel > -200.0f))) {
+ // We are collapsed, and they moved enough to allow us to
+ // expand. Animate in the notifications.
+ mAnimAccel = 2000.0f;
+ if (vel < 0) {
+ mAnimVel = 0;
+ }
+ }
+ else {
+ // We are collapsed, but they didn't move sufficiently to cause
+ // us to retract. Animate back to the collapsed position.
+ mAnimAccel = -2000.0f;
+ if (vel > 0) {
+ mAnimVel = 0;
+ }
+ }
+ }
+ //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
+ // + " mAnimAccel=" + mAnimAccel);
+
+ long now = SystemClock.uptimeMillis();
+ mAnimLastTime = now;
+ mCurAnimationTime = now + ANIM_FRAME_DURATION;
+ mAnimating = true;
+ mHandler.removeMessages(MSG_ANIMATE);
+ mHandler.removeMessages(MSG_ANIMATE_REVEAL);
+ mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurAnimationTime);
+ stopTracking();
+ }
+
+ boolean interceptTouchEvent(MotionEvent event) {
+ if (SPEW) {
+ Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
+ + mDisabled);
+ }
+
+ if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+ return false;
+ }
+
+ final int statusBarSize = mStatusBarView.getHeight();
+ final int hitSize = statusBarSize*2;
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ final int y = (int)event.getRawY();
+
+ if (!mExpanded) {
+ mViewDelta = statusBarSize - y;
+ } else {
+ mTrackingView.getLocationOnScreen(mAbsPos);
+ mViewDelta = mAbsPos[1] + mTrackingView.getHeight() - y;
+ }
+ if ((!mExpanded && y < hitSize) ||
+ (mExpanded && y > (mDisplay.getHeight()-hitSize))) {
+
+ // We drop events at the edge of the screen to make the windowshade come
+ // down by accident less, especially when pushing open a device with a keyboard
+ // that rotates (like g1 and droid)
+ int x = (int)event.getRawX();
+ final int edgeBorder = mEdgeBorder;
+ if (x >= edgeBorder && x < mDisplay.getWidth() - edgeBorder) {
+ prepareTracking(y, !mExpanded);// opening if we're not already fully visible
+ mVelocityTracker.addMovement(event);
+ }
+ }
+ } else if (mTracking) {
+ mVelocityTracker.addMovement(event);
+ final int minY = statusBarSize + mCloseView.getHeight();
+ if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ int y = (int)event.getRawY();
+ if (mAnimatingReveal && y < minY) {
+ // nothing
+ } else {
+ mAnimatingReveal = false;
+ updateExpandedViewPos(y + mViewDelta);
+ }
+ } else if (event.getAction() == MotionEvent.ACTION_UP) {
+ mVelocityTracker.computeCurrentVelocity(1000);
+
+ float yVel = mVelocityTracker.getYVelocity();
+ boolean negative = yVel < 0;
+
+ float xVel = mVelocityTracker.getXVelocity();
+ if (xVel < 0) {
+ xVel = -xVel;
+ }
+ if (xVel > 150.0f) {
+ xVel = 150.0f; // limit how much we care about the x axis
+ }
+
+ float vel = (float)Math.hypot(yVel, xVel);
+ if (negative) {
+ vel = -vel;
+ }
+
+ performFling((int)event.getRawY(), vel, false);
+ }
+
+ }
+ return false;
+ }
+
+ private class Launcher implements View.OnClickListener {
+ private PendingIntent mIntent;
+ private String mPkg;
+ private String mTag;
+ private int mId;
+
+ Launcher(PendingIntent intent, String pkg, String tag, int id) {
+ mIntent = intent;
+ mPkg = pkg;
+ mTag = tag;
+ mId = id;
+ }
+
+ public void onClick(View v) {
+ try {
+ // The intent we are sending is for the application, which
+ // won't have permission to immediately start an activity after
+ // the user switches to home. We know it is safe to do at this
+ // point, so make sure new activity switches are now allowed.
+ ActivityManagerNative.getDefault().resumeAppSwitches();
+ } catch (RemoteException e) {
+ }
+
+ if (mIntent != null) {
+ int[] pos = new int[2];
+ v.getLocationOnScreen(pos);
+ Intent overlay = new Intent();
+ overlay.setSourceBounds(
+ new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
+ try {
+ mIntent.send(PhoneStatusBarService.this, 0, overlay);
+ } catch (PendingIntent.CanceledException e) {
+ // the stack trace isn't very helpful here. Just log the exception message.
+ Slog.w(TAG, "Sending contentIntent failed: " + e);
+ }
+ }
+
+ try {
+ mBarService.onNotificationClick(mPkg, mTag, mId);
+ } catch (RemoteException ex) {
+ // system process is dead if we're here.
+ }
+
+ // close the shade if it was open
+ animateCollapse();
+
+ // If this click was on the intruder alert, hide that instead
+ mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
+ }
+ }
+
+ private void tick(StatusBarNotification n) {
+ // Show the ticker if one is requested. Also don't do this
+ // until status bar window is attached to the window manager,
+ // because... well, what's the point otherwise? And trying to
+ // run a ticker without being attached will crash!
+ if (n.notification.tickerText != null && mStatusBarView.getWindowToken() != null) {
+ if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
+ | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
+ mTicker.addEntry(n);
+ }
+ }
+ }
+
+ /**
+ * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
+ * about the failure.
+ *
+ * WARNING: this will call back into us. Don't hold any locks.
+ */
+ void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
+ removeNotification(key);
+ try {
+ mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
+ } catch (RemoteException ex) {
+ // The end is nigh.
+ }
+ }
+
+ private class MyTicker extends Ticker {
+ MyTicker(Context context, StatusBarView sb) {
+ super(context, sb);
+ }
+
+ @Override
+ void tickerStarting() {
+ mTicking = true;
+ mIcons.setVisibility(View.GONE);
+ mTickerView.setVisibility(View.VISIBLE);
+ mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_up_in, null));
+ mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null));
+ if (mExpandedVisible) {
+ setDateViewVisibility(false, com.android.internal.R.anim.push_up_out);
+ }
+ }
+
+ @Override
+ void tickerDone() {
+ mIcons.setVisibility(View.VISIBLE);
+ mTickerView.setVisibility(View.GONE);
+ mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null));
+ mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_down_out,
+ mTickingDoneListener));
+ if (mExpandedVisible) {
+ setDateViewVisibility(true, com.android.internal.R.anim.push_down_in);
+ }
+ }
+
+ void tickerHalting() {
+ mIcons.setVisibility(View.VISIBLE);
+ mTickerView.setVisibility(View.GONE);
+ mIcons.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
+ mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.fade_out,
+ mTickingDoneListener));
+ if (mExpandedVisible) {
+ setDateViewVisibility(true, com.android.internal.R.anim.fade_in);
+ }
+ }
+ }
+
+ Animation.AnimationListener mTickingDoneListener = new Animation.AnimationListener() {;
+ public void onAnimationEnd(Animation animation) {
+ mTicking = false;
+ }
+ public void onAnimationRepeat(Animation animation) {
+ }
+ public void onAnimationStart(Animation animation) {
+ }
+ };
+
+ private Animation loadAnim(int id, Animation.AnimationListener listener) {
+ Animation anim = AnimationUtils.loadAnimation(PhoneStatusBarService.this, id);
+ if (listener != null) {
+ anim.setAnimationListener(listener);
+ }
+ return anim;
+ }
+
+ public String viewInfo(View v) {
+ return "(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
+ + " " + v.getWidth() + "x" + v.getHeight() + ")";
+ }
+
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump StatusBar from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (mQueueLock) {
+ pw.println("Current Status Bar state:");
+ pw.println(" mExpanded=" + mExpanded
+ + ", mExpandedVisible=" + mExpandedVisible);
+ pw.println(" mTicking=" + mTicking);
+ pw.println(" mTracking=" + mTracking);
+ pw.println(" mAnimating=" + mAnimating
+ + ", mAnimY=" + mAnimY + ", mAnimVel=" + mAnimVel
+ + ", mAnimAccel=" + mAnimAccel);
+ pw.println(" mCurAnimationTime=" + mCurAnimationTime
+ + " mAnimLastTime=" + mAnimLastTime);
+ pw.println(" mDisplayHeight=" + mDisplayHeight
+ + " mAnimatingReveal=" + mAnimatingReveal
+ + " mViewDelta=" + mViewDelta);
+ pw.println(" mDisplayHeight=" + mDisplayHeight);
+ pw.println(" mExpandedParams: " + mExpandedParams);
+ pw.println(" mExpandedView: " + viewInfo(mExpandedView));
+ pw.println(" mExpandedDialog: " + mExpandedDialog);
+ pw.println(" mTrackingParams: " + mTrackingParams);
+ pw.println(" mTrackingView: " + viewInfo(mTrackingView));
+ pw.println(" mOngoingTitle: " + viewInfo(mOngoingTitle));
+ pw.println(" mOngoingItems: " + viewInfo(mOngoingItems));
+ pw.println(" mLatestTitle: " + viewInfo(mLatestTitle));
+ pw.println(" mLatestItems: " + viewInfo(mLatestItems));
+ pw.println(" mNoNotificationsTitle: " + viewInfo(mNoNotificationsTitle));
+ pw.println(" mCloseView: " + viewInfo(mCloseView));
+ pw.println(" mTickerView: " + viewInfo(mTickerView));
+ pw.println(" mScrollView: " + viewInfo(mScrollView)
+ + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
+ pw.println("mNotificationLinearLayout: " + viewInfo(mNotificationLinearLayout));
+ }
+ /*
+ synchronized (mNotificationData) {
+ int N = mNotificationData.ongoingCount();
+ pw.println(" ongoingCount.size=" + N);
+ for (int i=0; i<N; i++) {
+ StatusBarNotification n = mNotificationData.getOngoing(i);
+ pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
+ pw.println(" data=" + n.data);
+ }
+ N = mNotificationData.latestCount();
+ pw.println(" ongoingCount.size=" + N);
+ for (int i=0; i<N; i++) {
+ StatusBarNotification n = mNotificationData.getLatest(i);
+ pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
+ pw.println(" data=" + n.data);
+ }
+ }
+ */
+
+ if (false) {
+ pw.println("see the logcat for a dump of the views we have created.");
+ // must happen on ui thread
+ mHandler.post(new Runnable() {
+ public void run() {
+ mStatusBarView.getLocationOnScreen(mAbsPos);
+ Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
+ + ") " + mStatusBarView.getWidth() + "x"
+ + mStatusBarView.getHeight());
+ mStatusBarView.debug();
+
+ mExpandedView.getLocationOnScreen(mAbsPos);
+ Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
+ + ") " + mExpandedView.getWidth() + "x"
+ + mExpandedView.getHeight());
+ mExpandedView.debug();
+
+ mTrackingView.getLocationOnScreen(mAbsPos);
+ Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
+ + ") " + mTrackingView.getWidth() + "x"
+ + mTrackingView.getHeight());
+ mTrackingView.debug();
+ }
+ });
+ }
+ }
+
+ void onBarViewAttached() {
+ WindowManager.LayoutParams lp;
+ int pixelFormat;
+ Drawable bg;
+
+ /// ---------- Tracking View --------------
+ pixelFormat = PixelFormat.RGBX_8888;
+ bg = mTrackingView.getBackground();
+ if (bg != null) {
+ pixelFormat = bg.getOpacity();
+ }
+
+ lp = new WindowManager.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ pixelFormat);
+// lp.token = mStatusBarView.getWindowToken();
+ lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ lp.setTitle("TrackingView");
+ lp.y = mTrackingPosition;
+ mTrackingParams = lp;
+
+ WindowManagerImpl.getDefault().addView(mTrackingView, lp);
+ }
+
+ void onTrackingViewAttached() {
+ WindowManager.LayoutParams lp;
+ int pixelFormat;
+ Drawable bg;
+
+ /// ---------- Expanded View --------------
+ pixelFormat = PixelFormat.TRANSLUCENT;
+
+ final int disph = mDisplay.getHeight();
+ lp = mExpandedDialog.getWindow().getAttributes();
+ lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ lp.height = getExpandedHeight();
+ lp.x = 0;
+ mTrackingPosition = lp.y = -disph; // sufficiently large negative
+ lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+ lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_DITHER
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ lp.format = pixelFormat;
+ lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ lp.setTitle("StatusBarExpanded");
+ mExpandedDialog.getWindow().setAttributes(lp);
+ mExpandedDialog.getWindow().setFormat(pixelFormat);
+ mExpandedParams = lp;
+
+ mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+ mExpandedDialog.setContentView(mExpandedView,
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ mExpandedDialog.getWindow().setBackgroundDrawable(null);
+ mExpandedDialog.show();
+ FrameLayout hack = (FrameLayout)mExpandedView.getParent();
+ }
+
+ void setDateViewVisibility(boolean visible, int anim) {
+ mDateView.setUpdates(visible);
+ mDateView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ mDateView.startAnimation(loadAnim(anim, null));
+ }
+
+ void setNotificationIconVisibility(boolean visible, int anim) {
+ int old = mNotificationIcons.getVisibility();
+ int v = visible ? View.VISIBLE : View.INVISIBLE;
+ if (old != v) {
+ mNotificationIcons.setVisibility(v);
+ mNotificationIcons.startAnimation(loadAnim(anim, null));
+ }
+ }
+
+ void updateExpandedViewPos(int expandedPosition) {
+ if (SPEW) {
+ Slog.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
+ + " mTrackingParams.y=" + mTrackingParams.y
+ + " mTrackingPosition=" + mTrackingPosition);
+ }
+
+ int h = mStatusBarView.getHeight();
+ int disph = mDisplay.getHeight();
+
+ // If the expanded view is not visible, make sure they're still off screen.
+ // Maybe the view was resized.
+ if (!mExpandedVisible) {
+ if (mTrackingView != null) {
+ mTrackingPosition = -disph;
+ if (mTrackingParams != null) {
+ mTrackingParams.y = mTrackingPosition;
+ WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
+ }
+ }
+ if (mExpandedParams != null) {
+ mExpandedParams.y = -disph;
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+ }
+ return;
+ }
+
+ // tracking view...
+ int pos;
+ if (expandedPosition == EXPANDED_FULL_OPEN) {
+ pos = h;
+ }
+ else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
+ pos = mTrackingPosition;
+ }
+ else {
+ if (expandedPosition <= disph) {
+ pos = expandedPosition;
+ } else {
+ pos = disph;
+ }
+ pos -= disph-h;
+ }
+ mTrackingPosition = mTrackingParams.y = pos;
+ mTrackingParams.height = disph-h;
+ WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
+
+ if (mExpandedParams != null) {
+ mCloseView.getLocationInWindow(mPositionTmp);
+ final int closePos = mPositionTmp[1];
+
+ mExpandedContents.getLocationInWindow(mPositionTmp);
+ final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
+
+ mExpandedParams.y = pos + mTrackingView.getHeight()
+ - (mTrackingParams.height-closePos) - contentsBottom;
+ int max = h;
+ if (mExpandedParams.y > max) {
+ mExpandedParams.y = max;
+ }
+ int min = mTrackingPosition;
+ if (mExpandedParams.y < min) {
+ mExpandedParams.y = min;
+ }
+
+ boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
+ if (!visible) {
+ // if the contents aren't visible, move the expanded view way off screen
+ // because the window itself extends below the content view.
+ mExpandedParams.y = -disph;
+ }
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+
+ // As long as this isn't just a repositioning that's not supposed to affect
+ // the user's perception of what's showing, call to say that the visibility
+ // has changed. (Otherwise, someone else will call to do that).
+ if (expandedPosition != EXPANDED_LEAVE_ALONE) {
+ if (SPEW) Slog.d(TAG, "updateExpandedViewPos visibilityChanged(" + visible + ")");
+ visibilityChanged(visible);
+ }
+ }
+
+ if (SPEW) {
+ Slog.d(TAG, "updateExpandedViewPos after expandedPosition=" + expandedPosition
+ + " mTrackingParams.y=" + mTrackingParams.y
+ + " mTrackingPosition=" + mTrackingPosition
+ + " mExpandedParams.y=" + mExpandedParams.y
+ + " mExpandedParams.height=" + mExpandedParams.height);
+ }
+ }
+
+ int getExpandedHeight() {
+ return mDisplay.getHeight() - mStatusBarView.getHeight() - mCloseView.getHeight();
+ }
+
+ void updateExpandedHeight() {
+ if (mExpandedView != null) {
+ mExpandedParams.height = getExpandedHeight();
+ mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+ }
+ }
+
+ /**
+ * The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
+ * This was added last-minute and is inconsistent with the way the rest of the notifications
+ * are handled, because the notification isn't really cancelled. The lights are just
+ * turned off. If any other notifications happen, the lights will turn back on. Steve says
+ * this is what he wants. (see bug 1131461)
+ */
+ void visibilityChanged(boolean visible) {
+ if (mPanelSlightlyVisible != visible) {
+ mPanelSlightlyVisible = visible;
+ try {
+ mBarService.onPanelRevealed();
+ } catch (RemoteException ex) {
+ // Won't fail unless the world has ended.
+ }
+ }
+ }
+
+ void performDisableActions(int net) {
+ int old = mDisabled;
+ int diff = net ^ old;
+ mDisabled = net;
+
+ // act accordingly
+ if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
+ if ((net & StatusBarManager.DISABLE_EXPAND) != 0) {
+ Slog.d(TAG, "DISABLE_EXPAND: yes");
+ animateCollapse();
+ }
+ }
+ if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ if ((net & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
+ if (mTicking) {
+ mNotificationIcons.setVisibility(View.INVISIBLE);
+ mTicker.halt();
+ } else {
+ setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
+ }
+ } else {
+ Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
+ if (!mExpandedVisible) {
+ setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
+ }
+ }
+ } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
+ if (mTicking && (net & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
+ mTicker.halt();
+ }
+ }
+ }
+
+ private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ try {
+ mBarService.onClearAllNotifications();
+ } catch (RemoteException ex) {
+ // system process is dead if we're here.
+ }
+ animateCollapse();
+ }
+ };
+
+ private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
+ || Intent.ACTION_SCREEN_OFF.equals(action)) {
+ //collapse();
+ }
+ else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+ updateResources();
+ }
+ }
+ };
+
+ private void setIntruderAlertVisibility(boolean vis) {
+ mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Reload some of our resources when the configuration changes.
+ *
+ * We don't reload everything when the configuration changes -- we probably
+ * should, but getting that smooth is tough. Someday we'll fix that. In the
+ * meantime, just update the things that we know change.
+ */
+ void updateResources() {
+ Resources res = getResources();
+
+ mClearButton.setText(getText(R.string.status_bar_clear_all_button));
+ mOngoingTitle.setText(getText(R.string.status_bar_ongoing_events_title));
+ mLatestTitle.setText(getText(R.string.status_bar_latest_events_title));
+ mNoNotificationsTitle.setText(getText(R.string.status_bar_no_notifications_title));
+
+ mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
+
+ if (false) Slog.v(TAG, "updateResources");
+ }
+
+ //
+ // tracing
+ //
+
+ void postStartTracing() {
+ mHandler.postDelayed(mStartTracing, 3000);
+ }
+
+ void vibrate() {
+ android.os.Vibrator vib = (android.os.Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
+ vib.vibrate(250);
+ }
+
+ Runnable mStartTracing = new Runnable() {
+ public void run() {
+ vibrate();
+ SystemClock.sleep(250);
+ Slog.d(TAG, "startTracing");
+ android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
+ mHandler.postDelayed(mStopTracing, 10000);
+ }
+ };
+
+ Runnable mStopTracing = new Runnable() {
+ public void run() {
+ android.os.Debug.stopMethodTracing();
+ Slog.d(TAG, "stopTracing");
+ vibrate();
+ }
+ };
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index 0d02447..a64c3e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -17,194 +17,53 @@
package com.android.systemui.statusbar;
import android.app.Service;
-import com.android.internal.statusbar.IStatusBar;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.statusbar.StatusBarIconList;
-import com.android.internal.statusbar.StatusBarNotification;
-
-import android.app.ActivityManagerNative;
-import android.app.Dialog;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.app.StatusBarManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.Message;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.util.Slog;
import android.util.Log;
-import android.view.Display;
import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
-import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RemoteViews;
-import android.widget.ScrollView;
-import android.widget.TextView;
-import android.widget.FrameLayout;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Set;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.StatusBarPolicy;
+import com.android.internal.statusbar.IStatusBar;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
+import com.android.systemui.R;
-public class StatusBarService extends Service implements CommandQueue.Callbacks {
+public abstract class StatusBarService extends Service implements CommandQueue.Callbacks {
static final String TAG = "StatusBarService";
- static final boolean SPEW = false;
-
- public static final String ACTION_STATUSBAR_START
- = "com.android.internal.policy.statusbar.START";
-
- static final int EXPANDED_LEAVE_ALONE = -10000;
- static final int EXPANDED_FULL_OPEN = -10001;
-
- private static final int MSG_ANIMATE = 1000;
- private static final int MSG_ANIMATE_REVEAL = 1001;
- private static final int MSG_SHOW_INTRUDER = 1002;
- private static final int MSG_HIDE_INTRUDER = 1003;
-
- // will likely move to a resource or other tunable param at some point
- private static final int INTRUDER_ALERT_DECAY_MS = 10000;
-
- static final int POSITION_TOP = 0;
- static final int POSITION_BOTTOM = 1;
-
- StatusBarPolicy mIconPolicy;
-
- CommandQueue mCommandQueue;
- IStatusBarService mBarService;
-
- int mIconSize;
- Display mDisplay;
- int mPosition;
-
- StatusBarView mStatusBarView;
- int mPixelFormat;
- H mHandler = new H();
- Object mQueueLock = new Object();
-
- // icons
- LinearLayout mIcons;
- IconMerger mNotificationIcons;
- LinearLayout mStatusIcons;
-
- // expanded notifications
- Dialog mExpandedDialog;
- ExpandedView mExpandedView;
- WindowManager.LayoutParams mExpandedParams;
- ScrollView mScrollView;
- View mNotificationLinearLayout;
- View mExpandedContents;
- // top bar
- TextView mNoNotificationsTitle;
- TextView mClearButton;
- // drag bar
- CloseDragHandle mCloseView;
- // ongoing
- NotificationData mOngoing = new NotificationData();
- TextView mOngoingTitle;
- LinearLayout mOngoingItems;
- // latest
- NotificationData mLatest = new NotificationData();
- TextView mLatestTitle;
- LinearLayout mLatestItems;
- // position
- int[] mPositionTmp = new int[2];
- boolean mExpanded;
- boolean mExpandedVisible;
- // the date view
- DateView mDateView;
+ protected CommandQueue mCommandQueue;
+ protected IStatusBarService mBarService;
- // the tracker view
- TrackingView mTrackingView;
- WindowManager.LayoutParams mTrackingParams;
- int mTrackingPosition; // the position of the top of the tracking view.
- private boolean mPanelSlightlyVisible;
+ // Up-call methods
+ protected abstract View makeStatusBarView();
+ protected abstract int getStatusBarGravity();
- // ticker
- private Ticker mTicker;
- private View mTickerView;
- private boolean mTicking;
-
- // Tracking finger for opening/closing.
- int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
- boolean mTracking;
- VelocityTracker mVelocityTracker;
-
- static final int ANIM_FRAME_DURATION = (1000/60);
-
- boolean mAnimating;
- long mCurAnimationTime;
- float mDisplayHeight;
- float mAnimY;
- float mAnimVel;
- float mAnimAccel;
- long mAnimLastTime;
- boolean mAnimatingReveal = false;
- int mViewDelta;
- int[] mAbsPos = new int[2];
-
- // for disabling the status bar
- int mDisabled = 0;
-
- private class ExpandedDialog extends Dialog {
- ExpandedDialog(Context context) {
- super(context, com.android.internal.R.style.Theme_Light_NoTitleBar);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
- switch (event.getKeyCode()) {
- case KeyEvent.KEYCODE_BACK:
- if (!down) {
- animateCollapse();
- }
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
+ /**
+ * Nobody binds to us.
+ */
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
}
@Override
public void onCreate() {
// First set up our views and stuff.
- final Resources res = getResources();
- mPosition = res.getInteger(R.integer.config_status_bar_position);
- mDisplay = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- makeStatusBarView(this);
+ View sb = makeStatusBarView();
// Connect in to the status bar manager service
StatusBarIconList iconList = new StatusBarIconList();
@@ -242,1379 +101,22 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
}
// Put up the view
- addStatusBarView();
-
- // Lastly, call to the icon policy to install/update all the icons.
- mIconPolicy = new StatusBarPolicy(this);
- }
-
- @Override
- public void onDestroy() {
- // we're never destroyed
- }
-
- // for immersive activities
- private View mIntruderAlertView;
-
- /**
- * Nobody binds to us.
- */
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- // ================================================================================
- // Constructing the view
- // ================================================================================
- private void makeStatusBarView(Context context) {
- Resources res = context.getResources();
-
- mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
-
- ExpandedView expanded = (ExpandedView)View.inflate(context,
- R.layout.status_bar_expanded, null);
- expanded.mService = this;
-
- mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null);
- mIntruderAlertView.setVisibility(View.GONE);
- mIntruderAlertView.setClickable(true);
-
- StatusBarView sb = (StatusBarView)View.inflate(context, R.layout.status_bar, null);
- sb.mService = this;
-
- // figure out which pixel-format to use for the status bar.
- mPixelFormat = PixelFormat.TRANSLUCENT;
- Drawable bg = sb.getBackground();
- if (bg != null) {
- mPixelFormat = bg.getOpacity();
- }
-
- mStatusBarView = sb;
- mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
- mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
- mIcons = (LinearLayout)sb.findViewById(R.id.icons);
- mTickerView = sb.findViewById(R.id.ticker);
- mDateView = (DateView)sb.findViewById(R.id.date);
-
- mExpandedDialog = new ExpandedDialog(context);
- mExpandedView = expanded;
- mExpandedContents = expanded.findViewById(R.id.notificationLinearLayout);
- mOngoingTitle = (TextView)expanded.findViewById(R.id.ongoingTitle);
- mOngoingItems = (LinearLayout)expanded.findViewById(R.id.ongoingItems);
- mLatestTitle = (TextView)expanded.findViewById(R.id.latestTitle);
- mLatestItems = (LinearLayout)expanded.findViewById(R.id.latestItems);
- mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
- mClearButton = (TextView)expanded.findViewById(R.id.clear_all_button);
- mClearButton.setOnClickListener(mClearButtonListener);
- mScrollView = (ScrollView)expanded.findViewById(R.id.scroll);
- mNotificationLinearLayout = expanded.findViewById(R.id.notificationLinearLayout);
-
- mOngoingTitle.setVisibility(View.GONE);
- mLatestTitle.setVisibility(View.GONE);
-
- mTicker = new MyTicker(context, sb);
-
- TickerView tickerView = (TickerView)sb.findViewById(R.id.tickerText);
- tickerView.mTicker = mTicker;
-
- mTrackingView = (TrackingView)View.inflate(context, R.layout.status_bar_tracking, null);
- mTrackingView.mService = this;
- mCloseView = (CloseDragHandle)mTrackingView.findViewById(R.id.close);
- mCloseView.mService = this;
-
- mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
-
- // the more notifications icon
- StatusBarIconView moreView = new StatusBarIconView(this, "more");
- moreView.set(new StatusBarIcon(null, R.drawable.stat_notify_more, 0));
- mNotificationIcons.addMoreView(moreView,
- new LinearLayout.LayoutParams(mIconSize, mIconSize));
-
- // set the inital view visibility
- setAreThereNotifications();
- mDateView.setVisibility(View.INVISIBLE);
-
- // receive broadcasts
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- context.registerReceiver(mBroadcastReceiver, filter);
- }
-
- protected void addStatusBarView() {
- Resources res = getResources();
+ final Resources res = getResources();
final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- final StatusBarView view = mStatusBarView;
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
height,
WindowManager.LayoutParams.TYPE_STATUS_BAR,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING,
PixelFormat.RGBX_8888);
- if (mPosition == POSITION_TOP) {
- lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
- } else {
- lp.gravity = Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
- }
+ lp.gravity = getStatusBarGravity();
lp.setTitle("StatusBar");
// TODO lp.windowAnimations = R.style.Animation_StatusBar;
+ WindowManagerImpl.getDefault().addView(sb, lp);
- WindowManagerImpl.getDefault().addView(view, lp);
-
- lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- PixelFormat.TRANSLUCENT);
- if (mPosition == POSITION_TOP) {
- lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
- } else {
- lp.gravity = Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
- }
- lp.y += height * 1.5; // FIXME
- lp.setTitle("IntruderAlert");
- lp.windowAnimations = com.android.internal.R.style.Animation_StatusBar_IntruderAlert;
-
- WindowManagerImpl.getDefault().addView(mIntruderAlertView, lp);
- }
-
- public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
- + " icon=" + icon);
- StatusBarIconView view = new StatusBarIconView(this, slot);
- view.set(icon);
- mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
+ Slog.d(TAG, "Added status bar view w/ gravity 0x" + Integer.toHexString(lp.gravity));
}
-
- public void updateIcon(String slot, int index, int viewIndex,
- StatusBarIcon old, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
- + " old=" + old + " icon=" + icon);
- StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
- view.set(icon);
- }
-
- public void removeIcon(String slot, int index, int viewIndex) {
- if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
- mStatusIcons.removeViewAt(viewIndex);
- }
-
- public void addNotification(IBinder key, StatusBarNotification notification) {
- StatusBarIconView iconView = addNotificationViews(key, notification);
- if (iconView == null) return;
-
- boolean immersive = false;
- try {
- immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
- Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
- } catch (RemoteException ex) {
- }
- if (immersive) {
- if ((notification.notification.flags & Notification.FLAG_HIGH_PRIORITY) != 0) {
- Slog.d(TAG, "Presenting high-priority notification in immersive activity");
- // @@@ special new transient ticker mode
- // 1. Populate mIntruderAlertView
-
- ImageView alertIcon = (ImageView) mIntruderAlertView.findViewById(R.id.alertIcon);
- TextView alertText = (TextView) mIntruderAlertView.findViewById(R.id.alertText);
- alertIcon.setImageDrawable(StatusBarIconView.getIcon(
- alertIcon.getContext(),
- iconView.getStatusBarIcon()));
- alertText.setText(notification.notification.tickerText);
-
- View button = mIntruderAlertView.findViewById(R.id.intruder_alert_content);
- button.setOnClickListener(
- new Launcher(notification.notification.contentIntent,
- notification.pkg, notification.tag, notification.id));
-
- // 2. Animate mIntruderAlertView in
- mHandler.sendEmptyMessage(MSG_SHOW_INTRUDER);
-
- // 3. Set alarm to age the notification off (TODO)
- mHandler.removeMessages(MSG_HIDE_INTRUDER);
- mHandler.sendEmptyMessageDelayed(MSG_HIDE_INTRUDER, INTRUDER_ALERT_DECAY_MS);
- }
- } else if (notification.notification.fullScreenIntent != null) {
- // not immersive & a full-screen alert should be shown
- Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
- + " sending fullScreenIntent");
- try {
- notification.notification.fullScreenIntent.send();
- } catch (PendingIntent.CanceledException e) {
- }
- } else {
- // usual case: status bar visible & not immersive
-
- // show the ticker
- tick(notification);
- }
-
- // Recalculate the position of the sliding windows and the titles.
- setAreThereNotifications();
- updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
- }
-
- public void updateNotification(IBinder key, StatusBarNotification notification) {
- Slog.d(TAG, "updateNotification key=" + key + " notification=" + notification);
-
- NotificationData oldList;
- int oldIndex = mOngoing.findEntry(key);
- if (oldIndex >= 0) {
- oldList = mOngoing;
- } else {
- oldIndex = mLatest.findEntry(key);
- if (oldIndex < 0) {
- Slog.w(TAG, "updateNotification for unknown key: " + key);
- return;
- }
- oldList = mLatest;
- }
- final NotificationData.Entry oldEntry = oldList.getEntryAt(oldIndex);
- final StatusBarNotification oldNotification = oldEntry.notification;
- final RemoteViews oldContentView = oldNotification.notification.contentView;
-
- final RemoteViews contentView = notification.notification.contentView;
-
- if (false) {
- Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
- + " ongoing=" + oldNotification.isOngoing()
- + " expanded=" + oldEntry.expanded
- + " contentView=" + oldContentView);
- Slog.d(TAG, "new notification: when=" + notification.notification.when
- + " ongoing=" + oldNotification.isOngoing()
- + " contentView=" + contentView);
- }
-
- // Can we just reapply the RemoteViews in place? If when didn't change, the order
- // didn't change.
- if (notification.notification.when == oldNotification.notification.when
- && notification.isOngoing() == oldNotification.isOngoing()
- && oldEntry.expanded != null
- && contentView != null && oldContentView != null
- && contentView.getPackage() != null
- && oldContentView.getPackage() != null
- && oldContentView.getPackage().equals(contentView.getPackage())
- && oldContentView.getLayoutId() == contentView.getLayoutId()) {
- if (SPEW) Slog.d(TAG, "reusing notification");
- oldEntry.notification = notification;
- try {
- // Reapply the RemoteViews
- contentView.reapply(this, oldEntry.content);
- // update the contentIntent
- final PendingIntent contentIntent = notification.notification.contentIntent;
- if (contentIntent != null) {
- oldEntry.content.setOnClickListener(new Launcher(contentIntent,
- notification.pkg, notification.tag, notification.id));
- }
- // Update the icon.
- final StatusBarIcon ic = new StatusBarIcon(notification.pkg,
- notification.notification.icon, notification.notification.iconLevel,
- notification.notification.number);
- if (!oldEntry.icon.set(ic)) {
- handleNotificationError(key, notification, "Couldn't update icon: " + ic);
- return;
- }
- }
- catch (RuntimeException e) {
- // It failed to add cleanly. Log, and remove the view from the panel.
- Slog.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
- removeNotificationViews(key);
- addNotificationViews(key, notification);
- }
- } else {
- if (SPEW) Slog.d(TAG, "not reusing notification");
- removeNotificationViews(key);
- addNotificationViews(key, notification);
- }
-
- // Restart the ticker if it's still running
- tick(notification);
-
- // Recalculate the position of the sliding windows and the titles.
- setAreThereNotifications();
- updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
- }
-
- public void removeNotification(IBinder key) {
- if (SPEW) Slog.d(TAG, "removeNotification key=" + key);
- StatusBarNotification old = removeNotificationViews(key);
-
- if (old != null) {
- // Cancel the ticker if it's still running
- mTicker.removeEntry(old);
-
- // Recalculate the position of the sliding windows and the titles.
- setAreThereNotifications();
- updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
- }
- }
-
- private int chooseIconIndex(boolean isOngoing, int viewIndex) {
- final int latestSize = mLatest.size();
- if (isOngoing) {
- return latestSize + (mOngoing.size() - viewIndex);
- } else {
- return latestSize - viewIndex;
- }
- }
-
- View[] makeNotificationView(StatusBarNotification notification, ViewGroup parent) {
- Notification n = notification.notification;
- RemoteViews remoteViews = n.contentView;
- if (remoteViews == null) {
- return null;
- }
-
- // create the row view
- LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View row = inflater.inflate(R.layout.status_bar_latest_event, parent, false);
-
- // bind the click event to the content area
- ViewGroup content = (ViewGroup)row.findViewById(R.id.content);
- content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- content.setOnFocusChangeListener(mFocusChangeListener);
- PendingIntent contentIntent = n.contentIntent;
- if (contentIntent != null) {
- content.setOnClickListener(new Launcher(contentIntent, notification.pkg,
- notification.tag, notification.id));
- }
-
- View expanded = null;
- Exception exception = null;
- try {
- expanded = remoteViews.apply(this, content);
- }
- catch (RuntimeException e) {
- exception = e;
- }
- if (expanded == null) {
- String ident = notification.pkg + "/0x" + Integer.toHexString(notification.id);
- Slog.e(TAG, "couldn't inflate view for notification " + ident, exception);
- return null;
- } else {
- content.addView(expanded);
- row.setDrawingCacheEnabled(true);
- }
-
- return new View[] { row, content, expanded };
- }
-
- StatusBarIconView addNotificationViews(IBinder key, StatusBarNotification notification) {
- NotificationData list;
- ViewGroup parent;
- final boolean isOngoing = notification.isOngoing();
- if (isOngoing) {
- list = mOngoing;
- parent = mOngoingItems;
- } else {
- list = mLatest;
- parent = mLatestItems;
- }
- // Construct the expanded view.
- final View[] views = makeNotificationView(notification, parent);
- if (views == null) {
- handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
- + notification);
- return null;
- }
- final View row = views[0];
- final View content = views[1];
- final View expanded = views[2];
- // Construct the icon.
- final StatusBarIconView iconView = new StatusBarIconView(this,
- notification.pkg + "/0x" + Integer.toHexString(notification.id));
- final StatusBarIcon ic = new StatusBarIcon(notification.pkg, notification.notification.icon,
- notification.notification.iconLevel, notification.notification.number);
- if (!iconView.set(ic)) {
- handleNotificationError(key, notification, "Coulding create icon: " + ic);
- return null;
- }
- // Add the expanded view.
- final int viewIndex = list.add(key, notification, row, content, expanded, iconView);
- parent.addView(row, viewIndex);
- // Add the icon.
- final int iconIndex = chooseIconIndex(isOngoing, viewIndex);
- mNotificationIcons.addView(iconView, iconIndex,
- new LinearLayout.LayoutParams(mIconSize, mIconSize));
- return iconView;
- }
-
- StatusBarNotification removeNotificationViews(IBinder key) {
- NotificationData.Entry entry = mOngoing.remove(key);
- if (entry == null) {
- entry = mLatest.remove(key);
- if (entry == null) {
- Slog.w(TAG, "removeNotification for unknown key: " + key);
- return null;
- }
- }
- // Remove the expanded view.
- ((ViewGroup)entry.row.getParent()).removeView(entry.row);
- // Remove the icon.
- ((ViewGroup)entry.icon.getParent()).removeView(entry.icon);
-
- return entry.notification;
- }
-
- private void setAreThereNotifications() {
- boolean ongoing = mOngoing.hasVisibleItems();
- boolean latest = mLatest.hasVisibleItems();
-
- // (no ongoing notifications are clearable)
- if (mLatest.hasClearableItems()) {
- mClearButton.setVisibility(View.VISIBLE);
- } else {
- mClearButton.setVisibility(View.INVISIBLE);
- }
-
- mOngoingTitle.setVisibility(ongoing ? View.VISIBLE : View.GONE);
- mLatestTitle.setVisibility(latest ? View.VISIBLE : View.GONE);
-
- if (ongoing || latest) {
- mNoNotificationsTitle.setVisibility(View.GONE);
- } else {
- mNoNotificationsTitle.setVisibility(View.VISIBLE);
- }
- }
-
-
- /**
- * State is one or more of the DISABLE constants from StatusBarManager.
- */
- public void disable(int state) {
- final int old = mDisabled;
- final int diff = state ^ old;
- mDisabled = state;
-
- if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
- if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
- Slog.d(TAG, "DISABLE_EXPAND: yes");
- animateCollapse();
- }
- }
- if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
- if (mTicking) {
- mTicker.halt();
- } else {
- setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
- }
- } else {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
- if (!mExpandedVisible) {
- setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
- }
- }
- } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
- if (mTicking && (state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
- Slog.d(TAG, "DISABLE_NOTIFICATION_TICKER: yes");
- mTicker.halt();
- }
- }
- }
-
- /**
- * All changes to the status bar and notifications funnel through here and are batched.
- */
- private class H extends Handler {
- public void handleMessage(Message m) {
- switch (m.what) {
- case MSG_ANIMATE:
- doAnimation();
- break;
- case MSG_ANIMATE_REVEAL:
- doRevealAnimation();
- break;
- case MSG_SHOW_INTRUDER:
- setIntruderAlertVisibility(true);
- break;
- case MSG_HIDE_INTRUDER:
- setIntruderAlertVisibility(false);
- break;
- }
- }
- }
-
- View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
- public void onFocusChange(View v, boolean hasFocus) {
- // Because 'v' is a ViewGroup, all its children will be (un)selected
- // too, which allows marqueeing to work.
- v.setSelected(hasFocus);
- }
- };
-
- private void makeExpandedVisible() {
- if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
- if (mExpandedVisible) {
- return;
- }
- mExpandedVisible = true;
- visibilityChanged(true);
-
- updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
- mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
- mExpandedView.requestFocus(View.FOCUS_FORWARD);
- mTrackingView.setVisibility(View.VISIBLE);
-
- if (!mTicking) {
- setDateViewVisibility(true, com.android.internal.R.anim.fade_in);
- }
- }
-
- public void animateExpand() {
- if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return ;
- }
- if (mExpanded) {
- return;
- }
-
- prepareTracking(0, true);
- performFling(0, 2000.0f, true);
- }
-
- public void animateCollapse() {
- if (SPEW) {
- Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
- + " mExpandedVisible=" + mExpandedVisible
- + " mExpanded=" + mExpanded
- + " mAnimating=" + mAnimating
- + " mAnimY=" + mAnimY
- + " mAnimVel=" + mAnimVel);
- }
-
- if (!mExpandedVisible) {
- return;
- }
-
- int y;
- if (mAnimating) {
- y = (int)mAnimY;
- } else {
- y = mDisplay.getHeight()-1;
- }
- // Let the fling think that we're open so it goes in the right direction
- // and doesn't try to re-open the windowshade.
- mExpanded = true;
- prepareTracking(y, false);
- performFling(y, -2000.0f, true);
- }
-
- void performExpand() {
- if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return ;
- }
- if (mExpanded) {
- return;
- }
-
- mExpanded = true;
- makeExpandedVisible();
- updateExpandedViewPos(EXPANDED_FULL_OPEN);
-
- if (false) postStartTracing();
- }
-
- void performCollapse() {
- if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
- + " mExpandedVisible=" + mExpandedVisible);
-
- if (!mExpandedVisible) {
- return;
- }
- mExpandedVisible = false;
- visibilityChanged(false);
- mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
- mTrackingView.setVisibility(View.GONE);
-
- if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
- setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
- }
- setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
-
- if (!mExpanded) {
- return;
- }
- mExpanded = false;
- }
-
- void doAnimation() {
- if (mAnimating) {
- if (SPEW) Slog.d(TAG, "doAnimation");
- if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
- incrementAnim();
- if (SPEW) Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
- if (mAnimY >= mDisplay.getHeight()-1) {
- if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
- mAnimating = false;
- updateExpandedViewPos(EXPANDED_FULL_OPEN);
- performExpand();
- }
- else if (mAnimY < mStatusBarView.getHeight()) {
- if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
- mAnimating = false;
- updateExpandedViewPos(0);
- performCollapse();
- }
- else {
- updateExpandedViewPos((int)mAnimY);
- mCurAnimationTime += ANIM_FRAME_DURATION;
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurAnimationTime);
- }
- }
- }
-
- void stopTracking() {
- mTracking = false;
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
-
- void incrementAnim() {
- long now = SystemClock.uptimeMillis();
- float t = ((float)(now - mAnimLastTime)) / 1000; // ms -> s
- final float y = mAnimY;
- final float v = mAnimVel; // px/s
- final float a = mAnimAccel; // px/s/s
- mAnimY = y + (v*t) + (0.5f*a*t*t); // px
- mAnimVel = v + (a*t); // px/s
- mAnimLastTime = now; // ms
- //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
- // + " mAnimAccel=" + mAnimAccel);
- }
-
- void doRevealAnimation() {
- final int h = mCloseView.getHeight() + mStatusBarView.getHeight();
- if (mAnimatingReveal && mAnimating && mAnimY < h) {
- incrementAnim();
- if (mAnimY >= h) {
- mAnimY = h;
- updateExpandedViewPos((int)mAnimY);
- } else {
- updateExpandedViewPos((int)mAnimY);
- mCurAnimationTime += ANIM_FRAME_DURATION;
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE_REVEAL),
- mCurAnimationTime);
- }
- }
- }
-
- void prepareTracking(int y, boolean opening) {
- mTracking = true;
- mVelocityTracker = VelocityTracker.obtain();
- if (opening) {
- mAnimAccel = 2000.0f;
- mAnimVel = 200;
- mAnimY = mStatusBarView.getHeight();
- updateExpandedViewPos((int)mAnimY);
- mAnimating = true;
- mAnimatingReveal = true;
- mHandler.removeMessages(MSG_ANIMATE);
- mHandler.removeMessages(MSG_ANIMATE_REVEAL);
- long now = SystemClock.uptimeMillis();
- mAnimLastTime = now;
- mCurAnimationTime = now + ANIM_FRAME_DURATION;
- mAnimating = true;
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE_REVEAL),
- mCurAnimationTime);
- makeExpandedVisible();
- } else {
- // it's open, close it?
- if (mAnimating) {
- mAnimating = false;
- mHandler.removeMessages(MSG_ANIMATE);
- }
- updateExpandedViewPos(y + mViewDelta);
- }
- }
-
- void performFling(int y, float vel, boolean always) {
- mAnimatingReveal = false;
- mDisplayHeight = mDisplay.getHeight();
-
- mAnimY = y;
- mAnimVel = vel;
-
- //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
-
- if (mExpanded) {
- if (!always && (
- vel > 200.0f
- || (y > (mDisplayHeight-25) && vel > -200.0f))) {
- // We are expanded, but they didn't move sufficiently to cause
- // us to retract. Animate back to the expanded position.
- mAnimAccel = 2000.0f;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are expanded and are now going to animate away.
- mAnimAccel = -2000.0f;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- } else {
- if (always || (
- vel > 200.0f
- || (y > (mDisplayHeight/2) && vel > -200.0f))) {
- // We are collapsed, and they moved enough to allow us to
- // expand. Animate in the notifications.
- mAnimAccel = 2000.0f;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are collapsed, but they didn't move sufficiently to cause
- // us to retract. Animate back to the collapsed position.
- mAnimAccel = -2000.0f;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- }
- //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
- // + " mAnimAccel=" + mAnimAccel);
-
- long now = SystemClock.uptimeMillis();
- mAnimLastTime = now;
- mCurAnimationTime = now + ANIM_FRAME_DURATION;
- mAnimating = true;
- mHandler.removeMessages(MSG_ANIMATE);
- mHandler.removeMessages(MSG_ANIMATE_REVEAL);
- mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ANIMATE), mCurAnimationTime);
- stopTracking();
- }
-
- boolean interceptTouchEvent(MotionEvent event) {
- if (SPEW) {
- Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
- + mDisabled);
- }
-
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return false;
- }
-
- final int statusBarSize = mStatusBarView.getHeight();
- final int hitSize = statusBarSize*2;
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- final int y = (int)event.getRawY();
-
- if (!mExpanded) {
- mViewDelta = statusBarSize - y;
- } else {
- mTrackingView.getLocationOnScreen(mAbsPos);
- mViewDelta = mAbsPos[1] + mTrackingView.getHeight() - y;
- }
- if ((!mExpanded && y < hitSize) ||
- (mExpanded && y > (mDisplay.getHeight()-hitSize))) {
-
- // We drop events at the edge of the screen to make the windowshade come
- // down by accident less, especially when pushing open a device with a keyboard
- // that rotates (like g1 and droid)
- int x = (int)event.getRawX();
- final int edgeBorder = mEdgeBorder;
- if (x >= edgeBorder && x < mDisplay.getWidth() - edgeBorder) {
- prepareTracking(y, !mExpanded);// opening if we're not already fully visible
- mVelocityTracker.addMovement(event);
- }
- }
- } else if (mTracking) {
- mVelocityTracker.addMovement(event);
- final int minY = statusBarSize + mCloseView.getHeight();
- if (event.getAction() == MotionEvent.ACTION_MOVE) {
- int y = (int)event.getRawY();
- if (mAnimatingReveal && y < minY) {
- // nothing
- } else {
- mAnimatingReveal = false;
- updateExpandedViewPos(y + mViewDelta);
- }
- } else if (event.getAction() == MotionEvent.ACTION_UP) {
- mVelocityTracker.computeCurrentVelocity(1000);
-
- float yVel = mVelocityTracker.getYVelocity();
- boolean negative = yVel < 0;
-
- float xVel = mVelocityTracker.getXVelocity();
- if (xVel < 0) {
- xVel = -xVel;
- }
- if (xVel > 150.0f) {
- xVel = 150.0f; // limit how much we care about the x axis
- }
-
- float vel = (float)Math.hypot(yVel, xVel);
- if (negative) {
- vel = -vel;
- }
-
- performFling((int)event.getRawY(), vel, false);
- }
-
- }
- return false;
- }
-
- private class Launcher implements View.OnClickListener {
- private PendingIntent mIntent;
- private String mPkg;
- private String mTag;
- private int mId;
-
- Launcher(PendingIntent intent, String pkg, String tag, int id) {
- mIntent = intent;
- mPkg = pkg;
- mTag = tag;
- mId = id;
- }
-
- public void onClick(View v) {
- try {
- // The intent we are sending is for the application, which
- // won't have permission to immediately start an activity after
- // the user switches to home. We know it is safe to do at this
- // point, so make sure new activity switches are now allowed.
- ActivityManagerNative.getDefault().resumeAppSwitches();
- } catch (RemoteException e) {
- }
-
- if (mIntent != null) {
- int[] pos = new int[2];
- v.getLocationOnScreen(pos);
- Intent overlay = new Intent();
- overlay.setSourceBounds(
- new Rect(pos[0], pos[1], pos[0]+v.getWidth(), pos[1]+v.getHeight()));
- try {
- mIntent.send(StatusBarService.this, 0, overlay);
- } catch (PendingIntent.CanceledException e) {
- // the stack trace isn't very helpful here. Just log the exception message.
- Slog.w(TAG, "Sending contentIntent failed: " + e);
- }
- }
-
- try {
- mBarService.onNotificationClick(mPkg, mTag, mId);
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
-
- // close the shade if it was open
- animateCollapse();
-
- // If this click was on the intruder alert, hide that instead
- mHandler.sendEmptyMessage(MSG_HIDE_INTRUDER);
- }
- }
-
- private void tick(StatusBarNotification n) {
- // Show the ticker if one is requested. Also don't do this
- // until status bar window is attached to the window manager,
- // because... well, what's the point otherwise? And trying to
- // run a ticker without being attached will crash!
- if (n.notification.tickerText != null && mStatusBarView.getWindowToken() != null) {
- if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
- | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
- mTicker.addEntry(n);
- }
- }
- }
-
- /**
- * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
- * about the failure.
- *
- * WARNING: this will call back into us. Don't hold any locks.
- */
- void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
- removeNotification(key);
- try {
- mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
- } catch (RemoteException ex) {
- // The end is nigh.
- }
- }
-
- private class MyTicker extends Ticker {
- MyTicker(Context context, StatusBarView sb) {
- super(context, sb);
- }
-
- @Override
- void tickerStarting() {
- mTicking = true;
- mIcons.setVisibility(View.GONE);
- mTickerView.setVisibility(View.VISIBLE);
- mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_up_in, null));
- mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_up_out, null));
- if (mExpandedVisible) {
- setDateViewVisibility(false, com.android.internal.R.anim.push_up_out);
- }
- }
-
- @Override
- void tickerDone() {
- mIcons.setVisibility(View.VISIBLE);
- mTickerView.setVisibility(View.GONE);
- mIcons.startAnimation(loadAnim(com.android.internal.R.anim.push_down_in, null));
- mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.push_down_out,
- mTickingDoneListener));
- if (mExpandedVisible) {
- setDateViewVisibility(true, com.android.internal.R.anim.push_down_in);
- }
- }
-
- void tickerHalting() {
- mIcons.setVisibility(View.VISIBLE);
- mTickerView.setVisibility(View.GONE);
- mIcons.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null));
- mTickerView.startAnimation(loadAnim(com.android.internal.R.anim.fade_out,
- mTickingDoneListener));
- if (mExpandedVisible) {
- setDateViewVisibility(true, com.android.internal.R.anim.fade_in);
- }
- }
- }
-
- Animation.AnimationListener mTickingDoneListener = new Animation.AnimationListener() {;
- public void onAnimationEnd(Animation animation) {
- mTicking = false;
- }
- public void onAnimationRepeat(Animation animation) {
- }
- public void onAnimationStart(Animation animation) {
- }
- };
-
- private Animation loadAnim(int id, Animation.AnimationListener listener) {
- Animation anim = AnimationUtils.loadAnimation(StatusBarService.this, id);
- if (listener != null) {
- anim.setAnimationListener(listener);
- }
- return anim;
- }
-
- public String viewInfo(View v) {
- return "(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
- + " " + v.getWidth() + "x" + v.getHeight() + ")";
- }
-
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump StatusBar from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
- }
-
- synchronized (mQueueLock) {
- pw.println("Current Status Bar state:");
- pw.println(" mExpanded=" + mExpanded
- + ", mExpandedVisible=" + mExpandedVisible);
- pw.println(" mTicking=" + mTicking);
- pw.println(" mTracking=" + mTracking);
- pw.println(" mAnimating=" + mAnimating
- + ", mAnimY=" + mAnimY + ", mAnimVel=" + mAnimVel
- + ", mAnimAccel=" + mAnimAccel);
- pw.println(" mCurAnimationTime=" + mCurAnimationTime
- + " mAnimLastTime=" + mAnimLastTime);
- pw.println(" mDisplayHeight=" + mDisplayHeight
- + " mAnimatingReveal=" + mAnimatingReveal
- + " mViewDelta=" + mViewDelta);
- pw.println(" mDisplayHeight=" + mDisplayHeight);
- pw.println(" mExpandedParams: " + mExpandedParams);
- pw.println(" mExpandedView: " + viewInfo(mExpandedView));
- pw.println(" mExpandedDialog: " + mExpandedDialog);
- pw.println(" mTrackingParams: " + mTrackingParams);
- pw.println(" mTrackingView: " + viewInfo(mTrackingView));
- pw.println(" mOngoingTitle: " + viewInfo(mOngoingTitle));
- pw.println(" mOngoingItems: " + viewInfo(mOngoingItems));
- pw.println(" mLatestTitle: " + viewInfo(mLatestTitle));
- pw.println(" mLatestItems: " + viewInfo(mLatestItems));
- pw.println(" mNoNotificationsTitle: " + viewInfo(mNoNotificationsTitle));
- pw.println(" mCloseView: " + viewInfo(mCloseView));
- pw.println(" mTickerView: " + viewInfo(mTickerView));
- pw.println(" mScrollView: " + viewInfo(mScrollView)
- + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
- pw.println("mNotificationLinearLayout: " + viewInfo(mNotificationLinearLayout));
- }
- /*
- synchronized (mNotificationData) {
- int N = mNotificationData.ongoingCount();
- pw.println(" ongoingCount.size=" + N);
- for (int i=0; i<N; i++) {
- StatusBarNotification n = mNotificationData.getOngoing(i);
- pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
- pw.println(" data=" + n.data);
- }
- N = mNotificationData.latestCount();
- pw.println(" ongoingCount.size=" + N);
- for (int i=0; i<N; i++) {
- StatusBarNotification n = mNotificationData.getLatest(i);
- pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
- pw.println(" data=" + n.data);
- }
- }
- */
-
- if (false) {
- pw.println("see the logcat for a dump of the views we have created.");
- // must happen on ui thread
- mHandler.post(new Runnable() {
- public void run() {
- mStatusBarView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mStatusBarView.getWidth() + "x"
- + mStatusBarView.getHeight());
- mStatusBarView.debug();
-
- mExpandedView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mExpandedView.getWidth() + "x"
- + mExpandedView.getHeight());
- mExpandedView.debug();
-
- mTrackingView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mTrackingView.getWidth() + "x"
- + mTrackingView.getHeight());
- mTrackingView.debug();
- }
- });
- }
- }
-
- void onBarViewAttached() {
- WindowManager.LayoutParams lp;
- int pixelFormat;
- Drawable bg;
-
- /// ---------- Tracking View --------------
- pixelFormat = PixelFormat.RGBX_8888;
- bg = mTrackingView.getBackground();
- if (bg != null) {
- pixelFormat = bg.getOpacity();
- }
-
- lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- pixelFormat);
-// lp.token = mStatusBarView.getWindowToken();
- lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
- lp.setTitle("TrackingView");
- lp.y = mTrackingPosition;
- mTrackingParams = lp;
-
- WindowManagerImpl.getDefault().addView(mTrackingView, lp);
- }
-
- void onTrackingViewAttached() {
- WindowManager.LayoutParams lp;
- int pixelFormat;
- Drawable bg;
-
- /// ---------- Expanded View --------------
- pixelFormat = PixelFormat.TRANSLUCENT;
-
- final int disph = mDisplay.getHeight();
- lp = mExpandedDialog.getWindow().getAttributes();
- lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
- lp.height = getExpandedHeight();
- lp.x = 0;
- mTrackingPosition = lp.y = -disph; // sufficiently large negative
- lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
- lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_DITHER
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- lp.format = pixelFormat;
- lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
- lp.setTitle("StatusBarExpanded");
- mExpandedDialog.getWindow().setAttributes(lp);
- mExpandedDialog.getWindow().setFormat(pixelFormat);
- mExpandedParams = lp;
-
- mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- mExpandedDialog.setContentView(mExpandedView,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- mExpandedDialog.getWindow().setBackgroundDrawable(null);
- mExpandedDialog.show();
- FrameLayout hack = (FrameLayout)mExpandedView.getParent();
- }
-
- void setDateViewVisibility(boolean visible, int anim) {
- mDateView.setUpdates(visible);
- mDateView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- mDateView.startAnimation(loadAnim(anim, null));
- }
-
- void setNotificationIconVisibility(boolean visible, int anim) {
- int old = mNotificationIcons.getVisibility();
- int v = visible ? View.VISIBLE : View.INVISIBLE;
- if (old != v) {
- mNotificationIcons.setVisibility(v);
- mNotificationIcons.startAnimation(loadAnim(anim, null));
- }
- }
-
- void updateExpandedViewPos(int expandedPosition) {
- if (SPEW) {
- Slog.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
- + " mTrackingParams.y=" + mTrackingParams.y
- + " mTrackingPosition=" + mTrackingPosition);
- }
-
- int h = mStatusBarView.getHeight();
- int disph = mDisplay.getHeight();
-
- // If the expanded view is not visible, make sure they're still off screen.
- // Maybe the view was resized.
- if (!mExpandedVisible) {
- if (mTrackingView != null) {
- mTrackingPosition = -disph;
- if (mTrackingParams != null) {
- mTrackingParams.y = mTrackingPosition;
- WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
- }
- }
- if (mExpandedParams != null) {
- mExpandedParams.y = -disph;
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
- }
- return;
- }
-
- // tracking view...
- int pos;
- if (expandedPosition == EXPANDED_FULL_OPEN) {
- pos = h;
- }
- else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
- pos = mTrackingPosition;
- }
- else {
- if (expandedPosition <= disph) {
- pos = expandedPosition;
- } else {
- pos = disph;
- }
- pos -= disph-h;
- }
- mTrackingPosition = mTrackingParams.y = pos;
- mTrackingParams.height = disph-h;
- WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
-
- if (mExpandedParams != null) {
- mCloseView.getLocationInWindow(mPositionTmp);
- final int closePos = mPositionTmp[1];
-
- mExpandedContents.getLocationInWindow(mPositionTmp);
- final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
-
- mExpandedParams.y = pos + mTrackingView.getHeight()
- - (mTrackingParams.height-closePos) - contentsBottom;
- int max = h;
- if (mExpandedParams.y > max) {
- mExpandedParams.y = max;
- }
- int min = mTrackingPosition;
- if (mExpandedParams.y < min) {
- mExpandedParams.y = min;
- }
-
- boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
- if (!visible) {
- // if the contents aren't visible, move the expanded view way off screen
- // because the window itself extends below the content view.
- mExpandedParams.y = -disph;
- }
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-
- // As long as this isn't just a repositioning that's not supposed to affect
- // the user's perception of what's showing, call to say that the visibility
- // has changed. (Otherwise, someone else will call to do that).
- if (expandedPosition != EXPANDED_LEAVE_ALONE) {
- if (SPEW) Slog.d(TAG, "updateExpandedViewPos visibilityChanged(" + visible + ")");
- visibilityChanged(visible);
- }
- }
-
- if (SPEW) {
- Slog.d(TAG, "updateExpandedViewPos after expandedPosition=" + expandedPosition
- + " mTrackingParams.y=" + mTrackingParams.y
- + " mTrackingPosition=" + mTrackingPosition
- + " mExpandedParams.y=" + mExpandedParams.y
- + " mExpandedParams.height=" + mExpandedParams.height);
- }
- }
-
- int getExpandedHeight() {
- return mDisplay.getHeight() - mStatusBarView.getHeight() - mCloseView.getHeight();
- }
-
- void updateExpandedHeight() {
- if (mExpandedView != null) {
- mExpandedParams.height = getExpandedHeight();
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
- }
- }
-
- /**
- * The LEDs are turned o)ff when the notification panel is shown, even just a little bit.
- * This was added last-minute and is inconsistent with the way the rest of the notifications
- * are handled, because the notification isn't really cancelled. The lights are just
- * turned off. If any other notifications happen, the lights will turn back on. Steve says
- * this is what he wants. (see bug 1131461)
- */
- void visibilityChanged(boolean visible) {
- if (mPanelSlightlyVisible != visible) {
- mPanelSlightlyVisible = visible;
- try {
- mBarService.onPanelRevealed();
- } catch (RemoteException ex) {
- // Won't fail unless the world has ended.
- }
- }
- }
-
- void performDisableActions(int net) {
- int old = mDisabled;
- int diff = net ^ old;
- mDisabled = net;
-
- // act accordingly
- if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
- if ((net & StatusBarManager.DISABLE_EXPAND) != 0) {
- Slog.d(TAG, "DISABLE_EXPAND: yes");
- animateCollapse();
- }
- }
- if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- if ((net & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
- if (mTicking) {
- mNotificationIcons.setVisibility(View.INVISIBLE);
- mTicker.halt();
- } else {
- setNotificationIconVisibility(false, com.android.internal.R.anim.fade_out);
- }
- } else {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
- if (!mExpandedVisible) {
- setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
- }
- }
- } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
- if (mTicking && (net & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
- mTicker.halt();
- }
- }
- }
-
- private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
- public void onClick(View v) {
- try {
- mBarService.onClearAllNotifications();
- } catch (RemoteException ex) {
- // system process is dead if we're here.
- }
- animateCollapse();
- }
- };
-
- private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
- || Intent.ACTION_SCREEN_OFF.equals(action)) {
- //collapse();
- }
- else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
- updateResources();
- }
- }
- };
-
- private void setIntruderAlertVisibility(boolean vis) {
- mIntruderAlertView.setVisibility(vis ? View.VISIBLE : View.GONE);
- }
-
- /**
- * Reload some of our resources when the configuration changes.
- *
- * We don't reload everything when the configuration changes -- we probably
- * should, but getting that smooth is tough. Someday we'll fix that. In the
- * meantime, just update the things that we know change.
- */
- void updateResources() {
- Resources res = getResources();
-
- mClearButton.setText(getText(R.string.status_bar_clear_all_button));
- mOngoingTitle.setText(getText(R.string.status_bar_ongoing_events_title));
- mLatestTitle.setText(getText(R.string.status_bar_latest_events_title));
- mNoNotificationsTitle.setText(getText(R.string.status_bar_no_notifications_title));
-
- mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
-
- if (false) Slog.v(TAG, "updateResources");
- }
-
- //
- // tracing
- //
-
- void postStartTracing() {
- mHandler.postDelayed(mStartTracing, 3000);
- }
-
- void vibrate() {
- android.os.Vibrator vib = (android.os.Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
- vib.vibrate(250);
- }
-
- Runnable mStartTracing = new Runnable() {
- public void run() {
- vibrate();
- SystemClock.sleep(250);
- Slog.d(TAG, "startTracing");
- android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
- mHandler.postDelayed(mStopTracing, 10000);
- }
- };
-
- Runnable mStopTracing = new Runnable() {
- public void run() {
- android.os.Debug.stopMethodTracing();
- Slog.d(TAG, "stopTracing");
- vibrate();
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java
index 57452af..20fc41f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java
@@ -35,13 +35,12 @@ public class StatusBarView extends FrameLayout {
static final int DIM_ANIM_TIME = 400;
- StatusBarService mService;
+ PhoneStatusBarService mService;
boolean mTracking;
int mStartX, mStartY;
ViewGroup mNotificationIcons;
ViewGroup mStatusIcons;
View mDate;
- View mButtonArea;
FixedSizeDrawable mBackground;
boolean mNightMode = false;
@@ -65,8 +64,6 @@ public class StatusBarView extends FrameLayout {
mBackground = new FixedSizeDrawable(mDate.getBackground());
mBackground.setFixedBounds(0, 0, 0, 0);
mDate.setBackgroundDrawable(mBackground);
-
- mButtonArea = findViewById(R.id.buttons);
}
@Override
@@ -101,7 +98,7 @@ public class StatusBarView extends FrameLayout {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
- mService.updateExpandedViewPos(StatusBarService.EXPANDED_LEAVE_ALONE);
+ mService.updateExpandedViewPos(PhoneStatusBarService.EXPANDED_LEAVE_ALONE);
}
@Override
@@ -132,10 +129,6 @@ public class StatusBarView extends FrameLayout {
mDate.layout(mDate.getLeft(), mDate.getTop(), newDateRight, mDate.getBottom());
mBackground.setFixedBounds(-mDate.getLeft(), -mDate.getTop(), (r-l), (b-t));
-
- if (mButtonArea != null) {
- mButtonArea.getHitRect(mButtonBounds);
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/TrackingView.java b/packages/SystemUI/src/com/android/systemui/statusbar/TrackingView.java
index 9108eee..c59eb6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/TrackingView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/TrackingView.java
@@ -26,7 +26,7 @@ import android.widget.LinearLayout;
public class TrackingView extends LinearLayout {
final Display mDisplay;
- StatusBarService mService;
+ PhoneStatusBarService mService;
boolean mTracking;
int mStartX, mStartY;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
new file mode 100644
index 0000000..7835d42
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
@@ -0,0 +1,74 @@
+/*
+ * 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.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+
+public class NotificationIconArea extends LinearLayout {
+ private static final String TAG = "NotificationIconArea";
+
+ MoreView mMoreView;
+ IconLayout mIconLayout;
+ DraggerView mDraggerView;
+
+ public NotificationIconArea(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mMoreView = new MoreView(context);
+ addView(mMoreView, new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+
+ mIconLayout = new IconLayout(context);
+ addView(mIconLayout, new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+
+ mDraggerView = new DraggerView(context);
+ addView(mDraggerView, new LinearLayout.LayoutParams(
+ LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ }
+
+ class MoreView extends ImageView {
+ public MoreView(Context context) {
+ super(context);
+ setImageResource(R.drawable.stat_notify_more);
+ }
+ }
+
+ class IconLayout extends LinearLayout {
+ public IconLayout(Context context) {
+ super(context);
+ }
+ }
+
+ class DraggerView extends ImageView {
+ public DraggerView(Context context) {
+ super(context);
+ setImageResource(R.drawable.notification_dragger);
+ }
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
new file mode 100644
index 0000000..24d3c39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -0,0 +1,102 @@
+/*
+ * 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.systemui.statusbar.tablet;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.IBinder;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.statusbar.StatusBarIconList;
+import com.android.internal.statusbar.StatusBarNotification;
+
+import com.android.systemui.statusbar.*;
+import com.android.systemui.R;
+
+public class TabletStatusBarService extends StatusBarService {
+
+ View mStatusBarView;
+ NotificationIconArea mNotificationIconArea;
+
+ int mIconSize;
+
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ protected View makeStatusBarView() {
+ Resources res = getResources();
+
+ mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+
+ final View sb = View.inflate(this, R.layout.status_bar, null);
+ mStatusBarView = sb;
+
+ // the more notifications icon
+ mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
+
+ return sb;
+ }
+
+ protected int getStatusBarGravity() {
+ return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
+ }
+
+ public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
+ // TODO
+ }
+
+ public void updateIcon(String slot, int index, int viewIndex,
+ StatusBarIcon old, StatusBarIcon icon) {
+ // TODO
+ }
+
+ public void removeIcon(String slot, int index, int viewIndex) {
+ // TODO
+ }
+
+ public void addNotification(IBinder key, StatusBarNotification notification) {
+ // TODO
+ }
+
+ public void updateNotification(IBinder key, StatusBarNotification notification) {
+ // TODO
+ }
+
+ public void removeNotification(IBinder key) {
+ // TODO
+ }
+
+ public void disable(int state) {
+ // TODO
+ }
+
+ public void animateExpand() {
+ // TODO
+ }
+
+ public void animateCollapse() {
+ // TODO
+ }
+}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 8321473..070d1e8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -284,7 +284,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mTitleView != null) {
mTitleView.setText(title);
} else if (mActionBar != null) {
- mActionBar.setTitle(title);
+ mActionBar.setWindowTitle(title);
}
mTitle = title;
}
@@ -2334,7 +2334,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
} else {
mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
if (mActionBar != null && mActionBar.getTitle() == null) {
- mActionBar.setTitle(mTitle);
+ mActionBar.setWindowTitle(mTitle);
}
}
}
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index 995e31c..995e31c 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/services/audioflinger/A2dpAudioInterface.cpp
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
index 48154f9..48154f9 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/services/audioflinger/A2dpAudioInterface.h
diff --git a/libs/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 22ecc54..22ecc54 100644
--- a/libs/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
diff --git a/libs/audioflinger/AudioBufferProvider.h b/services/audioflinger/AudioBufferProvider.h
index 81c5c39..81c5c39 100644
--- a/libs/audioflinger/AudioBufferProvider.h
+++ b/services/audioflinger/AudioBufferProvider.h
diff --git a/libs/audioflinger/AudioDumpInterface.cpp b/services/audioflinger/AudioDumpInterface.cpp
index 6c11114..6c11114 100644
--- a/libs/audioflinger/AudioDumpInterface.cpp
+++ b/services/audioflinger/AudioDumpInterface.cpp
diff --git a/libs/audioflinger/AudioDumpInterface.h b/services/audioflinger/AudioDumpInterface.h
index 814ce5f..814ce5f 100644
--- a/libs/audioflinger/AudioDumpInterface.h
+++ b/services/audioflinger/AudioDumpInterface.h
diff --git a/libs/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 97eb6c0..771d885 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -6068,11 +6068,4 @@ status_t AudioFlinger::onTransact(
return BnAudioFlinger::onTransact(code, data, reply, flags);
}
-// ----------------------------------------------------------------------------
-
-void AudioFlinger::instantiate() {
- defaultServiceManager()->addService(
- String16("media.audio_flinger"), new AudioFlinger());
-}
-
}; // namespace android
diff --git a/libs/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 507c9ac..7013d76 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -31,10 +31,12 @@
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/threads.h>
-#include <binder/MemoryDealer.h>
#include <utils/SortedVector.h>
#include <utils/Vector.h>
+#include <binder/BinderService.h>
+#include <binder/MemoryDealer.h>
+
#include <hardware_legacy/AudioHardwareInterface.h>
#include "AudioBufferProvider.h"
@@ -58,10 +60,13 @@ class AudioResampler;
static const nsecs_t kStandbyTimeInNsecs = seconds(3);
-class AudioFlinger : public BnAudioFlinger
+class AudioFlinger :
+ public BinderService<AudioFlinger>,
+ public BnAudioFlinger
{
+ friend class BinderService<AudioFlinger>;
public:
- static void instantiate();
+ static char const* getServiceName() { return "media.audio_flinger"; }
virtual status_t dump(int fd, const Vector<String16>& args);
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/services/audioflinger/AudioHardwareGeneric.cpp
index d63c031..d63c031 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/services/audioflinger/AudioHardwareGeneric.cpp
diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/services/audioflinger/AudioHardwareGeneric.h
index aa4e78d..aa4e78d 100644
--- a/libs/audioflinger/AudioHardwareGeneric.h
+++ b/services/audioflinger/AudioHardwareGeneric.h
diff --git a/libs/audioflinger/AudioHardwareInterface.cpp b/services/audioflinger/AudioHardwareInterface.cpp
index 9a4a7f9..9a4a7f9 100644
--- a/libs/audioflinger/AudioHardwareInterface.cpp
+++ b/services/audioflinger/AudioHardwareInterface.cpp
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/services/audioflinger/AudioHardwareStub.cpp
index d481150..d481150 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/services/audioflinger/AudioHardwareStub.cpp
diff --git a/libs/audioflinger/AudioHardwareStub.h b/services/audioflinger/AudioHardwareStub.h
index 06a29de..06a29de 100644
--- a/libs/audioflinger/AudioHardwareStub.h
+++ b/services/audioflinger/AudioHardwareStub.h
diff --git a/libs/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 8aaa325..8aaa325 100644
--- a/libs/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
diff --git a/libs/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index aee3e17..aee3e17 100644
--- a/libs/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 549d661..549d661 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
diff --git a/libs/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index bb3905c..bb3905c 100644
--- a/libs/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
diff --git a/libs/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index a13d0bd..a13d0bd 100644
--- a/libs/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
diff --git a/libs/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 5dabacb..5dabacb 100644
--- a/libs/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
diff --git a/libs/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index 2dfac76..2dfac76 100644
--- a/libs/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
diff --git a/libs/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 1d247bd..1d247bd 100644
--- a/libs/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
diff --git a/libs/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h
index b72b62a..b72b62a 100644
--- a/libs/audioflinger/AudioResamplerCubic.h
+++ b/services/audioflinger/AudioResamplerCubic.h
diff --git a/libs/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
index 9e5e254..9e5e254 100644
--- a/libs/audioflinger/AudioResamplerSinc.cpp
+++ b/services/audioflinger/AudioResamplerSinc.cpp
diff --git a/libs/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
index e6cb90b..e6cb90b 100644
--- a/libs/audioflinger/AudioResamplerSinc.h
+++ b/services/audioflinger/AudioResamplerSinc.h
diff --git a/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 87975af..87975af 100644
--- a/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index b3e0ee6..b3e0ee6 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
index d3427ba..d3427ba 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
diff --git a/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 10668a4..c786f94 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -192,11 +192,6 @@ sp<CameraService::Client> CameraService::getClientById(int cameraId) {
return mClient[cameraId].promote();
}
-void CameraService::instantiate() {
- defaultServiceManager()->addService(String16("media.camera"),
- new CameraService());
-}
-
status_t CameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
// Permission checks
diff --git a/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8193e77..b0b2d7a 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -19,6 +19,8 @@
#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+#include <binder/BinderService.h>
+
#include <camera/ICameraService.h>
#include <camera/CameraHardwareInterface.h>
@@ -30,11 +32,14 @@ namespace android {
class MemoryHeapBase;
class MediaPlayer;
-class CameraService: public BnCameraService
+class CameraService :
+ public BinderService<CameraService>,
+ public BnCameraService
{
class Client;
+ friend class BinderService<CameraService>;
public:
- static void instantiate();
+ static char const* getServiceName() { return "media.camera"; }
CameraService();
virtual ~CameraService();
diff --git a/camera/libcameraservice/CannedJpeg.h b/services/camera/libcameraservice/CannedJpeg.h
index b6266fb..b6266fb 100644
--- a/camera/libcameraservice/CannedJpeg.h
+++ b/services/camera/libcameraservice/CannedJpeg.h
diff --git a/camera/libcameraservice/FakeCamera.cpp b/services/camera/libcameraservice/FakeCamera.cpp
index f3a6a67..f3a6a67 100644
--- a/camera/libcameraservice/FakeCamera.cpp
+++ b/services/camera/libcameraservice/FakeCamera.cpp
diff --git a/camera/libcameraservice/FakeCamera.h b/services/camera/libcameraservice/FakeCamera.h
index 724de20..724de20 100644
--- a/camera/libcameraservice/FakeCamera.h
+++ b/services/camera/libcameraservice/FakeCamera.h
diff --git a/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
index cf4e42f..cf4e42f 100644
--- a/camera/tests/CameraServiceTest/Android.mk
+++ b/services/camera/tests/CameraServiceTest/Android.mk
diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index 3c8d553..3c8d553 100644
--- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
diff --git a/services/java/com/android/server/ViewServer.java b/services/java/com/android/server/ViewServer.java
index 9c7db9b..b369f71 100644
--- a/services/java/com/android/server/ViewServer.java
+++ b/services/java/com/android/server/ViewServer.java
@@ -216,8 +216,11 @@ class ViewServer implements Runnable {
class ViewServerWorker implements Runnable, WindowManagerService.WindowChangeListener {
private Socket mClient;
private boolean mNeedWindowListUpdate;
+ private boolean mNeedFocusedWindowUpdate;
public ViewServerWorker(Socket client) {
mClient = client;
+ mNeedWindowListUpdate = false;
+ mNeedFocusedWindowUpdate = false;
}
public void run() {
@@ -285,20 +288,42 @@ class ViewServer implements Runnable {
}
}
+ public void focusChanged() {
+ synchronized(this) {
+ mNeedFocusedWindowUpdate = true;
+ notifyAll();
+ }
+ }
+
private boolean windowManagerAutolistLoop() {
mWindowManager.addWindowChangeListener(this);
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(mClient.getOutputStream()));
while (!Thread.interrupted()) {
+ boolean needWindowListUpdate = false;
+ boolean needFocusedWindowUpdate = false;
synchronized (this) {
- while (!mNeedWindowListUpdate) {
+ while (!mNeedWindowListUpdate && !mNeedFocusedWindowUpdate) {
wait();
}
- mNeedWindowListUpdate = false;
+ if (mNeedWindowListUpdate) {
+ mNeedWindowListUpdate = false;
+ needWindowListUpdate = true;
+ }
+ if (mNeedFocusedWindowUpdate) {
+ mNeedFocusedWindowUpdate = false;
+ needFocusedWindowUpdate = true;
+ }
+ }
+ if(needWindowListUpdate) {
+ out.write("LIST UPDATE\n");
+ out.flush();
+ }
+ if(needFocusedWindowUpdate) {
+ out.write("FOCUS UPDATE\n");
+ out.flush();
}
- out.write("UPDATE\n");
- out.flush();
}
} catch (Exception e) {
Slog.w(LOG_TAG, "Connection error: ", e);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index c986dcc..3475b2f 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -494,6 +494,7 @@ public class WindowManagerService extends IWindowManager.Stub
public interface WindowChangeListener {
public void windowsChanged();
+ public void focusChanged();
}
final Configuration mTempConfiguration = new Configuration();
@@ -4829,6 +4830,21 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ private void notifyFocusChanged() {
+ WindowChangeListener[] windowChangeListeners;
+ synchronized(mWindowMap) {
+ if(mWindowChangeListeners.isEmpty()) {
+ return;
+ }
+ windowChangeListeners = new WindowChangeListener[mWindowChangeListeners.size()];
+ windowChangeListeners = mWindowChangeListeners.toArray(windowChangeListeners);
+ }
+ int N = windowChangeListeners.length;
+ for(int i = 0; i < N; i++) {
+ windowChangeListeners[i].focusChanged();
+ }
+ }
+
private WindowState findWindow(int hashCode) {
if (hashCode == -1) {
return getFocusedWindow();
@@ -7716,7 +7732,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int ENABLE_SCREEN = 16;
public static final int APP_FREEZE_TIMEOUT = 17;
public static final int SEND_NEW_CONFIGURATION = 18;
- public static final int WINDOWS_CHANGED = 19;
+ public static final int REPORT_WINDOWS_CHANGE = 19;
private Session mLastReportedHold;
@@ -7768,6 +7784,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Ignore if process has died.
}
}
+ notifyFocusChanged();
}
} break;
@@ -8048,7 +8065,7 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- case WINDOWS_CHANGED: {
+ case REPORT_WINDOWS_CHANGE: {
if (mWindowsChanged) {
synchronized (mWindowMap) {
mWindowsChanged = false;
@@ -8279,8 +8296,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
if (mWindowsChanged && !mWindowChangeListeners.isEmpty()) {
- mH.removeMessages(H.WINDOWS_CHANGED);
- mH.sendMessage(mH.obtainMessage(H.WINDOWS_CHANGED));
+ mH.removeMessages(H.REPORT_WINDOWS_CHANGE);
+ mH.sendMessage(mH.obtainMessage(H.REPORT_WINDOWS_CHANGE));
}
} catch (RuntimeException e) {
mInLayout = false;
diff --git a/libs/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index a14bfb5..a14bfb5 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
diff --git a/libs/surfaceflinger/Barrier.h b/services/surfaceflinger/Barrier.h
index 6f8507e..6f8507e 100644
--- a/libs/surfaceflinger/Barrier.h
+++ b/services/surfaceflinger/Barrier.h
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/services/surfaceflinger/BlurFilter.cpp
index 1ffbd5b..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/services/surfaceflinger/BlurFilter.cpp
diff --git a/libs/surfaceflinger/BlurFilter.h b/services/surfaceflinger/BlurFilter.h
index 294db43..294db43 100644
--- a/libs/surfaceflinger/BlurFilter.h
+++ b/services/surfaceflinger/BlurFilter.h
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 2eac0a8..2eac0a8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 66bf521..66bf521 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index 1d09f84..1d09f84 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index 8369bb8..8369bb8 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
diff --git a/libs/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp
index 7f4f9fc..7f4f9fc 100644
--- a/libs/surfaceflinger/GLExtensions.cpp
+++ b/services/surfaceflinger/GLExtensions.cpp
diff --git a/libs/surfaceflinger/GLExtensions.h b/services/surfaceflinger/GLExtensions.h
index bbb284e..bbb284e 100644
--- a/libs/surfaceflinger/GLExtensions.h
+++ b/services/surfaceflinger/GLExtensions.h
diff --git a/libs/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 758da4e..758da4e 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
diff --git a/libs/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e1d283b..e1d283b 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
diff --git a/libs/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index d5aa53f..d5aa53f 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
diff --git a/libs/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 4288cf7..4288cf7 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp
index 64a43c7..64a43c7 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/services/surfaceflinger/LayerBlur.cpp
diff --git a/libs/surfaceflinger/LayerBlur.h b/services/surfaceflinger/LayerBlur.h
index 4c9ec64..4c9ec64 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/services/surfaceflinger/LayerBlur.h
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp
index 5f83636..5f83636 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/services/surfaceflinger/LayerBuffer.cpp
diff --git a/libs/surfaceflinger/LayerBuffer.h b/services/surfaceflinger/LayerBuffer.h
index 1c0bf83..1c0bf83 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/services/surfaceflinger/LayerBuffer.h
diff --git a/libs/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index a1f339e..a1f339e 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
diff --git a/libs/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index f032314..f032314 100644
--- a/libs/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
diff --git a/libs/surfaceflinger/MODULE_LICENSE_APACHE2 b/services/surfaceflinger/MODULE_LICENSE_APACHE2
index e69de29..e69de29 100644
--- a/libs/surfaceflinger/MODULE_LICENSE_APACHE2
+++ b/services/surfaceflinger/MODULE_LICENSE_APACHE2
diff --git a/libs/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index d668e88..d668e88 100644
--- a/libs/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
diff --git a/libs/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 890f809..890f809 100644
--- a/libs/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 68e8f19..3167c4c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -63,20 +63,6 @@
#define DISPLAY_COUNT 1
namespace android {
-
-// ---------------------------------------------------------------------------
-
-void SurfaceFlinger::instantiate() {
- defaultServiceManager()->addService(
- String16("SurfaceFlinger"), new SurfaceFlinger());
-}
-
-void SurfaceFlinger::shutdown() {
- // we should unregister here, but not really because
- // when (if) the service manager goes away, all the services
- // it has a reference to will leave too.
-}
-
// ---------------------------------------------------------------------------
SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0bfc170..8821e5c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -29,6 +29,7 @@
#include <binder/IMemory.h>
#include <binder/Permission.h>
+#include <binder/BinderService.h>
#include <ui/PixelFormat.h>
#include <surfaceflinger/ISurfaceComposer.h>
@@ -167,11 +168,13 @@ enum {
eTraversalNeeded = 0x02
};
-class SurfaceFlinger : public BnSurfaceComposer, protected Thread
+class SurfaceFlinger :
+ public BinderService<SurfaceFlinger>,
+ public BnSurfaceComposer,
+ protected Thread
{
public:
- static void instantiate();
- static void shutdown();
+ static char const* getServiceName() { return "SurfaceFlinger"; }
SurfaceFlinger();
virtual ~SurfaceFlinger();
diff --git a/libs/surfaceflinger/TextureManager.cpp b/services/surfaceflinger/TextureManager.cpp
index 6526032..3b326df 100644
--- a/libs/surfaceflinger/TextureManager.cpp
+++ b/services/surfaceflinger/TextureManager.cpp
@@ -107,7 +107,6 @@ bool TextureManager::isSupportedYuvFormat(int format)
{
switch (format) {
case HAL_PIXEL_FORMAT_YV12:
- case HAL_PIXEL_FORMAT_YV16:
return true;
}
return false;
@@ -118,7 +117,6 @@ bool TextureManager::isYuvFormat(int format)
switch (format) {
// supported YUV formats
case HAL_PIXEL_FORMAT_YV12:
- case HAL_PIXEL_FORMAT_YV16:
// Legacy/deprecated YUV formats
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
diff --git a/libs/surfaceflinger/TextureManager.h b/services/surfaceflinger/TextureManager.h
index c7c14e7..c7c14e7 100644
--- a/libs/surfaceflinger/TextureManager.h
+++ b/services/surfaceflinger/TextureManager.h
diff --git a/libs/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 5e27cc9..5e27cc9 100644
--- a/libs/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
diff --git a/libs/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index 20fa11a..20fa11a 100644
--- a/libs/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
diff --git a/libs/surfaceflinger/clz.cpp b/services/surfaceflinger/clz.cpp
index 2456b86..2456b86 100644
--- a/libs/surfaceflinger/clz.cpp
+++ b/services/surfaceflinger/clz.cpp
diff --git a/libs/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index 0ddf986..0ddf986 100644
--- a/libs/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
diff --git a/libs/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
index 5053e7d..5053e7d 100644
--- a/libs/surfaceflinger/tests/Android.mk
+++ b/services/surfaceflinger/tests/Android.mk
diff --git a/libs/surfaceflinger/tests/overlays/Android.mk b/services/surfaceflinger/tests/overlays/Android.mk
index 592b601..592b601 100644
--- a/libs/surfaceflinger/tests/overlays/Android.mk
+++ b/services/surfaceflinger/tests/overlays/Android.mk
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/services/surfaceflinger/tests/overlays/overlays.cpp
index c248a61..c248a61 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/services/surfaceflinger/tests/overlays/overlays.cpp
diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/services/surfaceflinger/tests/resize/Android.mk
index 24c2d01..24c2d01 100644
--- a/libs/surfaceflinger/tests/resize/Android.mk
+++ b/services/surfaceflinger/tests/resize/Android.mk
diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
index 127cca3..127cca3 100644
--- a/libs/surfaceflinger/tests/resize/resize.cpp
+++ b/services/surfaceflinger/tests/resize/resize.cpp
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 68d01d4..3618c7b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -336,6 +336,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh
intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
intent.putExtra(TestShellActivity.TOTAL_TEST_COUNT, mTestCount);
intent.putExtra(TestShellActivity.CURRENT_TEST_NUMBER, testNumber);
+ intent.putExtra(TestShellActivity.STOP_ON_REF_ERROR, true);
activity.startActivity(intent);
// Wait until done.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 0a04712..bf66fae 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -179,6 +179,7 @@ public class TestShellActivity extends Activity implements LayoutTestController
mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
mGetDrawtime = intent.getBooleanExtra(GET_DRAW_TIME, false);
mSaveImagePath = intent.getStringExtra(SAVE_IMAGE);
+ mStopOnRefError = intent.getBooleanExtra(STOP_ON_REF_ERROR, false);
setTitle("Test " + mCurrentTestNumber + " of " + mTotalTestCount);
float ratio = (float)mCurrentTestNumber / mTotalTestCount;
int progress = (int)(ratio * Window.PROGRESS_END);
@@ -699,8 +700,8 @@ public class TestShellActivity extends Activity implements LayoutTestController
// waiting for "notifyDone" signal to finish, then there's no point in waiting
// anymore because the JS execution is already terminated at this point and a
// "notifyDone" will never come out so it's just wasting time till timeout kicks in
- if (msg.contains("Uncaught ReferenceError:") || msg.contains("Uncaught TypeError:")
- && mWaitUntilDone) {
+ if ((msg.contains("Uncaught ReferenceError:") || msg.contains("Uncaught TypeError:"))
+ && mWaitUntilDone && mStopOnRefError) {
Log.w(LOGTAG, "Terminating test case on uncaught ReferenceError or TypeError.");
mHandler.postDelayed(new Runnable() {
public void run() {
@@ -857,6 +858,7 @@ public class TestShellActivity extends Activity implements LayoutTestController
private boolean mGetDrawtime;
private int mTotalTestCount;
private int mCurrentTestNumber;
+ private boolean mStopOnRefError;
// States
private boolean mTimedOut;
@@ -897,6 +899,7 @@ public class TestShellActivity extends Activity implements LayoutTestController
static final String SAVE_IMAGE = "SaveImage";
static final String TOTAL_TEST_COUNT = "TestCount";
static final String CURRENT_TEST_NUMBER = "TestNumber";
+ static final String STOP_ON_REF_ERROR = "StopOnReferenceError";
static final int DRAW_RUNS = 5;
static final String DRAW_TIME_LOG = "/sdcard/android/page_draw_time.txt";
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index f13cfaf..cb894f1 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -87,6 +87,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="RotationActivity"
+ android:label="_Rotation">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/MultisamplingActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/MultisamplingActivity.java
deleted file mode 100644
index 95b14aa..0000000
--- a/tests/HwAccelerationTest/src/com/google/android/test/hwui/MultisamplingActivity.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.test.hwui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.widget.FrameLayout;
-
-@SuppressWarnings({"UnusedDeclaration"})
-public class MultisamplingActivity extends Activity {
- private static final String LOG_TAG = "HwUi";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- DirtyBitmapView container = new DirtyBitmapView(this);
-
- ColorView color = new ColorView(this);
- container.addView(color, new DirtyBitmapView.LayoutParams(
- dipToPx(this, 100), dipToPx(this, 100), Gravity.CENTER));
-
- AlphaAnimation a = new AlphaAnimation(1.0f, 0.0f);
- a.setDuration(2000);
- a.setRepeatCount(Animation.INFINITE);
- a.setRepeatMode(Animation.REVERSE);
- color.startAnimation(a);
-
- setContentView(container);
- }
-
- @SuppressWarnings({"UnusedDeclaration"})
- static int dipToPx(Context c, int dip) {
- return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
- }
-
- static class ColorView extends View {
- ColorView(Context c) {
- super(c);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawRGB(0, 255, 0);
- }
- }
-
- static class DirtyBitmapView extends FrameLayout {
- private final Paint mPaint;
-
- DirtyBitmapView(Context c) {
- super(c);
- mPaint = new Paint();
- }
-
- @Override
- public void dispatchDraw(Canvas canvas) {
- canvas.drawRGB(255, 255, 255);
-
- mPaint.setColor(0xffff0000);
- canvas.drawRect(200.0f, 0.0f, 220.0f, 20.0f, mPaint);
-
- canvas.save();
- canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
- Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(100.0f, 100.0f, 110.0f, 110.0f,
- Canvas.EdgeType.BW));
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
- Canvas.EdgeType.BW));
- canvas.restore();
-
- canvas.save();
- canvas.scale(2.0f, 2.0f);
- canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
- Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(50.0f, 50.0f, 60.0f, 60.0f,
- Canvas.EdgeType.BW));
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
- Canvas.EdgeType.BW));
- canvas.restore();
-
- canvas.save();
- canvas.translate(20.0f, 20.0f);
- canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
- Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(80.0f, 80.0f, 90.0f, 90.0f,
- Canvas.EdgeType.BW));
- Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
- Canvas.EdgeType.BW));
- canvas.restore();
-
- canvas.save();
- canvas.scale(2.0f, 2.0f);
- canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
-
- mPaint.setColor(0xff00ff00);
- canvas.drawRect(0.0f, 0.0f, 20.0f, 20.0f, mPaint);
-
- mPaint.setColor(0xff0000ff);
- canvas.drawRect(20.0f, 0.0f, 40.0f, 20.0f, mPaint);
-
- canvas.restore();
-
- final int restoreTo = canvas.save();
- canvas.saveLayerAlpha(0.0f, 100.0f, getWidth(), 150.0f, 127,
- Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- mPaint.setColor(0xff0000ff);
- canvas.drawRect(0.0f, 100.0f, 40.0f, 150.0f, mPaint);
- mPaint.setColor(0xff00ffff);
- canvas.drawRect(40.0f, 100.0f, 140.0f, 150.0f, mPaint);
- mPaint.setColor(0xffff00ff);
- canvas.drawRect(140.0f, 100.0f, 240.0f, 150.0f, mPaint);
- canvas.restoreToCount(restoreTo);
-
- super.dispatchDraw(canvas);
- }
- }
-} \ No newline at end of file
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/RotationActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/RotationActivity.java
new file mode 100644
index 0000000..e629cb8
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/RotationActivity.java
@@ -0,0 +1,63 @@
+/*
+ * 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.google.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class RotationActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ DrawingView container = new DrawingView(this);
+
+ setContentView(container);
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ static int dipToPx(Context c, int dip) {
+ return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
+ }
+
+ static class DrawingView extends View {
+ private final Paint mPaint;
+
+ DrawingView(Context c) {
+ super(c);
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ canvas.save();
+ canvas.translate(dipToPx(getContext(), 400), dipToPx(getContext(), 200));
+ canvas.rotate(45.0f);
+ canvas.drawRGB(255, 255, 255);
+ mPaint.setColor(0xffff0000);
+ canvas.drawRect(-80.0f, -80.0f, 80.0f, 80.0f, mPaint);
+ canvas.drawRect(0.0f, 0.0f, 220.0f, 220.0f, mPaint);
+ canvas.restore();
+ }
+ }
+}
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 6d606a9..135a633 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -52,13 +52,15 @@ include $(BUILD_SYSTEM)/base_rules.mk
$(LOCAL_BUILT_MODULE): $(built_core_dep) \
$(built_framework_dep) \
$(built_layoutlib_create_jar)
- @echo "host layoutlib_create: $@"
- @mkdir -p $(dir $@)
- @rm -f $@
+ $(hide) echo "host layoutlib_create: $@"
+ $(hide) mkdir -p $(dir $@)
+ $(hide) rm -f $@
+ $(hide) ls -l $(built_framework_classes)
$(hide) java -jar $(built_layoutlib_create_jar) \
$@ \
$(built_core_classes) \
$(built_framework_classes)
+ $(hide) ls -l $(built_framework_classes)
#